]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/file.c
Fix data corruption bug
[netatalk.git] / etc / afpd / file.c
index 07813ef4ccb05f51c8cab5fb4e87958a25fdf1fc..407dc6f9d9e5855e1bdde254ae888acf19e9956b 100644 (file)
@@ -119,7 +119,7 @@ char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t
 
     if (!utf8) {
         /* want mac name */
-        if (utf8_encoding()) {
+        if (utf8_encoding(vol->v_obj)) {
             /* but name is an utf8 mac name */
             char *u, *m;
            
@@ -239,32 +239,29 @@ restart:
                         vol->v_path);
                     vol->v_cdb = cnid_open(vol->v_path, vol->v_umask, "tdb", flags, NULL, NULL);
                     if (vol->v_cdb) {
-                        /* set ro mode*/
-                        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;
                 goto exit;
             }
         }
-        else if (adp && (adcnid != dbcnid)) { /* 4 */
+        else if (adp && adcnid && (adcnid != dbcnid)) { /* 4 */
             /* Update the ressource fork. For a folder adp is always null */
             LOG(log_debug, logtype_afpd, "get_id(%s/%s): calling ad_setid(old: %u, new: %u)",
                 getcwdpath(), upath, htonl(adcnid), htonl(dbcnid));
             if (ad_setid(adp, st->st_dev, st->st_ino, dbcnid, did, vol->v_stamp)) {
-                ad_flush(adp);
+                if (ad_flush(adp) != 0)
+                    LOG(log_error, logtype_afpd, "get_id(\"%s\"): can't flush", fullpathname(upath));
             }
         }
     }
@@ -299,7 +296,7 @@ int getmetadata(const AFPObj *obj,
     data = buf;
 
     if ( ((bitmap & ( (1 << FILPBIT_FINFO)|(1 << FILPBIT_LNAME)|(1 <<FILPBIT_PDINFO) ) ) && !path->m_name)
-         || (bitmap & ( (1 << FILPBIT_LNAME) ) && utf8_encoding()) /* FIXME should be m_name utf8 filename */
+         || (bitmap & ( (1 << FILPBIT_LNAME) ) && utf8_encoding(obj)) /* FIXME should be m_name utf8 filename */
          || (bitmap & (1 << FILPBIT_FNUM))) {
         if (!path->id) {
             bstring fullpath;
@@ -316,7 +313,7 @@ int getmetadata(const AFPObj *obj,
 
                 /* Get macname from unixname first */
                 if (path->m_name == NULL) {
-                    if ((path->m_name = utompath(vol, upath, id, utf8_encoding())) == NULL) {
+                    if ((path->m_name = utompath(vol, upath, id, utf8_encoding(obj))) == NULL) {
                         LOG(log_error, logtype_afpd, "getmetadata: utompath error");
                         return AFPERR_MISC;
                     }
@@ -348,7 +345,7 @@ int getmetadata(const AFPObj *obj,
             return afp_errno;
 
         if (!path->m_name) {
-            path->m_name = utompath(vol, upath, id, utf8_encoding());
+            path->m_name = utompath(vol, upath, id, utf8_encoding(vol->v_obj));
         }
     }
     while ( bitmap != 0 ) {
@@ -467,7 +464,7 @@ int getmetadata(const AFPObj *obj,
                to "pXYZ" when we created it.  See IA, Ver 2.
                <shirsch@adelphia.net> */
         case FILPBIT_PDINFO :
-            if (afp_version >= 30) { /* UTF8 name */
+            if (obj->afp_version >= 30) { /* UTF8 name */
                 utf8 = kTextEncodingUTF8;
                 utf_nameoff = data;
                 data += sizeof( uint16_t );
@@ -591,11 +588,8 @@ int getmetadata(const AFPObj *obj,
 }
                 
 /* ----------------------- */
-int getfilparams(const AFPObj *obj,
-                 struct vol *vol,
-                 uint16_t bitmap,
-                 struct path *path, struct dir *dir, 
-                 char *buf, size_t *buflen )
+int getfilparams(const AFPObj *obj, struct vol *vol, uint16_t bitmap, struct path *path,
+                 struct dir *dir, char *buf, size_t *buflen, int in_enumerate)
 {
     struct adouble     ad, *adp;
     int                 opened = 0;
@@ -609,7 +603,12 @@ int getfilparams(const AFPObj *obj,
 
     if (opened) {
         char *upath;
-        flags = (bitmap & (1 << FILPBIT_ATTR)) ? ADFLAGS_CHECK_OF : 0;
+        /*
+         * Dont check for and resturn open fork attributes when enumerating
+         * This saves a lot of syscalls, the client will hopefully only use the result
+         * in FPGetFileParms where we return the correct value
+         */
+        flags = (!in_enumerate &&(bitmap & (1 << FILPBIT_ATTR))) ? ADFLAGS_CHECK_OF : 0;
 
         adp = of_ad(vol, path, &ad);
         upath = path->u_name;
@@ -702,6 +701,7 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_,
             return( AFPERR_ACCESS );
         case EDQUOT:
         case ENOSPC :
+           LOG(log_info, logtype_afpd, "afp_createfile: DISK FULL");
             return( AFPERR_DFULL );
         default :
             return( AFPERR_PARAM );
@@ -727,8 +727,14 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_,
         return AFPERR_MISC;
     }
 
-    (void)get_id(vol, &ad, &st, dir->d_did, upath, strlen(upath));
+    cnid_t id;
+    if ((id = get_id(vol, &ad, &st, dir->d_did, upath, strlen(upath))) == CNID_INVALID) {
+        LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): CNID error", upath);
+        goto createfile_iderr;
+    }
+    (void)ad_setid(&ad, st.st_dev, st.st_ino, id, dir->d_did, vol->v_stamp);
 
+createfile_iderr:
     ad_flush(&ad);
     ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF );
     fce_register_new_file(s_path);
@@ -919,7 +925,7 @@ int setfilparams(const AFPObj *obj, struct vol *vol,
             }
             break;
         case FILPBIT_PDINFO :
-            if (afp_version < 30) { /* else it's UTF8 name */
+            if (obj->afp_version < 30) { /* else it's UTF8 name */
                 achar = *buf;
                 buf += 2;
                 /* Keep special case to support crlf translations */
@@ -1004,7 +1010,7 @@ int setfilparams(const AFPObj *obj, struct vol *vol,
             }
             break;
         case FILPBIT_PDINFO :
-            if (afp_version < 30) { /* else it's UTF8 name */
+            if (obj->afp_version < 30) { /* else it's UTF8 name */
                 memcpy(ad_entry( adp, ADEID_FINDERI ), fdType, 4 );
                 memcpy(ad_entry( adp, ADEID_FINDERI ) + 4, "pdos", 4 );
                 break;
@@ -1148,14 +1154,14 @@ size_t      plen = 0;
 uint16_t   len16;
 uint32_t   hint;
 
-    if ( type != 2 && !(afp_version >= 30 && type == 3) ) {
+    if ( type != 2 && !(vol->v_obj->afp_version >= 30 && type == 3) ) {
         return -1;
     }
     ibuf++;
     switch (type) {
     case 2:
         if (( plen = (unsigned char)*ibuf++ ) != 0 ) {
-            if (afp_version >= 30) {
+            if (vol->v_obj->afp_version >= 30) {
                 /* convert it to UTF8 
                 */
                 if ((plen = mtoUTF8(vol, ibuf, plen, newname, AFPOBJ_TMPSIZ)) == (size_t)-1)
@@ -1249,6 +1255,19 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si
     if (ad_open(adp, s_path->u_name, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF | ADFLAGS_RDONLY | ADFLAGS_SETSHRMD) < 0) {
         return AFPERR_DENYCONF;
     }
+#ifdef HAVE_FSHARE_T
+    fshare_t shmd;
+    shmd.f_access = F_RDACC;
+    shmd.f_deny = F_NODNY;
+    if (fcntl(ad_data_fileno(adp), F_SHARE, &shmd) != 0) {
+        retvalue = AFPERR_DENYCONF;
+        goto copy_exit;
+    }
+    if (AD_RSRC_OPEN(adp) && fcntl(ad_reso_fileno(adp), F_SHARE, &shmd) != 0) {
+        retvalue = AFPERR_DENYCONF;
+        goto copy_exit;
+    }
+#endif
     denyreadset = (ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || 
                   ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 );
 
@@ -1299,7 +1318,7 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si
     /* newname is always only a filename so curdir *is* its
      * parent folder
     */
-    if (NULL == (upath = mtoupath(d_vol, newname, curdir->d_did, utf8_encoding()))) {
+    if (NULL == (upath = mtoupath(d_vol, newname, curdir->d_did, utf8_encoding(d_vol->v_obj)))) {
         retvalue =AFPERR_PARAM;
         goto copy_exit;
     }
@@ -1417,6 +1436,7 @@ done:
     case EDQUOT:
     case EFBIG:
     case ENOSPC:
+       LOG(log_info, logtype_afpd, "copyfile: DISK FULL");
         return AFPERR_DFULL;
     case ENOENT:
         return AFPERR_NOOBJ;
@@ -1676,7 +1696,7 @@ reenumerate_id(struct vol *vol, char *name, struct dir *dir)
 
 /* ------------------------------
    resolve a file id */
-int afp_resolveid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
+int afp_resolveid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
 {
     struct vol         *vol;
     struct dir         *dir;
@@ -1762,17 +1782,17 @@ retry:
     /* directories are bad */
     if (S_ISDIR(path.st.st_mode)) {
         /* OS9 and OSX don't return the same error code  */
-        return (afp_version >=30)?AFPERR_NOID:AFPERR_BADTYPE;
+        return (obj->afp_version >=30)?AFPERR_NOID:AFPERR_BADTYPE;
     }
 
     memcpy(&bitmap, ibuf, sizeof(bitmap));
     bitmap = ntohs( bitmap );
-    if (NULL == (path.m_name = utompath(vol, upath, cnid, utf8_encoding()))) {
+    if (NULL == (path.m_name = utompath(vol, upath, cnid, utf8_encoding(obj)))) {
         return AFPERR_NOID;
     }
     path.id = cnid;
     if (AFP_OK != (err = getfilparams(obj, vol, bitmap, &path , curdir, 
-                                      rbuf + sizeof(bitmap), &buflen))) {
+                                      rbuf + sizeof(bitmap), &buflen, 0))) {
         return err;
     }
     *rbuflen = buflen + sizeof(bitmap);