diff options
Diffstat (limited to 'updater/install.cpp')
-rw-r--r-- | updater/install.cpp | 81 |
1 files changed, 43 insertions, 38 deletions
diff --git a/updater/install.cpp b/updater/install.cpp index ed55ea517..59c54dd4c 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -95,25 +95,33 @@ void uiPrintf(State* _Nonnull state, const char* _Nonnull format, ...) { uiPrint(state, error_msg); } +static bool is_dir(const std::string& dirpath) { + struct stat st; + return stat(dirpath.c_str(), &st) == 0 && S_ISDIR(st.st_mode); +} + // Create all parent directories of name, if necessary. -static int make_parents(char* name) { - char* p; - for (p = name + (strlen(name)-1); p > name; --p) { - if (*p != '/') continue; - *p = '\0'; - if (make_parents(name) < 0) return -1; - int result = mkdir(name, 0700); - if (result == 0) printf("created [%s]\n", name); - *p = '/'; - if (result == 0 || errno == EEXIST) { - // successfully created or already existed; we're done - return 0; - } else { - printf("failed to mkdir %s: %s\n", name, strerror(errno)); - return -1; +static bool make_parents(const std::string& name) { + size_t prev_end = 0; + while (prev_end < name.size()) { + size_t next_end = name.find('/', prev_end + 1); + if (next_end == std::string::npos) { + break; + } + std::string dir_path = name.substr(0, next_end); + if (!is_dir(dir_path)) { + int result = mkdir(dir_path.c_str(), 0700); + if (result != 0) { + printf("failed to mkdir %s when make parents for %s: %s\n", dir_path.c_str(), + name.c_str(), strerror(errno)); + return false; + } + + printf("created [%s]\n", dir_path.c_str()); } + prev_end = next_end; } - return 0; + return true; } // mount(fs_type, partition_type, location, mount_point) @@ -342,7 +350,7 @@ Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& src_name = args[0]; - std::string& dst_name = args[1]; + const std::string& dst_name = args[1]; if (src_name.empty()) { return ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", @@ -352,7 +360,7 @@ Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { return ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", name); } - if (make_parents(&dst_name[0]) != 0) { + if (!make_parents(dst_name)) { return ErrorAbort(state, kFileRenameFailure, "Creating parent of %s failed, error %s", dst_name.c_str(), strerror(errno)); } else if (access(dst_name.c_str(), F_OK) == 0 && access(src_name.c_str(), F_OK) != 0) { @@ -558,8 +566,9 @@ Value* PackageExtractFileFn(const char* name, State* state, } } -// symlink target src1 src2 ... -// unlinks any previously existing src1, src2, etc before creating symlinks. +// symlink(target, [src1, src2, ...]) +// Creates all sources as symlinks to target. It unlinks any previously existing src1, src2, etc +// before creating symlinks. Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc == 0) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc); @@ -571,33 +580,29 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { std::vector<std::string> srcs; if (!ReadArgs(state, argc-1, argv+1, &srcs)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", + name); } - int bad = 0; - for (int i = 0; i < argc-1; ++i) { - if (unlink(srcs[i].c_str()) < 0) { - if (errno != ENOENT) { - printf("%s: failed to remove %s: %s\n", - name, srcs[i].c_str(), strerror(errno)); - ++bad; - } - } - if (make_parents(&srcs[i][0])) { + size_t bad = 0; + for (const auto& src : srcs) { + if (unlink(src.c_str()) == -1 && errno != ENOENT) { + printf("%s: failed to remove %s: %s\n", name, src.c_str(), strerror(errno)); + ++bad; + } else if (!make_parents(src)) { printf("%s: failed to symlink %s to %s: making parents failed\n", - name, srcs[i].c_str(), target.c_str()); + name, src.c_str(), target.c_str()); ++bad; - } - if (symlink(target.c_str(), srcs[i].c_str()) < 0) { + } else if (symlink(target.c_str(), src.c_str()) == -1) { printf("%s: failed to symlink %s to %s: %s\n", - name, srcs[i].c_str(), target.c_str(), strerror(errno)); + name, src.c_str(), target.c_str(), strerror(errno)); ++bad; } } - if (bad) { - return ErrorAbort(state, kSymlinkFailure, "%s: some symlinks failed", name); + if (bad != 0) { + return ErrorAbort(state, kSymlinkFailure, "%s: Failed to create %zu symlink(s)", name, bad); } - return StringValue(""); + return StringValue("t"); } struct perm_parsed_args { |