]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/fork.c
Patch to allow for read-only advisory locks (thanks to
[netatalk.git] / etc / afpd / fork.c
index 7b1b8abbf489e4cb81bd25c030002febec019bbf..f38c438014cdde061045e0d8c63b2c387c03599a 100644 (file)
@@ -1,11 +1,21 @@
 /*
+ * $Id: fork.c,v 1.9 2001-10-24 04:13:22 jmarcus Exp $
+ *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
 #include <stdio.h>
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_FCNTL_H
 #include <fcntl.h>
+#endif /* HAVE_FCNTL_H */
 #include <dirent.h>
 #include <string.h>
 #include <errno.h>
@@ -26,7 +36,9 @@
 #include <atalk/afp.h>
 #include <atalk/adouble.h>
 #include <atalk/util.h>
+#ifdef CNID_DB
 #include <atalk/cnid.h>
+#endif
 
 #include "fork.h"
 #include "file.h"
@@ -58,7 +70,7 @@ static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
     } else {
        aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
        if ( ad_refresh( ofork->of_ad ) < 0 ) {
-           syslog( LOG_ERR, "getforkparams: ad_refresh: %m");
+           syslog( LOG_ERR, "getforkparams: ad_refresh: %s", strerror(errno) );
            return( AFPERR_PARAM );
        }
        /* See afp_closefork() for why this is bad */
@@ -145,7 +157,7 @@ static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
                memcpy(data, ufinderi, 8 );
                if (( em = getextmap( ofork->of_name )) != NULL ) {
                    memcpy(data, em->em_type, sizeof( em->em_type ));
-                   memcpy(data + 4, em->em_creator, 
+                   memcpy(data + 4, em->em_creator,
                            sizeof( em->em_creator ));
                }
            }
@@ -163,29 +175,28 @@ static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
            break;
 
        case FILPBIT_FNUM :
-           /*
-            * See file.c getfilparams() for why this is done this
-            * way.
-            */
+               aint = 0;
 #if AD_VERSION > AD_VERSION1
-           if (isad) 
-             memcpy(&aint, ad_entry(ofork->of_ad, ADEID_DID), sizeof(aint));
-           else
-             aint = 0;
-           
-           if (!(aint = cnid_add(ofork->of_vol->v_db, &st, 
-                                 ofork->of_dir->d_did, 
-                                 upath, strlen(upath), aint))) {
-#endif
+        /* look in AD v2 header */
+        if (isad)
+               memcpy(&aint, ad_entry(ofork->of_ad, ADEID_DID), sizeof(aint));
+#endif /* AD_VERSION > AD_VERSION1 */
+
+#ifdef CNID_DB
+        aint = cnid_add(ofork->of_vol->v_db, &st,
+                                 ofork->of_dir->d_did,
+                                 upath, strlen(upath), aint);
+#endif /* CNID_DB */
+
+               if (aint == 0) {
 #ifdef AFS
              aint = st.st_ino;
-#else AFS
+#else /* AFS */
              aint = ( st.st_dev << 16 ) | ( st.st_ino & 0x0000ffff );
-#endif AFS
-#if AD_VERSION > AD_VERSION1
+#endif /* AFS */
            }
-#endif
-           memcpy(data, &aint, sizeof( aint ));
+
+               memcpy(data, &aint, sizeof( aint ));
            data += sizeof( aint );
            break;
 
@@ -295,68 +306,101 @@ int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
                           adsame)) == NULL ) {
        return( AFPERR_NFILE );
     }
