aboutsummaryrefslogtreecommitdiffstats
path: root/pseudo.c
diff options
context:
space:
mode:
Diffstat (limited to 'pseudo.c')
-rw-r--r--pseudo.c71
1 files changed, 43 insertions, 28 deletions
diff --git a/pseudo.c b/pseudo.c
index ef91407..e98e5d6 100644
--- a/pseudo.c
+++ b/pseudo.c
@@ -3,18 +3,7 @@
*
* Copyright (c) 2008-2013 Wind River Systems, Inc.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * SPDX-License-Identifier: LGPL-2.1-only
*
*/
#include <stdlib.h>
@@ -256,10 +245,12 @@ main(int argc, char *argv[]) {
/* Options are processed, preserve them... */
pseudo_set_value("PSEUDO_OPTS", opts);
- if (!pseudo_get_prefix(argv[0])) {
+ s = pseudo_get_prefix(argv[0]);
+ if (!s) {
pseudo_diag("Can't figure out prefix. Set PSEUDO_PREFIX or invoke with full path.\n");
exit(PSEUDO_EXIT_PSEUDO_PREFIX);
}
+ free(s);
/* move database */
if (opt_m || opt_M) {
@@ -691,31 +682,30 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon
}
break;
default:
- if (strcmp(msg->path, path_by_ino)) {
+ /* Ignore NAMELESS FILE entries since those could be created by other threads on new files */
+ if (strcmp(msg->path, path_by_ino) && strcmp(path_by_ino, "NAMELESS FILE")) {
mismatch = 1;
}
break;
}
if (mismatch) {
- /* a mismatch, but we were planning to delete
- * the file, so it must have gotten deleted
- * already.
- */
if (by_ino.deleting != 0) {
- pseudo_debug(PDBGF_FILE, "inode mismatch for '%s' -- old one was marked for deletion, deleting.\n",
+ /* a mismatch, likely a race but we were planning to
+ * delete the file, or are in the middle of a rename
+ * so continue, need the old entry for a rename.
+ */
+ pseudo_debug(PDBGF_FILE, "inode mismatch for '%s' -- old one was marked for deletion.\n",
msg->path);
- pdb_did_unlink_file(path_by_ino, &by_ino, by_ino.deleting);
} else {
- int flags = 0;
- if (msg->nlink > 1) {
- flags = PDBGF_FILE | PDBGF_VERBOSE;
- }
- pseudo_debug(flags, "path mismatch [%d link%s]: ino %llu db '%s' req '%s'.\n",
+ pseudo_diag("path mismatch [%d link%s]: ino %llu db '%s' req '%s'.\n",
msg->nlink,
msg->nlink == 1 ? "" : "s",
(unsigned long long) msg_header.ino,
path_by_ino ? path_by_ino : "no path",
msg->path);
+ found_ino = 0;
+ msg->result = RESULT_ABORT;
+ goto op_exit;
}
}
} else {
@@ -1035,6 +1025,24 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon
break;
}
+ switch (msg->op) {
+ case OP_FCHOWN: /* FALLTHROUGH */
+ case OP_FCHMOD: /* FALLTHROUGH */
+ case OP_FSTAT:
+ if (!found_path && !found_ino && (msg->nlink == 0)) {
+ /* If nlink is 0 for an fchown/fchmod/fstat, we probably have an fd which is
+ * unlinked and we don't want to do inode/path matching against it. Marking it
+ * as may unlink gives the right hints in the database to ensure we
+ * handle correctly whilst maintaining the permissions whilst the
+ * file exists for the fd. */
+ pdb_may_unlink_file(msg, msg->client);
+ }
+ break;
+ default:
+ break;
+ }
+
+op_exit:
/* in the case of an exact match, we just used the pointer
* rather than allocating space.
*/
@@ -1098,9 +1106,15 @@ pseudo_db_check(int fix) {
int fixup_needed = 0;
pseudo_debug(PDBGF_DB, "Checking <%s>\n", m->path);
if (lstat(m->path, &buf)) {
- errors = EXIT_FAILURE;
- pseudo_diag("can't stat <%s>\n", m->path);
- continue;
+ if (!fix) {
+ pseudo_diag("can't stat <%s>\n", m->path);
+ errors = EXIT_FAILURE;
+ continue;
+ } else {
+ pseudo_debug(PDBGF_DB, "can't stat <%s>\n", m->path);
+ fixup_needed = 2;
+ goto do_fixup;
+ }
}
/* can't check for device type mismatches, uid/gid, or
* permissions, because those are the very things we
@@ -1136,6 +1150,7 @@ pseudo_db_check(int fix) {
S_ISDIR(m->mode));
fixup_needed = 2;
}
+ do_fixup:
if (fixup_needed) {
/* in fixup mode, either delete (mismatches) or
* correct (dev/ino).