X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Ffile.c;h=323642f9ce92f305e7b9b905fdf102c726119656;hp=a1674601d3b39bfe40c7b745ccf22f1486755e03;hb=465246e257d9aff9855e3e35d8fd5983db932b45;hpb=7e8176ccdb84296ac46cd211c8a1a6884d1d95f3 diff --git a/etc/afpd/file.c b/etc/afpd/file.c index a1674601..323642f9 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. */ @@ -39,6 +37,7 @@ char *strchr (), *strrchr (); #include #include #include +#include #include "directory.h" #include "dircache.h" @@ -47,7 +46,6 @@ char *strchr (), *strrchr (); #include "fork.h" #include "file.h" #include "filedir.h" -#include "globals.h" #include "unix.h" /* the format for the finderinfo fields (from IM: Toolbox Essentials): @@ -167,8 +165,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)); @@ -202,9 +200,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; @@ -214,9 +230,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) { @@ -234,7 +250,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"); @@ -268,9 +284,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); } @@ -299,6 +316,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; @@ -307,6 +326,7 @@ int getmetadata(struct vol *vol, || (bitmap & ( (1 << FILPBIT_LNAME) ) && utf8_encoding()) /* FIXME should be m_name utf8 filename */ || (bitmap & (1 << FILPBIT_FNUM))) { if (!path->id) { + bstring fullpath; struct dir *cachedfile; int len = strlen(upath); if ((cachedfile = dircache_search_by_name(vol, dir, upath, len)) != NULL) @@ -322,17 +342,26 @@ int getmetadata(struct vol *vol, if (path->m_name == NULL) { if ((path->m_name = utompath(vol, upath, id, utf8_encoding())) == NULL) { LOG(log_error, logtype_afpd, "getmetadata: utompath error"); - exit(EXITERR_SYS); + return AFPERR_MISC; } } - if ((cachedfile = dir_new(path->m_name, upath, vol, dir->d_did, id, NULL)) == NULL) { + /* Build fullpath */ + if (((fullpath = bstrcpy(dir->d_fullpath)) == NULL) + || (bconchar(fullpath, '/') != BSTR_OK) + || (bcatcstr(fullpath, upath)) != BSTR_OK) { + LOG(log_error, logtype_afpd, "getmetadata: fullpath: %s", strerror(errno)); + return AFPERR_MISC; + } + + if ((cachedfile = dir_new(path->m_name, upath, vol, dir->d_did, id, fullpath, st)) == NULL) { LOG(log_error, logtype_afpd, "getmetadata: error from dir_new"); - exit(EXITERR_SYS); + return AFPERR_MISC; } - if ((dircache_add(cachedfile)) != 0) { + + if ((dircache_add(vol, cachedfile)) != 0) { LOG(log_error, logtype_afpd, "getmetadata: fatal dircache error"); - exit(EXITERR_SYS); + return AFPERR_MISC; } } } else { @@ -595,6 +624,8 @@ 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; @@ -728,11 +759,22 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, path = s_path->m_name; ad_setname(adp, 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( adp); ad_close( adp, ADFLAGS_DF|ADFLAGS_HF ); createfile_done: - curdir->offcnt++; + curdir->d_offcnt++; #ifdef DROPKLUDGE if (vol->v_flags & AFPVOL_DROPBOX) { @@ -1079,6 +1121,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 : @@ -1326,7 +1371,7 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si retvalue = err; goto copy_exit; } - curdir->offcnt++; + curdir->d_offcnt++; #ifdef DROPKLUDGE if (vol->v_flags & AFPVOL_DROPBOX) { @@ -1810,7 +1855,7 @@ reenumerate_id(struct vol *vol, char *name, struct dir *dir) if (dirreenumerate(dir, &st)) { /* we already did it once and the dir haven't been modified */ - return dir->offcnt; + return dir->d_offcnt; } data.vol = vol; @@ -2218,12 +2263,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)) || @@ -2317,5 +2361,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; }