V2: The implementation uses vfs_fun_at2() instead of vfs_fun_at() to further simplify code. We also expose symlinkat though syscall.
This patch implements the symlinkat() function and enhances tst-symlink.cc to unit test it. #Refs 1188 Signed-off-by: Waldemar Kozaczuk <[email protected]> --- exported_symbols/osv_ld-musl.so.1.symbols | 1 + exported_symbols/osv_libc.so.6.symbols | 1 + fs/vfs/main.cc | 13 +++++++++++++ linux.cc | 1 + tests/tst-symlink.cc | 18 +++++++++++++++--- 5 files changed, 31 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 9b2e2c02..8e3d4e5e 100644 --- a/fs/vfs/main.cc +++ b/fs/vfs/main.cc @@ -1132,6 +1132,19 @@ int symlink(const char *oldpath, const char *newpath) return 0; } +OSV_LIBC_API +int symlinkat(const char *oldpath, int newdirfd, const char *newpath) +{ + if (!oldpath) { + errno = EINVAL; + return -1; + } + + return vfs_fun_at2(newdirfd, newpath, [oldpath](const char * path) { + return symlink(oldpath, path); + }); +} + TRACEPOINT(trace_vfs_unlink, "\"%s\"", const char*); TRACEPOINT(trace_vfs_unlink_ret, ""); TRACEPOINT(trace_vfs_unlink_err, "%d", int); diff --git a/linux.cc b/linux.cc index 5c271df1..dd0dabd1 100644 --- a/linux.cc +++ b/linux.cc @@ -496,6 +496,7 @@ OSV_LIBC_API long syscall(long number, ...) SYSCALL3(lseek, int, off_t, int); SYSCALL2(statfs, const char *, struct statfs *); SYSCALL3(unlinkat, int, const char *, int); + SYSCALL3(symlinkat, const char *, int, const char *); } debug_always("syscall(): unimplemented system call %d\n", number); 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 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/20220520191210.141585-1-jwkozaczuk%40gmail.com.
