static bool cgm_bind_dir(const char *root, const char *dirname) { nih_local char *cgpath = NULL; /* /sys should have been mounted by now */ cgpath = NIH_MUST( nih_strdup(NULL, root) ); NIH_MUST( nih_strcat(&cgpath, NULL, "/sys/fs/cgroup") ); if (!dir_exists(cgpath)) { ERROR("%s does not exist", cgpath); return false; } /* mount a tmpfs there so we can create subdirs */ if (mount("cgroup", cgpath, "tmpfs", 0, "size=10000,mode=755")) { SYSERROR("Failed to mount tmpfs at %s", cgpath); return false; } NIH_MUST( nih_strcat(&cgpath, NULL, "/cgmanager") ); if (mkdir(cgpath, 0755) < 0) { SYSERROR("Failed to create %s", cgpath); return false; } if (mount(dirname, cgpath, "none", MS_BIND, 0)) { SYSERROR("Failed to bind mount %s to %s", dirname, cgpath); return false; } return true; }
int remove_on_empty_main(const char *controller, const char *cgroup, struct ucred p, struct ucred r) { char rcgpath[MAXPATHLEN]; size_t cgroup_len; nih_local char *working = NULL, *wcgroup = NULL; if (!sane_cgroup(cgroup)) { nih_error("%s: unsafe cgroup", __func__); return -1; } // Get r's current cgroup in rcgpath if (!compute_pid_cgroup(r.pid, controller, "", rcgpath, NULL)) { nih_error("%s: Could not determine the requested cgroup", __func__); return -1; } cgroup_len = strlen(cgroup); if (strlen(rcgpath) + cgroup_len > MAXPATHLEN) { nih_error("%s: Path name too long", __func__); return -1; } wcgroup = NIH_MUST( nih_strdup(NULL, cgroup) ); if (!normalize_path(wcgroup)) return -1; working = NIH_MUST( nih_strdup(NULL, rcgpath) ); NIH_MUST( nih_strcat(&working, NULL, "/") ); NIH_MUST( nih_strcat(&working, NULL, wcgroup) ); if (!dir_exists(working)) { return -1; } // must have write access if (!may_access(r.pid, r.uid, r.gid, working, O_WRONLY)) { nih_error("%s: pid %d (%u:%u) may not remove %s", __func__, r.pid, r.uid, r.gid, working); return -1; } NIH_MUST( nih_strcat(&working, NULL, "/notify_on_release") ); if (!set_value_trusted(working, "1\n")) { nih_error("Failed to set remove_on_empty for %s:%s", controller, working); return -1; } return 0; }
/** * type_var_to_string: * @parent: parent object for new string, * @var: variable to convert. * * Returns a string for the given variable @var, consisting of the type * and variable name separated by a space if appropriate. * * If @parent is not NULL, it should be a pointer to another object which * will be used as a parent for the returned string. When all parents * of the returned string are freed, the returned string will also be * freed. * * Returns: the newly allocated string or NULL if insufficient memory. **/ char * type_var_to_string (const void *parent, TypeVar * var) { char *str; nih_assert (var != NULL); if (strchr (var->type, '*')) { str = nih_sprintf (parent, "%s%s", var->type, var->name); } else { str = nih_sprintf (parent, "%s %s", var->type, var->name); } if (! str) return NULL; if (var->array) { if (! nih_strcat (&str, parent, "[]")) { nih_free (str); return NULL; } } return str; }
int remove_main(const char *controller, const char *cgroup, struct ucred p, struct ucred r, int recursive, int32_t *existed) { char rcgpath[MAXPATHLEN]; size_t cgroup_len; nih_local char *working = NULL, *copy = NULL, *wcgroup = NULL; char *p1; *existed = 1; if (!sane_cgroup(cgroup)) { nih_error("%s: unsafe cgroup", __func__); return -1; } // Get r's current cgroup in rcgpath if (!compute_pid_cgroup(r.pid, controller, "", rcgpath, NULL)) { nih_error("%s: Could not determine the requested cgroup", __func__); return -1; } cgroup_len = strlen(cgroup); if (strlen(rcgpath) + cgroup_len > MAXPATHLEN) { nih_error("%s: Path name too long", __func__); return -1; } wcgroup = NIH_MUST( nih_strdup(NULL, cgroup) ); if (!normalize_path(wcgroup)) return -1; working = NIH_MUST( nih_strdup(NULL, rcgpath) ); NIH_MUST( nih_strcat(&working, NULL, "/") ); NIH_MUST( nih_strcat(&working, NULL, wcgroup) ); if (!dir_exists(working)) { *existed = -1; return 0; } // must have write access to the parent dir copy = NIH_MUST( nih_strdup(NULL, working) ); if (!(p1 = strrchr(copy, '/'))) return -1; *p1 = '\0'; if (!may_access(r.pid, r.uid, r.gid, copy, O_WRONLY)) { nih_error("%s: pid %d (%u:%u) may not remove %s", __func__, r.pid, r.uid, r.gid, copy); return -1; } if (!recursive) { if (rmdir(working) < 0) { nih_error("%s: Failed to remove %s: %s", __func__, working, strerror(errno)); return -1; } } else if (recursive_rmdir(working) < 0) return -1; nih_info(_("Removed %s for %d (%u:%u)"), working, r.pid, r.uid, r.gid); return 0; }
void test_strcat (void) { char *str, *ret; TEST_FUNCTION ("nih_strcat"); /* Check that we can extend a string with another, resulting in the * original string being modified and the new pointer stored in the * argument and returned. */ TEST_FEATURE ("with string"); TEST_ALLOC_FAIL { char *tmp; TEST_ALLOC_SAFE { str = nih_strdup (NULL, "this is a test"); } tmp = str; ret = nih_strcat (&str, NULL, " of strdup"); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_EQ_P (str, tmp); TEST_EQ_STR (str, "this is a test"); nih_free (str); continue; } TEST_NE (ret, NULL); TEST_EQ_P (ret, str); TEST_ALLOC_SIZE (str, 25); TEST_EQ_STR (str, "this is a test of strdup"); nih_free (str); } /* Check that when no string is passed, this behaves as strdup. */ TEST_FEATURE ("with NULL"); TEST_ALLOC_FAIL { str = NULL; ret = nih_strcat (&str, NULL, "test of strdup"); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_EQ_P (str, NULL); continue; } TEST_NE (ret, NULL); TEST_EQ_P (ret, str); TEST_ALLOC_SIZE (str, 15); TEST_EQ_STR (str, "test of strdup"); nih_free (str); } }