X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Ffile.c;h=71c248a450a50dea658b5836a9bd0675023fce4c;hb=40c614d84ae5bf7c1808a30a2ccac8db12228519;hp=8d5d0ad0e5c607b3b37ceaa0b4e503d6336a5743;hpb=83c9131bbca30fe8834e681420e12cc5c7db8c5a;p=netatalk.git diff --git a/etc/afpd/file.c b/etc/afpd/file.c index 8d5d0ad0..71c248a4 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "directory.h" #include "dircache.h" @@ -100,7 +101,7 @@ void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *a } } - if (islink){ + if (islink && !vol_syml_opt(vol)) { uint16_t linkflag; memcpy(&linkflag, (char *)data + FINDERINFO_FRFLAGOFF, 2); linkflag |= htons(FINDERINFO_ISALIAS); @@ -604,7 +605,7 @@ int getfilparams(const AFPObj *obj, struct vol *vol, uint16_t bitmap, struct pat struct adouble ad, *adp; int opened = 0; int rc; - int flags; + int flags; /* uninitialized ok */ LOG(log_debug, logtype_afpd, "getfilparams(\"%s\")", path->u_name); @@ -640,7 +641,9 @@ int getfilparams(const AFPObj *obj, struct vol *vol, uint16_t bitmap, struct pat } } rc = getmetadata(obj, vol, bitmap, path, dir, buf, buflen, adp); - ad_close(adp, ADFLAGS_HF | flags); + + if (opened) + ad_close(adp, ADFLAGS_HF | flags); return( rc ); } @@ -685,7 +688,7 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, ad_init(&ad, vol); /* if upath is deleted we already in trouble anyway */ - if ((of = of_findname(s_path))) { + if ((of = of_findname(vol, s_path))) { if (creatf) return AFPERR_BUSY; else @@ -747,11 +750,10 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, 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); + sl_index_file(path); -createfile_done: curdir->d_offcnt++; - setvoltime(obj, vol ); return (retvalue); @@ -838,7 +840,10 @@ 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); + int fp; + ssize_t len; + char symbuf[MAXPATHLEN+1]; #ifdef DEBUG LOG(log_debug9, logtype_afpd, "begin setfilparams:"); @@ -880,29 +885,33 @@ int setfilparams(const AFPObj *obj, struct vol *vol, break; case FILPBIT_FINFO : change_mdate = 1; - memcpy(finder_buf, buf, 32 ); - if (memcmp(buf, "slnkrhap", 8) == 0 && !S_ISLNK(path->st.st_mode)) { - int fp; - ssize_t len; - int erc=1; - char buf[PATH_MAX+1]; - if ((fp = open(path->u_name, O_RDONLY)) >= 0) { - if ((len = read(fp, buf, PATH_MAX+1))) { - if (unlink(path->u_name) == 0) { - buf[len] = 0; - erc = symlink(buf, path->u_name); - if (!erc) - of_stat(path); - } - } - close(fp); + if (memcmp(buf,"slnkrhap",8) == 0 + && !(S_ISLNK(path->st.st_mode)) + && !(vol->v_flags & AFPVOL_FOLLOWSYM)) { + /* request to turn this into a symlink */ + if ((fp = open(path->u_name, O_RDONLY)) == -1) { + err = AFPERR_MISC; + goto setfilparam_done; } - if (erc != 0) { - err=AFPERR_BITMAP; + len = read(fp, symbuf, MAXPATHLEN); + close(fp); + if (!(len > 0)) { + err = AFPERR_MISC; goto setfilparam_done; } + if (unlink(path->u_name) != 0) { + err = AFPERR_MISC; + goto setfilparam_done; + } + symbuf[len] = 0; + if (symlink(symbuf, path->u_name) != 0) { + err = AFPERR_MISC; + goto setfilparam_done; + } + of_stat(vol, path); symlinked = 1; } + memcpy(finder_buf, buf, 32 ); buf += 32; break; case FILPBIT_UNIXPR : @@ -980,6 +989,12 @@ int setfilparams(const AFPObj *obj, struct vol *vol, isad = 0; } else if ((ad_get_MD_flags( adp ) & O_CREAT) ) { ad_setname(adp, path->m_name); + cnid_t id; + if ((id = get_id(vol, adp, &path->st, curdir->d_did, upath, strlen(upath))) == CNID_INVALID) { + LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): CNID error", upath); + return AFPERR_MISC; + } + (void)ad_setid(adp, path->st.st_dev, path->st.st_ino, id, curdir->d_did, vol->v_stamp); } bit = 0; @@ -1085,7 +1100,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; @@ -1110,7 +1125,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 ); } @@ -1344,7 +1359,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; } @@ -1362,8 +1377,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, @@ -1385,13 +1401,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; @@ -1424,12 +1444,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) { @@ -1671,7 +1704,7 @@ static int reenumerate_loop(struct dirent *de, char *mname _U_, void *data) cnid_t did = param->did; cnid_t aint; - if ( lstat(de->d_name, &path.st) < 0 ) + if (ostat(de->d_name, &path.st, vol_syml_opt(vol)) < 0) return 0; /* update or add to cnid */ @@ -1696,7 +1729,7 @@ reenumerate_id(struct vol *vol, char *name, struct dir *dir) } /* FIXME use of_statdir ? */ - if (lstat(name, &st)) { + if (ostat(name, &st, vol_syml_opt(vol))) { return -1; } @@ -1775,7 +1808,7 @@ retry: memset(&path, 0, sizeof(path)); path.u_name = upath; - if ( of_stat(&path) < 0 ) { + if (of_stat(vol, &path) < 0 ) { #ifdef ESTALE /* with nfs and our working directory is deleted */ if (errno == ESTALE) { @@ -1870,7 +1903,7 @@ int afp_deleteid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ } err = AFP_OK; - if ((movecwd(vol, dir) < 0) || (lstat(upath, &st) < 0)) { + if ((movecwd(vol, dir) < 0) || (ostat(upath, &st, vol_syml_opt(vol)) < 0)) { switch (errno) { case EACCES: case EPERM: @@ -1933,7 +1966,7 @@ static struct adouble *find_adouble(const AFPObj *obj, struct vol *vol, struct p return NULL; } - if ((*of = of_findname(path))) { + if ((*of = of_findname(vol, path))) { /* reuse struct adouble so it won't break locks */ adp = (*of)->of_ad; } @@ -2078,11 +2111,13 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U * NOTE: the temp file will be in the dest file's directory. it * will also be inaccessible from AFP. */ memcpy(temp, APPLETEMP, sizeof(APPLETEMP)); - if (!mktemp(temp)) { + int fd; + if ((fd = mkstemp(temp)) == -1) { err = AFPERR_MISC; goto err_exchangefile; } - + close(fd); + if (crossdev) { /* FIXME we need to close fork for copy, both s_of and d_of are null */ ad_close(adsp, ADFLAGS_HF); @@ -2090,17 +2125,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); @@ -2112,10 +2147,10 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U if (did) cnid_delete(vol->v_cdb, did); - if ((did && ( (crossdev && lstat( upath, &srcst) < 0) || + if ((did && ( (crossdev && ostat(upath, &srcst, vol_syml_opt(vol)) < 0) || cnid_update(vol->v_cdb, did, &srcst, curdir->d_did,upath, dlen) < 0)) || - (sid && ( (crossdev && lstat(p, &destst) < 0) || + (sid && ( (crossdev && ostat(p, &destst, vol_syml_opt(vol)) < 0) || cnid_update(vol->v_cdb, sid, &destst, sdir->d_did,supath, slen) < 0)) ) { switch (errno) { @@ -2175,17 +2210,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: