X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fenumerate.c;h=80141e801850fa54f047c28dfd57fcadc108289a;hb=acb180395693ed05a4e6a1edb6796c8e6f644a72;hp=b8a403bd4fd958a9b5de04d9c6cca5ccb3ea5bc2;hpb=8f6bea54f2115259a524ebade0fa346be1e0c2dd;p=netatalk.git diff --git a/etc/afpd/enumerate.c b/etc/afpd/enumerate.c index b8a403bd..80141e80 100644 --- a/etc/afpd/enumerate.c +++ b/etc/afpd/enumerate.c @@ -19,14 +19,16 @@ #include #include #include +#include #include #include +#include +#include #include "desktop.h" #include "directory.h" #include "dircache.h" #include "volume.h" -#include "globals.h" #include "file.h" #include "fork.h" #include "filedir.h" @@ -39,7 +41,7 @@ */ struct savedir { u_short sd_vid; - u_int32_t sd_did; + uint32_t sd_did; int sd_buflen; char *sd_buf; char *sd_last; @@ -154,7 +156,7 @@ for_each_dirent(const struct vol *vol, char *name, dir_loop fn, void *data) macnamelength(1) + macname(31) + utf8(4) + utf8namelen(2) + utf8name(255) + oddpadding(1) */ -#define REPLY_PARAM_MAXLEN (4 + 104 + 1 + MACFILELEN + 4 + 2 + 255 + 1) +#define REPLY_PARAM_MAXLEN (4 + 104 + 1 + MACFILELEN + 4 + 2 + UTF8FILELEN_EARLY + 1) /* ----------------------------- */ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, @@ -168,9 +170,9 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, int did, ret, len, first = 1; size_t esz; char *data, *start; - u_int16_t vid, fbitmap, dbitmap, reqcnt, actcnt = 0; - u_int16_t temp16; - u_int32_t sindex, maxsz, sz = 0; + uint16_t vid, fbitmap, dbitmap, reqcnt, actcnt = 0; + uint16_t temp16; + uint32_t sindex, maxsz, sz = 0; struct path *o_path; struct path s_path; int header; @@ -268,13 +270,11 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, return path_error(o_path, AFPERR_NODIR ); } - LOG(log_debug, logtype_afpd, "enumerate(vid:%u, did:%u, cwddid:%u, cwd:'%s', name:'%s', f/d:%04x/%04x, rc:%u, i:%u, max:%u)", - ntohs(vid), ntohl(did), ntohl(curdir->d_did), - cfrombstring(curdir->d_fullpath), o_path->u_name, - fbitmap, dbitmap, reqcnt, sindex, maxsz); + LOG(log_debug, logtype_afpd, "enumerate(\"%s/%s\", f/d:%04x/%04x, rc:%u, i:%u, max:%u)", + getcwdpath(), o_path->u_name, fbitmap, dbitmap, reqcnt, sindex, maxsz); - data = rbuf + 3 * sizeof( u_int16_t ); - sz = 3 * sizeof( u_int16_t ); /* fbitmap, dbitmap, reqcount */ + data = rbuf + 3 * sizeof( uint16_t ); + sz = 3 * sizeof( uint16_t ); /* fbitmap, dbitmap, reqcount */ /* * Read the directory into a pre-malloced buffer, stored @@ -284,12 +284,13 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, if ( sindex == 1 || curdir->d_did != sd.sd_did || vid != sd.sd_vid ) { sd.sd_last = sd.sd_buf; /* if dir was in the cache we don't have the inode */ - if (( !o_path->st_valid && lstat( ".", &o_path->st ) < 0 ) || - (ret = for_each_dirent(vol, ".", enumerate_loop, (void *)&sd)) < 0) + if (( !o_path->st_valid && ostat(".", &o_path->st, vol_syml_opt(vol)) < 0 ) || + (ret = for_each_dirent(vol, ".", enumerate_loop, (void *)&sd)) < 0) { + LOG(log_error, logtype_afpd, "enumerate: loop error: %s (%d)", strerror(errno), errno); switch (errno) { case EACCES: - return AFPERR_ACCESS; + return AFPERR_ACCESS; case ENOTDIR: return AFPERR_BADTYPE; case ENOMEM: @@ -346,25 +347,37 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, continue; } memset(&s_path, 0, sizeof(s_path)); + + /* conversions on the fly */ + const char *convname; s_path.u_name = sd.sd_last; - if (of_stat( &s_path) < 0 ) { - /* - * Somebody else plays with the dir, well it can be us with - * "Empty Trash..." - */ + if (ad_convert(sd.sd_last, &s_path.st, vol, &convname) == 0 && convname) { + s_path.u_name = (char *)convname; + } + if (of_stat(vol, &s_path) < 0 ) { /* so the next time it won't try to stat it again * another solution would be to invalidate the cache with * sd.sd_did = 0 but if it's not ENOENT error it will start again */ *sd.sd_last = 0; sd.sd_last += len + 1; - curdir->offcnt--; /* a little lie */ + curdir->d_offcnt--; /* a little lie */ continue; } + /* Fixup CNID db if ad_convert resulted in a rename (then convname != NULL) */ + if (convname) { + s_path.id = cnid_lookup(vol->v_cdb, &s_path.st, curdir->d_did, sd.sd_last, strlen(sd.sd_last)); + if (s_path.id != CNID_INVALID) { + if (cnid_update(vol->v_cdb, s_path.id, &s_path.st, curdir->d_did, (char *)convname, strlen(convname)) != 0) + LOG(log_error, logtype_afpd, "enumerate: error updating CNID of \"%s\"", fullpathname(convname)); + } + } + sd.sd_last += len + 1; s_path.m_name = NULL; + /* * If a fil/dir is not a dir, it's a file. This is slightly * inaccurate, since that means /dev/null is a file, /dev/printer @@ -382,15 +395,16 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, return AFPERR_MISC; } } - if ((ret = getdirparams(vol, dbitmap, &s_path, dir, data + header , &esz)) != AFP_OK) + if ((ret = getdirparams(obj, vol, dbitmap, &s_path, dir, data + header , &esz)) != AFP_OK) return( ret ); } else { if ( fbitmap == 0 ) { continue; } - if (AFP_OK != ( ret = getfilparams(vol, fbitmap, &s_path, curdir, - data + header , &esz )) ) { + /* files are added to the dircache in getfilparams() -> getmetadata() */ + if (AFP_OK != ( ret = getfilparams(obj, vol, fbitmap, &s_path, curdir, + data + header, &esz, 1)) ) { return( ret ); } } @@ -439,6 +453,15 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, if ( actcnt == 0 ) { sd.sd_did = 0; /* invalidate sd struct to force re-read */ + /* + * in case were converting adouble stuff: + * after enumerating the whole dir we should have converted everything + * thus the .AppleDouble dir shouls be empty thus we can no try to + * delete it + */ + if (vol->v_adouble == AD_VERSION_EA && ! (vol->v_flags & AFPVOL_NOV2TOEACONV)) + (void)rmdir(".AppleDouble"); + return( AFPERR_NOOBJ ); } sd.sd_sindex = sindex + actcnt;