static int vmwareUpdateVMStatus(struct vmware_driver *driver, virDomainObjPtr vm) { virCommandPtr cmd; char *outbuf = NULL; char *vmxAbsolutePath = NULL; char *parsedVmxPath = NULL; char *str; char *saveptr = NULL; bool found = false; int oldState = virDomainObjGetState(vm, NULL); int newState; int ret = -1; cmd = virCommandNewArgList(VMRUN, "-T", vmw_types[driver->type], "list", NULL); virCommandSetOutputBuffer(cmd, &outbuf); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if (virFileResolveAllLinks(((vmwareDomainPtr) vm->privateData)->vmxPath, &vmxAbsolutePath) < 0) goto cleanup; for (str = outbuf ; (parsedVmxPath = strtok_r(str, "\n", &saveptr)) != NULL; str = NULL) { if (parsedVmxPath[0] != '/') continue; if (STREQ(parsedVmxPath, vmxAbsolutePath)) { found = true; /* If the vmx path is in the output, the domain is running or * is paused but we have no way to detect if it is paused or not. */ if (oldState == VIR_DOMAIN_PAUSED) newState = oldState; else newState = VIR_DOMAIN_RUNNING; break; } } if (!found) { vm->def->id = -1; newState = VIR_DOMAIN_SHUTOFF; } virDomainObjSetState(vm, newState, 0); ret = 0; cleanup: virCommandFree(cmd); VIR_FREE(outbuf); VIR_FREE(vmxAbsolutePath); return ret; }
/** * virPidFileReadPathIfAlive: * @path: path to pidfile * @pid: variable to return pid in * @binpath: path of executable associated with the pidfile * * This will attempt to read a pid from @path, and store it * in @pid. The @pid will only be set, however, if the * pid in @path is running, and its executable path * resolves to @binpath. This adds protection against * recycling of previously reaped pids. * * If @binpath is NULL the check for the executable path * is skipped. * * 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 virPidFileReadPathIfAlive(const char *path, pid_t *pid, const char *binPath) { int ret; bool isLink; char *procPath = NULL; char *procLink = NULL; size_t procLinkLen; char *resolvedBinPath = NULL; char *resolvedProcLink = NULL; const char deletedText[] = " (deleted)"; size_t deletedTextLen = strlen(deletedText); pid_t retPid; /* only set this at the very end on success */ *pid = -1; if ((ret = virPidFileReadPath(path, &retPid)) < 0) goto cleanup; #ifndef WIN32 /* Check that it's still alive. Safe to skip this sanity check on * mingw, which lacks kill(). */ if (kill(retPid, 0) < 0) { ret = 0; retPid = -1; goto cleanup; } #endif if (!binPath) { /* we only knew the pid, and that pid is alive, so we can * return it. */ ret = 0; goto cleanup; } if (virAsprintf(&procPath, "/proc/%lld/exe", (long long)retPid) < 0) { ret = -ENOMEM; goto cleanup; } if ((ret = virFileIsLink(procPath)) < 0) goto cleanup; isLink = ret; if (isLink && virFileLinkPointsTo(procPath, binPath)) { /* the link in /proc/$pid/exe is a symlink to a file * that has the same inode as the file at binpath. */ ret = 0; goto cleanup; } /* Even if virFileLinkPointsTo returns a mismatch, it could be * that the binary was deleted/replaced after it was executed. In * that case the link in /proc/$pid/exe will contain * "$procpath (deleted)". Read that link, remove the " (deleted)" * part, and see if it has the same canonicalized name as binpath. */ if (!(procLink = areadlink(procPath))) { ret = -errno; goto cleanup; } procLinkLen = strlen(procLink); if (procLinkLen > deletedTextLen) procLink[procLinkLen - deletedTextLen] = 0; if ((ret = virFileResolveAllLinks(binPath, &resolvedBinPath)) < 0) goto cleanup; if ((ret = virFileResolveAllLinks(procLink, &resolvedProcLink)) < 0) goto cleanup; ret = STREQ(resolvedBinPath, resolvedProcLink) ? 0 : -1; cleanup: VIR_FREE(procPath); VIR_FREE(procLink); VIR_FREE(resolvedProcLink); VIR_FREE(resolvedBinPath); /* return the originally set pid of -1 unless we proclaim success */ if (ret == 0) *pid = retPid; return ret; }