X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fdirectory.c;h=b139cbcd661952e1ebe5aef0ecdf6a7c605706ed;hb=b0bcb8f6b0571592a50ce039882c9319e012a270;hp=b981af66c03fb6c4b94cff562402dcc78dbcd13d;hpb=3858412d6efa2798fdc9b3f5613275e49dd63513;p=netatalk.git diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index b981af66..b139cbcd 100644 --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "directory.h" #include "dircache.h" @@ -37,7 +39,6 @@ #include "fork.h" #include "file.h" #include "filedir.h" -#include "globals.h" #include "unix.h" #include "mangle.h" #include "hash.h" @@ -265,7 +266,7 @@ copydir_done: */ static int diroffcnt(struct dir *dir, struct stat *st) { - return st->st_ctime == dir->ctime; + return st->st_ctime == dir->d_ctime; } /* --------------------- */ @@ -468,6 +469,7 @@ struct dir *dirlookup_bypath(const struct vol *vol, const char *path) l = bsplit(rpath, '/'); for (int i = 0; i < l->qty ; i++) { /* 3. */ did = cnid; + EC_ZERO(bcatcstr(statpath, "/")); EC_ZERO(bconcat(statpath, l->entry[i])); EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st), "lstat(rpath: %s, elem: %s): %s: %s", @@ -480,8 +482,7 @@ struct dir *dirlookup_bypath(const struct vol *vol, const char *path) if ((dir = dircache_search_by_name(vol, /* 5. */ dir, cfrombstr(l->entry[i]), - blength(l->entry[i]), - st.st_ctime)) == NULL) { + blength(l->entry[i]))) == NULL) { if ((cnid = cnid_add(vol->v_cdb, /* 6. */ &st, did, @@ -494,8 +495,6 @@ struct dir *dirlookup_bypath(const struct vol *vol, const char *path) if ((dir = dirlookup(vol, cnid)) == NULL) /* 7. */ EC_FAIL; } - - EC_ZERO(bcatcstr(statpath, "/")); } EC_CLEANUP: @@ -514,7 +513,7 @@ EC_CLEANUP: * Resolve a DID, allocate a struct dir for it * 1. Check for special CNIDs 0 (invalid), 1 and 2. * 2a. Check if the DID is in the cache. - * 2b. Check if it's really a dir (d_fullpath != NULL) because we cache files too. + * 2b. Check if it's really a dir because we cache files too. * 3. If it's not in the cache resolve it via the database. * 4. Build complete server-side path to the dir. * 5. Check if it exists and is a directory. @@ -539,7 +538,7 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did) int utf8; int err = 0; - LOG(log_debug, logtype_afpd, "dirlookup(did: %u)", ntohl(did)); + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): START", ntohl(did)); /* check for did 0, 1 and 2 */ if (did == 0 || vol == NULL) { /* 1 */ @@ -557,18 +556,19 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did) /* Search the cache */ if ((ret = dircache_search_by_did(vol, did)) != NULL) { /* 2a */ - if (ret->d_fullpath == NULL) { /* 2b */ + if (ret->d_flags & DIRF_ISFILE) { /* 2b */ afp_errno = AFPERR_BADTYPE; ret = NULL; goto exit; } if (lstat(cfrombstr(ret->d_fullpath), &st) != 0) { - LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {lstat: %s}", ntohl(did), strerror(errno)); + LOG(log_debug, logtype_afpd, "dirlookup(did: %u, path: \"%s\"): lstat: %s", + ntohl(did), cfrombstr(ret->d_fullpath), strerror(errno)); switch (errno) { case ENOENT: case ENOTDIR: /* It's not there anymore, so remove it */ - LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {calling dir_remove()}", ntohl(did)); + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): calling dir_remove", ntohl(did)); dir_remove(vol, ret); afp_errno = AFPERR_NOOBJ; ret = NULL; @@ -590,6 +590,7 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did) /* Get it from the database */ cnid = did; + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): querying CNID database", ntohl(did)); if ((upath = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL) { afp_errno = AFPERR_NOOBJ; err = 1; @@ -607,7 +608,8 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did) * - DIRDID_ROOT is hit * - a cached entry is found */ - LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {recursion for did: %u}", ntohl(pdid)); + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): recursion for did: %u", + ntohl(did), ntohl(pdid)); if ((pdir = dirlookup(vol, pdid)) == NULL) { err = 1; goto exit; @@ -622,9 +624,10 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did) } /* stat it and check if it's a dir */ - LOG(log_debug, logtype_afpd, "dirlookup: {stating %s}", cfrombstr(fullpath)); + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): stating \"%s\"", + ntohl(did), cfrombstr(fullpath)); - if (stat(cfrombstr(fullpath), &st) != 0) { /* 5a */ + if (lstat(cfrombstr(fullpath), &st) != 0) { /* 5a */ switch (errno) { case ENOENT: afp_errno = AFPERR_NOOBJ; @@ -655,7 +658,7 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did) } /* Create struct dir */ - if ((ret = dir_new(mpath, upath, vol, pdid, did, fullpath, st.st_ctime)) == NULL) { /* 6 */ + if ((ret = dir_new(mpath, upath, vol, pdid, did, fullpath, &st)) == NULL) { /* 6 */ LOG(log_error, logtype_afpd, "dirlookup(did: %u) {%s, %s}: %s", ntohl(did), mpath, upath, strerror(errno)); err = 1; goto exit; @@ -680,7 +683,7 @@ exit: } } if (ret) - LOG(log_debug, logtype_afpd, "dirlookup(did: %u): pdid: %u, \"%s\"", + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): RESULT: pdid: %u, path: \"%s\"", ntohl(ret->d_did), ntohl(ret->d_pdid), cfrombstr(ret->d_fullpath)); return ret; @@ -778,8 +781,8 @@ int caseenumerate(const struct vol *vol, struct path *path, struct dir *dir) * @param vol (r) pointer to struct vol * @param pdid (r) Parent CNID * @param did (r) CNID - * @param path (r) Full unix path to dir or NULL for files - * @param ctime (r) st_ctime from stat + * @param path (r) Full unix path to object + * @param st (r) struct stat of object * * @returns pointer to new struct dir or NULL on error * @@ -791,7 +794,7 @@ struct dir *dir_new(const char *m_name, cnid_t pdid, cnid_t did, bstring path, - time_t ctime) + struct stat *st) { struct dir *dir; @@ -825,7 +828,11 @@ struct dir *dir_new(const char *m_name, dir->d_pdid = pdid; dir->d_vid = vol->v_vid; dir->d_fullpath = path; - dir->ctime_dircache = ctime; + dir->dcache_ctime = st->st_ctime; + dir->dcache_ino = st->st_ino; + if (!S_ISDIR(st->st_mode)) + dir->d_flags = DIRF_ISFILE; + dir->d_rights_cache = 0xffffffff; return dir; } @@ -879,7 +886,7 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i AFP_ASSERT(path); AFP_ASSERT(len > 0); - if ((cdir = dircache_search_by_name(vol, dir, path->u_name, strlen(path->u_name), path->st.st_ctime)) != NULL) { + if ((cdir = dircache_search_by_name(vol, dir, path->u_name, strlen(path->u_name))) != NULL) { /* there's a stray entry in the dircache */ LOG(log_debug, logtype_afpd, "dir_add(did:%u,'%s/%s'): {stray cache entry: did:%u,'%s', removing}", ntohl(dir->d_did), cfrombstr(dir->d_fullpath), path->u_name, @@ -892,7 +899,7 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i /* get_id needs adp for reading CNID from adouble file */ ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if ((ad_open_metadata(path->u_name, ADFLAGS_DIR, 0, &ad)) == 0) /* 1 */ + if ((ad_open(&ad, path->u_name, ADFLAGS_HF | ADFLAGS_DIR)) == 0) /* 1 */ adp = &ad; /* Get CNID */ @@ -923,7 +930,13 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i } /* Allocate and initialize struct dir */ - if ((cdir = dir_new( path->m_name, path->u_name, vol, dir->d_did, id, fullpath, path->st.st_ctime)) == NULL) { /* 3 */ + if ((cdir = dir_new(path->m_name, + path->u_name, + vol, + dir->d_did, + id, + fullpath, + &path->st)) == NULL) { /* 3 */ err = 4; goto exit; } @@ -1281,7 +1294,7 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath) /* Search the cache */ int unamelen = strlen(ret.u_name); - cdir = dircache_search_by_name(vol, dir, ret.u_name, unamelen, ret.st.st_ctime); /* 14 */ + cdir = dircache_search_by_name(vol, dir, ret.u_name, unamelen); /* 14 */ if (cdir == NULL) { /* Not in cache, create one */ if ((cdir = dir_add(vol, dir, &ret, unamelen)) == NULL) { /* 15 */ @@ -1431,8 +1444,8 @@ int file_access(struct path *path, int mode) /* --------------------- */ void setdiroffcnt(struct dir *dir, struct stat *st, u_int32_t count) { - dir->offcnt = count; - dir->ctime = st->st_ctime; + dir->d_offcnt = count; + dir->d_ctime = st->st_ctime; dir->d_flags &= ~DIRF_CNID; } @@ -1442,7 +1455,7 @@ void setdiroffcnt(struct dir *dir, struct stat *st, u_int32_t count) */ int dirreenumerate(struct dir *dir, struct stat *st) { - return st->st_ctime == dir->ctime && (dir->d_flags & DIRF_CNID); + return st->st_ctime == dir->d_ctime && (dir->d_flags & DIRF_CNID); } /* ------------------------------ @@ -1474,10 +1487,21 @@ int getdirparams(const struct vol *vol, (1 << DIRPBIT_FINFO)))) { ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if ( !ad_metadata( upath, ADFLAGS_CREATE|ADFLAGS_DIR, &ad) ) { + if ( !ad_metadata( upath, ADFLAGS_DIR, &ad) ) isad = 1; if (ad.ad_md->adf_flags & O_CREAT) { /* We just created it */ + if (s_path->m_name == NULL) { + if ((s_path->m_name = utompath(vol, + upath, + dir->d_did, + utf8_encoding())) == NULL) { + LOG(log_error, logtype_afpd, + "getdirparams(\"%s\"): can't assign macname", + cfrombstr(dir->d_fullpath)); + return AFPERR_MISC; + } + } ad_setname(&ad, s_path->m_name); ad_setid( &ad, s_path->st.st_dev, @@ -1581,11 +1605,11 @@ int getdirparams(const struct vol *vol, ashort = 0; /* this needs to handle current directory access rights */ if (diroffcnt(dir, st)) { - ashort = (dir->offcnt > 0xffff)?0xffff:dir->offcnt; + ashort = (dir->d_offcnt > 0xffff)?0xffff:dir->d_offcnt; } else if ((ret = for_each_dirent(vol, upath, NULL,NULL)) >= 0) { setdiroffcnt(dir, st, ret); - ashort = (dir->offcnt > 0xffff)?0xffff:dir->offcnt; + ashort = (dir->d_offcnt > 0xffff)?0xffff:dir->d_offcnt; } ashort = htons( ashort ); memcpy( data, &ashort, sizeof( ashort )); @@ -1891,7 +1915,7 @@ int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *b } ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (ad_open_metadata( upath, ADFLAGS_DIR, O_CREAT, &ad) < 0) { + if (ad_open(&ad, upath, ADFLAGS_HF | ADFLAGS_DIR, O_CREAT, 0777) != 0) { /* * Check to see what we're trying to set. If it's anything * but ACCESS, UID, or GID, give an error. If it's any of those @@ -1913,7 +1937,7 @@ int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *b * Check to see if a create was necessary. If it was, we'll want * to set our name, etc. */ - if ( (ad_get_HF_flags( &ad ) & O_CREAT)) { + if ( (ad_get_MD_flags( &ad ) & O_CREAT)) { ad_setname(&ad, cfrombstr(curdir->d_m_name)); } } @@ -2233,7 +2257,7 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_ return AFPERR_MISC; } - curdir->offcnt++; + curdir->d_offcnt++; if ((dir = dir_add(vol, curdir, s_path, strlen(s_path->u_name))) == NULL) { return AFPERR_MISC; @@ -2244,7 +2268,7 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_ } ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (ad_open_metadata( ".", ADFLAGS_DIR, O_CREAT, &ad ) < 0) { + if (ad_open(&ad, ".", ADFLAGS_HF | ADFLAGS_DIR, O_CREAT, 0777) < 0) { if (vol_noadouble(vol)) goto createdir_done; return( AFPERR_ACCESS ); @@ -2252,6 +2276,8 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_ ad_setname(&ad, s_path->m_name); ad_setid( &ad, s_path->st.st_dev, s_path->st.st_ino, dir->d_did, did, vol->v_stamp); + fce_register_new_dir(s_path); + ad_flush( &ad); ad_close_metadata( &ad); @@ -2310,7 +2336,7 @@ int renamedir(const struct vol *vol, ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (!ad_open_metadata( dst, ADFLAGS_DIR, 0, &ad)) { + if (ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_DIR) == 0) { ad_setname(&ad, newname); ad_flush( &ad); ad_close_metadata( &ad); @@ -2489,9 +2515,6 @@ int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *r rbuf += sizeof( id ); *rbuflen = 2 * sizeof( id ); break; - case UUID_LOCAL: - free(name); - return (AFPERR_NOITEM); default: return AFPERR_MISC; }