X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Ffile.c;h=0459656f1ed51572135398ef97adfd818470e5fa;hb=6d60f95c388da5f8f901d67e0018cf4896e6c6dc;hp=51a33e8c30ba0bd2e823b856e9f331bd484053d4;hpb=8a499a0f43b31b821fca2ee8251da7d7722b577d;p=netatalk.git diff --git a/etc/afpd/file.c b/etc/afpd/file.c index 51a33e8c..0459656f 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -1,6 +1,4 @@ /* - * $Id: file.c,v 1.141 2010/03/12 15:16:49 franklahm Exp $ - * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. */ @@ -12,22 +10,7 @@ #include #include -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); - -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - #include #include #include @@ -41,6 +24,7 @@ char *strchr (), *strrchr (); #include #include "directory.h" +#include "dircache.h" #include "desktop.h" #include "volume.h" #include "fork.h" @@ -166,8 +150,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)); @@ -201,9 +185,27 @@ char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t (1 << FILPBIT_FNUM) |\ (1 << FILPBIT_UNIXPR))) -/* -------------------------- */ -uint32_t get_id(struct vol *vol, struct adouble *adp, const struct stat *st, - const cnid_t did, char *upath, const int len) +/*! + * @brief Get CNID for did/upath args both from database and adouble file + * + * 1. Get the objects CNID as stored in its adouble file + * 2. Get the objects CNID from the database + * 3. If there's a problem with a "dbd" database, fallback to "tdb" in memory + * 4. In case 2 and 3 differ, store 3 in the adouble file + * + * @param vol (rw) volume + * @param adp (rw) adouble struct of object upath, might be NULL + * @param st (r) stat of upath, must NOT be NULL + * @param did (r) parent CNID of upath + * @param upath (r) name of object + * @param len (r) strlen of upath + */ +uint32_t get_id(struct vol *vol, + struct adouble *adp, + const struct stat *st, + const cnid_t did, + const char *upath, + const int len) { static int first = 1; /* mark if this func is called the first time */ u_int32_t adcnid; @@ -213,9 +215,9 @@ restart: if (vol->v_cdb != NULL) { /* prime aint with what we think is the cnid, set did to zero for catching moved files */ - adcnid = ad_getid(adp, st->st_dev, st->st_ino, 0, vol->v_stamp); + adcnid = ad_getid(adp, st->st_dev, st->st_ino, 0, vol->v_stamp); /* (1) */ - dbcnid = cnid_add(vol->v_cdb, st, did, upath, len, adcnid); + dbcnid = cnid_add(vol->v_cdb, st, did, upath, len, adcnid); /* (2) */ /* Throw errors if cnid_add fails. */ if (dbcnid == CNID_INVALID) { switch (errno) { @@ -233,7 +235,7 @@ restart: /* we have to do it here for "dbd" because it uses "lazy opening" */ /* In order to not end in a loop somehow with goto restart below */ /* */ - if (first && (strcmp(vol->v_cnidscheme, "dbd") == 0)) { + if (first && (strcmp(vol->v_cnidscheme, "dbd") == 0)) { /* (3) */ cnid_close(vol->v_cdb); free(vol->v_cnidscheme); vol->v_cnidscheme = strdup("tdb"); @@ -267,9 +269,10 @@ restart: goto exit; } } - else if (adp && (adcnid != dbcnid)) { + else if (adp && (adcnid != dbcnid)) { /* 4 */ /* Update the ressource fork. For a folder adp is always null */ - LOG(log_debug, logtype_afpd, "get_id: calling ad_setid. adcnid: %u, dbcnid: %u", htonl(adcnid), htonl(dbcnid)); + 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); } @@ -298,6 +301,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; @@ -308,7 +313,7 @@ int getmetadata(struct vol *vol, if (!path->id) { struct dir *cachedfile; int len = strlen(upath); - if (cachedfile = dircache_search_by_name(vol, dir, upath, len)) + if ((cachedfile = dircache_search_by_name(vol, dir, upath, len, st->st_ctime)) != NULL) id = cachedfile->d_did; else { id = get_id(vol, adp, st, dir->d_did, upath, len); @@ -325,11 +330,12 @@ int getmetadata(struct vol *vol, } } - if ((cachedfile = dir_new(path->m_name, upath, vol, dir->d_did, id, NULL)) == NULL) { + if ((cachedfile = dir_new(path->m_name, upath, vol, dir->d_did, id, NULL, st->st_ctime)) == NULL) { LOG(log_error, logtype_afpd, "getmetadata: error from dir_new"); exit(EXITERR_SYS); } - if ((dircache_add(cachedfile)) != 0) { + + if ((dircache_add(vol, cachedfile)) != 0) { LOG(log_error, logtype_afpd, "getmetadata: fatal dircache error"); exit(EXITERR_SYS); } @@ -594,17 +600,19 @@ 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; if (opened) { char *upath; - int flags = (bitmap & (1 << FILPBIT_ATTR))?ADFLAGS_OPENFORKS:0; + int flags = (bitmap & (1 << FILPBIT_ATTR)) ? ADFLAGS_CHECK_OF : 0; adp = of_ad(vol, path, &ad); upath = path->u_name; - if ( ad_metadata( upath, flags|ADFLAGS_CREATE, adp) < 0 ) { + if ( ad_metadata( upath, flags, adp) < 0 ) { switch (errno) { case EACCES: LOG(log_error, logtype_afpd, "getfilparams(%s): %s: check resource fork permission?", @@ -621,9 +629,7 @@ int getfilparams(struct vol *vol, } } rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp); - if ( adp ) { - ad_close_metadata( adp); - } + ad_close_metadata( adp); return( rc ); } @@ -631,7 +637,7 @@ int getfilparams(struct vol *vol, /* ----------------------------- */ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { - struct adouble ad, *adp; + struct adouble ad; struct vol *vol; struct dir *dir; struct ofork *of = NULL; @@ -647,9 +653,8 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, memcpy(&vid, ibuf, sizeof( vid )); ibuf += sizeof( vid ); - if (NULL == ( vol = getvolbyvid( vid )) ) { + if (NULL == ( vol = getvolbyvid( vid )) ) return( AFPERR_PARAM ); - } if (vol->v_flags & AFPVOL_RO) return AFPERR_VLOCK; @@ -657,44 +662,35 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, memcpy(&did, ibuf, sizeof( did)); ibuf += sizeof( did ); - if (NULL == ( dir = dirlookup( vol, did )) ) { + if (NULL == ( dir = dirlookup( vol, did )) ) return afp_errno; - } - if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) return get_afp_errno(AFPERR_PARAM); - } - if ( *s_path->m_name == '\0' ) { + if ( *s_path->m_name == '\0' ) return( AFPERR_BADTYPE ); - } upath = s_path->u_name; + ad_init(&ad, vol->v_adouble, vol->v_ad_options); /* if upath is deleted we already in trouble anyway */ if ((of = of_findname(s_path))) { - adp = of->of_ad; - } else { - ad_init(&ad, vol->v_adouble, vol->v_ad_options); - adp = &ad; - } - if ( creatf) { - /* on a hard create, fail if file exists and is open */ - if (of) + if (creatf) return AFPERR_BUSY; + else + return AFPERR_EXIST; + } + + if ( creatf) openf = O_RDWR|O_CREAT|O_TRUNC; - } else { + else /* on a soft create, if the file is open then ad_open won't fail - because open syscall is not called - */ - if (of) { - return AFPERR_EXIST; - } + because open syscall is not called */ openf = O_RDWR|O_CREAT|O_EXCL; - } - if ( ad_open( upath, ADFLAGS_DF|ADFLAGS_HF|ADFLAGS_NOHF|ADFLAGS_CREATE, - openf, 0666, adp) < 0 ) { + if ( ad_open(&ad, upath, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF, + openf, 0666, openf, 0666) < 0 ) { switch ( errno ) { case EROFS: return AFPERR_VLOCK; @@ -711,34 +707,39 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, return( AFPERR_PARAM ); } } - if ( ad_reso_fileno( adp ) == -1 ) { /* Hard META / HF */ + if ( ad_meta_fileno( &ad ) == -1 ) { /* Hard META / HF */ /* on noadouble volumes, just creating the data fork is ok */ if (vol_noadouble(vol)) { - ad_close( adp, ADFLAGS_DF ); + ad_close( &ad, ADFLAGS_DF ); goto createfile_done; } /* FIXME with hard create on an existing file, we already * corrupted the data file. */ netatalk_unlink( upath ); - ad_close( adp, ADFLAGS_DF ); + ad_close( &ad, ADFLAGS_DF ); return AFPERR_ACCESS; } path = s_path->m_name; - ad_setname(adp, path); - ad_flush( adp); - ad_close( adp, ADFLAGS_DF|ADFLAGS_HF ); + ad_setname(&ad, 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(&ad); + ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF ); createfile_done: curdir->offcnt++; -#ifdef DROPKLUDGE - if (vol->v_flags & AFPVOL_DROPBOX) { - retvalue = matchfile2dirperms(upath, vol, did); - } -#endif /* DROPKLUDGE */ - setvoltime(obj, vol ); return (retvalue); @@ -953,7 +954,7 @@ int setfilparams(struct vol *vol, /* second try with adouble open */ - if ( ad_open_metadata( upath, 0, O_CREAT, adp) < 0) { + if ( ad_open(adp, upath, ADFLAGS_HF, O_RDWR | O_CREAT, 0666) < 0) { LOG(log_debug, logtype_afpd, "setfilparams: ad_open_metadata error"); /* * For some things, we don't need an adouble header: @@ -966,7 +967,7 @@ int setfilparams(struct vol *vol, } LOG(log_debug, logtype_afpd, "setfilparams: no adouble perms, but only FILPBIT_MDATE and/or FILPBIT_UNIXPR"); isad = 0; - } else if ((ad_get_HF_flags( adp ) & O_CREAT) ) { + } else if ((ad_get_MD_flags( adp ) & O_CREAT) ) { ad_setname(adp, path->m_name); } @@ -1047,7 +1048,6 @@ setfilparam_done: if (isad) { ad_flush( adp); ad_close_metadata( adp); - } if (change_parent_mdate && gettimeofday(&tv, NULL) == 0) { @@ -1078,6 +1078,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 : @@ -1130,9 +1133,8 @@ int renamefile(const struct vol *vol, int sdir_fd, char *src, char *dst, char *n } } - /* don't care if we can't open the newly renamed ressource fork - */ - if (!ad_open( dst, ADFLAGS_HF, O_RDWR, 0666, adp)) { + /* don't care if we can't open the newly renamed ressource fork */ + if (ad_open(adp, dst, ADFLAGS_HF, O_RDWR) == 0) { ad_setname(adp, newname); ad_flush( adp ); ad_close( adp, ADFLAGS_HF ); @@ -1260,11 +1262,11 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si adp = of_ad(s_vol, s_path, &ad); - if (ad_open(s_path->u_name , ADFLAGS_DF |ADFLAGS_HF | ADFLAGS_NOHF, O_RDONLY, 0, adp) < 0) { + if (ad_open(adp, s_path->u_name, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF, O_RDONLY, O_RDONLY) < 0) { return AFPERR_DENYCONF; } - denyreadset = (getforkmode(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || - getforkmode(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 ); + denyreadset = (ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || + ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 ); if (denyreadset) { retvalue = AFPERR_DENYCONF; @@ -1280,9 +1282,6 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si goto copy_exit; } -#ifdef FORCE_UIDGID - /* FIXME svid != dvid && dvid's user can't read svid */ -#endif if (NULL == ( d_vol = getvolbyvid( dvid )) ) { retvalue = AFPERR_PARAM; goto copy_exit; @@ -1327,12 +1326,6 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si } curdir->offcnt++; -#ifdef DROPKLUDGE - if (vol->v_flags & AFPVOL_DROPBOX) { - retvalue=matchfile2dirperms(upath, vol, ddid); /* FIXME sdir or ddid */ - } -#endif /* DROPKLUDGE */ - setvoltime(obj, d_vol ); copy_exit: @@ -1471,7 +1464,7 @@ int copyfile(const struct vol *s_vol, adflags |= ADFLAGS_HF; } - if (ad_openat(sfd, src, adflags | ADFLAGS_NOHF, O_RDONLY, 0, adp) < 0) { + if (ad_openat(adp, sfd, src, adflags | ADFLAGS_NOHF, O_RDONLY, O_RDONLY) < 0) { ret_err = errno; goto done; } @@ -1489,7 +1482,7 @@ int copyfile(const struct vol *s_vol, } ad_init(&add, d_vol->v_adouble, d_vol->v_ad_options); - if (ad_open(dst , adflags, O_RDWR|O_CREAT|O_EXCL, st.st_mode, &add) < 0) { + if (ad_open(&add, dst, adflags, O_RDWR|O_CREAT|O_EXCL, st.st_mode, O_RDWR|O_CREAT|O_EXCL, st.st_mode) < 0) { ret_err = errno; ad_close( adp, adflags ); if (EEXIST != ret_err) { @@ -1604,7 +1597,7 @@ int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib) * moreover sometimes deletefile is called with a no existent file and * ad_open would create a 0 byte resource fork */ - if ( ad_metadataat(dirfd, file, ADFLAGS_OPENFORKS, &ad) == 0 ) { + if ( ad_metadataat(dirfd, file, ADFLAGS_CHECK_OF, &ad) == 0 ) { if ((err = check_attrib(&ad))) { ad_close_metadata(&ad); return err; @@ -1615,7 +1608,7 @@ int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib) /* try to open both forks at once */ adflags = ADFLAGS_DF; - if ( ad_openat(dirfd, file, adflags |ADFLAGS_HF|ADFLAGS_NOHF, O_RDONLY, 0, &ad ) < 0 ) { + if ( ad_openat(&ad, dirfd, file, adflags |ADFLAGS_HF|ADFLAGS_NOHF, O_RDONLY, O_RDONLY) < 0 ) { switch (errno) { case ENOENT: err = AFPERR_NOOBJ; @@ -1758,32 +1751,12 @@ 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 ( lstat(de->d_name, &path.st) < 0 ) return 0; /* update or add to cnid */ aint = cnid_add(vol->v_cdb, &path.st, did, de->d_name, strlen(de->d_name), 0); /* ignore errors */ -#if AD_VERSION > AD_VERSION1 - if (aint != CNID_INVALID && !S_ISDIR(path.st.st_mode)) { - struct adouble ad, *adp; - - path.st_errno = 0; - path.st_valid = 1; - path.u_name = de->d_name; - - adp = of_ad(vol, &path, &ad); - - if ( ad_open_metadata( de->d_name, 0, 0, adp ) < 0 ) { - return 0; - } - if (ad_setid(adp, path.st.st_dev, path.st.st_ino, aint, did, vol->v_stamp)) { - ad_flush(adp); - } - ad_close_metadata(adp); - } -#endif /* AD_VERSION > AD_VERSION1 */ - return 0; } @@ -2045,7 +2018,7 @@ static struct adouble *find_adouble(struct path *path, struct ofork **of, struct adp = (*of)->of_ad; } else { - ret = ad_open( path->u_name, ADFLAGS_HF, O_RDONLY, 0, adp); + ret = ad_open(adp, path->u_name, ADFLAGS_HF, O_RDONLY); /* META and HF */ if ( !ret && ad_reso_fileno(adp) != -1 && !(adp->ad_resource_fork.adf_flags & ( O_RDWR | O_WRONLY))) { /* from AFP spec. @@ -2217,12 +2190,11 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U /* id's need switching. src -> dest and dest -> src. * we need to re-stat() if it was a cross device copy. */ - if (sid) { - cnid_delete(vol->v_cdb, sid); - } - if (did) { - cnid_delete(vol->v_cdb, did); - } + if (sid) + cnid_delete(vol->v_cdb, sid); + if (did) + cnid_delete(vol->v_cdb, did); + if ((did && ( (crossdev && lstat( upath, &srcst) < 0) || cnid_update(vol->v_cdb, did, &srcst, curdir->d_did,upath, dlen) < 0)) || @@ -2316,5 +2288,11 @@ err_exchangefile: ad_close(addp, ADFLAGS_HF); } + struct dir *cached; + if ((cached = dircache_search_by_did(vol, sid)) != NULL) + (void)dir_remove(vol, cached); + if ((cached = dircache_search_by_did(vol, did)) != NULL) + (void)dir_remove(vol, cached); + return err; }