diff options
-rw-r--r-- | ChangeLog.txt | 7 | ||||
-rw-r--r-- | ports/unix/guts/rename.c | 6 | ||||
-rw-r--r-- | pseudo.c | 21 | ||||
-rw-r--r-- | pseudo_db.c | 10 | ||||
-rw-r--r-- | pseudo_db.h | 2 |
5 files changed, 36 insertions, 10 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt index 48a3261..edb85b1 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,6 +1,13 @@ 2014-10-03: * (seebs) in fact, suppress a lot of sanity checks entirely for did_unlink. + * (seebs) merge get_file_path functionality into find_file_dev, + since you never call find_file_dev unless you want to do that. + * (seebs) If a file is in the database by inode but not path, + don't try to create a new link for it. + * (seebs) when renaming, the link of the "old" file name should be + contingent on whether *it* was in the database, not whether + the *new* name was in the database. Whoops. 2014-10-02: * (seebs) use sqlite3_bind_int64 for inodes. diff --git a/ports/unix/guts/rename.c b/ports/unix/guts/rename.c index ad28293..b8ee8b0 100644 --- a/ports/unix/guts/rename.c +++ b/ports/unix/guts/rename.c @@ -11,6 +11,7 @@ int oldrc, newrc; int save_errno; int old_db_entry = 0; + int may_unlinked = 0; pseudo_debug(PDBGF_OP, "rename: %s->%s\n", oldpath ? oldpath : "<nil>", @@ -32,10 +33,13 @@ /* as with unlink, we have to mark that the file may get deleted */ msg = pseudo_client_op(OP_MAY_UNLINK, 0, -1, -1, newpath, newrc ? NULL : &newbuf); if (msg && msg->result == RESULT_SUCCEED) + may_unlinked = 1; + msg = pseudo_client_op(OP_STAT, 0, -1, -1, oldpath, oldrc ? NULL : &oldbuf); + if (msg && msg->result == RESULT_SUCCEED) old_db_entry = 1; rc = real_rename(oldpath, newpath); save_errno = errno; - if (old_db_entry) { + if (may_unlinked) { if (rc == -1) { /* since we failed, that wasn't really unlinked -- put * it back. @@ -571,6 +571,9 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon found_ino = 1; /* note: we have to avoid freeing this later */ path_by_ino = msg->path; + if (msg->op == OP_LINK) { + pseudo_debug(PDBGF_FILE, "[matches existing link]"); + } } } @@ -589,9 +592,8 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon } /* search on original inode -- in case of mismatch */ if (msg->dev && msg->ino) { - if (!pdb_find_file_dev(&by_ino, &row)) { + if (!pdb_find_file_dev(&by_ino, &row, &path_by_ino)) { found_ino = 1; - path_by_ino = pdb_get_file_path(&by_ino); } } } @@ -820,8 +822,11 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon /* just in case find_file_path screwed up the msg */ msg->mode = msg_header.mode; } - /* if the path is not known, link it */ - if (!found_path) { + /* if we've never seen the file at all before, link it. + * If we have it in the db by inode, but not by name, + * it got fixed during the sanity checks. + */ + if (!found_path && !found_ino) { pseudo_debug(PDBGF_FILE, "(new) "); pdb_link_file(msg, NULL); } @@ -847,8 +852,12 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon msg->uid = msg_header.uid; msg->gid = msg_header.gid; } - /* if the path is not known, link it */ - if (!found_path) { + /* if we've never seen the file at all before, link it. + * If we have it in the db by inode, but not by name, + * it got fixed during the sanity checks. + */ + if (!found_path && !found_ino) { + pseudo_debug(PDBGF_FILE, "(new) "); pdb_link_file(msg, NULL); } break; diff --git a/pseudo_db.c b/pseudo_db.c index bbc71f0..f60f0ab 100644 --- a/pseudo_db.c +++ b/pseudo_db.c @@ -1401,7 +1401,7 @@ pdb_link_file(pseudo_msg_t *msg, long long *row) { sqlite3_bind_int(insert, 5, msg->gid); sqlite3_bind_int(insert, 6, msg->mode); sqlite3_bind_int(insert, 7, msg->rdev); - pseudo_debug(PDBGF_DB, "linking %s: dev %llu, ino %llu, mode %o, owner %d\n", + pseudo_debug(PDBGF_DB | PDBGF_FILE, "linking %s: dev %llu, ino %llu, mode %o, owner %d\n", (msg->pathlen ? msg->path : "<nil> (as NAMELESS FILE)"), (unsigned long long) msg->dev, (unsigned long long) msg->ino, (int) msg->mode, msg->uid); @@ -2113,7 +2113,7 @@ pdb_get_file_path(pseudo_msg_t *msg) { /* find file using dev/inode as key */ int -pdb_find_file_dev(pseudo_msg_t *msg, long long *row) { +pdb_find_file_dev(pseudo_msg_t *msg, long long *row, char **path) { static sqlite3_stmt *select; int rc; char *sql = "SELECT * FROM files WHERE dev = ? AND ino = ?;"; @@ -2145,6 +2145,12 @@ pdb_find_file_dev(pseudo_msg_t *msg, long long *row) { msg->mode = (unsigned long) sqlite3_column_int64(select, 6); msg->rdev = (unsigned long) sqlite3_column_int64(select, 7); msg->deleting = (int) sqlite3_column_int64(select, 8); + /* stash path */ + if (path) { + *path = strdup((char *) sqlite3_column_text(select, 1)); + pseudo_debug(PDBGF_FILE, "find_file_dev: path %s\n", + *path ? *path : "<nil>"); + } rc = 0; break; case SQLITE_DONE: diff --git a/pseudo_db.h b/pseudo_db.h index a8d9676..07c547b 100644 --- a/pseudo_db.h +++ b/pseudo_db.h @@ -53,7 +53,7 @@ extern int pdb_rename_file(const char *oldpath, pseudo_msg_t *msg); extern int pdb_renumber_all(dev_t from, dev_t to); extern int pdb_find_file_exact(pseudo_msg_t *msg, long long *row); extern int pdb_find_file_path(pseudo_msg_t *msg, long long *row); -extern int pdb_find_file_dev(pseudo_msg_t *msg, long long *row); +extern int pdb_find_file_dev(pseudo_msg_t *msg, long long *row, char **path); extern int pdb_find_file_ino(pseudo_msg_t *msg, long long *row); extern char *pdb_get_file_path(pseudo_msg_t *msg); extern int pdb_get_xattr(long long file_id, char **value, size_t *len); |