diff options
Diffstat (limited to 'pseudo.c')
-rw-r--r-- | pseudo.c | 71 |
1 files changed, 43 insertions, 28 deletions
@@ -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). |