/* Install ".<filename>.hmac" file for FIPS self-checks */ static int hmac_install(const char *src, const char *dst, const char *hmacpath) { _cleanup_free_ char *srcpath = strdup(src); _cleanup_free_ char *dstpath = strdup(dst); _cleanup_free_ char *srchmacname = NULL; _cleanup_free_ char *dsthmacname = NULL; int ret; if (!(srcpath && dstpath)) return -ENOMEM; size_t dlen = dir_len(src); if (endswith(src, ".hmac")) return 0; if (!hmacpath) { hmac_install(src, dst, "/lib/fipscheck"); hmac_install(src, dst, "/lib64/fipscheck"); hmac_install(src, dst, "/lib/hmaccalc"); hmac_install(src, dst, "/lib64/hmaccalc"); } srcpath[dlen] = '\0'; dstpath[dir_len(dst)] = '\0'; if (hmacpath) { ret = asprintf(&srchmacname, "%s/%s.hmac", hmacpath, &src[dlen + 1]); if (ret < 0) { log_error("Out of memory!"); exit(EXIT_FAILURE); } ret = asprintf(&dsthmacname, "%s/%s.hmac", hmacpath, &src[dlen + 1]); if (ret < 0) { log_error("Out of memory!"); exit(EXIT_FAILURE); } } else { ret = asprintf(&srchmacname, "%s/.%s.hmac", srcpath, &src[dlen + 1]); if (ret < 0) { log_error("Out of memory!"); exit(EXIT_FAILURE); } ret = asprintf(&dsthmacname, "%s/.%s.hmac", dstpath, &src[dlen + 1]); if (ret < 0) { log_error("Out of memory!"); exit(EXIT_FAILURE); } } log_debug("hmac cp '%s' '%s')", srchmacname, dsthmacname); dracut_install(srchmacname, dsthmacname, false, false, true); return 0; }
char * dir_name (char const *file) { size_t length = dir_len (file); bool append_dot = (length == FILE_SYSTEM_PREFIX_LEN (file)); char *dir = xmalloc (length + append_dot + 1); memcpy (dir, file, length); if (append_dot) dir[length++] = '.'; dir[length] = 0; return dir; }
char * dir_name (char const *file) { size_t length = dir_len (file); bool append_dot = (length == 0 || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && length == FILE_SYSTEM_PREFIX_LEN (file) && file[2] != '\0' && ! ISSLASH (file[2]))); char *dir = xmalloc (length + append_dot + 1); memcpy (dir, file, length); if (append_dot) dir[length++] = '.'; dir[length] = '\0'; return dir; }
/** * Return an absolute path corresponding to PATH, which is absolute or relative * to the directory containing BASE_FILE, or NULL on error */ static char * absolutePathFromBaseFile(const char *base_file, const char *path) { char *res; size_t d_len = dir_len (base_file); /* If path is already absolute, or if dirname(base_file) is ".", just return a copy of path. */ if (*path == '/' || d_len == 0) return strdup(path); /* Ensure that the following cast-to-int is valid. */ if (d_len > INT_MAX) return NULL; virAsprintf(&res, "%.*s/%s", (int) d_len, base_file, path); return res; }
static int parent_dir_changed(struct archive_string *dir, struct archive_entry *entry) { const char *path; size_t l; l = dir_len(entry); path = tk_archive_entry_pathname(entry); if (tk_archive_strlen(dir) > 0) { if (l == 0) { tk_archive_string_empty(dir); return (1); } if (strncmp(dir->s, path, l) == 0) return (0); /* The parent directory is the same. */ } else if (l == 0) return (0); /* The parent directory is the same. */ tk_archive_strncpy(dir, path, l); return (1); }
static char *convert_abs_rel(const char *from, const char *target) { /* we use the 4*MAXPATHLEN, which should not overrun */ char relative_from[MAXPATHLEN * 4]; _cleanup_free_ char *realtarget = NULL; _cleanup_free_ char *target_dir_p = NULL, *realpath_p = NULL; const char *realfrom = from; size_t level = 0, fromlevel = 0, targetlevel = 0; int l; size_t i, rl, dirlen; int ret; target_dir_p = strdup(target); if (!target_dir_p) return strdup(from); dirlen = dir_len(target_dir_p); target_dir_p[dirlen] = '\0'; realpath_p = realpath(target_dir_p, NULL); if (realpath_p == NULL) { log_warning("convert_abs_rel(): target '%s' directory has no realpath.", target); return strdup(from); } /* dir_len() skips double /'s e.g. //lib64, so we can't skip just one * character - need to skip all leading /'s */ rl = strlen(target); for (i = dirlen + 1; i < rl; ++i) if (target_dir_p[i] != '/') break; ret = asprintf(&realtarget, "%s/%s", realpath_p, &target_dir_p[i]); if (ret < 0) { log_error("Out of memory!"); exit(EXIT_FAILURE); } /* now calculate the relative path from <from> to <target> and store it in <relative_from> */ relative_from[0] = 0; rl = 0; /* count the pathname elements of realtarget */ for (targetlevel = 0, i = 0; realtarget[i]; i++) if (realtarget[i] == '/') targetlevel++; /* count the pathname elements of realfrom */ for (fromlevel = 0, i = 0; realfrom[i]; i++) if (realfrom[i] == '/') fromlevel++; /* count the pathname elements, which are common for both paths */ for (level = 0, i = 0; realtarget[i] && (realtarget[i] == realfrom[i]); i++) if (realtarget[i] == '/') level++; /* add "../" to the relative_from path, until the common pathname is reached */ for (i = level; i < targetlevel; i++) { if (i != level) relative_from[rl++] = '/'; relative_from[rl++] = '.'; relative_from[rl++] = '.'; } /* set l to the next uncommon pathname element in realfrom */ for (l = 1, i = 1; i < level; i++) for (l++; realfrom[l] && realfrom[l] != '/'; l++) ; /* skip next '/' */ l++; /* append the uncommon rest of realfrom to the relative_from path */ for (i = level; i <= fromlevel; i++) { if (rl) relative_from[rl++] = '/'; while (realfrom[l] && realfrom[l] != '/') relative_from[rl++] = realfrom[l++]; l++; } relative_from[rl] = 0; return strdup(relative_from); }
static int dracut_install(const char *src, const char *dst, bool isdir, bool resolvedeps, bool hashdst) { struct stat sb, db; _cleanup_free_ char *fulldstpath = NULL; _cleanup_free_ char *fulldstdir = NULL; int ret; bool src_exists = true; char *i = NULL; char *existing; log_debug("dracut_install('%s', '%s')", src, dst); existing = hashmap_get(items_failed, src); if (existing) { if (strcmp(existing, src) == 0) { log_debug("hash hit items_failed for '%s'", src); return 1; } } if (hashdst) { existing = hashmap_get(items, dst); if (existing) { if (strcmp(existing, dst) == 0) { log_debug("hash hit items for '%s'", dst); return 0; } } } if (lstat(src, &sb) < 0) { src_exists = false; if (!isdir) { i = strdup(src); hashmap_put(items_failed, i, i); /* src does not exist */ return 1; } } i = strdup(dst); if (!i) return -ENOMEM; hashmap_put(items, i, i); ret = asprintf(&fulldstpath, "%s%s", destrootdir, dst); if (ret < 0) { log_error("Out of memory!"); exit(EXIT_FAILURE); } ret = stat(fulldstpath, &sb); if (ret != 0 && (errno != ENOENT)) { log_error("ERROR: stat '%s': %m", fulldstpath); return 1; } if (ret == 0) { if (resolvedeps && S_ISREG(sb.st_mode) && (sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { log_debug("'%s' already exists, but checking for any deps", fulldstpath); ret = resolve_deps(src); } else log_debug("'%s' already exists", fulldstpath); /* dst does already exist */ return ret; } /* check destination directory */ fulldstdir = strdup(fulldstpath); fulldstdir[dir_len(fulldstdir)] = '\0'; ret = stat(fulldstdir, &db); if (ret < 0) { _cleanup_free_ char *dname = NULL; if (errno != ENOENT) { log_error("ERROR: stat '%s': %m", fulldstdir); return 1; } /* create destination directory */ log_debug("dest dir '%s' does not exist", fulldstdir); dname = strdup(dst); if (!dname) return 1; dname[dir_len(dname)] = '\0'; ret = dracut_install(dname, dname, true, false, true); if (ret != 0) { log_error("ERROR: failed to create directory '%s'", fulldstdir); return 1; } } if (isdir && !src_exists) { log_info("mkdir '%s'", fulldstpath); ret = mkdir(fulldstpath, 0755); return ret; } /* ready to install src */ if (S_ISDIR(sb.st_mode)) { log_info("mkdir '%s'", fulldstpath); ret = mkdir(fulldstpath, sb.st_mode | S_IWUSR); return ret; } if (S_ISLNK(sb.st_mode)) { _cleanup_free_ char *abspath = NULL; abspath = realpath(src, NULL); if (abspath == NULL) return 1; if (dracut_install(abspath, abspath, false, resolvedeps, hashdst)) { log_debug("'%s' install error", abspath); return 1; } if (lstat(abspath, &sb) != 0) { log_debug("lstat '%s': %m", abspath); return 1; } if (lstat(fulldstpath, &sb) != 0) { _cleanup_free_ char *absdestpath = NULL; ret = asprintf(&absdestpath, "%s%s", destrootdir, abspath); if (ret < 0) { log_error("Out of memory!"); exit(EXIT_FAILURE); } ln_r(absdestpath, fulldstpath); } if (arg_hmac) { /* copy .hmac files also */ hmac_install(src, dst, NULL); } return 0; } if (sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { if (resolvedeps) ret += resolve_deps(src); if (arg_hmac) { /* copy .hmac files also */ hmac_install(src, dst, NULL); } } log_debug("dracut_install ret = %d", ret); log_info("cp '%s' '%s'", src, fulldstpath); if (arg_hostonly) mark_hostonly(dst); ret += cp(src, fulldstpath); if (ret == 0 && logfile_f) dracut_log_cp(src); log_debug("dracut_install ret = %d", ret); return ret; }
int main (void) { struct test *t; bool ok = true; for (t = tests; t->name; t++) { char *dir = dir_name (t->name); int dirlen = dir_len (t->name); char *last = last_component (t->name); char *base = base_name (t->name); int baselen = base_len (base); char *stripped = strdup (t->name); bool modified = strip_trailing_slashes (stripped); bool absolute = IS_ABSOLUTE_FILE_NAME (t->name); if (! (strcmp (dir, t->dir) == 0 && (dirlen == strlen (dir) || (dirlen + 1 == strlen (dir) && dir[dirlen] == '.')))) { ok = false; printf ("dir_name '%s': got '%s' len %d," " expected '%s' len %ld\n", t->name, dir, dirlen, t->dir, (unsigned long) strlen (t->dir)); } if (strcmp (last, t->last)) { ok = false; printf ("last_component '%s': got '%s', expected '%s'\n", t->name, last, t->last); } if (! (strcmp (base, t->base) == 0 && (baselen == strlen (base) || (baselen + 1 == strlen (base) && ISSLASH (base[baselen]))))) { ok = false; printf ("base_name '%s': got '%s' len %d," " expected '%s' len %ld\n", t->name, base, baselen, t->base, (unsigned long) strlen (t->base)); } if (strcmp (stripped, t->stripped) || modified != t->modified) { ok = false; printf ("strip_trailing_slashes '%s': got %s %s, expected %s %s\n", t->name, stripped, modified ? "changed" : "unchanged", t->stripped, t->modified ? "changed" : "unchanged"); } if (t->absolute != absolute) { ok = false; printf ("'%s': got %s, expected %s\n", t->name, absolute ? "absolute" : "relative", t->absolute ? "absolute" : "relative"); } free (dir); free (base); free (stripped); } return ok ? 0 : 1; }