]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/file.c
Changed behaviour for TimeMachine volumes in case there's a problem
[netatalk.git] / etc / afpd / file.c
index d3bf5600b36e1f68c91a15d3b1fadfe2eaa73f71..efc002bc0bfd11eb8797e8046b1aa71bda92e240 100644 (file)
@@ -37,6 +37,8 @@ char *strchr (), *strrchr ();
 #include <atalk/util.h>
 #include <atalk/cnid.h>
 #include <atalk/unix.h>
+#include <atalk/globals.h>
+#include <atalk/fce_api.h>
 
 #include "directory.h"
 #include "dircache.h"
@@ -45,7 +47,6 @@ char *strchr (), *strrchr ();
 #include "fork.h"
 #include "file.h"
 #include "filedir.h"
-#include "globals.h"
 #include "unix.h"
 
 /* the format for the finderinfo fields (from IM: Toolbox Essentials):
@@ -165,8 +166,8 @@ char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t
     else {
         u_int16_t temp;
 
-        if (aint > 255)  /* FIXME safeguard, anyway if no ascii char it's game over*/
-           aint = 255;
+        if (aint > UTF8FILELEN_EARLY)  /* FIXME safeguard, anyway if no ascii char it's game over*/
+           aint = UTF8FILELEN_EARLY;
 
         utf8 = vol->v_kTextEncoding;
         memcpy(data, &utf8, sizeof(utf8));
@@ -263,21 +264,17 @@ restart:
                         vol->v_path);
                     vol->v_cdb = cnid_open(vol->v_path, vol->v_umask, "tdb", flags, NULL, NULL);
                     if (vol->v_cdb) {
-                        /* deactivate cnid caching/storing in AppleDouble files and set ro mode*/
                         vol->v_flags &= ~AFPVOL_CACHE;
-                        vol->v_flags |= AFPVOL_RO;
-#ifdef SERVERTEXT
-                        /* kill ourself with SIGUSR2 aka msg pending */
-                        setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB instead."
-                                   "Check server messages for details. Switching to read-only mode.");
-                        kill(getpid(), SIGUSR2);
-#endif
-                        goto restart; /* not try again with the temp CNID db */
+                        if (!(vol->v_flags & AFPVOL_TM)) {
+                            vol->v_flags |= AFPVOL_RO;
+                            setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB instead."
+                                       "Check server messages for details. Switching to read-only mode.");
+                            kill(getpid(), SIGUSR2);
+                        }
+                        goto restart; /* now try again with the temp CNID db */
                     } else {
-#ifdef SERVERTEXT
                         setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB failed too!"
                                    "Check server messages for details, can't recover from this state!");
-#endif
                     }
                 }
                 afp_errno = AFPERR_MISC;
