Hello fellow hackers,

I've written up a short patch to add a sysctl to control the appending of
/compat/linux/ to path requests in Linux mode.  We had to get ADSM's Linux
client working on FreeBSD so we could do backups of our systems.  Luckily
it comes statically linked so all was needed was this sysctl and some
creative redirections (there's a bug in the termio ioctl() emulation
still...) to get it working.

Patch is attached.  Alternately you can poke
http://www.freebsd.org/~dwhite/linux.pathmunge.patch. These are against
-current.  I have a nasty #ifdef hack for 3.3 that requires Makefile
changes to compile (you want to keep the fixed and unfixed kernel modules
around on 3.3!).  

Please let me know if you have comments/suggestions/etc.  If no one whines
too badly I'll commit these later this week and finally break my
declaration against making kernel changes. :)

Doug White                    |  FreeBSD: The Power to Serve
[EMAIL PROTECTED]     |  www.FreeBSD.org

Index: linux_mib.c
===================================================================
RCS file: /usr/local/cvs/src/sys/i386/linux/linux_mib.c,v
retrieving revision 1.2
diff -u -r1.2 linux_mib.c
--- linux_mib.c 1999/08/28 02:16:31     1.2
+++ linux_mib.c 1999/12/07 06:33:35
@@ -43,6 +43,7 @@
        char    pr_osname[LINUX_MAX_UTSNAME];
        char    pr_osrelease[LINUX_MAX_UTSNAME];
        int     pr_oss_version;
+        int     pr_pathmunge;
 };
 
 SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0,
@@ -111,6 +112,28 @@
            0, 0, linux_sysctl_oss_version, "I",
            "Linux OSS version");
 
+static int        linux_pathmunge = 1;
+
+static int
+linux_sysctl_pathmunge SYSCTL_HANDLER_ARGS
+{
+       int pathmunge;
+       int error;
+
+       pathmunge = linux_get_pathmunge(req->p);
+       error = sysctl_handle_int(oidp, &pathmunge, 0, req);
+       if (error || req->newptr == NULL)
+               return (error);
+       error = linux_set_pathmunge(req->p, pathmunge);
+       return (error);
+}
+
+SYSCTL_PROC(_compat_linux, OID_AUTO, pathmunge,
+           CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON,
+           0, 0, linux_sysctl_pathmunge, "I",
+           "Linux Path Munge");
+
+
 static struct linux_prison *
 get_prison(struct proc *p)
 {
@@ -226,6 +249,38 @@
                lpr->pr_oss_version = oss_version;
        else
                linux_oss_version = oss_version;
+
+       return (0);
+}
+int
+linux_get_pathmunge(p)
+       struct proc *p;
+{
+       register struct prison *pr;
+       register struct linux_prison *lpr;
+
+       pr = p->p_prison;
+       if (pr != NULL && pr->pr_linux != NULL) {
+               lpr = pr->pr_linux;
+               if (lpr->pr_pathmunge)
+                       return (lpr->pr_pathmunge);
+       }
+
+       return (linux_pathmunge);
+}
+
+int
+linux_set_pathmunge(p, pathmunge)
+       struct proc *p;
+       int pathmunge;
+{
+       register struct linux_prison *lpr;
+
+       lpr = get_prison(p);
+       if (lpr != NULL)
+               lpr->pr_pathmunge = pathmunge;
+       else
+               linux_pathmunge = pathmunge;
 
        return (0);
 }
Index: linux_mib.h
===================================================================
RCS file: /usr/local/cvs/src/sys/i386/linux/linux_mib.h,v
retrieving revision 1.2
diff -u -r1.2 linux_mib.h
--- linux_mib.h 1999/08/28 02:16:32     1.2
+++ linux_mib.h 1999/12/07 05:22:18
@@ -1,3 +1,4 @@
+
 /*-
  * Copyright (c) 1999 Marcel Moolenaar
  * All rights reserved.
@@ -39,5 +40,8 @@
 
 int    linux_get_oss_version   __P((struct proc *p));
 int    linux_set_oss_version   __P((struct proc *p, int oss_version));
+
+int    linux_get_pathmunge     __P((struct proc *p));
+int    linux_set_pathmunge     __P((struct proc *p, int pathmunge));
 
 #endif /* _LINUX_MIB_H_ */
Index: linux_util.c
===================================================================
RCS file: /usr/local/cvs/src/sys/i386/linux/linux_util.c,v
retrieving revision 1.8
diff -u -r1.8 linux_util.c
--- linux_util.c        1999/08/28 00:45:25     1.8
+++ linux_util.c        1999/12/08 05:22:49
@@ -38,6 +38,7 @@
 #include <sys/vnode.h>
 
 #include <i386/linux/linux_util.h>
+#include <i386/linux/linux_mib.h>
 
 const char      linux_emul_path[] = "/compat/linux";
 
@@ -69,8 +70,22 @@
        buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
        *pbuf = path;
 
-       for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
-               continue;
+       /* 
+        * Look at the compat.linux.pathmunge sysctl to determine 
+        * whether to add the linux_emul_path on the front of the
+        * requested file.  Software that does tree walks, such
+        * as backup clients, get locked into the /compat/linux
+        * subtree if this is set.  Setting the sysctl to 0
+        * makes Linux apps access files like any other, but must
+        * be statically linked or they'll never find their libs.
+        */
+
+       if(linux_get_pathmunge(p)) {
+               for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
+                       continue;
+       } else {
+               ptr = buf;
+       }
 
        sz = MAXPATHLEN - (ptr - buf);
 



To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to