Skip to content

Commit 10d2281

Browse files
authored
Merge pull request #456 from tjwoodall/plugin-test
Plugin test
2 parents 263d3d3 + fe0525a commit 10d2281

File tree

5 files changed

+461
-0
lines changed

5 files changed

+461
-0
lines changed

tests/plugin/.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
!Makefile
2+
convert
3+
shared-storage-plugin.so
4+
fuse-overlayfs.h
5+
plugin-manager.h
6+
utils.c
7+
utils.h

tests/plugin/Makefile

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
all: shared-storage-plugin.so convert
2+
3+
# Files that we copy from fuse-overlayfs for the purposes of this test.
4+
IMPORT_FILES = utils.c utils.h fuse-overlayfs.h plugin-manager.h config.h
5+
6+
# These are the V1 versions of the plugin definitions. We want to compile the
7+
# plugin with these specific versions to ensure that we maintain backwards
8+
# compatibility.
9+
fuse-overlayfs.h plugin-manager.h utils.h utils.c:
10+
git show v1.16:$@ >$@
11+
12+
config.h:
13+
cp ../../$@ .
14+
15+
shared-storage-plugin.so: shared-storage-plugin.c $(IMPORT_FILES)
16+
gcc -fPIC -I. -shared -o shared-storage-plugin.so shared-storage-plugin.c utils.c
17+
18+
convert: convert.c
19+
gcc convert.c -o convert
20+
21+
clean:
22+
rm $(IMPORT_FILES) shared-storage-plugin.so convert

