X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fcnid_dbd%2Fdbd_lookup.c;h=04c536584b96a7d765bae32df9276bb2de78fea0;hb=be96d276348da0a7e66eeec844b306e8a5fa8fac;hp=df24cc4c5c5270bddc40688e623e72a88ea8fc79;hpb=516cd7ae0378bd5205b401a4430ed6811a4a30e3;p=netatalk.git diff --git a/etc/cnid_dbd/dbd_lookup.c b/etc/cnid_dbd/dbd_lookup.c index df24cc4c..04c53658 100644 --- a/etc/cnid_dbd/dbd_lookup.c +++ b/etc/cnid_dbd/dbd_lookup.c @@ -1,5 +1,5 @@ /* - * $Id: dbd_lookup.c,v 1.14 2009-11-30 15:27:48 didg Exp $ + * $Id: dbd_lookup.c,v 1.18 2010-01-19 14:57:11 franklahm Exp $ * * Copyright (C) Joerg Lenneis 2003 * Copyright (C) Frank Lahm 2009 @@ -8,8 +8,10 @@ /* 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 (for AFPVOL_CACHE volumes). In certain cases we can +use this hint to determince the right CNID. The lines... @@ -46,6 +48,8 @@ Result in dbd_lookup (-: not found, +: found): 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 ---------------------------------------- @@ -61,7 +65,11 @@ Result in dbd_lookup: - didname Possible solution: -strcmp names, if they match keep CNID. +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 ------------------------------------------------------------ @@ -108,7 +116,8 @@ to be safe we must assign new CNIDs to both files. #include #include #include -#include +#include + #include #include @@ -138,6 +147,8 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, rply->namelen = 0; rply->cnid = 0; + + LOG(log_maxdebug, logtype_cnid, "dbd_lookup(): START"); buf = pack_cnid_data(rqst); @@ -179,6 +190,9 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, 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 */ @@ -189,22 +203,46 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, } /* 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) { - rqst->cnid = id_devino; - if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0) - return -1; + 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); + + if (! roflag) { + rqst->cnid = id_devino; + 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) { - rqst->cnid = id_didname; - if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0) - return -1; + + 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); + + if (! roflag) { + rqst->cnid = id_didname; + 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; } @@ -238,9 +276,8 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, } if ( ! didname) { - LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): CNID resolve problem: server side rename oder reused inode", - ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); - /* Case 2) ? */ + LOG(log_debug, logtype_cnid, "dbd_lookup(CNID hint: %u, DID:%u, \"%s\", 0x%llx/0x%llx): CNID resolve problem: server side rename oder reused inode", + ntohl(rqst->cnid), ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); if (rqst->cnid == id_devino) { LOG(log_debug, logtype_cnid, "dbd_lookup: server side mv (with resource fork)"); update = 1;