X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fcnid_dbd%2Fdbd_lookup.c;h=f77b9fc2cb5f95a3abea20009fee1d980a7296ed;hb=9f957894d9a60f32adc56edddf72fa767ded8219;hp=1f310fe9af7d53f653e8210ba657cf51677e4863;hpb=e4a6f1483c43b81c3dca414e58d1e9be4ff86031;p=netatalk.git diff --git a/etc/cnid_dbd/dbd_lookup.c b/etc/cnid_dbd/dbd_lookup.c index 1f310fe9..f77b9fc2 100644 --- a/etc/cnid_dbd/dbd_lookup.c +++ b/etc/cnid_dbd/dbd_lookup.c @@ -1,5 +1,4 @@ /* - * $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 @@ -8,8 +7,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. In certain cases we can use this hint to determince +the right CNID. The lines... @@ -46,6 +47,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 ---------------------------------------- @@ -64,6 +67,8 @@ Possible solution: 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 ------------------------------------------------------------ @@ -110,9 +115,11 @@ to be safe we must assign new CNIDs to both files. #include #include #include -#include +#include + #include #include +#include #include "pack.h" #include "dbif.h" @@ -123,7 +130,7 @@ to be safe we must assign new CNIDs to both files. * 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; @@ -140,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); @@ -181,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 */ @@ -191,22 +203,42 @@ 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) { + 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; } @@ -226,15 +258,14 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, 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; } @@ -246,12 +277,11 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, 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; } } @@ -259,17 +289,16 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, 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; }