This patch enhances the unlinkat() implementation to handle
the AT_FDCWD dirfd and AT_REMOVEDIR flags. 

We also enhance tst-remove.cc to test unlinkat.

Signed-off-by: Waldemar Kozaczuk <[email protected]>
---
 fs/vfs/main.cc      | 18 ++++++++++++++----
 tests/tst-remove.cc | 18 ++++++++++++++++--
 2 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc
index a72042b2..4f0ce463 100644
--- a/fs/vfs/main.cc
+++ b/fs/vfs/main.cc
@@ -1154,11 +1154,21 @@ int unlink(const char *pathname)
 OSV_LIBC_API
 int unlinkat(int dirfd, const char *pathname, int flags)
 {
-    //TODO: Really implement it
-    if (dirfd != AT_FDCWD || flags) {
-        UNIMPLEMENTED("unlinkat() with non-zero flags or dirfd != AT_FDCWD");
+    if (pathname[0] == '/' || dirfd == AT_FDCWD) {
+        if (flags & AT_REMOVEDIR) {
+            return rmdir(pathname);
+        } else {
+            return unlink(pathname);
+        }
     }
-    return unlink(pathname);
+
+    return vfs_fun_at(dirfd, pathname, [flags](const char *absolute_path) {
+        if (flags & AT_REMOVEDIR) {
+            return rmdir(absolute_path);
+        } else {
+            return unlink(absolute_path);
+        }
+    });
 }
 
 TRACEPOINT(trace_vfs_stat, "\"%s\" %p", const char*, struct stat*);
diff --git a/tests/tst-remove.cc b/tests/tst-remove.cc
index 6851cba0..fdf4037d 100644
--- a/tests/tst-remove.cc
+++ b/tests/tst-remove.cc
@@ -42,6 +42,8 @@ bool do_expect(T actual, T expected, const char *actuals, 
const char *expecteds,
 int main(int argc, char **argv)
 {
     expect(mkdir("/tmp/tst-remove", 0777), 0);
+    auto tst_remove_dir = open("/tmp/tst-remove", O_DIRECTORY);
+    expect(tst_remove_dir != -1, true);
 
     /********* test unlink() **************/
     // unlink() non-existant file returns ENOENT
@@ -79,12 +81,24 @@ int main(int argc, char **argv)
     expect_errno(rmdir("/tmp/tst-remove/f"), ENOTDIR);
     expect(unlink("/tmp/tst-remove/f"), 0);
 
-    /********* test remove() ***************/
-    // TODO...
+    /********* test unlinkat() ***************/
+    expect(mknod("/tmp/tst-remove/u", 0777|S_IFREG, 0), 0);
+    expect(unlinkat(tst_remove_dir, "u", 0), 0);
 
+    expect(mknod("/tmp/tst-remove/u2", 0777|S_IFREG, 0), 0);
+    expect(chdir("/tmp/tst-remove"), 0);
+    expect(unlinkat(AT_FDCWD, "u2", 0), 0);
+
+    expect(mkdir("/tmp/tst-remove/ud", 0777), 0);
+    expect(unlinkat(tst_remove_dir, "ud", AT_REMOVEDIR), 0);
+
+    expect(mkdir("/tmp/tst-remove/ud2", 0777), 0);
+    expect(chdir("/tmp/tst-remove"), 0);
+    expect(unlinkat(AT_FDCWD, "ud2", AT_REMOVEDIR), 0);
 
     // Finally remove the temporary directory (assumes the above left
     // nothing in it)
+    expect(close(tst_remove_dir), 0);
     expect(rmdir("/tmp/tst-remove"), 0);
 
 
-- 
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/20220518032614.76774-1-jwkozaczuk%40gmail.com.

Reply via email to