[PATCH] vfs: implement symlinkat

12 views
Skip to first unread message

Waldemar Kozaczuk

unread,
May 17, 2022, 11:26:55 PM5/17/22
to osv...@googlegroups.com, Waldemar Kozaczuk
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

Nadav Har'El

unread,
May 18, 2022, 3:00:07 AM5/18/22
to Waldemar Kozaczuk, Osv Dev
And here again, if vfs_fun_at() did that at_fdcwd if() above, this code would have been even simpler.

--
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 osv-dev+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/20220518032648.76794-1-jwkozaczuk%40gmail.com.

Waldemar Kozaczuk

unread,
May 20, 2022, 3:12:16 PM5/20/22
to osv...@googlegroups.com, Waldemar Kozaczuk
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 <jwkoz...@gmail.com>
---
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(-)
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);

Commit Bot

unread,
May 27, 2022, 11:15:18 AM5/27/22
to osv...@googlegroups.com, Waldemar Kozaczuk
From: Waldemar Kozaczuk <jwkoz...@gmail.com>
Committer: Waldemar Kozaczuk <jwkoz...@gmail.com>
Branch: master

vfs: implement symlinkat

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 <jwkoz...@gmail.com>

---
diff --git a/exported_symbols/osv_ld-musl.so.1.symbols b/exported_symbols/osv_ld-musl.so.1.symbols
--- 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
--- 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
--- 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
--- 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
Reply all
Reply to author
Forward
0 new messages