diff options
author | 2018-03-01 10:56:31 -0600 | |
---|---|---|
committer | 2018-03-01 10:56:31 -0600 | |
commit | dfc21be28185956f61bd904022312f781cbe1572 (patch) | |
tree | 2fed9ea774115882502ee73937ae45cf99b8daae | |
parent | d7c31a25e4b02af0c64e6be0b4b0a9ac4ffc9da2 (diff) | |
download | pseudo-dfc21be28185956f61bd904022312f781cbe1572.tar.gz pseudo-dfc21be28185956f61bd904022312f781cbe1572.tar.bz2 pseudo-dfc21be28185956f61bd904022312f781cbe1572.zip |
Don't delete things and not create them.
When OP_CREAT comes in, if there's an existing entry with the
same inode, we nuke that entry because CREAT implies a new file
got that inode, and if there's an existing entry with the same
path, we don't create a link, because there's already something
there.
So if there's a single entry with the same path and inode, it
gets deleted and not recreated. Oops.
Now distinguishing between a single exact match of both path
and inode, and distinct matches by path and by inode.
This addresses a use case where parallel creations could
in theory cause pseudo to mistakenly drop database entries,
potentially. (I could only trigger it by doing this to files
which had existing entries, and then deleting the files outside
of pseudo, though.)
Signed-off-by: seebs <seebs@seebs.net>
-rw-r--r-- | ChangeLog.txt | 6 | ||||
-rw-r--r-- | pseudo.c | 7 |
2 files changed, 11 insertions, 2 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt index 169e707..e0783fb 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,9 @@ +2018-03-01: + * (seebs) If you get a CREAT for an existing file, and it matches + both path and inode, don't delete the entry because the inode + matched and then not create it because the path used to match + before you delete it. + 2018-02-26: * (seebs) implement mkstemps, mkostemp, and mkostemps. Actually, move implementation all to mkostemps, then implement the others @@ -444,7 +444,7 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon char *path_by_ino = 0; char *oldpath = 0; size_t oldpathlen = 0; - int found_path = 0, found_ino = 0; + int found_path = 0, found_ino = 0, found_exact = 0; int prefer_ino = 0; int xattr_flags = 0; int trailing_slash = 0; @@ -543,6 +543,7 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon *msg = msg_header; found_path = 1; found_ino = 1; + found_exact = 1; /* note: we have to avoid freeing this later */ path_by_ino = msg->path; if (msg->op == OP_LINK) { @@ -768,9 +769,11 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon break; case OP_CREAT: /* implies a new file -- not a link, which would be OP_LINK */ - if (found_ino) { + if (found_ino && !found_exact) { /* CREAT should never be sent if the file existed. * So, any existing entry is an error. Nuke it. + * ... But only if it wasn't a match on both inode *and* + * path, because if it were, that would be harmless. */ pseudo_diag("creat for '%s' replaces existing %llu ['%s'].\n", msg->pathlen ? msg->path : "no path", |