Merge "updater: Add more testcase for symlink()."
This commit is contained in:
@@ -14,6 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <android-base/file.h>
|
#include <android-base/file.h>
|
||||||
@@ -212,10 +216,15 @@ TEST_F(UpdaterTest, rename) {
|
|||||||
// Parents create successfully.
|
// Parents create successfully.
|
||||||
TemporaryFile temp_file3;
|
TemporaryFile temp_file3;
|
||||||
TemporaryDir td;
|
TemporaryDir td;
|
||||||
std::string temp_dir = std::string(td.path) + "/aaa/bbb/a.txt";
|
std::string temp_dir(td.path);
|
||||||
std::string script3("rename(\"" + std::string(temp_file3.path) + "\", \"" +
|
std::string dst_file = temp_dir + "/aaa/bbb/a.txt";
|
||||||
temp_dir + "\")");
|
std::string script3("rename(\"" + std::string(temp_file3.path) + "\", \"" + dst_file + "\")");
|
||||||
expect(temp_dir.c_str(), script3.c_str(), kNoCause);
|
expect(dst_file.c_str(), script3.c_str(), kNoCause);
|
||||||
|
|
||||||
|
// Clean up the temp files under td.
|
||||||
|
ASSERT_EQ(0, unlink(dst_file.c_str()));
|
||||||
|
ASSERT_EQ(0, rmdir((temp_dir + "/aaa/bbb").c_str()));
|
||||||
|
ASSERT_EQ(0, rmdir((temp_dir + "/aaa").c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(UpdaterTest, symlink) {
|
TEST_F(UpdaterTest, symlink) {
|
||||||
@@ -227,7 +236,31 @@ TEST_F(UpdaterTest, symlink) {
|
|||||||
std::string script1("symlink(\"" + std::string(temp_file1.path) + "\", \"\")");
|
std::string script1("symlink(\"" + std::string(temp_file1.path) + "\", \"\")");
|
||||||
expect(nullptr, script1.c_str(), kSymlinkFailure);
|
expect(nullptr, script1.c_str(), kSymlinkFailure);
|
||||||
|
|
||||||
// symlink failed to remove old src.
|
std::string script2("symlink(\"" + std::string(temp_file1.path) + "\", \"src1\", \"\")");
|
||||||
std::string script2("symlink(\"" + std::string(temp_file1.path) + "\", \"/proc\")");
|
|
||||||
expect(nullptr, script2.c_str(), kSymlinkFailure);
|
expect(nullptr, script2.c_str(), kSymlinkFailure);
|
||||||
|
|
||||||
|
// symlink failed to remove old src.
|
||||||
|
std::string script3("symlink(\"" + std::string(temp_file1.path) + "\", \"/proc\")");
|
||||||
|
expect(nullptr, script3.c_str(), kSymlinkFailure);
|
||||||
|
|
||||||
|
// symlink can create symlinks.
|
||||||
|
TemporaryFile temp_file;
|
||||||
|
std::string content = "magicvalue";
|
||||||
|
ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file.path));
|
||||||
|
|
||||||
|
TemporaryDir td;
|
||||||
|
std::string src1 = std::string(td.path) + "/symlink1";
|
||||||
|
std::string src2 = std::string(td.path) + "/symlink2";
|
||||||
|
std::string script4("symlink(\"" + std::string(temp_file.path) + "\", \"" +
|
||||||
|
src1 + "\", \"" + src2 + "\")");
|
||||||
|
expect("t", script4.c_str(), kNoCause);
|
||||||
|
|
||||||
|
// Verify the created symlinks.
|
||||||
|
struct stat sb;
|
||||||
|
ASSERT_TRUE(lstat(src1.c_str(), &sb) == 0 && S_ISLNK(sb.st_mode));
|
||||||
|
ASSERT_TRUE(lstat(src2.c_str(), &sb) == 0 && S_ISLNK(sb.st_mode));
|
||||||
|
|
||||||
|
// Clean up the leftovers.
|
||||||
|
ASSERT_EQ(0, unlink(src1.c_str()));
|
||||||
|
ASSERT_EQ(0, unlink(src2.c_str()));
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-20
@@ -566,8 +566,9 @@ Value* PackageExtractFileFn(const char* name, State* state,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// symlink target src1 src2 ...
|
// symlink(target, [src1, src2, ...])
|
||||||
// unlinks any previously existing src1, src2, etc before creating symlinks.
|
// 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[]) {
|
Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc);
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc);
|
||||||
@@ -579,33 +580,29 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
|
|||||||
|
|
||||||
std::vector<std::string> srcs;
|
std::vector<std::string> srcs;
|
||||||
if (!ReadArgs(state, argc-1, argv+1, &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;
|
size_t bad = 0;
|
||||||
for (int i = 0; i < argc-1; ++i) {
|
for (const auto& src : srcs) {
|
||||||
if (unlink(srcs[i].c_str()) < 0) {
|
if (unlink(src.c_str()) == -1 && errno != ENOENT) {
|
||||||
if (errno != ENOENT) {
|
printf("%s: failed to remove %s: %s\n", name, src.c_str(), strerror(errno));
|
||||||
printf("%s: failed to remove %s: %s\n",
|
++bad;
|
||||||
name, srcs[i].c_str(), strerror(errno));
|
} else if (!make_parents(src)) {
|
||||||
++bad;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!make_parents(srcs[i])) {
|
|
||||||
printf("%s: failed to symlink %s to %s: making parents failed\n",
|
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;
|
++bad;
|
||||||
}
|
} else if (symlink(target.c_str(), src.c_str()) == -1) {
|
||||||
if (symlink(target.c_str(), srcs[i].c_str()) < 0) {
|
|
||||||
printf("%s: failed to symlink %s to %s: %s\n",
|
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;
|
++bad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bad) {
|
if (bad != 0) {
|
||||||
return ErrorAbort(state, kSymlinkFailure, "%s: some symlinks failed", name);
|
return ErrorAbort(state, kSymlinkFailure, "%s: Failed to create %zu symlink(s)", name, bad);
|
||||||
}
|
}
|
||||||
return StringValue("");
|
return StringValue("t");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct perm_parsed_args {
|
struct perm_parsed_args {
|
||||||
|
|||||||
Reference in New Issue
Block a user