/*
- * $Id: dbd_lookup.c,v 1.16 2009-12-09 15:25:28 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* Copyright (C) Frank Lahm 2009
/*
CNID salvation spec:
-general rule: better safe then sorry, so we always delete CNIDs and assing
-new ones in case of a lookup mismatch.
+general rule: better safe then sorry, so we always delete CNIDs and assign
+new ones in case of a lookup mismatch. afpd also sends us the CNID found
+in the adouble file. In certain cases we can use this hint to determince
+the right CNID.
The lines...
Possible solution:
None. Delete old data, file gets new CNID in both cases (rename and inode).
+If we got a hint and hint matches the CNID from devino we keep it and update
+the record.
2) UNIX mv from one folder to another
----------------------------------------
strcmp names, if they match keep CNID. Unfortunately this also can't be
distinguished from a new file with a reused inode. So me must assign
a new CNID.
+If we got a hint and hint matches the CNID from devino we keep it and update
+the record.
3) Restore from backup ie change of inode number -- or emacs
------------------------------------------------------------
#include <string.h>
#include <sys/param.h>
#include <errno.h>
-#include <netatalk/endian.h>
+#include <arpa/inet.h>
+
#include <atalk/logger.h>
#include <atalk/cnid_dbd_private.h>
+#include <atalk/cnid.h>
#include "pack.h"
#include "dbif.h"
* up the database if there's a problem.
*/
-int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int roflag)
+int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
{
unsigned char *buf;
DBT key, devdata, diddata;
rply->namelen = 0;
rply->cnid = 0;
+
+ LOG(log_maxdebug, logtype_cnid, "dbd_lookup(): START");
buf = pack_cnid_data(rqst);
type_didname = ntohl(type_didname);
}
+ LOG(log_maxdebug, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx) {devino: %u, didname: %u}",
+ rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, devino, didname);
+
/* Have we found anything at all ? */
if (!devino && !didname) {
/* nothing found */
}
/* Check for type (file/dir) mismatch */
- if (devino && (type_devino != rqst->type)) {
- /* one is a dir one is a file, remove from db */
- if (! roflag) {
+ if ((devino && (type_devino != rqst->type)) || (didname && (type_didname != rqst->type))) {
+
+ if (devino && (type_devino != rqst->type)) {
+ /* one is a dir one is a file, remove from db */
+
+ LOG(log_debug, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): type mismatch for devino",
+ rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
+
rqst->cnid = id_devino;
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ rc = dbd_delete(dbd, rqst, rply, DBIF_CNID);
+ rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DEVINO);
+ rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DIDNAME);
+ if (rc < 0) {
+ LOG(log_error, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): error deleting type mismatch for devino",
+ rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
return -1;
+ }
}
- rply->result = CNID_DBD_RES_NOTFOUND;
- return 1;
- } else if (didname && (type_didname != rqst->type)) {
- /* same: one is a dir one is a file, remove from db */
- if (! roflag) {
+
+ if (didname && (type_didname != rqst->type)) {
+ /* same: one is a dir one is a file, remove from db */
+
+ LOG(log_debug, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): type mismatch for didname",
+ rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
+
rqst->cnid = id_didname;
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ rc = dbd_delete(dbd, rqst, rply, DBIF_CNID);
+ rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DEVINO);
+ rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DIDNAME);
+ if (rc < 0) {
+ LOG(log_error, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): error deleting type mismatch for didname",
+ rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
return -1;
+ }
}
+
rply->result = CNID_DBD_RES_NOTFOUND;
return 1;
}
ntohl(rqst->did), rqst->name, ntohl(id_didname),
(unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(id_devino));
- if (! roflag) {
- rqst->cnid = id_devino;
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
- return -1;
+ rqst->cnid = id_devino;
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ return -1;
+
+ rqst->cnid = id_didname;
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ return -1;
- rqst->cnid = id_didname;
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
- return -1;
- }
rply->result = CNID_DBD_RES_NOTFOUND;
return 1;
}
LOG(log_debug, logtype_cnid, "dbd_lookup: server side mv (with resource fork)");
update = 1;
} else {
- if ( ! roflag) {
- rqst->cnid = id_devino;
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
- return -1;
- }
+ rqst->cnid = id_devino;
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ return -1;
rply->result = CNID_DBD_RES_NOTFOUND;
+ rqst->cnid = CNID_INVALID; /* invalidate CNID hint */
return 1;
}
}
if ( ! devino) {
LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): CNID resolve problem: changed dev/ino",
ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
- if ( ! roflag) {
- rqst->cnid = id_didname;
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
- return -1;
- }
+ rqst->cnid = id_didname;
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ return -1;
rply->result = CNID_DBD_RES_NOTFOUND;
+ rqst->cnid = CNID_INVALID; /* invalidate CNID hint */
return 1;
}
/* This is also a catch all if we've forgot to catch some possibility with the preceding ifs*/
- if (!update || roflag) {
+ if (!update) {
rply->result = CNID_DBD_RES_NOTFOUND;
return 1;
}