@@ -316,6 +313,8 @@ int getmetadata(struct vol *vol,
     struct stat         *st;
     struct maccess     ma;
 
+    LOG(log_debug, logtype_afpd, "getmetadata(\"%s\")", path->u_name);
+
     upath = path->u_name;
     st = &path->st;
     data = buf;
@@ -324,9 +323,10 @@ int getmetadata(struct vol *vol,
          || (bitmap & ( (1 << FILPBIT_LNAME) ) && utf8_encoding()) /* FIXME should be m_name utf8 filename */
          || (bitmap & (1 << FILPBIT_FNUM))) {
         if (!path->id) {
+            bstring fullpath;
             struct dir *cachedfile;
             int len = strlen(upath);
-            if ((cachedfile = dircache_search_by_name(vol, dir, upath, len, st->st_ctime)) != NULL)
+            if ((cachedfile = dircache_search_by_name(vol, dir, upath, len)) != NULL)
                 id = cachedfile->d_did;
             else {
                 id = get_id(vol, adp, st, dir->d_did, upath, len);
@@ -339,18 +339,26 @@ int getmetadata(struct vol *vol,
                 if (path->m_name == NULL) {
                     if ((path->m_name = utompath(vol, upath, id, utf8_encoding())) == NULL) {
                         LOG(log_error, logtype_afpd, "getmetadata: utompath error");
-                        exit(EXITERR_SYS);
+                        return AFPERR_MISC;
                     }
                 }
                 
-                if ((cachedfile = dir_new(path->m_name, upath, vol, dir->d_did, id, NULL, st->st_ctime)) == NULL) {
+                /* Build fullpath */
+                if (((fullpath = bstrcpy(dir->d_fullpath)) == NULL)
+                    || (bconchar(fullpath, '/') != BSTR_OK)
+                    || (bcatcstr(fullpath, upath)) != BSTR_OK) {
+                    LOG(log_error, logtype_afpd, "getmetadata: fullpath: %s", strerror(errno));
+                    return AFPERR_MISC;
+                }
+
+                if ((cachedfile = dir_new(path->m_name, upath, vol, dir->d_did, id, fullpath, st)) == NULL) {
                     LOG(log_error, logtype_afpd, "getmetadata: error from dir_new");
-                    exit(EXITERR_SYS);
+                    return AFPERR_MISC;
                 }
 
-                if ((dircache_add(cachedfile)) != 0) {
+                if ((dircache_add(vol, cachedfile)) != 0) {
                     LOG(log_error, logtype_afpd, "getmetadata: fatal dircache error");
-                    exit(EXITERR_SYS);
+                    return AFPERR_MISC;
                 }
             }
         } else {
@@ -382,9 +390,9 @@ int getmetadata(struct vol *vol,
             /* FIXME do we want a visual clue if the file is read only
              */
             struct maccess     ma;
-            accessmode( ".", &ma, dir , NULL);
+            accessmode(vol, ".", &ma, dir , NULL);
             if ((ma.ma_user & AR_UWRITE)) {
-               accessmode( upath, &ma, dir , st);
+               accessmode(vol, upath, &ma, dir , st);
                if (!(ma.ma_user & AR_UWRITE)) {
                        ashort |= htons(ATTRBIT_NOWRITE);
                 }
@@ -551,7 +559,7 @@ int getmetadata(struct vol *vol,
             break;
         case FILPBIT_UNIXPR :
             /* accessmode may change st_mode with ACLs */
-            accessmode( upath, &ma, dir , st);
+            accessmode(vol, upath, &ma, dir , st);
 
             aint = htonl(st->st_uid);
             memcpy( data, &aint, sizeof( aint ));
@@ -613,6 +621,8 @@ int getfilparams(struct vol *vol,
     int                 opened = 0;
     int rc;    
 
+    LOG(log_debug, logtype_afpd, "getfilparams(\"%s\")", path->u_name);
+
     opened = PARAM_NEED_ADP(bitmap);
     adp = NULL;
 
@@ -746,11 +756,25 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_,
 
     path = s_path->m_name;
     ad_setname(adp, path);
+
+    struct stat st;
+    if (lstat(upath, &st) != 0) {
+        LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): stat: %s",
+            upath, strerror(errno));
+        ad_close( adp, ADFLAGS_DF|ADFLAGS_HF);
+        return AFPERR_MISC;
+    }
+
+    (void)get_id(vol, adp, &st, dir->d_did, upath, strlen(upath));
+
     ad_flush( adp);
+
+    fce_register_new_file(s_path);
+
     ad_close( adp, ADFLAGS_DF|ADFLAGS_HF );
 
 createfile_done:
-    curdir->offcnt++;
+    curdir->d_offcnt++;
 
 #ifdef DROPKLUDGE
     if (vol->v_flags & AFPVOL_DROPBOX) {
@@ -1097,6 +1121,9 @@ int renamefile(const struct vol *vol, int sdir_fd, char *src, char *dst, char *n
 {
     int                rc;
 
+    LOG(log_debug, logtype_afpd,
+        "renamefile: src[%d, \"%s\"] -> dst[\"%s\"]", sdir_fd, src, dst);
+
     if ( unix_rename( sdir_fd, src, -1, dst ) < 0 ) {
         switch ( errno ) {
         case ENOENT :
@@ -1344,7 +1371,7 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si
         retvalue = err;
         goto copy_exit;
     }
-    curdir->offcnt++;
+    curdir->d_offcnt++;
 
 #ifdef DROPKLUDGE
     if (vol->v_flags & AFPVOL_DROPBOX) {
@@ -1524,7 +1551,8 @@ int copyfile(const struct vol *s_vol,
     if (ad_reso_fileno(adp) == -1 || 0 == (err = copy_fork(ADEID_RFORK, &add, adp))){
         /* copy the data fork */
         if ((err = copy_fork(ADEID_DFORK, &add, adp)) == 0) {
-            err = d_vol->vfs->vfs_copyfile(d_vol, sfd, src, dst);
+            if (ad_meta_fileno(adp) != -1)
+                err = d_vol->vfs->vfs_copyfile(d_vol, sfd, src, dst);
         }
     }
 
@@ -1828,7 +1856,7 @@ reenumerate_id(struct vol *vol, char *name, struct dir *dir)
 
     if (dirreenumerate(dir, &st)) {
         /* we already did it once and the dir haven't been modified */
-       return dir->offcnt;
+       return dir->d_offcnt;
     }
     
     data.vol = vol;