summaryrefslogtreecommitdiff
path: root/test/release_unlink_race.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/release_unlink_race.c')
-rw-r--r--test/release_unlink_race.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/test/release_unlink_race.c b/test/release_unlink_race.c
new file mode 100644
index 0000000..2edb200
--- /dev/null
+++ b/test/release_unlink_race.c
@@ -0,0 +1,111 @@
+/*
+ This program can be distributed under the terms of the GNU GPLv2.
+ See the file COPYING.
+*/
+
+#define FUSE_USE_VERSION 31
+
+#define _GNU_SOURCE
+
+#include <fuse.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+static void *xmp_init(struct fuse_conn_info *conn,
+ struct fuse_config *cfg)
+{
+ (void) conn;
+
+ cfg->use_ino = 1;
+ cfg->nullpath_ok = 1;
+ cfg->entry_timeout = 0;
+ cfg->attr_timeout = 0;
+ cfg->negative_timeout = 0;
+
+ return NULL;
+}
+
+static int xmp_getattr(const char *path, struct stat *stbuf,
+ struct fuse_file_info *fi)
+{
+ int res;
+
+ (void) path;
+
+ if(fi)
+ res = fstat(fi->fh, stbuf);
+ else
+ res = lstat(path, stbuf);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_unlink(const char *path)
+{
+ int res;
+
+ res = unlink(path);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_rename(const char *from, const char *to, unsigned int flags)
+{
+ int res;
+
+ if (flags)
+ return -EINVAL;
+
+ if(!getenv("RELEASEUNLINKRACE_DELAY_DISABLE")) usleep(100000);
+
+ res = rename(from, to);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_create(const char *path, mode_t mode, struct fuse_file_info *fi)
+{
+ int fd;
+
+ fd = open(path, fi->flags, mode);
+ if (fd == -1)
+ return -errno;
+
+ fi->fh = fd;
+ return 0;
+}
+
+static int xmp_release(const char *path, struct fuse_file_info *fi)
+{
+ (void) path;
+
+ if(!getenv("RELEASEUNLINKRACE_DELAY_DISABLE")) usleep(100000);
+
+ close(fi->fh);
+
+ return 0;
+}
+
+static const struct fuse_operations xmp_oper = {
+ .init = xmp_init,
+ .getattr = xmp_getattr,
+ .unlink = xmp_unlink,
+ .rename = xmp_rename,
+ .create = xmp_create,
+ .release = xmp_release,
+};
+
+int main(int argc, char *argv[])
+{
+ umask(0);
+ return fuse_main(argc, argv, &xmp_oper, NULL);
+}