int sha1sum_file(char *fnam, unsigned char *digest) { char *buf; int ret; FILE *f; long flen; if (!fnam) return -1; process_lock(); f = fopen_cloexec(fnam, "r"); process_unlock(); if (f < 0) { SYSERROR("Error opening template"); return -1; } if (fseek(f, 0, SEEK_END) < 0) { SYSERROR("Error seeking to end of template"); lock_fclose(f); return -1; } if ((flen = ftell(f)) < 0) { SYSERROR("Error telling size of template"); lock_fclose(f); return -1; } if (fseek(f, 0, SEEK_SET) < 0) { SYSERROR("Error seeking to start of template"); lock_fclose(f); return -1; } if ((buf = malloc(flen+1)) == NULL) { SYSERROR("Out of memory"); lock_fclose(f); return -1; } if (fread(buf, 1, flen, f) != flen) { SYSERROR("Failure reading template"); free(buf); lock_fclose(f); return -1; } if (lock_fclose(f) < 0) { SYSERROR("Failre closing template"); free(buf); return -1; } buf[flen] = '\0'; ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, buf, flen, (void *)digest); free(buf); return ret; }
void Sender::createDataFile(char* apcDir) { if (apcDir == NULL) { return; } mDataFileName = (char*)malloc(strlen(apcDir) + 12); sprintf(mDataFileName, "%s/0000000000", apcDir); mDataFile = fopen_cloexec(mDataFileName, "wb"); if (!mDataFile) { logg->logError("Failed to open binary file: %s", mDataFileName); handleException(); } }
static bool collect_subsytems(void) { char *line = NULL, *tab1; size_t sz = 0, i; FILE *f; if (subsystems) // already initialized return true; f = fopen_cloexec("/proc/cgroups", "r"); if (!f) return false; while (getline(&line, &sz, f) != -1) { char **tmp; if (line[0] == '#') continue; if (!line[0]) continue; tab1 = strchr(line, '\t'); if (!tab1) continue; *tab1 = '\0'; tmp = realloc(subsystems, (nr_subsystems+1)*sizeof(char *)); if (!tmp) goto out_free; subsystems = tmp; tmp[nr_subsystems] = strdup(line); if (!tmp[nr_subsystems]) goto out_free; nr_subsystems++; } fclose(f); if (!nr_subsystems) { ERROR("No cgroup subsystems found"); return false; } return true; out_free: fclose(f); for (i = 0; i < nr_subsystems; i++) free(subsystems[i]); free(subsystems); subsystems = NULL; nr_subsystems = 0; return false; }
bool FtraceSource::prepare() { { struct sigaction act; act.sa_handler = handler; act.sa_flags = (int)SA_RESETHAND; if (sigaction(SIGUSR1, &act, NULL) != 0) { logg->logError("sigaction failed: %s\n", strerror(errno)); handleException(); } } gSessionData->ftraceDriver.prepare(); if (DriverSource::readIntDriver("/sys/kernel/debug/tracing/tracing_on", &mTracingOn)) { logg->logError("Unable to read if ftrace is enabled"); handleException(); } if (DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", "0") != 0) { logg->logError("Unable to turn ftrace off before truncating the buffer"); handleException(); } { int fd; fd = open("/sys/kernel/debug/tracing/trace", O_WRONLY | O_TRUNC | O_CLOEXEC, 0666); if (fd < 0) { logg->logError("Unable truncate ftrace buffer: %s", strerror(errno)); handleException(); } close(fd); } if (DriverSource::writeDriver("/sys/kernel/debug/tracing/trace_clock", "perf") != 0) { logg->logError("Unable to switch ftrace to the perf clock, please ensure you are running Linux 3.10 or later"); handleException(); } mFtraceFh = fopen_cloexec("/sys/kernel/debug/tracing/trace_pipe", "rb"); if (mFtraceFh == NULL) { logg->logError("Unable to open trace_pipe"); handleException(); } return true; }
static bool collect_subsytems(void) { char *line = NULL; nih_local char **cgm_subsys_list = NULL; size_t sz = 0; FILE *f = NULL; if (subsystems) // already initialized return true; subsystems_inone = malloc(2 * sizeof(char *)); if (!subsystems_inone) return false; subsystems_inone[0] = "all"; subsystems_inone[1] = NULL; if (lxc_list_controllers(&cgm_subsys_list)) { while (cgm_subsys_list[nr_subsystems]) { char **tmp = NIH_MUST( realloc(subsystems, (nr_subsystems+2)*sizeof(char *)) ); tmp[nr_subsystems] = NIH_MUST( strdup(cgm_subsys_list[nr_subsystems++]) ); subsystems = tmp; } if (nr_subsystems) subsystems[nr_subsystems] = NULL; goto collected; } INFO("cgmanager_list_controllers failed, falling back to /proc/self/cgroups"); f = fopen_cloexec("/proc/self/cgroup", "r"); if (!f) { f = fopen_cloexec("/proc/1/cgroup", "r"); if (!f) return false; } while (getline(&line, &sz, f) != -1) { /* file format: hierarchy:subsystems:group, * with multiple subsystems being ,-separated */ char *slist, *end, *p, *saveptr = NULL, **tmp; if (!line[0]) continue; slist = strchr(line, ':'); if (!slist) continue; slist++; end = strchr(slist, ':'); if (!end) continue; *end = '\0'; for (p = strtok_r(slist, ",", &saveptr); p; p = strtok_r(NULL, ",", &saveptr)) { tmp = realloc(subsystems, (nr_subsystems+2)*sizeof(char *)); if (!tmp) goto out_free; subsystems = tmp; tmp[nr_subsystems] = strdup(p); tmp[nr_subsystems+1] = NULL; if (!tmp[nr_subsystems]) goto out_free; nr_subsystems++; } } fclose(f); f = NULL; free(line); line = NULL; collected: if (!nr_subsystems) { ERROR("No cgroup subsystems found"); return false; } /* make sure that cgroup.use can be and is honored */ const char *cgroup_use = lxc_global_config_value("lxc.cgroup.use"); if (!cgroup_use && errno != 0) goto final_verify; if (cgroup_use) { if (!verify_and_prune(cgroup_use)) { free_subsystems(); return false; } subsystems_inone[0] = NIH_MUST( strdup(cgroup_use) ); cgm_all_controllers_same = false; } final_verify: return verify_final_subsystems(cgroup_use); out_free: free(line); if (f) fclose(f); free_subsystems(); return false; }
const char *lxc_global_config_value(const char *option_name) { static const char * const options[][2] = { { "lxc.bdev.lvm.vg", DEFAULT_VG }, { "lxc.bdev.lvm.thin_pool", DEFAULT_THIN_POOL }, { "lxc.bdev.zfs.root", DEFAULT_ZFSROOT }, { "lxc.lxcpath", NULL }, { "lxc.default_config", NULL }, { "lxc.cgroup.pattern", DEFAULT_CGROUP_PATTERN }, { "lxc.cgroup.use", NULL }, { NULL, NULL }, }; /* placed in the thread local storage pool for non-bionic targets */ #ifdef HAVE_TLS static __thread const char *values[sizeof(options) / sizeof(options[0])] = { 0 }; #else static const char *values[sizeof(options) / sizeof(options[0])] = { 0 }; #endif char *user_config_path = NULL; char *user_default_config_path = NULL; char *user_lxc_path = NULL; if (geteuid() > 0) { const char *user_home = getenv("HOME"); if (!user_home) user_home = "/"; user_config_path = malloc(sizeof(char) * (22 + strlen(user_home))); user_default_config_path = malloc(sizeof(char) * (26 + strlen(user_home))); user_lxc_path = malloc(sizeof(char) * (19 + strlen(user_home))); sprintf(user_config_path, "%s/.config/lxc/lxc.conf", user_home); sprintf(user_default_config_path, "%s/.config/lxc/default.conf", user_home); sprintf(user_lxc_path, "%s/.local/share/lxc/", user_home); } else { user_config_path = strdup(LXC_GLOBAL_CONF); user_default_config_path = strdup(LXC_DEFAULT_CONFIG); user_lxc_path = strdup(LXCPATH); } const char * const (*ptr)[2]; size_t i; char buf[1024], *p, *p2; FILE *fin = NULL; for (i = 0, ptr = options; (*ptr)[0]; ptr++, i++) { if (!strcmp(option_name, (*ptr)[0])) break; } if (!(*ptr)[0]) { free(user_config_path); free(user_default_config_path); free(user_lxc_path); errno = EINVAL; return NULL; } if (values[i]) { free(user_config_path); free(user_default_config_path); free(user_lxc_path); return values[i]; } fin = fopen_cloexec(user_config_path, "r"); free(user_config_path); if (fin) { while (fgets(buf, 1024, fin)) { if (buf[0] == '#') continue; p = strstr(buf, option_name); if (!p) continue; /* see if there was just white space in front * of the option name */ for (p2 = buf; p2 < p; p2++) { if (*p2 != ' ' && *p2 != '\t') break; } if (p2 < p) continue; p = strchr(p, '='); if (!p) continue; /* see if there was just white space after * the option name */ for (p2 += strlen(option_name); p2 < p; p2++) { if (*p2 != ' ' && *p2 != '\t') break; } if (p2 < p) continue; p++; while (*p && (*p == ' ' || *p == '\t')) p++; if (!*p) continue; free(user_default_config_path); if (strcmp(option_name, "lxc.lxcpath") == 0) { free(user_lxc_path); user_lxc_path = copy_global_config_value(p); remove_trailing_slashes(user_lxc_path); values[i] = user_lxc_path; goto out; } values[i] = copy_global_config_value(p); free(user_lxc_path); goto out; } } /* could not find value, use default */ if (strcmp(option_name, "lxc.lxcpath") == 0) { remove_trailing_slashes(user_lxc_path); values[i] = user_lxc_path; free(user_default_config_path); } else if (strcmp(option_name, "lxc.default_config") == 0) { values[i] = user_default_config_path; free(user_lxc_path); } else { free(user_default_config_path); free(user_lxc_path); values[i] = (*ptr)[1]; } /* special case: if default value is NULL, * and there is no config, don't view that * as an error... */ if (!values[i]) errno = 0; out: if (fin) fclose(fin); return values[i]; }
const char *lxc_global_config_value(const char *option_name) { static const char *options[][2] = { { "lvm_vg", DEFAULT_VG }, { "lvm_thin_pool", DEFAULT_THIN_POOL }, { "zfsroot", DEFAULT_ZFSROOT }, { "lxcpath", LXCPATH }, { "cgroup.pattern", DEFAULT_CGROUP_PATTERN }, { "cgroup.use", NULL }, { NULL, NULL }, }; /* Protected by a mutex to eliminate conflicting load and store operations */ static const char *values[sizeof(options) / sizeof(options[0])] = { 0 }; const char *(*ptr)[2]; const char *value; size_t i; char buf[1024], *p, *p2; FILE *fin = NULL; for (i = 0, ptr = options; (*ptr)[0]; ptr++, i++) { if (!strcmp(option_name, (*ptr)[0])) break; } if (!(*ptr)[0]) { errno = EINVAL; return NULL; } static_lock(); if (values[i]) { value = values[i]; static_unlock(); return value; } static_unlock(); process_lock(); fin = fopen_cloexec(LXC_GLOBAL_CONF, "r"); process_unlock(); if (fin) { while (fgets(buf, 1024, fin)) { if (buf[0] == '#') continue; p = strstr(buf, option_name); if (!p) continue; /* see if there was just white space in front * of the option name */ for (p2 = buf; p2 < p; p2++) { if (*p2 != ' ' && *p2 != '\t') break; } if (p2 < p) continue; p = strchr(p, '='); if (!p) continue; /* see if there was just white space after * the option name */ for (p2 += strlen(option_name); p2 < p; p2++) { if (*p2 != ' ' && *p2 != '\t') break; } if (p2 < p) continue; p++; while (*p && (*p == ' ' || *p == '\t')) p++; if (!*p) continue; static_lock(); values[i] = copy_global_config_value(p); static_unlock(); goto out; } } /* could not find value, use default */ static_lock(); values[i] = (*ptr)[1]; /* special case: if default value is NULL, * and there is no config, don't view that * as an error... */ if (!values[i]) errno = 0; static_unlock(); out: process_lock(); if (fin) fclose(fin); process_unlock(); static_lock(); value = values[i]; static_unlock(); return value; }
static bool collect_subsytems(void) { char *line = NULL; size_t sz = 0; FILE *f; if (subsystems) // already initialized return true; subsystems_inone = malloc(2 * sizeof(char *)); if (!subsystems_inone) return false; subsystems_inone[0] = "all"; subsystems_inone[1] = NULL; f = fopen_cloexec("/proc/self/cgroup", "r"); if (!f) { f = fopen_cloexec("/proc/1/cgroup", "r"); if (!f) return false; } while (getline(&line, &sz, f) != -1) { /* file format: hierarchy:subsystems:group, * with multiple subsystems being ,-separated */ char *slist, *end, *p, *saveptr = NULL, **tmp; if (!line[0]) continue; slist = strchr(line, ':'); if (!slist) continue; slist++; end = strchr(slist, ':'); if (!end) continue; *end = '\0'; for (p = strtok_r(slist, ",", &saveptr); p; p = strtok_r(NULL, ",", &saveptr)) { tmp = realloc(subsystems, (nr_subsystems+2)*sizeof(char *)); if (!tmp) goto out_free; subsystems = tmp; tmp[nr_subsystems] = strdup(p); tmp[nr_subsystems+1] = NULL; if (!tmp[nr_subsystems]) goto out_free; nr_subsystems++; } } fclose(f); free(line); if (!nr_subsystems) { ERROR("No cgroup subsystems found"); return false; } return true; out_free: free(line); fclose(f); free_subsystems(); return false; }
/* * Sets the process title to the specified title. Note: * 1. this function requires root to succeed * 2. it clears /proc/self/environ * 3. it may not succed (e.g. if title is longer than /proc/self/environ + * the original title) */ int setproctitle(char *title) { char buf[2048], *tmp; FILE *f; int i, len, ret = 0; unsigned long arg_start, arg_end, env_start, env_end; f = fopen_cloexec("/proc/self/stat", "r"); if (!f) { return -1; } tmp = fgets(buf, sizeof(buf), f); fclose(f); if (!tmp) { return -1; } /* Skip the first 47 fields, column 48-51 are ARG_START and * ARG_END. */ tmp = strchr(buf, ' '); for (i = 0; i < 46; i++) { if (!tmp) return -1; tmp = strchr(tmp+1, ' '); } if (!tmp) return -1; i = sscanf(tmp, "%lu %lu %lu %lu", &arg_start, &arg_end, &env_start, &env_end); if (i != 4) { return -1; } /* Include the null byte here, because in the calculations below we * want to have room for it. */ len = strlen(title) + 1; /* We're truncating the environment, so we should use at most the * length of the argument + environment for the title. */ if (len > env_end - arg_start) { arg_end = env_end; len = env_end - arg_start; } else { /* Only truncate the environment if we're actually going to * overwrite part of it. */ if (len >= arg_end - arg_start) { env_start = env_end; } arg_end = arg_start + len; /* check overflow */ if (arg_end < len || arg_end < arg_start) { return -1; } } strcpy((char*)arg_start, title); ret |= prctl(PR_SET_MM, PR_SET_MM_ARG_START, arg_start, 0, 0); ret |= prctl(PR_SET_MM, PR_SET_MM_ARG_END, arg_end, 0, 0); ret |= prctl(PR_SET_MM, PR_SET_MM_ENV_START, env_start, 0, 0); ret |= prctl(PR_SET_MM, PR_SET_MM_ENV_END, env_end, 0, 0); return ret; }
mxml_node_t *EventsXML::getTree() { #include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len char path[PATH_MAX]; mxml_node_t *xml = NULL; FILE *fl; // Avoid unused variable warning (void)events_xml_len; // Load the provided or default events xml if (gSessionData->mEventsXMLPath) { strncpy(path, gSessionData->mEventsXMLPath, PATH_MAX); fl = fopen_cloexec(path, "r"); if (fl) { xml = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); fclose(fl); } } if (xml == NULL) { logg->logMessage("Unable to locate events.xml, using default"); xml = mxmlLoadString(NULL, (const char *)events_xml, MXML_NO_CALLBACK); } // Append additional events XML if (gSessionData->mEventsXMLAppend) { fl = fopen_cloexec(gSessionData->mEventsXMLAppend, "r"); if (fl == NULL) { logg->logError("Unable to open additional events XML %s", gSessionData->mEventsXMLAppend); handleException(); } mxml_node_t *append = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); fclose(fl); mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND); if (!events) { logg->logError("Unable to find <events> node in the events.xml, please ensure the first two lines of events XML starts with:\n" "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<events>"); handleException(); } XMLList *categoryList = NULL; XMLList *eventList = NULL; { // Make list of all categories in xml mxml_node_t *node = xml; while (true) { node = mxmlFindElement(node, xml, "category", NULL, NULL, MXML_DESCEND); if (node == NULL) { break; } categoryList = new XMLList(categoryList, node); } // Make list of all events in xml node = xml; while (true) { node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND); if (node == NULL) { break; } eventList = new XMLList(eventList, node); } } // Handle events for (mxml_node_t *node = mxmlFindElement(append, append, "event", NULL, NULL, MXML_DESCEND), *next = mxmlFindElement(node, append, "event", NULL, NULL, MXML_DESCEND); node != NULL; node = next, next = mxmlFindElement(node, append, "event", NULL, NULL, MXML_DESCEND)) { const char *const category = mxmlElementGetAttr(mxmlGetParent(node), "name"); const char *const title = mxmlElementGetAttr(node, "title"); const char *const name = mxmlElementGetAttr(node, "name"); if (category == NULL || title == NULL || name == NULL) { logg->logError("Not all event XML nodes have the required title and name and parent name attributes"); handleException(); } // Replace any duplicate events for (XMLList *event = eventList; event != NULL; event = event->getPrev()) { const char *const category2 = mxmlElementGetAttr(mxmlGetParent(event->getNode()), "name"); const char *const title2 = mxmlElementGetAttr(event->getNode(), "title"); const char *const name2 = mxmlElementGetAttr(event->getNode(), "name"); if (category2 == NULL || title2 == NULL || name2 == NULL) { logg->logError("Not all event XML nodes have the required title and name and parent name attributes"); handleException(); } if (strcmp(category, category2) == 0 && strcmp(title, title2) == 0 && strcmp(name, name2) == 0) { logg->logMessage("Replacing counter %s %s: %s", category, title, name); mxml_node_t *parent = mxmlGetParent(event->getNode()); mxmlDelete(event->getNode()); mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node); event->setNode(node); break; } } } // Handle categories for (mxml_node_t *node = strcmp(mxmlGetElement(append), "category") == 0 ? append : mxmlFindElement(append, append, "category", NULL, NULL, MXML_DESCEND), *next = mxmlFindElement(node, append, "category", NULL, NULL, MXML_DESCEND); node != NULL; node = next, next = mxmlFindElement(node, append, "category", NULL, NULL, MXML_DESCEND)) { // After replacing duplicate events, a category may be empty if (mxmlGetFirstChild(node) == NULL) { continue; } const char *const name = mxmlElementGetAttr(node, "name"); if (name == NULL) { logg->logError("Not all event XML categories have the required name attribute"); handleException(); } // Merge identically named categories bool merged = false; for (XMLList *category = categoryList; category != NULL; category = category->getPrev()) { const char *const name2 = mxmlElementGetAttr(category->getNode(), "name"); if (name2 == NULL) { logg->logError("Not all event XML categories have the required name attribute"); handleException(); } if (strcmp(name, name2) == 0) { logg->logMessage("Merging category %s", name); while (true) { mxml_node_t *child = mxmlGetFirstChild(node); if (child == NULL) { break; } mxmlAdd(category->getNode(), MXML_ADD_AFTER, mxmlGetLastChild(category->getNode()), child); } merged = true; break; } } if (merged) { continue; } // Add new categories logg->logMessage("Appending category %s", name); mxmlAdd(events, MXML_ADD_AFTER, mxmlGetLastChild(events), node); } XMLList::free(eventList); XMLList::free(categoryList); mxmlDelete(append); } return xml; }