[prev in list] [next in list] [prev in thread] [next in thread] 

List:       freebsd-hackers
Subject:    No flames please: Linux mknod compatibilty
From:       João_Carlos_Mendes_Luís <jonny () jonny ! eng ! br>
Date:       2004-06-28 22:49:31
Message-ID: 40E0A07B.6030405 () jonny ! eng ! br
[Download RAW message or body]

Hi everybody,

     First of all, please copy all answers back to me, since I am not anymore 
subscribed to -hackers.  (Panic: time fault)

     I´ve done some changes to the kernel mknod(2) handling to make it more 
compatible to the Linux behaviour, allowing one to create files of type VREG, 
VSOCK and VFIFO with mknod(2).  I already know that BSD way is that one should 
use creat(2), bind(2) and mkfifo(2) functions for these, but, if all these are 
indeed vnodes, why bother if one use mkfifo(2) or mknod(2) to create fifos?? 
The only vnode type I think I left out is VDIR, because it needs to be 
initialized with "." and "..".

     I first came with this idea using rsync for a full backup, noticing it 
could not copy fifos or sockets.  I could simply fix rsync, but I thought 
"fixing" FreeBSD would be a little bit funnier!   ;-)

     To allow your appreciation, here are my patches.  I am not an expert in VFS 
coding, so it should probably be checked by an expert before commiting.  All I 
can say is that it worked for me.

     I'll submit a PR after this email, to make it faster to commit.    ;-)


----8<--------8<--------8<--------8<--------8<--------8<--------8<----
--- RELENG_4/src/sys/kern/vfs_syscalls.c.orig   Mon Jun 28 18:11:58 2004
+++ RELENG_4/src/sys/kern/vfs_syscalls.c        Mon Jun 28 19:26:31 2004
@@ -1187,14 +1187,20 @@
         register struct vnode *vp;
         struct vattr vattr;
         int error;
-       int whiteout = 0;
+       int vtype;
         struct nameidata nd;

-       switch (SCARG(uap, mode) & S_IFMT) {
+       vtype = SCARG(uap, mode) & S_IFMT;
+       switch ( vtype ) {
         case S_IFCHR:
         case S_IFBLK:
                 error = suser(p);
                 break;
+       case S_IFREG:
+       case S_IFIFO:
+       case S_IFSOCK:
+               error = 0;
+               break;
         default:
                 error = suser_xxx(0, p, PRISON_ROOT);
                 break;
@@ -1202,7 +1208,7 @@
         if (error)
                 return (error);
         bwillwrite();
-       NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
+       NDINIT(&nd, CREATE, LOCKPARENT, 
(vtype==S_IFSOCK)?UIO_SYSSPACE:UIO_USERSPACE, SCARG(uap, path), p);
         if ((error = namei(&nd)) != 0)
                 return (error);
         vp = nd.ni_vp;
@@ -1212,9 +1218,8 @@
                 VATTR_NULL(&vattr);
                 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
                 vattr.va_rdev = SCARG(uap, dev);
-               whiteout = 0;

-               switch (SCARG(uap, mode) & S_IFMT) {
+               switch ( vtype ) {
                 case S_IFMT:    /* used by badsect to flag bad sectors */
                         vattr.va_type = VBAD;
                         break;
@@ -1224,8 +1229,17 @@
                 case S_IFBLK:
                         vattr.va_type = VBLK;
                         break;
+               case S_IFREG:
+                       vattr.va_type = VREG;
+                       break;
+               case S_IFSOCK:
+                       vattr.va_type = VSOCK;
+                       break;
+               case S_IFIFO:
+                       vattr.va_type = VFIFO;
+                       break;
                 case S_IFWHT:
-                       whiteout = 1;
+                       /* NOTHING */
                         break;
                 default:
                         error = EINVAL;
@@ -1234,9 +1248,18 @@
         }
         if (!error) {
                 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
-               if (whiteout)
+               switch ( vtype ) {
+                   case S_IFWHT:
                         error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
-               else {
+                       break;
+                   case S_IFREG:
+                   case S_IFSOCK:
+                       error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp,
+                                               &nd.ni_cnd, &vattr);
+                       if (error == 0)
+                               vput(nd.ni_vp);
+                       break;
+                   default:
                         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
                                                 &nd.ni_cnd, &vattr);
                         if (error == 0)
----8<--------8<--------8<--------8<--------8<--------8<--------8<----

And here is a small test program, ran on both Linux and FreeBSD:

----8<--------8<--------8<--------8<--------8<--------8<--------8<----
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

main()
{
mknod( "test1", S_IFSOCK|0777, 0 );
perror( "mknod" );
errno=0;
mknod( "test2", S_IFIFO|0777, 0 );
perror( "mknod" );
errno=0;
mknod( "test3", S_IFREG|0777, 0 );
perror( "mknod" );
errno=0;
mknod( "test4", S_IFBLK|0777, 0 );
perror( "mknod" );
errno=0;
mknod( "test5", S_IFCHR|0777, 0 );
perror( "mknod" );
errno=0;
}
----8<--------8<--------8<--------8<--------8<--------8<--------8<----

_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org"
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic