/*
- * $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.
*/
(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;
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) {
/* 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");
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);
}
if (!path->id) {
struct dir *cachedfile;
int len = strlen(upath);
- if ((cachedfile = dircache_search_by_name(vol, dir, upath, len)) != NULL)
+ 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);
}
}
- 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) {
LOG(log_error, logtype_afpd, "getmetadata: fatal dircache error");
exit(EXITERR_SYS);
/* 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))
||
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;
}