xref: /third_party/libfuse/test/test_syscalls.c (revision 6881f68f)
1#define _GNU_SOURCE
2#include "fuse_config.h"
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <stdarg.h>
7#include <string.h>
8#include <unistd.h>
9#include <fcntl.h>
10#include <dirent.h>
11#include <utime.h>
12#include <errno.h>
13#include <assert.h>
14#include <sys/socket.h>
15#include <sys/types.h>
16#include <sys/stat.h>
17#include <sys/un.h>
18
19#ifndef ALLPERMS
20# define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)/* 07777 */
21#endif
22
23
24static const char *basepath;
25static const char *basepath_r;
26static char testfile[1024];
27static char testfile2[1024];
28static char testdir[1024];
29static char testdir2[1024];
30static char testsock[1024];
31static char subfile[1280];
32
33static char testfile_r[1024];
34static char testfile2_r[1024];
35static char testdir_r[1024];
36static char testdir2_r[1024];
37static char subfile_r[1280];
38
39static char testname[256];
40static char testdata[] = "abcdefghijklmnopqrstuvwxyz";
41static char testdata2[] = "1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./";
42static const char *testdir_files[] = { "f1", "f2", NULL};
43static long seekdir_offsets[4];
44static char zerodata[4096];
45static int testdatalen = sizeof(testdata) - 1;
46static int testdata2len = sizeof(testdata2) - 1;
47static unsigned int testnum = 0;
48static unsigned int select_test = 0;
49static unsigned int skip_test = 0;
50static unsigned int unlinked_test = 0;
51
52#define MAX_ENTRIES 1024
53#define MAX_TESTS 100
54
55static struct test {
56	int fd;
57	struct stat stat;
58} tests[MAX_TESTS];
59
60static void test_perror(const char *func, const char *msg)
61{
62	fprintf(stderr, "%s %s() - %s: %s\n", testname, func, msg,
63		strerror(errno));
64}
65
66static void test_error(const char *func, const char *msg, ...)
67	__attribute__ ((format (printf, 2, 3)));
68
69static void __start_test(const char *fmt, ...)
70	__attribute__ ((format (printf, 1, 2)));
71
72static void test_error(const char *func, const char *msg, ...)
73{
74	va_list ap;
75	fprintf(stderr, "%s %s() - ", testname, func);
76	va_start(ap, msg);
77	vfprintf(stderr, msg, ap);
78	va_end(ap);
79	fprintf(stderr, "\n");
80}
81
82static int is_dot_or_dotdot(const char *name) {
83    return name[0] == '.' &&
84           (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
85}
86
87static void success(void)
88{
89	fprintf(stderr, "%s OK\n", testname);
90}
91
92#define this_test (&tests[testnum-1])
93#define next_test (&tests[testnum])
94
95static void __start_test(const char *fmt, ...)
96{
97	unsigned int n;
98	va_list ap;
99	n = sprintf(testname, "%3i [", testnum);
100	va_start(ap, fmt);
101	n += vsprintf(testname + n, fmt, ap);
102	va_end(ap);
103	sprintf(testname + n, "]");
104	// Use dedicated testfile per test
105	sprintf(testfile, "%s/testfile.%d", basepath, testnum);
106	sprintf(testfile_r, "%s/testfile.%d", basepath_r, testnum);
107	if (testnum > MAX_TESTS) {
108		fprintf(stderr, "%s - too many tests\n", testname);
109		exit(1);
110	}
111	this_test->fd = -1;
112}
113
114#define start_test(msg, args...) { \
115	testnum++; \
116	if ((select_test && testnum != select_test) || \
117	    (testnum == skip_test)) { \
118		return 0; \
119	} \
120	__start_test(msg, ##args);		\
121}
122
123#define PERROR(msg) test_perror(__FUNCTION__, msg)
124#define ERROR(msg, args...) test_error(__FUNCTION__, msg, ##args)
125
126#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
127
128static int st_check_size(struct stat *st, int len)
129{
130	if (st->st_size != len) {
131		ERROR("length %u instead of %u", (int) st->st_size,
132		      (int) len);
133		return -1;
134	}
135	return 0;
136}
137
138static int check_size(const char *path, int len)
139{
140	struct stat stbuf;
141	int res = stat(path, &stbuf);
142	if (res == -1) {
143		PERROR("stat");
144		return -1;
145	}
146	return st_check_size(&stbuf, len);
147}
148
149static int check_testfile_size(const char *path, int len)
150{
151	this_test->stat.st_size = len;
152	return check_size(path, len);
153}
154
155static int st_check_type(struct stat *st, mode_t type)
156{
157	if ((st->st_mode & S_IFMT) != type) {
158		ERROR("type 0%o instead of 0%o", st->st_mode & S_IFMT, type);
159		return -1;
160	}
161	return 0;
162}
163
164static int check_type(const char *path, mode_t type)
165{
166	struct stat stbuf;
167	int res = lstat(path, &stbuf);
168	if (res == -1) {
169		PERROR("lstat");
170		return -1;
171	}
172	return st_check_type(&stbuf, type);
173}
174
175static int st_check_mode(struct stat *st, mode_t mode)
176{
177	if ((st->st_mode & ALLPERMS) != mode) {
178		ERROR("mode 0%o instead of 0%o", st->st_mode & ALLPERMS,
179		      mode);
180		return -1;
181	}
182	return 0;
183}
184
185static int check_mode(const char *path, mode_t mode)
186{
187	struct stat stbuf;
188	int res = lstat(path, &stbuf);
189	if (res == -1) {
190		PERROR("lstat");
191		return -1;
192	}
193	return st_check_mode(&stbuf, mode);
194}
195
196static int check_testfile_mode(const char *path, mode_t mode)
197{
198	this_test->stat.st_mode &= ~ALLPERMS;
199	this_test->stat.st_mode |= mode;
200	return check_mode(path, mode);
201}
202
203static int check_times(const char *path, time_t atime, time_t mtime)
204{
205	int err = 0;
206	struct stat stbuf;
207	int res = lstat(path, &stbuf);
208	if (res == -1) {
209		PERROR("lstat");
210		return -1;
211	}
212	if (stbuf.st_atime != atime) {
213		ERROR("atime %li instead of %li", stbuf.st_atime, atime);
214		err--;
215	}
216	if (stbuf.st_mtime != mtime) {
217		ERROR("mtime %li instead of %li", stbuf.st_mtime, mtime);
218		err--;
219	}
220	if (err)
221		return -1;
222
223	return 0;
224}
225
226#if 0
227static int fcheck_times(int fd, time_t atime, time_t mtime)
228{
229	int err = 0;
230	struct stat stbuf;
231	int res = fstat(fd, &stbuf);
232	if (res == -1) {
233		PERROR("fstat");
234		return -1;
235	}
236	if (stbuf.st_atime != atime) {
237		ERROR("atime %li instead of %li", stbuf.st_atime, atime);
238		err--;
239	}
240	if (stbuf.st_mtime != mtime) {
241		ERROR("mtime %li instead of %li", stbuf.st_mtime, mtime);
242		err--;
243	}
244	if (err)
245		return -1;
246
247	return 0;
248}
249#endif
250
251static int st_check_nlink(struct stat *st, nlink_t nlink)
252{
253	if (st->st_nlink != nlink) {
254		ERROR("nlink %li instead of %li", (long) st->st_nlink,
255		      (long) nlink);
256		return -1;
257	}
258	return 0;
259}
260
261static int check_nlink(const char *path, nlink_t nlink)
262{
263	struct stat stbuf;
264	int res = lstat(path, &stbuf);
265	if (res == -1) {
266		PERROR("lstat");
267		return -1;
268	}
269	return st_check_nlink(&stbuf, nlink);
270}
271
272static int fcheck_stat(int fd, int flags, struct stat *st)
273{
274	struct stat stbuf;
275	int res = fstat(fd, &stbuf);
276	if (res == -1) {
277		if (flags & O_PATH) {
278			// With O_PATH fd, the server does not have to keep
279			// the inode alive so FUSE inode may be stale or bad
280			if (errno == ESTALE || errno == EIO ||
281			    errno == ENOENT || errno == EBADF)
282				return 0;
283		}
284		PERROR("fstat");
285		return -1;
286	}
287
288	int err = 0;
289	err += st_check_type(&stbuf, st->st_mode & S_IFMT);
290	err += st_check_mode(&stbuf, st->st_mode & ALLPERMS);
291	err += st_check_size(&stbuf, st->st_size);
292	err += st_check_nlink(&stbuf, st->st_nlink);
293
294	return err;
295}
296
297static int check_nonexist(const char *path)
298{
299	struct stat stbuf;
300	int res = lstat(path, &stbuf);
301	if (res == 0) {
302		ERROR("file should not exist");
303		return -1;
304	}
305	if (errno != ENOENT) {
306		ERROR("file should not exist: %s", strerror(errno));
307		return -1;
308	}
309	return 0;
310}
311
312static int check_buffer(const char *buf, const char *data, unsigned len)
313{
314	if (memcmp(buf, data, len) != 0) {
315		ERROR("data mismatch");
316		return -1;
317	}
318	return 0;
319}
320
321static int check_data(const char *path, const char *data, int offset,
322		      unsigned len)
323{
324	char buf[4096];
325	int res;
326	int fd = open(path, O_RDONLY);
327	if (fd == -1) {
328		PERROR("open");
329		return -1;
330	}
331	if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
332		PERROR("lseek");
333		close(fd);
334		return -1;
335	}
336	while (len) {
337		int rdlen = len < sizeof(buf) ? len : sizeof(buf);
338		res = read(fd, buf, rdlen);
339		if (res == -1) {
340			PERROR("read");
341			close(fd);
342			return -1;
343		}
344		if (res != rdlen) {
345			ERROR("short read: %u instead of %u", res, rdlen);
346			close(fd);
347			return -1;
348		}
349		if (check_buffer(buf, data, rdlen) != 0) {
350			close(fd);
351			return -1;
352		}
353		data += rdlen;
354		len -= rdlen;
355	}
356	res = close(fd);
357	if (res == -1) {
358		PERROR("close");
359		return -1;
360	}
361	return 0;
362}
363
364static int fcheck_data(int fd, const char *data, int offset,
365		       unsigned len)
366{
367	char buf[4096];
368	int res;
369	if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
370		PERROR("lseek");
371		return -1;
372	}
373	while (len) {
374		int rdlen = len < sizeof(buf) ? len : sizeof(buf);
375		res = read(fd, buf, rdlen);
376		if (res == -1) {
377			PERROR("read");
378			return -1;
379		}
380		if (res != rdlen) {
381			ERROR("short read: %u instead of %u", res, rdlen);
382			return -1;
383		}
384		if (check_buffer(buf, data, rdlen) != 0) {
385			return -1;
386		}
387		data += rdlen;
388		len -= rdlen;
389	}
390	return 0;
391}
392
393static int check_dir_contents(const char *path, const char **contents)
394{
395	int i;
396	int res;
397	int err = 0;
398	int found[MAX_ENTRIES];
399	const char *cont[MAX_ENTRIES];
400	DIR *dp;
401
402	for (i = 0; contents[i]; i++) {
403		assert(i < MAX_ENTRIES - 3);
404		found[i] = 0;
405		cont[i] = contents[i];
406	}
407	cont[i] = NULL;
408
409	dp = opendir(path);
410	if (dp == NULL) {
411		PERROR("opendir");
412		return -1;
413	}
414	memset(found, 0, sizeof(found));
415	while(1) {
416		struct dirent *de;
417		errno = 0;
418		de = readdir(dp);
419		if (de == NULL) {
420			if (errno) {
421				PERROR("readdir");
422				closedir(dp);
423				return -1;
424			}
425			break;
426		}
427		if (is_dot_or_dotdot(de->d_name))
428			continue;
429		for (i = 0; cont[i] != NULL; i++) {
430			assert(i < MAX_ENTRIES);
431			if (strcmp(cont[i], de->d_name) == 0) {
432				if (found[i]) {
433					ERROR("duplicate entry <%s>",
434					      de->d_name);
435					err--;
436				} else
437					found[i] = 1;
438				break;
439			}
440		}
441		if (!cont[i]) {
442			ERROR("unexpected entry <%s>", de->d_name);
443			err --;
444		}
445	}
446	for (i = 0; cont[i] != NULL; i++) {
447		if (!found[i]) {
448			ERROR("missing entry <%s>", cont[i]);
449			err--;
450		}
451	}
452	res = closedir(dp);
453	if (res == -1) {
454		PERROR("closedir");
455		return -1;
456	}
457	if (err)
458		return -1;
459
460	return 0;
461}
462
463static int create_file(const char *path, const char *data, int len)
464{
465	int res;
466	int fd;
467
468	unlink(path);
469	fd = creat(path, 0644);
470	if (fd == -1) {
471		PERROR("creat");
472		return -1;
473	}
474	if (len) {
475		res = write(fd, data, len);
476		if (res == -1) {
477			PERROR("write");
478			close(fd);
479			return -1;
480		}
481		if (res != len) {
482			ERROR("write is short: %u instead of %u", res, len);
483			close(fd);
484			return -1;
485		}
486	}
487	res = close(fd);
488	if (res == -1) {
489		PERROR("close");
490		return -1;
491	}
492	res = check_type(path, S_IFREG);
493	if (res == -1)
494		return -1;
495	res = check_mode(path, 0644);
496	if (res == -1)
497		return -1;
498	res = check_nlink(path, 1);
499	if (res == -1)
500		return -1;
501	res = check_size(path, len);
502	if (res == -1)
503		return -1;
504
505	if (len) {
506		res = check_data(path, data, 0, len);
507		if (res == -1)
508			return -1;
509	}
510
511	return 0;
512}
513
514static int create_path_fd(const char *path, const char *data, int len)
515{
516	int path_fd;
517	int res;
518
519	res = create_file(path, data, len);
520	if (res == -1)
521		return -1;
522
523	path_fd = open(path, O_PATH);
524	if (path_fd == -1)
525		PERROR("open(O_PATH)");
526
527	return path_fd;
528}
529
530// Can be called once per test
531static int create_testfile(const char *path, const char *data, int len)
532{
533	struct test *t = this_test;
534	struct stat *st = &t->stat;
535	int res, fd;
536
537	if (t->fd > 0) {
538		ERROR("testfile already created");
539		return -1;
540	}
541
542	fd = create_path_fd(path, data, len);
543	if (fd == -1)
544		return -1;
545
546	t->fd = fd;
547
548	res = fstat(fd, st);
549	if (res == -1) {
550		PERROR("fstat");
551		return -1;
552	}
553
554	return 0;
555}
556
557static int check_unlinked_testfile(int fd)
558{
559	struct stat *st = &this_test->stat;
560
561	st->st_nlink = 0;
562	return fcheck_stat(fd, O_PATH, st);
563}
564
565// Check recorded testfiles after all tests completed
566static int check_unlinked_testfiles(void)
567{
568	int fd;
569	int res, err = 0;
570	int num = testnum;
571
572	if (!unlinked_test)
573		return 0;
574
575	testnum = 0;
576	while (testnum < num) {
577		fd = next_test->fd;
578		start_test("check_unlinked_testfile");
579		if (fd == -1)
580			continue;
581
582		err += check_unlinked_testfile(fd);
583		res = close(fd);
584		if (res == -1) {
585			PERROR("close(test_fd)");
586			err--;
587		}
588	}
589
590	if (err) {
591		fprintf(stderr, "%i unlinked testfile checks failed\n", -err);
592		return 1;
593	}
594
595	return err;
596}
597
598static int cleanup_dir(const char *path, const char **dir_files, int quiet)
599{
600	int i;
601	int err = 0;
602
603	for (i = 0; dir_files[i]; i++) {
604		int res;
605		char fpath[1280];
606		sprintf(fpath, "%s/%s", path, dir_files[i]);
607		res = unlink(fpath);
608		if (res == -1 && !quiet) {
609			PERROR("unlink");
610			err --;
611		}
612	}
613	if (err)
614		return -1;
615
616	return 0;
617}
618
619static int create_dir(const char *path, const char **dir_files)
620{
621	int res;
622	int i;
623
624	rmdir(path);
625	res = mkdir(path, 0755);
626	if (res == -1) {
627		PERROR("mkdir");
628		return -1;
629	}
630	res = check_type(path, S_IFDIR);
631	if (res == -1)
632		return -1;
633	res = check_mode(path, 0755);
634	if (res == -1)
635		return -1;
636
637	for (i = 0; dir_files[i]; i++) {
638		char fpath[1280];
639		sprintf(fpath, "%s/%s", path, dir_files[i]);
640		res = create_file(fpath, "", 0);
641		if (res == -1) {
642			cleanup_dir(path, dir_files, 1);
643			return -1;
644		}
645	}
646	res = check_dir_contents(path, dir_files);
647	if (res == -1) {
648		cleanup_dir(path, dir_files, 1);
649		return -1;
650	}
651
652	return 0;
653}
654
655static int test_truncate(int len)
656{
657	const char *data = testdata;
658	int datalen = testdatalen;
659	int res;
660
661	start_test("truncate(%u)", (int) len);
662	res = create_testfile(testfile, data, datalen);
663	if (res == -1)
664		return -1;
665
666	res = truncate(testfile, len);
667	if (res == -1) {
668		PERROR("truncate");
669		return -1;
670	}
671	res = check_testfile_size(testfile, len);
672	if (res == -1)
673		return -1;
674
675	if (len > 0) {
676		if (len <= datalen) {
677			res = check_data(testfile, data, 0, len);
678			if (res == -1)
679				return -1;
680		} else {
681			res = check_data(testfile, data, 0, datalen);
682			if (res == -1)
683				return -1;
684			res = check_data(testfile, zerodata, datalen,
685					 len - datalen);
686			if (res == -1)
687				return -1;
688		}
689	}
690	res = unlink(testfile);
691	if (res == -1) {
692		PERROR("unlink");
693		return -1;
694	}
695	res = check_nonexist(testfile);
696	if (res == -1)
697		return -1;
698
699	success();
700	return 0;
701}
702
703static int test_ftruncate(int len, int mode)
704{
705	const char *data = testdata;
706	int datalen = testdatalen;
707	int res;
708	int fd;
709
710	start_test("ftruncate(%u) mode: 0%03o", len, mode);
711	res = create_testfile(testfile, data, datalen);
712	if (res == -1)
713		return -1;
714
715	fd = open(testfile, O_WRONLY);
716	if (fd == -1) {
717		PERROR("open");
718		return -1;
719	}
720
721	res = fchmod(fd, mode);
722	if (res == -1) {
723		PERROR("fchmod");
724		close(fd);
725		return -1;
726	}
727	res = check_testfile_mode(testfile, mode);
728	if (res == -1) {
729		close(fd);
730		return -1;
731	}
732	res = ftruncate(fd, len);
733	if (res == -1) {
734		PERROR("ftruncate");
735		close(fd);
736		return -1;
737	}
738	close(fd);
739	res = check_testfile_size(testfile, len);
740	if (res == -1)
741		return -1;
742
743	if (len > 0) {
744		if (len <= datalen) {
745			res = check_data(testfile, data, 0, len);
746			if (res == -1)
747				return -1;
748		} else {
749			res = check_data(testfile, data, 0, datalen);
750			if (res == -1)
751				return -1;
752			res = check_data(testfile, zerodata, datalen,
753					 len - datalen);
754			if (res == -1)
755				return -1;
756		}
757	}
758	res = unlink(testfile);
759	if (res == -1) {
760		PERROR("unlink");
761		return -1;
762	}
763	res = check_nonexist(testfile);
764	if (res == -1)
765		return -1;
766
767	success();
768	return 0;
769}
770
771static int test_seekdir(void)
772{
773	int i;
774	int res;
775	DIR *dp;
776	struct dirent *de;
777
778	start_test("seekdir");
779	res = create_dir(testdir, testdir_files);
780	if (res == -1)
781		return res;
782
783	dp = opendir(testdir);
784	if (dp == NULL) {
785		PERROR("opendir");
786		return -1;
787	}
788
789	/* Remember dir offsets */
790	for (i = 0; i < ARRAY_SIZE(seekdir_offsets); i++) {
791		seekdir_offsets[i] = telldir(dp);
792		errno = 0;
793		de = readdir(dp);
794		if (de == NULL) {
795			if (errno) {
796				PERROR("readdir");
797				goto fail;
798			}
799			break;
800		}
801	}
802
803	/* Walk until the end of directory */
804	while (de)
805		de = readdir(dp);
806
807	/* Start from the last valid dir offset and seek backwards */
808	for (i--; i >= 0; i--) {
809		seekdir(dp, seekdir_offsets[i]);
810		de = readdir(dp);
811		if (de == NULL) {
812			ERROR("Unexpected end of directory after seekdir()");
813			goto fail;
814		}
815	}
816
817	closedir(dp);
818	res = cleanup_dir(testdir, testdir_files, 0);
819	if (!res)
820		success();
821	return res;
822fail:
823	closedir(dp);
824	cleanup_dir(testdir, testdir_files, 1);
825	return -1;
826}
827
828#ifdef HAVE_COPY_FILE_RANGE
829static int test_copy_file_range(void)
830{
831	const char *data = testdata;
832	int datalen = testdatalen;
833	int err = 0;
834	int res;
835	int fd_in, fd_out;
836	off_t pos_in = 0, pos_out = 0;
837
838	start_test("copy_file_range");
839	unlink(testfile);
840	fd_in = open(testfile, O_CREAT | O_RDWR, 0644);
841	if (fd_in == -1) {
842		PERROR("creat");
843		return -1;
844	}
845	res = write(fd_in, data, datalen);
846	if (res == -1) {
847		PERROR("write");
848		close(fd_in);
849		return -1;
850	}
851	if (res != datalen) {
852		ERROR("write is short: %u instead of %u", res, datalen);
853		close(fd_in);
854		return -1;
855	}
856
857	unlink(testfile2);
858	fd_out = creat(testfile2, 0644);
859	if (fd_out == -1) {
860		PERROR("creat");
861		close(fd_in);
862		return -1;
863	}
864	res = copy_file_range(fd_in, &pos_in, fd_out, &pos_out, datalen, 0);
865	if (res == -1) {
866		PERROR("copy_file_range");
867		close(fd_in);
868		close(fd_out);
869		return -1;
870	}
871	if (res != datalen) {
872		ERROR("copy is short: %u instead of %u", res, datalen);
873		close(fd_in);
874		close(fd_out);
875		return -1;
876	}
877
878	res = close(fd_in);
879	if (res == -1) {
880		PERROR("close");
881		close(fd_out);
882		return -1;
883	}
884	res = close(fd_out);
885	if (res == -1) {
886		PERROR("close");
887		return -1;
888	}
889
890	err = check_data(testfile2, data, 0, datalen);
891
892	res = unlink(testfile);
893	if (res == -1) {
894		PERROR("unlink");
895		return -1;
896	}
897	res = check_nonexist(testfile);
898	if (res == -1)
899		return -1;
900	if (err)
901		return -1;
902
903	res = unlink(testfile2);
904	if (res == -1) {
905		PERROR("unlink");
906		return -1;
907	}
908	res = check_nonexist(testfile2);
909	if (res == -1)
910		return -1;
911	if (err)
912		return -1;
913
914	success();
915	return 0;
916}
917#else
918static int test_copy_file_range(void)
919{
920	return 0;
921}
922#endif
923
924static int test_utime(void)
925{
926	struct utimbuf utm;
927	time_t atime = 987631200;
928	time_t mtime = 123116400;
929	int res;
930
931	start_test("utime");
932	res = create_testfile(testfile, NULL, 0);
933	if (res == -1)
934		return -1;
935
936	utm.actime = atime;
937	utm.modtime = mtime;
938	res = utime(testfile, &utm);
939	if (res == -1) {
940		PERROR("utime");
941		return -1;
942	}
943	res = check_times(testfile, atime, mtime);
944	if (res == -1) {
945		return -1;
946	}
947	res = unlink(testfile);
948	if (res == -1) {
949		PERROR("unlink");
950		return -1;
951	}
952	res = check_nonexist(testfile);
953	if (res == -1)
954		return -1;
955
956	success();
957	return 0;
958}
959
960static int test_create(void)
961{
962	const char *data = testdata;
963	int datalen = testdatalen;
964	int err = 0;
965	int res;
966	int fd;
967
968	start_test("create");
969	unlink(testfile);
970	fd = creat(testfile, 0644);
971	if (fd == -1) {
972		PERROR("creat");
973		return -1;
974	}
975	res = write(fd, data, datalen);
976	if (res == -1) {
977		PERROR("write");
978		close(fd);
979		return -1;
980	}
981	if (res != datalen) {
982		ERROR("write is short: %u instead of %u", res, datalen);
983		close(fd);
984		return -1;
985	}
986	res = close(fd);
987	if (res == -1) {
988		PERROR("close");
989		return -1;
990	}
991	res = check_type(testfile, S_IFREG);
992	if (res == -1)
993		return -1;
994	err += check_mode(testfile, 0644);
995	err += check_nlink(testfile, 1);
996	err += check_size(testfile, datalen);
997	err += check_data(testfile, data, 0, datalen);
998	res = unlink(testfile);
999	if (res == -1) {
1000		PERROR("unlink");
1001		return -1;
1002	}
1003	res = check_nonexist(testfile);
1004	if (res == -1)
1005		return -1;
1006	if (err)
1007		return -1;
1008
1009	success();
1010	return 0;
1011}
1012
1013static int test_create_unlink(void)
1014{
1015	const char *data = testdata;
1016	int datalen = testdatalen;
1017	int err = 0;
1018	int res;
1019	int fd;
1020
1021	start_test("create+unlink");
1022	unlink(testfile);
1023	fd = open(testfile, O_CREAT | O_RDWR | O_TRUNC, 0644);
1024	if (fd == -1) {
1025		PERROR("creat");
1026		return -1;
1027	}
1028	res = unlink(testfile);
1029	if (res == -1) {
1030		PERROR("unlink");
1031		close(fd);
1032		return -1;
1033	}
1034	res = check_nonexist(testfile);
1035	if (res == -1) {
1036		close(fd);
1037		return -1;
1038	}
1039	res = write(fd, data, datalen);
1040	if (res == -1) {
1041		PERROR("write");
1042		close(fd);
1043		return -1;
1044	}
1045	if (res != datalen) {
1046		ERROR("write is short: %u instead of %u", res, datalen);
1047		close(fd);
1048		return -1;
1049	}
1050	struct stat st = {
1051		.st_mode = S_IFREG | 0644,
1052		.st_size = datalen,
1053	};
1054	err = fcheck_stat(fd, O_RDWR, &st);
1055	err += fcheck_data(fd, data, 0, datalen);
1056	res = close(fd);
1057	if (res == -1) {
1058		PERROR("close");
1059		err--;
1060	}
1061	if (err)
1062		return -1;
1063
1064	success();
1065	return 0;
1066}
1067
1068#ifndef __FreeBSD__
1069static int test_mknod(void)
1070{
1071	int err = 0;
1072	int res;
1073
1074	start_test("mknod");
1075	unlink(testfile);
1076	res = mknod(testfile, 0644, 0);
1077	if (res == -1) {
1078		PERROR("mknod");
1079		return -1;
1080	}
1081	res = check_type(testfile, S_IFREG);
1082	if (res == -1)
1083		return -1;
1084	err += check_mode(testfile, 0644);
1085	err += check_nlink(testfile, 1);
1086	err += check_size(testfile, 0);
1087	res = unlink(testfile);
1088	if (res == -1) {
1089		PERROR("unlink");
1090		return -1;
1091	}
1092	res = check_nonexist(testfile);
1093	if (res == -1)
1094		return -1;
1095	if (err)
1096		return -1;
1097
1098	success();
1099	return 0;
1100}
1101#endif
1102
1103#define test_open(exist, flags, mode)  do_test_open(exist, flags, #flags, mode)
1104
1105static int do_test_open(int exist, int flags, const char *flags_str, int mode)
1106{
1107	char buf[4096];
1108	const char *data = testdata;
1109	int datalen = testdatalen;
1110	unsigned currlen = 0;
1111	int err = 0;
1112	int res;
1113	int fd;
1114	off_t off;
1115
1116	start_test("open(%s, %s, 0%03o)", exist ? "+" : "-", flags_str, mode);
1117	unlink(testfile);
1118	if (exist) {
1119		res = create_file(testfile_r, testdata2, testdata2len);
1120		if (res == -1)
1121			return -1;
1122
1123		currlen = testdata2len;
1124	}
1125
1126	fd = open(testfile, flags, mode);
1127	if ((flags & O_CREAT) && (flags & O_EXCL) && exist) {
1128		if (fd != -1) {
1129			ERROR("open should have failed");
1130			close(fd);
1131			return -1;
1132		} else if (errno == EEXIST)
1133			goto succ;
1134	}
1135	if (!(flags & O_CREAT) && !exist) {
1136		if (fd != -1) {
1137			ERROR("open should have failed");
1138			close(fd);
1139			return -1;
1140		} else if (errno == ENOENT)
1141			goto succ;
1142	}
1143	if (fd == -1) {
1144		PERROR("open");
1145		return -1;
1146	}
1147
1148	if (flags & O_TRUNC)
1149		currlen = 0;
1150
1151	err += check_type(testfile, S_IFREG);
1152	if (exist)
1153		err += check_mode(testfile, 0644);
1154	else
1155		err += check_mode(testfile, mode);
1156	err += check_nlink(testfile, 1);
1157	err += check_size(testfile, currlen);
1158	if (exist && !(flags & O_TRUNC) && (mode & S_IRUSR))
1159		err += check_data(testfile, testdata2, 0, testdata2len);
1160
1161	res = write(fd, data, datalen);
1162	if ((flags & O_ACCMODE) != O_RDONLY) {
1163		if (res == -1) {
1164			PERROR("write");
1165			err --;
1166		} else if (res != datalen) {
1167			ERROR("write is short: %u instead of %u", res, datalen);
1168			err --;
1169		} else {
1170			if (datalen > (int) currlen)
1171				currlen = datalen;
1172
1173			err += check_size(testfile, currlen);
1174
1175			if (mode & S_IRUSR) {
1176				err += check_data(testfile, data, 0, datalen);
1177				if (exist && !(flags & O_TRUNC) &&
1178				    testdata2len > datalen)
1179					err += check_data(testfile,
1180							  testdata2 + datalen,
1181							  datalen,
1182							  testdata2len - datalen);
1183			}
1184		}
1185	} else {
1186		if (res != -1) {
1187			ERROR("write should have failed");
1188			err --;
1189		} else if (errno != EBADF) {
1190			PERROR("write");
1191			err --;
1192		}
1193	}
1194	off = lseek(fd, SEEK_SET, 0);
1195	if (off == (off_t) -1) {
1196		PERROR("lseek");
1197		err--;
1198	} else if (off != 0) {
1199		ERROR("offset should have returned 0");
1200		err --;
1201	}
1202	res = read(fd, buf, sizeof(buf));
1203	if ((flags & O_ACCMODE) != O_WRONLY) {
1204		if (res == -1) {
1205			PERROR("read");
1206			err--;
1207		} else {
1208			int readsize =
1209				currlen < sizeof(buf) ? currlen : sizeof(buf);
1210			if (res != readsize) {
1211				ERROR("read is short: %i instead of %u",
1212				      res, readsize);
1213				err--;
1214			} else {
1215				if ((flags & O_ACCMODE) != O_RDONLY) {
1216					err += check_buffer(buf, data, datalen);
1217					if (exist && !(flags & O_TRUNC) &&
1218					    testdata2len > datalen)
1219						err += check_buffer(buf + datalen,
1220								    testdata2 + datalen,
1221								    testdata2len - datalen);
1222				} else if (exist)
1223					err += check_buffer(buf, testdata2,
1224							    testdata2len);
1225			}
1226		}
1227	} else {
1228		if (res != -1) {
1229			ERROR("read should have failed");
1230			err --;
1231		} else if (errno != EBADF) {
1232			PERROR("read");
1233			err --;
1234		}
1235	}
1236
1237	res = close(fd);
1238	if (res == -1) {
1239		PERROR("close");
1240		return -1;
1241	}
1242	res = unlink(testfile);
1243	if (res == -1) {
1244		PERROR("unlink");
1245		return -1;
1246	}
1247	res = check_nonexist(testfile);
1248	if (res == -1)
1249		return -1;
1250	res = check_nonexist(testfile_r);
1251	if (res == -1)
1252		return -1;
1253	if (err)
1254		return -1;
1255
1256succ:
1257	success();
1258	return 0;
1259}
1260
1261#define test_open_acc(flags, mode, err)	 \
1262	do_test_open_acc(flags, #flags, mode, err)
1263
1264static int do_test_open_acc(int flags, const char *flags_str, int mode, int err)
1265{
1266	const char *data = testdata;
1267	int datalen = testdatalen;
1268	int res;
1269	int fd;
1270
1271	start_test("open_acc(%s) mode: 0%03o message: '%s'", flags_str, mode,
1272		   strerror(err));
1273	unlink(testfile);
1274	res = create_testfile(testfile, data, datalen);
1275	if (res == -1)
1276		return -1;
1277
1278	res = chmod(testfile, mode);
1279	if (res == -1) {
1280		PERROR("chmod");
1281		return -1;
1282	}
1283
1284	res = check_testfile_mode(testfile, mode);
1285	if (res == -1)
1286		return -1;
1287
1288	fd = open(testfile, flags);
1289	if (fd == -1) {
1290		if (err != errno) {
1291			PERROR("open");
1292			return -1;
1293		}
1294	} else {
1295		if (err) {
1296			ERROR("open should have failed");
1297			close(fd);
1298			return -1;
1299		}
1300		close(fd);
1301	}
1302
1303	res = unlink(testfile);
1304	if (res == -1) {
1305		PERROR("unlink");
1306		return -1;
1307	}
1308	res = check_nonexist(testfile);
1309	if (res == -1)
1310		return -1;
1311	res = check_nonexist(testfile_r);
1312	if (res == -1)
1313		return -1;
1314
1315	success();
1316	return 0;
1317}
1318
1319static int test_symlink(void)
1320{
1321	char buf[1024];
1322	const char *data = testdata;
1323	int datalen = testdatalen;
1324	int linklen = strlen(testfile);
1325	int err = 0;
1326	int res;
1327
1328	start_test("symlink");
1329	res = create_testfile(testfile, data, datalen);
1330	if (res == -1)
1331		return -1;
1332
1333	unlink(testfile2);
1334	res = symlink(testfile, testfile2);
1335	if (res == -1) {
1336		PERROR("symlink");
1337		return -1;
1338	}
1339	res = check_type(testfile2, S_IFLNK);
1340	if (res == -1)
1341		return -1;
1342	err += check_mode(testfile2, 0777);
1343	err += check_nlink(testfile2, 1);
1344	res = readlink(testfile2, buf, sizeof(buf));
1345	if (res == -1) {
1346		PERROR("readlink");
1347		err--;
1348	}
1349	if (res != linklen) {
1350		ERROR("short readlink: %u instead of %u", res, linklen);
1351		err--;
1352	}
1353	if (memcmp(buf, testfile, linklen) != 0) {
1354		ERROR("link mismatch");
1355		err--;
1356	}
1357	err += check_size(testfile2, datalen);
1358	err += check_data(testfile2, data, 0, datalen);
1359	res = unlink(testfile2);
1360	if (res == -1) {
1361		PERROR("unlink");
1362		return -1;
1363	}
1364	res = check_nonexist(testfile2);
1365	if (res == -1)
1366		return -1;
1367	if (err)
1368		return -1;
1369
1370	res = unlink(testfile);
1371	if (res == -1) {
1372		PERROR("unlink");
1373		return -1;
1374	}
1375	res = check_nonexist(testfile);
1376	if (res == -1)
1377		return -1;
1378
1379	success();
1380	return 0;
1381}
1382
1383static int test_link(void)
1384{
1385	const char *data = testdata;
1386	int datalen = testdatalen;
1387	int err = 0;
1388	int res;
1389
1390	start_test("link");
1391	res = create_testfile(testfile, data, datalen);
1392	if (res == -1)
1393		return -1;
1394
1395	unlink(testfile2);
1396	res = link(testfile, testfile2);
1397	if (res == -1) {
1398		PERROR("link");
1399		return -1;
1400	}
1401	res = check_type(testfile2, S_IFREG);
1402	if (res == -1)
1403		return -1;
1404	err += check_mode(testfile2, 0644);
1405	err += check_nlink(testfile2, 2);
1406	err += check_size(testfile2, datalen);
1407	err += check_data(testfile2, data, 0, datalen);
1408	res = unlink(testfile);
1409	if (res == -1) {
1410		PERROR("unlink");
1411		return -1;
1412	}
1413	res = check_nonexist(testfile);
1414	if (res == -1)
1415		return -1;
1416
1417	err += check_nlink(testfile2, 1);
1418	res = unlink(testfile2);
1419	if (res == -1) {
1420		PERROR("unlink");
1421		return -1;
1422	}
1423	res = check_nonexist(testfile2);
1424	if (res == -1)
1425		return -1;
1426	if (err)
1427		return -1;
1428
1429	success();
1430	return 0;
1431}
1432
1433static int test_link2(void)
1434{
1435	const char *data = testdata;
1436	int datalen = testdatalen;
1437	int err = 0;
1438	int res;
1439
1440	start_test("link-unlink-link");
1441	res = create_testfile(testfile, data, datalen);
1442	if (res == -1)
1443		return -1;
1444
1445	unlink(testfile2);
1446	res = link(testfile, testfile2);
1447	if (res == -1) {
1448		PERROR("link");
1449		return -1;
1450	}
1451	res = unlink(testfile);
1452	if (res == -1) {
1453		PERROR("unlink");
1454		return -1;
1455	}
1456	res = check_nonexist(testfile);
1457	if (res == -1)
1458		return -1;
1459	res = link(testfile2, testfile);
1460	if (res == -1) {
1461		PERROR("link");
1462	}
1463	res = check_type(testfile, S_IFREG);
1464	if (res == -1)
1465		return -1;
1466	err += check_mode(testfile, 0644);
1467	err += check_nlink(testfile, 2);
1468	err += check_size(testfile, datalen);
1469	err += check_data(testfile, data, 0, datalen);
1470
1471	res = unlink(testfile2);
1472	if (res == -1) {
1473		PERROR("unlink");
1474		return -1;
1475	}
1476	err += check_nlink(testfile, 1);
1477	res = unlink(testfile);
1478	if (res == -1) {
1479		PERROR("unlink");
1480		return -1;
1481	}
1482	res = check_nonexist(testfile);
1483	if (res == -1)
1484		return -1;
1485	if (err)
1486		return -1;
1487
1488	success();
1489	return 0;
1490}
1491
1492static int test_rename_file(void)
1493{
1494	const char *data = testdata;
1495	int datalen = testdatalen;
1496	int err = 0;
1497	int res;
1498
1499	start_test("rename file");
1500	res = create_testfile(testfile, data, datalen);
1501	if (res == -1)
1502		return -1;
1503
1504	unlink(testfile2);
1505	res = rename(testfile, testfile2);
1506	if (res == -1) {
1507		PERROR("rename");
1508		return -1;
1509	}
1510	res = check_nonexist(testfile);
1511	if (res == -1)
1512		return -1;
1513	res = check_type(testfile2, S_IFREG);
1514	if (res == -1)
1515		return -1;
1516	err += check_mode(testfile2, 0644);
1517	err += check_nlink(testfile2, 1);
1518	err += check_size(testfile2, datalen);
1519	err += check_data(testfile2, data, 0, datalen);
1520	res = unlink(testfile2);
1521	if (res == -1) {
1522		PERROR("unlink");
1523		return -1;
1524	}
1525	res = check_nonexist(testfile2);
1526	if (res == -1)
1527		return -1;
1528	if (err)
1529		return -1;
1530
1531	success();
1532	return 0;
1533}
1534
1535static int test_rename_dir(void)
1536{
1537	int err = 0;
1538	int res;
1539
1540	start_test("rename dir");
1541	res = create_dir(testdir, testdir_files);
1542	if (res == -1)
1543		return -1;
1544
1545	rmdir(testdir2);
1546	res = rename(testdir, testdir2);
1547	if (res == -1) {
1548		PERROR("rename");
1549		cleanup_dir(testdir, testdir_files, 1);
1550		return -1;
1551	}
1552	res = check_nonexist(testdir);
1553	if (res == -1) {
1554		cleanup_dir(testdir, testdir_files, 1);
1555		return -1;
1556	}
1557	res = check_type(testdir2, S_IFDIR);
1558	if (res == -1) {
1559		cleanup_dir(testdir2, testdir_files, 1);
1560		return -1;
1561	}
1562	err += check_mode(testdir2, 0755);
1563	err += check_dir_contents(testdir2, testdir_files);
1564	err += cleanup_dir(testdir2, testdir_files, 0);
1565	res = rmdir(testdir2);
1566	if (res == -1) {
1567		PERROR("rmdir");
1568		return -1;
1569	}
1570	res = check_nonexist(testdir2);
1571	if (res == -1)
1572		return -1;
1573	if (err)
1574		return -1;
1575
1576	success();
1577	return 0;
1578}
1579
1580static int test_rename_dir_loop(void)
1581{
1582#define PATH(p)		(snprintf(path, sizeof path, "%s/%s", testdir, p), path)
1583#define PATH2(p)	(snprintf(path2, sizeof path2, "%s/%s", testdir, p), path2)
1584
1585	char path[1280], path2[1280];
1586	int err = 0;
1587	int res;
1588
1589	start_test("rename dir loop");
1590
1591	res = create_dir(testdir, testdir_files);
1592	if (res == -1)
1593		return -1;
1594
1595	res = mkdir(PATH("a"), 0755);
1596	if (res == -1) {
1597		PERROR("mkdir");
1598		goto fail;
1599	}
1600
1601	res = rename(PATH("a"), PATH2("a"));
1602	if (res == -1) {
1603		PERROR("rename");
1604		goto fail;
1605	}
1606
1607	errno = 0;
1608	res = rename(PATH("a"), PATH2("a/b"));
1609	if (res == 0 || errno != EINVAL) {
1610		PERROR("rename");
1611		goto fail;
1612	}
1613
1614	res = mkdir(PATH("a/b"), 0755);
1615	if (res == -1) {
1616		PERROR("mkdir");
1617		goto fail;
1618	}
1619
1620	res = mkdir(PATH("a/b/c"), 0755);
1621	if (res == -1) {
1622		PERROR("mkdir");
1623		goto fail;
1624	}
1625
1626	errno = 0;
1627	res = rename(PATH("a"), PATH2("a/b/c"));
1628	if (res == 0 || errno != EINVAL) {
1629		PERROR("rename");
1630		goto fail;
1631	}
1632
1633	errno = 0;
1634	res = rename(PATH("a"), PATH2("a/b/c/a"));
1635	if (res == 0 || errno != EINVAL) {
1636		PERROR("rename");
1637		goto fail;
1638	}
1639
1640	errno = 0;
1641	res = rename(PATH("a/b/c"), PATH2("a"));
1642	if (res == 0 || errno != ENOTEMPTY) {
1643		PERROR("rename");
1644		goto fail;
1645	}
1646
1647	res = open(PATH("a/foo"), O_CREAT, 0644);
1648	if (res == -1) {
1649		PERROR("open");
1650		goto fail;
1651	}
1652	close(res);
1653
1654	res = rename(PATH("a/foo"), PATH2("a/bar"));
1655	if (res == -1) {
1656		PERROR("rename");
1657		goto fail;
1658	}
1659
1660	res = rename(PATH("a/bar"), PATH2("a/foo"));
1661	if (res == -1) {
1662		PERROR("rename");
1663		goto fail;
1664	}
1665
1666	res = rename(PATH("a/foo"), PATH2("a/b/bar"));
1667	if (res == -1) {
1668		PERROR("rename");
1669		goto fail;
1670	}
1671
1672	res = rename(PATH("a/b/bar"), PATH2("a/foo"));
1673	if (res == -1) {
1674		PERROR("rename");
1675		goto fail;
1676	}
1677
1678	res = rename(PATH("a/foo"), PATH2("a/b/c/bar"));
1679	if (res == -1) {
1680		PERROR("rename");
1681		goto fail;
1682	}
1683
1684	res = rename(PATH("a/b/c/bar"), PATH2("a/foo"));
1685	if (res == -1) {
1686		PERROR("rename");
1687		goto fail;
1688	}
1689
1690	res = open(PATH("a/bar"), O_CREAT, 0644);
1691	if (res == -1) {
1692		PERROR("open");
1693		goto fail;
1694	}
1695	close(res);
1696
1697	res = rename(PATH("a/foo"), PATH2("a/bar"));
1698	if (res == -1) {
1699		PERROR("rename");
1700		goto fail;
1701	}
1702
1703	unlink(PATH("a/bar"));
1704
1705	res = rename(PATH("a/b"), PATH2("a/d"));
1706	if (res == -1) {
1707		PERROR("rename");
1708		goto fail;
1709	}
1710
1711	res = rename(PATH("a/d"), PATH2("a/b"));
1712	if (res == -1) {
1713		PERROR("rename");
1714		goto fail;
1715	}
1716
1717	res = mkdir(PATH("a/d"), 0755);
1718	if (res == -1) {
1719		PERROR("mkdir");
1720		goto fail;
1721	}
1722
1723	res = rename(PATH("a/b"), PATH2("a/d"));
1724	if (res == -1) {
1725		PERROR("rename");
1726		goto fail;
1727	}
1728
1729	res = rename(PATH("a/d"), PATH2("a/b"));
1730	if (res == -1) {
1731		PERROR("rename");
1732		goto fail;
1733	}
1734
1735	res = mkdir(PATH("a/d"), 0755);
1736	if (res == -1) {
1737		PERROR("mkdir");
1738		goto fail;
1739	}
1740
1741	res = mkdir(PATH("a/d/e"), 0755);
1742	if (res == -1) {
1743		PERROR("mkdir");
1744		goto fail;
1745	}
1746
1747	errno = 0;
1748	res = rename(PATH("a/b"), PATH2("a/d"));
1749	if (res == 0 || (errno != ENOTEMPTY && errno != EEXIST)) {
1750		PERROR("rename");
1751		goto fail;
1752	}
1753
1754	rmdir(PATH("a/d/e"));
1755	rmdir(PATH("a/d"));
1756
1757 	rmdir(PATH("a/b/c"));
1758	rmdir(PATH("a/b"));
1759	rmdir(PATH("a"));
1760
1761	err += cleanup_dir(testdir, testdir_files, 0);
1762	res = rmdir(testdir);
1763	if (res == -1) {
1764		PERROR("rmdir");
1765		goto fail;
1766	}
1767	res = check_nonexist(testdir);
1768	if (res == -1)
1769		return -1;
1770	if (err)
1771		return -1;
1772
1773	success();
1774	return 0;
1775
1776fail:
1777	unlink(PATH("a/bar"));
1778
1779	rmdir(PATH("a/d/e"));
1780	rmdir(PATH("a/d"));
1781
1782 	rmdir(PATH("a/b/c"));
1783	rmdir(PATH("a/b"));
1784	rmdir(PATH("a"));
1785
1786	cleanup_dir(testdir, testdir_files, 1);
1787	rmdir(testdir);
1788
1789	return -1;
1790
1791#undef PATH2
1792#undef PATH
1793}
1794
1795#ifndef __FreeBSD__
1796static int test_mkfifo(void)
1797{
1798	int res;
1799	int err = 0;
1800
1801	start_test("mkfifo");
1802	unlink(testfile);
1803	res = mkfifo(testfile, 0644);
1804	if (res == -1) {
1805		PERROR("mkfifo");
1806		return -1;
1807	}
1808	res = check_type(testfile, S_IFIFO);
1809	if (res == -1)
1810		return -1;
1811	err += check_mode(testfile, 0644);
1812	err += check_nlink(testfile, 1);
1813	res = unlink(testfile);
1814	if (res == -1) {
1815		PERROR("unlink");
1816		return -1;
1817	}
1818	res = check_nonexist(testfile);
1819	if (res == -1)
1820		return -1;
1821	if (err)
1822		return -1;
1823
1824	success();
1825	return 0;
1826}
1827#endif
1828
1829static int test_mkdir(void)
1830{
1831	int res;
1832	int err = 0;
1833	const char *dir_contents[] = {NULL};
1834
1835	start_test("mkdir");
1836	rmdir(testdir);
1837	res = mkdir(testdir, 0755);
1838	if (res == -1) {
1839		PERROR("mkdir");
1840		return -1;
1841	}
1842	res = check_type(testdir, S_IFDIR);
1843	if (res == -1)
1844		return -1;
1845	err += check_mode(testdir, 0755);
1846	/* Some file systems (like btrfs) don't track link
1847	   count for directories */
1848	//err += check_nlink(testdir, 2);
1849	err += check_dir_contents(testdir, dir_contents);
1850	res = rmdir(testdir);
1851	if (res == -1) {
1852		PERROR("rmdir");
1853		return -1;
1854	}
1855	res = check_nonexist(testdir);
1856	if (res == -1)
1857		return -1;
1858	if (err)
1859		return -1;
1860
1861	success();
1862	return 0;
1863}
1864
1865static int test_socket(void)
1866{
1867	struct sockaddr_un su;
1868	int fd;
1869	int res;
1870	int err = 0;
1871    const size_t test_sock_len = strlen(testsock) + 1;
1872
1873	start_test("socket");
1874	if (test_sock_len > sizeof(su.sun_path)) {
1875		fprintf(stderr, "Need to shorten mount point by %zu chars\n",
1876			strlen(testsock) + 1 - sizeof(su.sun_path));
1877		return -1;
1878	}
1879	unlink(testsock);
1880	fd = socket(AF_UNIX, SOCK_STREAM, 0);
1881	if (fd < 0) {
1882		PERROR("socket");
1883		return -1;
1884	}
1885	su.sun_family = AF_UNIX;
1886
1887	strncpy(su.sun_path, testsock, test_sock_len);
1888	su.sun_path[sizeof(su.sun_path) - 1] = '\0';
1889	res = bind(fd, (struct sockaddr*)&su, sizeof(su));
1890	if (res == -1) {
1891		PERROR("bind");
1892		return -1;
1893	}
1894
1895	res = check_type(testsock, S_IFSOCK);
1896	if (res == -1) {
1897		close(fd);
1898		return -1;
1899	}
1900	err += check_nlink(testsock, 1);
1901	close(fd);
1902	res = unlink(testsock);
1903	if (res == -1) {
1904		PERROR("unlink");
1905		return -1;
1906	}
1907	res = check_nonexist(testsock);
1908	if (res == -1)
1909		return -1;
1910	if (err)
1911		return -1;
1912
1913	success();
1914	return 0;
1915}
1916
1917#define test_create_ro_dir(flags)	 \
1918	do_test_create_ro_dir(flags, #flags)
1919
1920static int do_test_create_ro_dir(int flags, const char *flags_str)
1921{
1922	int res;
1923	int err = 0;
1924	int fd;
1925
1926	start_test("open(%s) in read-only directory", flags_str);
1927	rmdir(testdir);
1928	res = mkdir(testdir, 0555);
1929	if (res == -1) {
1930		PERROR("mkdir");
1931		return -1;
1932	}
1933	fd = open(subfile, flags, 0644);
1934	if (fd != -1) {
1935		close(fd);
1936		unlink(subfile);
1937		ERROR("open should have failed");
1938		err--;
1939	} else {
1940		res = check_nonexist(subfile);
1941		if (res == -1)
1942			err--;
1943	}
1944	unlink(subfile);
1945	res = rmdir(testdir);
1946	if (res == -1) {
1947		PERROR("rmdir");
1948		return -1;
1949	}
1950	res = check_nonexist(testdir);
1951	if (res == -1)
1952		return -1;
1953	if (err)
1954		return -1;
1955
1956	success();
1957	return 0;
1958}
1959
1960int main(int argc, char *argv[])
1961{
1962	int err = 0;
1963	int a;
1964	int is_root;
1965
1966	umask(0);
1967	if (argc < 2 || argc > 4) {
1968		fprintf(stderr, "usage: %s testdir [:realdir] [[-]test#] [-u]\n", argv[0]);
1969		return 1;
1970	}
1971	basepath = argv[1];
1972	basepath_r = basepath;
1973	for (a = 2; a < argc; a++) {
1974		char *endptr;
1975		char *arg = argv[a];
1976		if (arg[0] == ':') {
1977			basepath_r = arg + 1;
1978		} else {
1979			if (arg[0] == '-') {
1980				arg++;
1981				if (arg[0] == 'u') {
1982					unlinked_test = 1;
1983					endptr = arg + 1;
1984				} else {
1985					skip_test = strtoul(arg, &endptr, 10);
1986				}
1987			} else {
1988				select_test = strtoul(arg, &endptr, 10);
1989			}
1990			if (arg[0] == '\0' || *endptr != '\0') {
1991				fprintf(stderr, "invalid option: '%s'\n", argv[a]);
1992				return 1;
1993			}
1994		}
1995	}
1996	assert(strlen(basepath) < 512);
1997	assert(strlen(basepath_r) < 512);
1998	if (basepath[0] != '/') {
1999		fprintf(stderr, "testdir must be an absolute path\n");
2000		return 1;
2001	}
2002
2003	sprintf(testfile, "%s/testfile", basepath);
2004	sprintf(testfile2, "%s/testfile2", basepath);
2005	sprintf(testdir, "%s/testdir", basepath);
2006	sprintf(testdir2, "%s/testdir2", basepath);
2007	sprintf(subfile, "%s/subfile", testdir2);
2008	sprintf(testsock, "%s/testsock", basepath);
2009
2010	sprintf(testfile_r, "%s/testfile", basepath_r);
2011	sprintf(testfile2_r, "%s/testfile2", basepath_r);
2012	sprintf(testdir_r, "%s/testdir", basepath_r);
2013	sprintf(testdir2_r, "%s/testdir2", basepath_r);
2014	sprintf(subfile_r, "%s/subfile", testdir2_r);
2015
2016	is_root = (geteuid() == 0);
2017
2018	err += test_create();
2019	err += test_create_unlink();
2020	err += test_symlink();
2021	err += test_link();
2022	err += test_link2();
2023#ifndef __FreeBSD__
2024	err += test_mknod();
2025	err += test_mkfifo();
2026#endif
2027	err += test_mkdir();
2028	err += test_rename_file();
2029	err += test_rename_dir();
2030	err += test_rename_dir_loop();
2031	err += test_seekdir();
2032	err += test_socket();
2033	err += test_utime();
2034	err += test_truncate(0);
2035	err += test_truncate(testdatalen / 2);
2036	err += test_truncate(testdatalen);
2037	err += test_truncate(testdatalen + 100);
2038	err += test_ftruncate(0, 0600);
2039	err += test_ftruncate(testdatalen / 2, 0600);
2040	err += test_ftruncate(testdatalen, 0600);
2041	err += test_ftruncate(testdatalen + 100, 0600);
2042	err += test_ftruncate(0, 0400);
2043	err += test_ftruncate(0, 0200);
2044	err += test_ftruncate(0, 0000);
2045	err += test_open(0, O_RDONLY, 0);
2046	err += test_open(1, O_RDONLY, 0);
2047	err += test_open(1, O_RDWR, 0);
2048	err += test_open(1, O_WRONLY, 0);
2049	err += test_open(0, O_RDWR | O_CREAT, 0600);
2050	err += test_open(1, O_RDWR | O_CREAT, 0600);
2051	err += test_open(0, O_RDWR | O_CREAT | O_TRUNC, 0600);
2052	err += test_open(1, O_RDWR | O_CREAT | O_TRUNC, 0600);
2053	err += test_open(0, O_RDONLY | O_CREAT, 0600);
2054	err += test_open(0, O_RDONLY | O_CREAT, 0400);
2055	err += test_open(0, O_RDONLY | O_CREAT, 0200);
2056	err += test_open(0, O_RDONLY | O_CREAT, 0000);
2057	err += test_open(0, O_WRONLY | O_CREAT, 0600);
2058	err += test_open(0, O_WRONLY | O_CREAT, 0400);
2059	err += test_open(0, O_WRONLY | O_CREAT, 0200);
2060	err += test_open(0, O_WRONLY | O_CREAT, 0000);
2061	err += test_open(0, O_RDWR | O_CREAT, 0400);
2062	err += test_open(0, O_RDWR | O_CREAT, 0200);
2063	err += test_open(0, O_RDWR | O_CREAT, 0000);
2064	err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0600);
2065	err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
2066	err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000);
2067	err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000);
2068	err += test_open_acc(O_RDONLY, 0600, 0);
2069	err += test_open_acc(O_WRONLY, 0600, 0);
2070	err += test_open_acc(O_RDWR,   0600, 0);
2071	err += test_open_acc(O_RDONLY, 0400, 0);
2072	err += test_open_acc(O_WRONLY, 0200, 0);
2073	if(!is_root) {
2074		err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES);
2075		err += test_open_acc(O_WRONLY, 0400, EACCES);
2076		err += test_open_acc(O_RDWR,   0400, EACCES);
2077		err += test_open_acc(O_RDONLY, 0200, EACCES);
2078		err += test_open_acc(O_RDWR,   0200, EACCES);
2079		err += test_open_acc(O_RDONLY, 0000, EACCES);
2080		err += test_open_acc(O_WRONLY, 0000, EACCES);
2081		err += test_open_acc(O_RDWR,   0000, EACCES);
2082	}
2083	err += test_create_ro_dir(O_CREAT);
2084	err += test_create_ro_dir(O_CREAT | O_EXCL);
2085	err += test_create_ro_dir(O_CREAT | O_WRONLY);
2086	err += test_create_ro_dir(O_CREAT | O_TRUNC);
2087	err += test_copy_file_range();
2088
2089	unlink(testfile2);
2090	unlink(testsock);
2091	rmdir(testdir);
2092	rmdir(testdir2);
2093
2094	if (err) {
2095		fprintf(stderr, "%i tests failed\n", -err);
2096		return 1;
2097	}
2098
2099	return check_unlinked_testfiles();
2100}
2101