/* * qemuTPMEmulatorGetPid * * @swtpmStateDir: the directory where swtpm writes the pidfile into * @shortName: short name of the domain * @pid: pointer to pid * * Return -errno upon error, or zero on successful reading of the pidfile. * If the PID was not still alive, zero will be returned, and @pid will be * set to -1; */ static int qemuTPMEmulatorGetPid(const char *swtpmStateDir, const char *shortName, pid_t *pid) { int ret; char *pidfile = qemuTPMEmulatorCreatePidFilename(swtpmStateDir, shortName); if (!pidfile) return -ENOMEM; ret = virPidFileReadPathIfAlive(pidfile, pid, swtpm_path); VIR_FREE(pidfile); return ret; }
/** * virPidFileReadIfAlive: * @dir: directory containing pidfile * @name: base filename of pidfile * @pid: variable to return pid in * @binpath: path of executable associated with the pidfile * * This will attempt to read a pid from the pidfile @name * in directory @dir, and store it in @pid. The @pid will * only be set, however, if the pid in @name is running, * and its executable path resolves to @binpath. This adds * protection against recycling of previously reaped pids. * * Returns -errno upon error, or zero on successful * reading of the pidfile. If the PID was not still * alive, zero will be returned, but @pid will be * set to -1. */ int virPidFileReadIfAlive(const char *dir, const char *name, pid_t *pid, const char *binpath) { int rc = 0; char *pidfile = NULL; if (name == NULL || dir == NULL) { rc = -EINVAL; goto cleanup; } if (!(pidfile = virPidFileBuildPath(dir, name))) { rc = -ENOMEM; goto cleanup; } rc = virPidFileReadPathIfAlive(pidfile, pid, binpath); cleanup: VIR_FREE(pidfile); return rc; }
/** * Verify and create a lock file for a character device * * @dev Path of the character device * * Returns 0 on success, -1 on error */ static int virChrdevLockFileCreate(const char *dev) { char *path = NULL; int ret = -1; int lockfd = -1; char *pidStr = NULL; pid_t pid; /* build lock file path */ if (!(path = virChrdevLockFilePath(dev))) goto cleanup; /* check if a log file and process holding the lock still exists */ if (virPidFileReadPathIfAlive(path, &pid, NULL) == 0 && pid >= 0) { /* the process exists, the lockfile is valid */ virReportError(VIR_ERR_OPERATION_FAILED, _("Requested device '%s' is locked by " "lock file '%s' held by process %lld"), dev, path, (long long) pid); goto cleanup; } else { /* clean up the stale/corrupted/nonexistent lockfile */ unlink(path); } /* lockfile doesn't (shouldn't) exist */ /* ensure correct format according to filesystem hierarchy standard */ /* http://www.pathname.com/fhs/pub/fhs-2.3.html#VARLOCKLOCKFILES */ if (virAsprintf(&pidStr, "%10lld\n", (long long) getpid()) < 0) goto cleanup; /* create the lock file */ if ((lockfd = open(path, O_WRONLY | O_CREAT | O_EXCL, 00644)) < 0) { /* If we run in session mode, we might have no access to the lock * file directory. We have to check for an permission denied error * and see if we can reach it. This should cause an error only if * we run in daemon mode and thus privileged. */ if (errno == EACCES && geteuid() != 0) { VIR_DEBUG("Skipping lock file creation for device '%s in path '%s'.", dev, path); ret = 0; goto cleanup; } virReportSystemError(errno, _("Couldn't create lock file for " "device '%s' in path '%s'"), dev, path); goto cleanup; } /* write the pid to the file */ if (safewrite(lockfd, pidStr, strlen(pidStr)) < 0) { virReportSystemError(errno, _("Couldn't write to lock file for " "device '%s' in path '%s'"), dev, path); VIR_FORCE_CLOSE(lockfd); unlink(path); goto cleanup; } /* we hold the lock */ ret = 0; cleanup: VIR_FORCE_CLOSE(lockfd); VIR_FREE(path); VIR_FREE(pidStr); return ret; }