summaryrefslogtreecommitdiffstats
path: root/updater/install.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'updater/install.cpp')
-rw-r--r--updater/install.cpp81
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 {