]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/fork.c
Enhance logging
[netatalk.git] / etc / afpd / fork.c
index 07ce3ab19f6e3a91ba69d4afef569cbf964df1a3..33aaf66d1c025b1be90da8170b05376a2f988d81 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: fork.c,v 1.68 2009-10-25 06:12:51 didg Exp $
+ * $Id: fork.c,v 1.73 2010-03-30 12:55:26 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -11,7 +11,6 @@
 
 #include <stdio.h>
 
-#include <dirent.h>
 #include <string.h>
 #include <errno.h>
 
 #include <atalk/atp.h>
 #include <atalk/asp.h>
 #include <atalk/afp.h>
-
 #include <atalk/util.h>
 #include <atalk/cnid.h>
+#include <atalk/globals.h>
 
 #include "fork.h"
 #include "file.h"
-#include "globals.h"
 #include "directory.h"
 #include "desktop.h"
 #include "volume.h"
@@ -74,20 +72,22 @@ static int getforkparams(struct ofork *ofork, u_int16_t bitmap, char *buf, size_
     }
 
     vol = ofork->of_vol;
-    dir = ofork->of_dir;
+    dir = dirlookup(vol, ofork->of_did);
 
     if (NULL == (path.u_name = mtoupath(vol, of_name(ofork), dir->d_did, utf8_encoding()))) {
         return( AFPERR_MISC );
     }
     path.m_name = of_name(ofork);
+    path.id = 0;
     st = &path.st;
     if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) | 
                     (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) | 
                     (1 << FILPBIT_MDATE) | (1 << FILPBIT_BDATE))) {
-        if ( ad_data_fileno( ofork->of_ad ) == -1 ) {
+        if ( ad_data_fileno( ofork->of_ad ) <= 0 ) {
+            /* 0 is for symlink */
             if (movecwd(vol, dir) < 0)
                 return( AFPERR_NOOBJ );
-            if ( stat( path.u_name, st ) < 0 )
+            if ( lstat( path.u_name, st ) < 0 )
                 return( AFPERR_NOOBJ );
         } else {
             if ( fstat( ad_data_fileno( ofork->of_ad ), st ) < 0 ) {
@@ -159,14 +159,14 @@ static int sum_neg(int is64, off_t offset, off_t reqcount)
 
 /* -------------------------
 */
-static int setforkmode(struct adouble *adp, int eid, int ofrefnum, int what)
+static int setforkmode(struct adouble *adp, int eid, int ofrefnum, off_t what)
 {
     return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, what, 1, ofrefnum);
 }
 
 /* -------------------------
 */
-int getforkmode(struct adouble *adp, int eid, int what)
+int getforkmode(struct adouble *adp, int eid, off_t what)
 {
     return ad_testlock(adp, eid,  what);
 }
@@ -432,7 +432,8 @@ int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si
                 goto openfork_err;
                 break;
             default:
-                LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) );
+                LOG(log_error, logtype_afpd, "afp_openfork('%s/%s'): ad_open: errno: %i (%s)",
+                    getcwdpath, s_path->m_name, errno, strerror(errno) );
                 goto openfork_err;
                 break;
             }
@@ -637,6 +638,7 @@ afp_setfork_err:
         case EDQUOT:
         case EFBIG:
         case ENOSPC:
+            LOG(log_error, logtype_afpd, "afp_setforkparams: DISK FULL");
             return AFPERR_DFULL;
         default:
             return AFPERR_PARAM;
@@ -843,7 +845,7 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si
     int                        eid, xlate = 0;
     u_int16_t          ofrefnum;
     u_char             nlmask, nlchar;
-    
+
     ibuf += 2;
     memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
     ibuf += sizeof( u_short );
@@ -892,6 +894,9 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si
         goto afp_read_err;
     }
 
+    LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd)",
+        of_name(ofork), (intmax_t)offset, (intmax_t)reqcount);
+
     savereqcount = reqcount;
     saveoff = offset;
     if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount,ofork->of_refnum) < 0) {
@@ -899,11 +904,14 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si
         goto afp_read_err;
     }
 
