]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/file.c
Dont copy our metadata EA in copyfile()
[netatalk.git] / etc / afpd / file.c
index c24d296b2f1049c76c6407267d6410847e7564cb..bc336a4e2b0cd721c678402ad83bd65b9dce2cd1 100644 (file)
@@ -77,6 +77,7 @@ static int default_type(void *finder)
 /* FIXME path : unix or mac name ? (for now it's unix name ) */
 void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *adp, void *data, int islink)
 {
+    struct extmap       *em;
     void                *ad_finder = NULL;
     int                 chk_ext = 0;
 
@@ -85,6 +86,9 @@ void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *a
 
     if (ad_finder) {
         memcpy(data, ad_finder, ADEDLEN_FINDERI);
+        /* default type ? */
+        if (default_type(ad_finder)) 
+            chk_ext = 1;
     }
     else {
         memcpy(data, ufinderi, ADEDLEN_FINDERI);
@@ -105,6 +109,12 @@ void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *a
         memcpy((char *)data + FINDERINFO_FRCREATOFF,"rhap",4); 
     }
 
+    /** Only enter if no appledouble information and no finder information found. */
+    if (chk_ext && (em = getextmap( upath ))) {
+        memcpy(data, em->em_type, sizeof( em->em_type ));
+        memcpy((char *)data + 4, em->em_creator, sizeof(em->em_creator));
+    }
+
     return data;
 }
 
@@ -239,32 +249,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));
             }
         }
     }
@@ -591,11 +598,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 +613,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 +711,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,11 +737,17 @@ 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);
+    fce_register(FCE_FILE_CREATE, fullpathname(upath), NULL, fce_file);
 
 createfile_done:
     curdir->d_offcnt++;