+       if (access & OPENACC_WR) {
+               /* try opening in read-write mode */
+               upath = mtoupath(vol, path);
+               ret = AFPERR_NOOBJ;
+               if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
+       switch ( errno ) {
+       case EROFS:
+         ret = AFPERR_VLOCK;
+       case EACCES:
+         goto openfork_err;
 
-    /* try opening in read-write mode with a fallback to read-only 
-     * if we don't need write access. */
-    upath = mtoupath(vol, path);
-    ret = AFPERR_NOOBJ;
-    if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
-       switch ( errno ) {
-       case EROFS:
-        ret = AFPERR_VLOCK;
-       case EACCES: 
-        if (access & OPENACC_WR)
-          goto openfork_err;
-        
-        if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
+         break;
+       case ENOENT:
+         {
+           struct stat st;
+
+               /* see if client asked for the data fork */
+               if (fork == OPENFORK_DATA) {
+                 if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
+           goto openfork_err;
+                 }
+                 adflags = ADFLAGS_DF;
+
+               } else if (stat(upath, &st) == 0) {
+                 /* here's the deal. we only try to create the resource 
+                  * fork if the user wants to open it for write acess. */
+                 if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0)
+           goto openfork_err;
+               } else 
+                 goto openfork_err;
+         }
+         break;
+    case EMFILE :
+       case ENFILE :
+         ret = AFPERR_NFILE;
+         goto openfork_err;
+         break;
+       case EISDIR :
+         ret = AFPERR_BADTYPE;
+         goto openfork_err;
+         break;
+       default:
+         syslog( LOG_ERR, "afp_openfork: ad_open: %s", strerror(errno) );
+         ret = AFPERR_PARAM;
+         goto openfork_err;
+         break;
+       }
+          }
+        } else {
+          /* try opening in read-only mode */
+          upath = mtoupath(vol, path);
+          ret = AFPERR_NOOBJ;
+          if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
+        switch ( errno ) {
+        case EROFS:
+          ret = AFPERR_VLOCK;
+        case EACCES:
           /* check for a read-only data fork */
           if ((adflags != ADFLAGS_HF) &&
-              (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0))
-            goto openfork_err;
-
-          adflags = ADFLAGS_DF;               
-        }
-        break;
-       case ENOENT:
-        { 
-          struct stat st;
-          
-          /* see if client asked for the data fork */
-          if (fork == OPENFORK_DATA) {
-            if (((access & OPENACC_WR) && 
-                 (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0)) 
-                || (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, 
-                            ofork->of_ad) < 0)) {
-              goto openfork_err;
-            }
-            adflags = ADFLAGS_DF;
-            
-          } else if (stat(upath, &st) == 0) {
-            /* here's the deal. we only try to create the resource
-             * fork if the user wants to open it for write access. */
-            if ((access & OPENACC_WR) && 
-                (ad_open(upath, adflags, O_RDWR | O_CREAT, 
-                         0666, ofork->of_ad) < 0))
-              goto openfork_err;
-          } else 
+                  (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0))
+                goto openfork_err;
+
+          adflags = ADFLAGS_DF;
+          break;
+        case ENOENT:
+          {
+            struct stat st;
+
+                /* see if client asked for the data fork */
+                if (fork == OPENFORK_DATA) {
+                  if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) {
             goto openfork_err;
+                  }
+                  adflags = ADFLAGS_DF;
+
+                } else if (stat(upath, &st) != 0) {
+                  goto openfork_err;
+                }
+          }
+          break;
+        case EMFILE :
+        case ENFILE :
+          ret = AFPERR_NFILE;
+          goto openfork_err;
+          break;
+        case EISDIR :
+          ret = AFPERR_BADTYPE;
+          goto openfork_err;
+          break;
+        default:
+          syslog( LOG_ERR, "afp_openfork: ad_open: %s", strerror(errno) );
+          goto openfork_err;
+          break;
         }
-        break;
-       case EMFILE :
-       case ENFILE :
-        ret = AFPERR_NFILE;
-        goto openfork_err;
-        break;
-       case EISDIR :
-        ret = AFPERR_BADTYPE;
-        goto openfork_err;
-        break;
-       default:
-        syslog( LOG_ERR, "afp_openfork: ad_open: %m" );
-        ret = AFPERR_PARAM;
-        goto openfork_err;
-        break;
-       }
+           }
     }
 
     if ((adflags & ADFLAGS_HF) &&
@@ -404,7 +448,7 @@ int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
       if (!ret && (access & OPENACC_RD)) {
        ofork->of_flags |= AFPFORK_ACCRD;
        ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK, 
-                     AD_FILELOCK_RD, 1, ofrefnum); 
+                     AD_FILELOCK_RD, 1, ofrefnum);
       }
     
       /* can we access the fork? */
@@ -447,7 +491,7 @@ int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
          break;
        default:
          *rbuflen = 0;
-         syslog( LOG_ERR, "afp_openfork: ad_lock: %m" );
+         syslog( LOG_ERR, "afp_openfork: ad_lock: %s", strerror(errno) );
          return( AFPERR_PARAM );
        }
       }
@@ -484,7 +528,7 @@ int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
 
     *rbuflen = 0;
     if (( ofork = of_find( ofrefnum )) == NULL ) {
-       syslog( LOG_ERR, "afp_setforkparams: of_find: %m" );
+       syslog( LOG_ERR, "afp_setforkparams: of_find: %s", strerror(errno) );
        return( AFPERR_PARAM );
     }
 
@@ -509,7 +553,8 @@ int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
          goto afp_setfork_err;
        
        if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
-           syslog( LOG_ERR, "afp_setforkparams: ad_flush: %m" );
+           syslog( LOG_ERR, "afp_setforkparams: ad_flush: %s",
+                   strerror(errno) );
            return( AFPERR_PARAM );
        }
     } else
@@ -519,7 +564,7 @@ int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
     if ( flushfork( ofork ) < 0 ) {
        syslog( LOG_ERR, "afp_setforkparams: flushfork: %m" );
     }
-#endif AFS
+#endif /* AFS */
 
     return( AFP_OK );
 
@@ -572,7 +617,7 @@ int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
     ibuf += sizeof(ofrefnum);
 
     if (( ofork = of_find( ofrefnum )) == NULL ) {
-       syslog( LOG_ERR, "afp_bytelock: of_find: %m" );
+       syslog( LOG_ERR, "afp_bytelock: of_find: %s", strerror(errno) );
        return( AFPERR_PARAM );
     }
 