-#define min(a,b)       ((a)<(b)?(a):(b))
-    *rbuflen = min( reqcount, *rbuflen );
+    *rbuflen = MIN(reqcount, *rbuflen);
+    LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): reading %jd bytes from file",
+        of_name(ofork), (intmax_t)offset, (intmax_t)reqcount, (intmax_t)*rbuflen);
     err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen, xlate);
     if (err < 0)
         goto afp_read_done;
+    LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): got %jd bytes from file",
+        of_name(ofork), (intmax_t)offset, (intmax_t)reqcount, (intmax_t)*rbuflen);
 
     /* dsi can stream requests. we can only do this if we're not checking
      * for an end-of-line character. oh well. */
@@ -931,10 +939,13 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si
         *rbuflen = cc;
         /* due to the nature of afp packets, we have to exit if we get
            an error. we can't do this with translation on. */
-#if 0 /* ifdef WITH_SENDFILE */
-        /* FIXME with OS X deadlock partial workaround we can't use sendfile */
+#ifdef WITH_SENDFILE 
         if (!(xlate || Debug(obj) )) {
-            if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset, dsi->datasize) < 0) {
+            int fd;
+                        
+            fd = ad_readfile_init(ofork->of_ad, eid, &offset, 0);
+
+            if (dsi_stream_read_file(dsi, fd, offset, dsi->datasize) < 0) {
                 if (errno == EINVAL || errno == ENOSYS)
                     goto afp_read_loop;
                 else {
@@ -957,12 +968,6 @@ afp_read_loop:
                 goto afp_read_exit;
 
             offset += *rbuflen;
-#ifdef DEBUG1
-            if (obj->options.flags & OPTION_DEBUG) {
-                printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
-                bprint(rbuf, *rbuflen);
-            }
-#endif
             /* dsi_read() also returns buffer size of next allocation */
             cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
             if (cc < 0)
@@ -1159,7 +1164,10 @@ static ssize_t write_file(struct ofork *ofork, int eid,
         case EDQUOT :
         case EFBIG :
         case ENOSPC :
+            LOG(log_error, logtype_afpd, "write_file: DISK FULL");
             return( AFPERR_DFULL );
+        case EACCES:
+            return AFPERR_ACCESS;
         default :
             LOG(log_error, logtype_afpd, "afp_write(%s): ad_write: %s", of_name(ofork), strerror(errno) );
             return( AFPERR_PARAM );
@@ -1176,7 +1184,7 @@ static ssize_t write_file(struct ofork *ofork, int eid,
 static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
 {
     struct ofork       *ofork;
-    off_t              offset, saveoff, reqcount;
+    off_t           offset, saveoff, reqcount, oldsize, newsize;
     int                        endflag, eid, xlate = 0, err = AFP_OK;
     u_int16_t          ofrefnum;
     ssize_t             cc;
@@ -1216,8 +1224,9 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s
         goto afp_write_err;
     }
 
+    oldsize = ad_size(ofork->of_ad, eid);
     if (endflag)
-        offset += ad_size(ofork->of_ad, eid);
+        offset += oldsize;
 
     /* handle bogus parameters */
     if (reqcount < 0 || offset < 0) {
@@ -1225,9 +1234,12 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s
         goto afp_write_err;
     }
 
+    newsize = ((offset + reqcount) > oldsize) ? (offset + reqcount) : oldsize;
+
     /* offset can overflow on 64-bit capable filesystems.
      * report disk full if that's going to happen. */
      if (sum_neg(is64, offset, reqcount)) {
+        LOG(log_error, logtype_afpd, "write_fork: DISK FULL");
         err = AFPERR_DFULL;
         goto afp_write_err;
     }
@@ -1331,6 +1343,12 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s
     if ( ad_meta_fileno( ofork->of_ad ) != -1 ) /* META */
         ofork->of_flags |= AFPFORK_DIRTY;
 
+    /* we have modified any fork, remember until close_fork */
+    ofork->of_flags |= AFPFORK_MODIFIED;
+
+    /* update write count */
+    ofork->of_vol->v_appended += (newsize > oldsize) ? (newsize - oldsize) : 0;
+
     *rbuflen = set_off_t (offset, rbuf, is64);
     return( AFP_OK );