@@ -822,7 +838,7 @@ int setfilparams(const AFPObj *obj, struct vol *vol,
     uint16_t           bitmap = f_bitmap;
     uint32_t           cdate,bdate;
     u_char              finder_buf[32];
-    int symlinked = 0;
+    int symlinked = S_ISLNK(path->st.st_mode);
 
 #ifdef DEBUG
     LOG(log_debug9, logtype_afpd, "begin setfilparams:");
@@ -996,6 +1012,17 @@ int setfilparams(const AFPObj *obj, struct vol *vol,
             ad_setdate(adp, AD_DATE_BACKUP, bdate);
             break;
         case FILPBIT_FINFO :
+            if (default_type( ad_entry( adp, ADEID_FINDERI ))
+                    && ( 
+                     ((em = getextmap( path->m_name )) &&
+                      !memcmp(finder_buf, em->em_type, sizeof( em->em_type )) &&
+                      !memcmp(finder_buf + 4, em->em_creator,sizeof( em->em_creator)))
+                     || ((em = getdefextmap()) &&
+                      !memcmp(finder_buf, em->em_type, sizeof( em->em_type )) &&
+                      !memcmp(finder_buf + 4, em->em_creator,sizeof( em->em_creator)))
+            )) {
+                memcpy(finder_buf, ufinderi, 8 );
+            }
             memcpy(ad_entry( adp, ADEID_FINDERI ), finder_buf, 32 );
             break;
         case FILPBIT_UNIXPR :
@@ -1058,7 +1085,7 @@ setfilparam_done:
  * adp         adouble struct of src file, if open, or & zeroed one
  *
  */
-int renamefile(const struct vol *vol, int sdir_fd, char *src, char *dst, char *newname, struct adouble *adp)
+int renamefile(struct vol *vol, struct dir *ddir, int sdir_fd, char *src, char *dst, char *newname, struct adouble *adp)
 {
     int                rc;
 
@@ -1083,7 +1110,7 @@ int renamefile(const struct vol *vol, int sdir_fd, char *src, char *dst, char *n
                /* FIXME  warning in syslog so admin'd know there's a conflict ?*/
                return AFPERR_OLOCK; /* little lie */
            }
-            if (AFP_OK != ( rc = copyfile(vol, vol, sdir_fd, src, dst, newname, NULL )) ) {
+            if (AFP_OK != ( rc = copyfile(vol, vol, ddir, sdir_fd, src, dst, newname, NULL )) ) {
                 /* on error copyfile delete dest */
                 return( rc );
             }
@@ -1249,6 +1276,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 );
 
@@ -1304,7 +1344,7 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si
         goto copy_exit;
     }
 
-    if ( (err = copyfile(s_vol, d_vol, -1, p, upath , newname, adp)) < 0 ) {
+    if ( (err = copyfile(s_vol, d_vol, curdir, -1, p, upath , newname, adp)) < 0 ) {
         retvalue = err;
         goto copy_exit;
     }
@@ -1322,8 +1362,9 @@ copy_exit:
  * because we are doing it elsewhere.
  * currently if newname is NULL then adp is NULL. 
  */
-int copyfile(const struct vol *s_vol,
-             const struct vol *d_vol, 
+int copyfile(struct vol *s_vol,
+             struct vol *d_vol, 
+             struct dir *d_dir, 
              int sfd,
              char *src,
              char *dst,
@@ -1345,13 +1386,17 @@ int copyfile(const struct vol *s_vol,
         adp = &ads;
     }
 
-    adflags = ADFLAGS_DF | ADFLAGS_RF | ADFLAGS_NORF;
+    adflags = ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF | ADFLAGS_RF | ADFLAGS_NORF;
 
     if (ad_openat(adp, sfd, src, adflags | ADFLAGS_RDONLY) < 0) {
         ret_err = errno;
         goto done;
     }
 
+    if (!AD_META_OPEN(adp))
+        /* no resource fork, don't create one for dst file */
+        adflags &= ~ADFLAGS_HF;
+
     if (!AD_RSRC_OPEN(adp))
         /* no resource fork, don't create one for dst file */
         adflags &= ~ADFLAGS_RF;
@@ -1384,12 +1429,25 @@ int copyfile(const struct vol *s_vol,
     if (err < 0)
        ret_err = errno;
 
-    if (!ret_err && newname && (adflags & ADFLAGS_HF)) {
-        /* set the new name in the resource fork */
-        ad_copy_header(&add, adp);
-        ad_setname(&add, newname);
-        ad_flush( &add );
+    if (AD_META_OPEN(&add)) {
+        if (AD_META_OPEN(adp))
+            ad_copy_header(&add, adp);
+        ad_setname(&add, dst);
+        cnid_t id;
+        struct stat stdest;
+        if (fstat(ad_meta_fileno(&add), &stdest) != 0) {
+            ret_err = errno;
+            goto error;
+        }
+        if ((id = get_id(d_vol, &add, &stdest, d_dir->d_did, dst, strlen(dst))) == CNID_INVALID) {
+            ret_err = EINVAL;
+            goto error;
+        }
+        (void)ad_setid(&add, stdest.st_dev, stdest.st_ino, id, d_dir->d_did, d_vol->v_stamp);
+        ad_flush(&add);
     }
+
+error:
     ad_close( adp, adflags );
 
     if (ad_close( &add, adflags ) <0) {
@@ -1417,6 +1475,7 @@ done:
     case EDQUOT:
     case EFBIG:
     case ENOSPC:
+       LOG(log_info, logtype_afpd, "copyfile: DISK FULL");
         return AFPERR_DFULL;
     case ENOENT:
         return AFPERR_NOOBJ;
@@ -1772,7 +1831,7 @@ retry:
     }
     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);
@@ -1934,9 +1993,6 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U
     uint32_t           sid, did;
     uint16_t           vid;
 
-    uid_t              uid;
-    gid_t              gid;
-
     *rbuflen = 0;
     ibuf += 2;
 
@@ -2052,17 +2108,17 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U
     }
 
     /* now, quickly rename the file. we error if we can't. */
-    if ((err = renamefile(vol, -1, p, temp, temp, adsp)) != AFP_OK)
+    if ((err = renamefile(vol, curdir, -1, p, temp, temp, adsp)) != AFP_OK)
         goto err_exchangefile;
     of_rename(vol, s_of, sdir, spath, curdir, temp);
 
     /* rename destination to source */
-    if ((err = renamefile(vol, -1, upath, p, spath, addp)) != AFP_OK)
+    if ((err = renamefile(vol, curdir, -1, upath, p, spath, addp)) != AFP_OK)
         goto err_src_to_tmp;
     of_rename(vol, d_of, curdir, path->m_name, sdir, spath);
 
     /* rename temp to destination */
-    if ((err = renamefile(vol, -1, temp, upath, path->m_name, adsp)) != AFP_OK)
+    if ((err = renamefile(vol, curdir, -1, temp, upath, path->m_name, adsp)) != AFP_OK)
         goto err_dest_to_src;
     of_rename(vol, s_of, curdir, temp, curdir, path->m_name);
 
@@ -2104,13 +2160,7 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U
 
     /* change perms, src gets dest perm and vice versa */
 
-    uid = geteuid();
-    gid = getegid();
-    if (seteuid(0)) {
-        LOG(log_error, logtype_afpd, "seteuid failed %s", strerror(errno));
-        err = AFP_OK; /* ignore error */
-        goto err_temp_to_dest;
-    }
+    become_root();
 
     /*
      * we need to exchange ACL entries as well
@@ -2134,10 +2184,7 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U
     setfilunixmode(vol, path, srcst.st_mode);
     setfilowner(vol, srcst.st_uid, srcst.st_gid, path);
 
-    if ( setegid(gid) < 0 || seteuid(uid) < 0) {
-        LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno));
-        exit(EXITERR_SYS);
-    }
+    unbecome_root();
 
     err = AFP_OK;
     goto err_exchangefile;
@@ -2146,17 +2193,17 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U
      * properly. */
 err_temp_to_dest:
     /* rename dest to temp */
-    renamefile(vol, -1, upath, temp, temp, adsp);
+    renamefile(vol, curdir, -1, upath, temp, temp, adsp);
     of_rename(vol, s_of, curdir, upath, curdir, temp);
 
 err_dest_to_src:
     /* rename source back to dest */
-    renamefile(vol, -1, p, upath, path->m_name, addp);
+    renamefile(vol, curdir, -1, p, upath, path->m_name, addp);
     of_rename(vol, d_of, sdir, spath, curdir, path->m_name);
 
 err_src_to_tmp:
     /* rename temp back to source */
-    renamefile(vol, -1, temp, p, spath, adsp);
+    renamefile(vol, curdir, -1, temp, p, spath, adsp);
     of_rename(vol, s_of, curdir, temp, sdir, spath);
 
 err_exchangefile: