This patch implements the symlinkat() function and enhances
tst-symlink.cc to unit test it.
Signed-off-by: Waldemar Kozaczuk <
jwkoz...@gmail.com>
---
exported_symbols/osv_ld-musl.so.1.symbols | 1 +
exported_symbols/osv_libc.so.6.symbols | 1 +
fs/vfs/main.cc | 12 ++++++++++++
tests/tst-symlink.cc | 18 +++++++++++++++---
4 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/exported_symbols/osv_ld-musl.so.1.symbols b/exported_symbols/osv_ld-musl.so.1.symbols
index f1c61a3f..3db22e0d 100644
--- a/exported_symbols/osv_ld-musl.so.1.symbols
+++ b/exported_symbols/osv_ld-musl.so.1.symbols
@@ -1081,6 +1081,7 @@ swab
swprintf
swscanf
symlink
+symlinkat
sync
syscall
sysconf
diff --git a/exported_symbols/osv_libc.so.6.symbols b/exported_symbols/osv_libc.so.6.symbols
index 7ae57c38..e29059bb 100644
--- a/exported_symbols/osv_libc.so.6.symbols
+++ b/exported_symbols/osv_libc.so.6.symbols
@@ -887,6 +887,7 @@ swprintf
__swprintf_chk
swscanf
symlink
+symlinkat
sync
syscall
sysconf
diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc
index 4f0ce463..1b0d7c11 100644
--- a/fs/vfs/main.cc
+++ b/fs/vfs/main.cc
@@ -1122,6 +1122,18 @@ int symlink(const char *oldpath, const char *newpath)
return 0;
}
+OSV_LIBC_API
+int symlinkat(const char *oldpath, int newdirfd, const char *newpath)
+{
+ if (newpath[0] == '/' || newdirfd == AT_FDCWD) {
+ return symlink(oldpath, newpath);
+ }
+
+ return vfs_fun_at(newdirfd, newpath, [oldpath](const char *absolute_path) {
+ return symlink(oldpath, absolute_path);
+ });
+}
+
TRACEPOINT(trace_vfs_unlink, "\"%s\"", const char*);
TRACEPOINT(trace_vfs_unlink_ret, "");
TRACEPOINT(trace_vfs_unlink_err, "%d", int);
diff --git a/tests/tst-symlink.cc b/tests/tst-symlink.cc
index 978cfda3..1322e79e 100644
--- a/tests/tst-symlink.cc
+++ b/tests/tst-symlink.cc
@@ -25,6 +25,9 @@
#define N1 "f1"
#define N2 "f2_AAA"
+#define N2B "f2_BBB"
+#define N2B "f2_BBB"
+#define N2C "f2_CCC"
#define N3 "f3"
#define N4 "f4"
#define N5 "f5"
@@ -91,6 +94,8 @@ int main(int argc, char **argv)
#endif
report(chdir(TESTDIR) == 0, "chdir");
+ auto test_dir = opendir(TESTDIR);
+ report(test_dir, "opendir");
/*
* test to check
@@ -115,6 +120,10 @@ int main(int argc, char **argv)
#else
report(symlink(N1, N2) == 0, "symlink");
report(search_dir(TESTDIR, N2) == true, "search dir");
+ report(symlinkat(N1, dirfd(test_dir), N2B) == 0, "symlinkat");
+ report(search_dir(TESTDIR, N2B) == true, "search dir N2B");
+ report(symlinkat(N1, AT_FDCWD, N2C) == 0, "symlinkat");
+ report(search_dir(TESTDIR, N2C) == true, "search dir N2B");
#endif
#if defined(READ_ONLY_FS)
@@ -125,6 +134,8 @@ int main(int argc, char **argv)
#else
report(access(N1, R_OK | W_OK) == 0, "access");
report(access(N2, R_OK | W_OK) == 0, "access");
+ report(access(N2B, R_OK | W_OK) == 0, "access");
+ report(access(N2C, R_OK | W_OK) == 0, "access");
#endif
rc = readlink(N2, path, sizeof(path));
@@ -157,6 +168,8 @@ int main(int argc, char **argv)
error = errno;
report(rc < 0 && errno == ENOENT, "ENOENT expected");
report(unlink(N2) == 0, "unlink");
+ report(unlinkat(dirfd(test_dir),N2B,0) == 0, "unlinkat");
+ report(unlinkat(dirfd(test_dir),N2C,0) == 0, "unlinkat");
/*
* IO Tests 1: write(file), read(symlink), truncate(symlink)
@@ -365,8 +378,6 @@ int main(int argc, char **argv)
report(search_dir(D2, N5) == true, "Symlink search");
report(rename(D2, D3) == 0, "rename(d2, d3)");
- auto test_dir = opendir(TESTDIR);
- report(test_dir, "opendir");
rc = readlinkat(dirfd(test_dir), D3, path, sizeof(path));
report(rc >= 0, "readlinkat");
path[rc] = 0;
@@ -381,7 +392,6 @@ int main(int argc, char **argv)
report(rc >= 0, "readlinkat");
path[rc] = 0;
report(strcmp(path, D1) == 0, "readlinkat path");
- report(closedir(test_dir) == 0, "closedir(test_dir)");
rc = readlink(D3, path, sizeof(path));
report(rc >= 0, "readlink");
path[rc] = 0;
@@ -399,6 +409,8 @@ int main(int argc, char **argv)
report(rmdir(D4) == 0, "rmdir");
#endif
+ report(closedir(test_dir) == 0, "closedir(test_dir)");
+
#if defined(READ_ONLY_FS)
report(-1 == rmdir(TESTDIR) && errno == ENOTEMPTY, "rmdir");
#else
--
2.34.1