@@ -672,7 +717,7 @@ static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
 
     cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
     if ( cc < 0 ) {
-       syslog( LOG_ERR, "afp_read: ad_read: %m" );
+       syslog( LOG_ERR, "afp_read: ad_read: %s", strerror(errno) );
        *rbuflen = 0;
        return( AFPERR_PARAM );
     }
@@ -733,7 +778,7 @@ int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
     ibuf += sizeof( u_short );
 
     if (( ofork = of_find( ofrefnum )) == NULL ) {
-       syslog( LOG_ERR, "afp_read: of_find: %m" );
+       syslog( LOG_ERR, "afp_read: of_find: %s", strerror(errno) );
        err = AFPERR_PARAM;
        goto afp_read_err;
     }
@@ -831,7 +876,7 @@ int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
          if (errno == EINVAL)
            goto afp_read_loop;
          else {
-           syslog(LOG_ERR, "afp_read: ad_readfile: %m");
+           syslog(LOG_ERR, "afp_read: ad_readfile: %s", strerror(errno));
            goto afp_read_exit;
          }
        }
@@ -841,7 +886,7 @@ int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
       }
 
 afp_read_loop:
-#endif
+#endif /* HAVE_SENDFILE_READ */
 
       /* fill up our buffer. */
       while (*rbuflen > 0) {
@@ -866,7 +911,7 @@ afp_read_loop:
       goto afp_read_done;
 
 afp_read_exit:
-      syslog(LOG_ERR, "afp_read: %m");
+      syslog(LOG_ERR, "afp_read: %s", strerror(errno));
       dsi_readdone(dsi);
       ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
       obj->exit(1);
@@ -914,12 +959,12 @@ int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
     memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
 
     if (( ofork = of_find( ofrefnum )) == NULL ) {
-       syslog( LOG_ERR, "afp_flushfork: of_find: %m" );
+       syslog( LOG_ERR, "afp_flushfork: of_find: %s", strerror(errno) );
        return( AFPERR_PARAM );
     }
 
     if ( flushfork( ofork ) < 0 ) {
-       syslog( LOG_ERR, "afp_flushfork: %m" );
+       syslog( LOG_ERR, "afp_flushfork: %s", strerror(errno) );
     }
 
     return( AFP_OK );
@@ -934,21 +979,18 @@ int flushfork( ofork )
 
     if ( ad_dfileno( ofork->of_ad ) != -1 &&
            fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
-       syslog( LOG_ERR, "flushfork: dfile(%d) %m", 
-               ad_dfileno(ofork->of_ad) );
+       syslog( LOG_ERR, "flushfork: dfile(%d) %s", 
+               ad_dfileno(ofork->of_ad), strerror(errno) );
        err = -1;
     }
 
     if ( ad_hfileno( ofork->of_ad ) != -1 ) {
-        if (ofork->of_flags & AFPFORK_RSRC) {
-         len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
-         ad_refresh(ofork->of_ad);
-         if (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK)) {
-           ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
-           doflush++;
-         }
-       }
 
+        /* read in the rfork length */
+       len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
+       ad_refresh(ofork->of_ad);
+
+       /* set the date if we're dirty */
         if ((ofork->of_flags & AFPFORK_DIRTY) &&
            (gettimeofday(&tv, NULL) == 0)) {
          ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
@@ -956,9 +998,19 @@ int flushfork( ofork )
          doflush++;
        }
 
-       /* flush the header. */
-       if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0)) 
-         err = -1;
+       /* if we're actually flushing this fork, make sure to set the
+        * length. otherwise, just use the stored length */
+        if ((ofork->of_flags & AFPFORK_RSRC) && 
+           (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK))) {
+           ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
+           doflush++;
+       }
+
+
+       /* flush the header (if it is a resource fork) */
+       if (ofork->of_flags & AFPFORK_RSRC)
+         if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0)) 
+           err = -1;
          
        if (fsync( ad_hfileno( ofork->of_ad )) < 0)
          err = -1;
@@ -1107,7 +1159,7 @@ int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
 
 #ifdef AFS
     writtenfork = ofork;
-#endif AFS
+#endif /* AFS */
 
     if ( ofork->of_flags & AFPFORK_DATA) {
        eid = ADEID_DFORK;
@@ -1213,7 +1265,7 @@ int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
          offset += cc;
          goto afp_write_done;
        }
-#endif
+#endif /* 0, was HAVE_SENDFILE_WRITE */
 
        /* loop until everything gets written. currently
          * dsi_write handles the end case by itself. */
@@ -1245,9 +1297,9 @@ afp_write_done:
     offset = htonl( offset );
 #if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
     bcopy(&offset, rbuf, sizeof(offset));
-#else
+#else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
     memcpy(rbuf, &offset, sizeof(offset));
-#endif
+#endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
     *rbuflen = sizeof(offset);
     return( AFP_OK );