]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/fork.c
Allow opening symlinks r/w, but don't actually allow writing. Fixes test426
[netatalk.git] / etc / afpd / fork.c
index f7d27826da01eeda01ebcb0d0269ae196dce0858..b9d03507e6b249e427dab70e8a6b6643388d3092 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: fork.c,v 1.65 2009-10-15 10:43:13 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>
 
@@ -80,14 +79,16 @@ static int getforkparams(struct ofork *ofork, u_int16_t bitmap, char *buf, size_
         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 ) {
@@ -910,14 +911,7 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si
     if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
         DSI    *dsi = obj->handle;
         off_t  size;
-        int    non_blocking = 0;
 
-#ifdef DEBUG1
-        if (obj->options.flags & OPTION_DEBUG) {
-            printf( "(read) reply: %d/%d, %d\n", *rbuflen,(int) reqcount, dsi->clientID);
-            bprint(rbuf, *rbuflen);
-        }
-#endif        
         /* reqcount isn't always truthful. we need to deal with that. */
         size = ad_size(ofork->of_ad, eid);
 
@@ -938,10 +932,12 @@ 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 +953,6 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si
 afp_read_loop:
 #endif 
 
-        /* fill up our buffer. */
-        if (*rbuflen) {
-            /* set to non blocking mode */
-            non_blocking = 1;
-            dsi_block(dsi, 1);
-        }
         /* fill up our buffer. */
         while (*rbuflen > 0) {
             cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,rbuflen, xlate);
@@ -982,10 +972,6 @@ afp_read_loop:
                 goto afp_read_exit;
             *rbuflen = cc;
         }
-        if (non_blocking) {
-            /* set back to blocking mode */
-            dsi_block(dsi, 0);
-        }
         dsi_readdone(dsi);
         goto afp_read_done;
 
@@ -1177,6 +1163,8 @@ static ssize_t write_file(struct ofork *ofork, int eid,
         case EFBIG :
         case ENOSPC :
             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 );
@@ -1331,12 +1319,6 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s
             /* loop until everything gets written. currently
                     * dsi_write handles the end case by itself. */
             while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
-#ifdef DEBUG1
-                if ( obj->options.flags & OPTION_DEBUG ) {
-                    printf("(write) command cont'd: %d\n", cc);
-                    bprint(rbuf, cc);
-                }
-#endif
                 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
                     dsi_writeflush(dsi);
                     *rbuflen = 0;
@@ -1386,9 +1368,9 @@ int afp_write_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *r
 int afp_getforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
 {
     struct ofork       *ofork;
-    int                        buflen, ret;
+    int             ret;
     u_int16_t          ofrefnum, bitmap;
-
+    size_t          buflen;
     ibuf += 2;
     memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
     ibuf += sizeof( ofrefnum );