tests/plugin/convert.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#define _GNU_SOURCE
2+
3+
#include <stdlib.h>
4+
#include <stdio.h>
5+
#include <unistd.h>
6+
#include <fcntl.h>
7+
#include <sys/stat.h>
8+
#include <sys/xattr.h>
9+
#include <dirent.h>
10+
#include <error.h>
11+
#include <string.h>
12+
#include <errno.h>
13+
14+
void
15+
convert (int dfd)
16+
{
17+
DIR *d;
18+
struct dirent *de;
19+
int fd;
20+
char p[64];
21+
char b[64];
22+
23+
d = fdopendir (dfd);
24+
if (d == NULL)
25+
{
26+
close (dfd);
27+
error (EXIT_FAILURE, errno, "cannot open directory");
28+
}
29+
30+
for (de = readdir (d); de; de = readdir (d))
31+
{
32+
struct stat st;
33+
mode_t newmode;
34+
35+
if (strcmp (de->d_name, ".") == 0 || strcmp (de->d_name, "..") == 0)
36+
continue;
37+
38+
printf ("convert %s\n", de->d_name);
39+
40+
if (fstatat (dirfd (d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
41+
error (EXIT_FAILURE, errno, "stat");
42+
43+
sprintf (b, "%o:%d:%d", st.st_mode & 0777, st.st_uid, st.st_gid);
44+
45+
newmode = (st.st_mode & ~0777) | 0755;
46+
47+
switch (st.st_mode & S_IFMT)
48+
{
49+
case S_IFDIR:
50+
fd = openat (dirfd (d), de->d_name, O_DIRECTORY);
51+
if (fd < 0)
52+
error (EXIT_FAILURE, errno, "open directory %s", de->d_name);
53+
54+
if (fsetxattr (fd, "user.original-permissions", b, strlen (b) + 1, XATTR_CREATE) < 0 && errno != EEXIST)
55+
error (EXIT_FAILURE, errno, "cannot set xattr for dir %s", de->d_name);
56+
if (fchmod (fd, newmode) < 0)
57+
error (EXIT_FAILURE, errno, "cannot set fchmod %s", de->d_name);
58+
59+
convert (fd);
60+
61+
break;
62+
63+
default:
64+
fd = openat (dirfd (d), de->d_name, O_PATH | O_NOFOLLOW);
65+
if (fd < 0)
66+
error (EXIT_FAILURE, errno, "open %s", de->d_name);
67+
68+
sprintf (p, "/proc/self/fd/%d", fd);
69+
70+
if (setxattr (p, "user.original-permissions", b, strlen (b) + 1, XATTR_CREATE) < 0 && errno != EEXIST && errno != EPERM)
71+
error (EXIT_FAILURE, errno, "cannot set xattr %s", de->d_name);
72+
73+
if (chmod (p, newmode) < 0 && errno != ENOTSUP)
74+
error (EXIT_FAILURE, errno, "cannot chmod %s", de->d_name);
75+
76+
close (fd);
77+
break;
78+
}
79+
}
80+
closedir (d);
81+
}
82+
83+
int
84+
main (int argc, char **argv)
85+
{
86+
int fd;
87+
88+
if (argc < 1)
89+
error (EXIT_FAILURE, 0, "specify a path");
90+
91+
fd = open (argv[1], O_DIRECTORY | O_NOFOLLOW);
92+
if (fd < 0)
93+
error (EXIT_FAILURE, 0, "open %s", argv[1]);
94+
convert (fd);
95+
return 0;
96+
}
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
#define _GNU_SOURCE
2+
3+
#include <stdlib.h>
4+
#include <stdio.h>
5+
#include <fcntl.h>
6+
#include <unistd.h>
7+
#include <string.h>
8+
#include <sys/stat.h>
9+
#include <sys/types.h>
10+
11+
#include <errno.h>
12+
13+
#include <sys/xattr.h>
14+
15+
#include <fuse-overlayfs.h>
16+
#include "utils.h"
17+
18+
static int
19+
test_file_exists (struct ovl_layer *l, const char *pathname)
20+
{
21+
return file_exists_at (l->fd, pathname);
22+
}
23+
24+
static int
25+
test_listxattr (struct ovl_layer *l, const char *path, char *buf, size_t size)
26+
{
27+
cleanup_close int fd = -1;
28+
char full_path[PATH_MAX];
29+
int ret;
30+
31+
full_path[0] = '\0';
32+
ret = open_fd_or_get_path (l, path, full_path, &fd, O_RDONLY);
33+
if (ret < 0)
34+
return ret;
35+
36+
if (fd >= 0)
37+
return flistxattr (fd, buf, size);
38+
39+
return llistxattr (full_path, buf, size);
40+
}
41+
42+
static int
43+
test_getxattr (struct ovl_layer *l, const char *path, const char *name, char *buf, size_t size)
44+
{
45+
cleanup_close int fd = -1;
46+
char full_path[PATH_MAX];
47+
int ret;
48+
49+
full_path[0] = '\0';
50+
ret = open_fd_or_get_path (l, path, full_path, &fd, O_RDONLY);
51+
if (ret < 0)
52+
return ret;
53+
54+
if (fd >= 0)
55+
return fgetxattr (fd, name, buf, size);
56+
57+
return lgetxattr (full_path, name, buf, size);
58+
}
59+
60+
static int
61+
test_fstat (struct ovl_layer *l, int fd, const char *path, unsigned int mask, struct stat *st)
62+
{
63+
char b[32];
64+
int r;
65+
mode_t mode;
66+
uid_t uid;
67+
gid_t gid;
68+
69+
r = fstat (fd, st);
70+
if (r < 0)
71+
return r;
72+
73+
r = fgetxattr (fd, "user.original-permissions", b, sizeof (b) - 1);
74+
if (r < 0 && errno == ENODATA)
75+
return 0;
76+
if (r < 0)
77+
return r;
78+
b[r] = '\0';
79+
80+
sscanf (b, "%o:%d:%d", &mode, &uid, &gid);
81+
82+
st->st_mode = (st->st_mode & ~0777) | mode;
83+
st->st_uid = uid;
84+
st->st_gid = gid;
85+
86+
return 0;
87+
}
88+
89+
static int
90+
test_statat (struct ovl_layer *l, const char *path, struct stat *st, int flags, unsigned int mask)
91+
{
92+
char p[PATH_MAX];
93+
char b[32];
94+
mode_t mode;
95+
int r;
96+
uid_t uid;
97+
gid_t gid;
98+
99+
r = TEMP_FAILURE_RETRY (fstatat (l->fd, path, st, flags));
100+
if (r < 0)
101+
return r;
102+
103+
sprintf (p, "%s/%s", l->path, path);
104+
105+
r = getxattr (p, "user.original-permissions", b, sizeof (b) - 1);
106+
if (r < 0 && (errno == ENODATA || errno == ENOENT))
107+
return 0;
108+
if (r < 0)
109+
return r;
110+
b[r] = '\0';
111+
112+
sscanf (b, "%o:%d:%d", &mode, &uid, &gid);
113+
114+
st->st_mode = (st->st_mode & ~0777) | mode;
115+
st->st_uid = uid;
116+
st->st_gid = gid;
117+
118+
return 0;
119+
}
120+
121+
static struct dirent *
122+
test_readdir (void *dirp)
123+
{
124+
return readdir (dirp);
125+
}
126+
127+
static void *
128+
test_opendir (struct ovl_layer *l, const char *path)
129+
{
130+
cleanup_close int cleanup_fd = -1;
131+
DIR *dp = NULL;
132+
133+
cleanup_fd = TEMP_FAILURE_RETRY (openat (l->fd, path, O_DIRECTORY));
134+
if (cleanup_fd < 0)
135+
return NULL;
136+
137+
dp = fdopendir (cleanup_fd);
138+
if (dp == NULL)
139+
return NULL;
140+
141+
cleanup_fd = -1;
142+
143+
return dp;
144+
}
145+
146+
static int
147+
test_closedir (void *dirp)
148+
{
149+
return closedir (dirp);
150+
}
151+
152+
static int
153+
test_openat (struct ovl_layer *l, const char *path, int flags, mode_t mode)
154+
{
155+
return TEMP_FAILURE_RETRY (openat (l->fd, path, flags, mode));
156+
}
157+
158+
static ssize_t
159+
test_readlinkat (struct ovl_layer *l, const char *path, char *buf, size_t bufsiz)
160+
{
161+
return TEMP_FAILURE_RETRY (readlinkat (l->fd, path, buf, bufsiz));
162+
}
163+
164+
static int
165+
test_load_data_source (struct ovl_layer *l, const char *opaque, const char *path, int n_layer)
166+
{
167+
l->path = realpath (path, NULL);
168+
if (l->path == NULL)
169+
return -1;
170+
171+
l->fd = open (l->path, O_DIRECTORY);
172+
if (l->fd < 0)
173+
{
174+
free (l->path);
175+
l->path = NULL;
176+
return l->fd;
177+
}
178+
179+
return 0;
180+
}
181+
182+
static int
183+
test_cleanup (struct ovl_layer *l)
184+
{
185+
return 0;
186+
}
187+
188+
static int
189+
test_num_of_layers (const char *opaque, const char *path)
190+
{
191+
return 1;
192+
}
193+
194+
static bool
195+
test_support_acls (struct ovl_layer *l)
196+
{
197+
return true;
198+
}
199+
200+
struct data_source test_ds = {
201+
.num_of_layers = test_num_of_layers,
202+
.load_data_source = test_load_data_source,
203+
.cleanup = test_cleanup,
204+
.file_exists = test_file_exists,
205+
.statat = test_statat,
206+
.fstat = test_fstat,
207+
.opendir = test_opendir,
208+
.readdir = test_readdir,
209+
.closedir = test_closedir,
210+
.openat = test_openat,
211+
.listxattr = test_listxattr,
212+
.getxattr = test_getxattr,
213+
.readlinkat = test_readlinkat,
214+
.support_acls = test_support_acls,
215+
/* get_nfs_filehandle is also available in V1 but this test explicitly builds
216+
* against the original version of the data_source to ensure backwards
217+
* compatibility is maintained */
218+
};
219+
220+
int
221+
plugin_version ()
222+
{
223+
return 1;
224+
}
225+
226+
const char *
227+
plugin_name ()
228+
{
229+
return "test";
230+
}
231+
232+
struct data_source *
233+
plugin_load (struct ovl_layer *layer, const char *opaque, const char *path)
234+
{
235+
return &test_ds;
236+
}
237+
238+
int
239+
plugin_release (struct ovl_layer *l)
240+
{
241+
return 0;
242+
}

0 commit comments

Comments
 (0)