10 #include <sys/types.h>
14 static char testfile
[1024];
15 static char testfile2
[1024];
16 static char testdir
[1024];
17 static char testdir2
[1024];
18 static char testname
[256];
19 static char testdata
[] = "abcdefghijklmnopqrstuvwxyz";
20 static char testdata2
[] = "1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./";
21 static const char *testdir_files
[] = { "f1", "f2", NULL
};
22 static char zerodata
[4096];
23 static int testdatalen
= sizeof(testdata
) - 1;
24 static int testdata2len
= sizeof(testdata2
) - 1;
26 #define MAX_ENTRIES 1024
28 static void test_perror(const char *func
, const char *msg
)
30 fprintf(stderr
, "[%s] %s() - %s: %s\n", testname
, func
, msg
,
34 static void test_error(const char *func
, const char *msg
, ...)
35 __attribute__ ((format (printf
, 2, 3)));
37 static void start_test(const char *fmt
, ...)
38 __attribute__ ((format (printf
, 1, 2)));
40 static void test_error(const char *func
, const char *msg
, ...)
43 fprintf(stderr
, "[%s] %s() - ", testname
, func
);
45 vfprintf(stderr
, msg
, ap
);
47 fprintf(stderr
, "\n");
50 static void success(void)
52 fprintf(stderr
, "[%s] OK\n", testname
);
55 static void start_test(const char *fmt
, ...)
59 vsprintf(testname
, fmt
, ap
);
63 #define PERROR(msg) test_perror(__FUNCTION__, msg)
64 #define ERROR(msg, args...) test_error(__FUNCTION__, msg, ##args)
66 static int check_size(const char *path
, int len
)
69 int res
= stat(path
, &stbuf
);
74 if (stbuf
.st_size
!= len
) {
75 ERROR("length %u instead of %u", (int) stbuf
.st_size
,
82 static int fcheck_size(int fd
, int len
)
85 int res
= fstat(fd
, &stbuf
);
90 if (stbuf
.st_size
!= len
) {
91 ERROR("length %u instead of %u", (int) stbuf
.st_size
,
98 static int check_type(const char *path
, mode_t type
)
101 int res
= lstat(path
, &stbuf
);
106 if ((stbuf
.st_mode
& S_IFMT
) != type
) {
107 ERROR("type 0%o instead of 0%o", stbuf
.st_mode
& S_IFMT
, type
);
113 static int fcheck_type(int fd
, mode_t type
)
116 int res
= fstat(fd
, &stbuf
);
121 if ((stbuf
.st_mode
& S_IFMT
) != type
) {
122 ERROR("type 0%o instead of 0%o", stbuf
.st_mode
& S_IFMT
, type
);
128 static int check_mode(const char *path
, mode_t mode
)
131 int res
= lstat(path
, &stbuf
);
136 if ((stbuf
.st_mode
& 07777) != mode
) {
137 ERROR("mode 0%o instead of 0%o", stbuf
.st_mode
& 07777, mode
);
143 static int fcheck_mode(int fd
, mode_t mode
)
146 int res
= fstat(fd
, &stbuf
);
151 if ((stbuf
.st_mode
& 07777) != mode
) {
152 ERROR("mode 0%o instead of 0%o", stbuf
.st_mode
& 07777, mode
);
158 static int check_times(const char *path
, time_t atime
, time_t mtime
)
162 int res
= lstat(path
, &stbuf
);
167 if (stbuf
.st_atime
!= atime
) {
168 ERROR("atime %li instead of %li", stbuf
.st_atime
, atime
);
171 if (stbuf
.st_mtime
!= mtime
) {
172 ERROR("mtime %li instead of %li", stbuf
.st_mtime
, mtime
);
181 static int fcheck_times(int fd
, time_t atime
, time_t mtime
)
185 int res
= fstat(fd
, &stbuf
);
190 if (stbuf
.st_atime
!= atime
) {
191 ERROR("atime %li instead of %li", stbuf
.st_atime
, atime
);
194 if (stbuf
.st_mtime
!= mtime
) {
195 ERROR("mtime %li instead of %li", stbuf
.st_mtime
, mtime
);
204 static int check_nlink(const char *path
, nlink_t nlink
)
207 int res
= lstat(path
, &stbuf
);
212 if (stbuf
.st_nlink
!= nlink
) {
213 ERROR("nlink %li instead of %li", (long) stbuf
.st_nlink
,
220 static int fcheck_nlink(int fd
, nlink_t nlink
)
223 int res
= fstat(fd
, &stbuf
);
228 if (stbuf
.st_nlink
!= nlink
) {
229 ERROR("nlink %li instead of %li", (long) stbuf
.st_nlink
,
236 static int check_nonexist(const char *path
)
239 int res
= lstat(path
, &stbuf
);
241 ERROR("file should not exist");
244 if (errno
!= ENOENT
) {
245 ERROR("file should not exist: %s", strerror(errno
));
251 static int check_buffer(const char *buf
, const char *data
, unsigned len
)
253 if (memcmp(buf
, data
, len
) != 0) {
254 ERROR("data mismatch");
260 static int check_data(const char *path
, const char *data
, int offset
,
265 int fd
= open(path
, O_RDONLY
);
270 if (lseek(fd
, offset
, SEEK_SET
) == (off_t
) -1) {
276 int rdlen
= len
< sizeof(buf
) ? len
: sizeof(buf
);
277 res
= read(fd
, buf
, rdlen
);
284 ERROR("short read: %u instead of %u", res
, rdlen
);
288 if (check_buffer(buf
, data
, rdlen
) != 0) {
303 static int fcheck_data(int fd
, const char *data
, int offset
,
308 if (lseek(fd
, offset
, SEEK_SET
) == (off_t
) -1) {
313 int rdlen
= len
< sizeof(buf
) ? len
: sizeof(buf
);
314 res
= read(fd
, buf
, rdlen
);
320 ERROR("short read: %u instead of %u", res
, rdlen
);
323 if (check_buffer(buf
, data
, rdlen
) != 0) {
332 static int check_dir_contents(const char *path
, const char **contents
)
337 int found
[MAX_ENTRIES
];
338 const char *cont
[MAX_ENTRIES
];
341 for (i
= 0; contents
[i
]; i
++) {
342 assert(i
< MAX_ENTRIES
- 3);
344 cont
[i
] = contents
[i
];
357 memset(found
, 0, sizeof(found
));
370 for (i
= 0; cont
[i
] != NULL
; i
++) {
371 assert(i
< MAX_ENTRIES
);
372 if (strcmp(cont
[i
], de
->d_name
) == 0) {
374 ERROR("duplicate entry <%s>",
383 ERROR("unexpected entry <%s>", de
->d_name
);
387 for (i
= 0; cont
[i
] != NULL
; i
++) {
389 ERROR("missing entry <%s>", cont
[i
]);
404 static int create_file(const char *path
, const char *data
, int len
)
410 fd
= creat(path
, 0644);
416 res
= write(fd
, data
, len
);
423 ERROR("write is short: %u instead of %u", res
, len
);
433 res
= check_type(path
, S_IFREG
);
436 res
= check_mode(path
, 0644);
439 res
= check_nlink(path
, 1);
442 res
= check_size(path
, len
);
447 res
= check_data(path
, data
, 0, len
);
455 static int cleanup_dir(const char *path
, const char **dir_files
, int quiet
)
460 for (i
= 0; dir_files
[i
]; i
++) {
463 sprintf(fpath
, "%s/%s", path
, dir_files
[i
]);
465 if (res
== -1 && !quiet
) {
476 static int create_dir(const char *path
, const char **dir_files
)
482 res
= mkdir(path
, 0755);
487 res
= check_type(path
, S_IFDIR
);
490 res
= check_mode(path
, 0755);
494 for (i
= 0; dir_files
[i
]; i
++) {
496 sprintf(fpath
, "%s/%s", path
, dir_files
[i
]);
497 res
= create_file(fpath
, "", 0);
499 cleanup_dir(path
, dir_files
, 1);
503 res
= check_dir_contents(path
, dir_files
);
505 cleanup_dir(path
, dir_files
, 1);
512 static int test_truncate(int len
)
514 const char *data
= testdata
;
515 int datalen
= testdatalen
;
518 start_test("truncate(%u)", (int) len
);
519 res
= create_file(testfile
, data
, datalen
);
523 res
= truncate(testfile
, len
);
528 res
= check_size(testfile
, len
);
533 if (len
<= datalen
) {
534 res
= check_data(testfile
, data
, 0, len
);
538 res
= check_data(testfile
, data
, 0, datalen
);
541 res
= check_data(testfile
, zerodata
, datalen
,
547 res
= unlink(testfile
);
552 res
= check_nonexist(testfile
);
560 static int test_ftruncate(int len
, int mode
)
562 const char *data
= testdata
;
563 int datalen
= testdatalen
;
567 start_test("ftruncate(%u) mode: 0%03o", len
, mode
);
568 res
= create_file(testfile
, data
, datalen
);
572 fd
= open(testfile
, O_WRONLY
);
578 res
= fchmod(fd
, mode
);
584 res
= check_mode(testfile
, mode
);
589 res
= ftruncate(fd
, len
);
596 res
= check_size(testfile
, len
);
601 if (len
<= datalen
) {
602 res
= check_data(testfile
, data
, 0, len
);
606 res
= check_data(testfile
, data
, 0, datalen
);
609 res
= check_data(testfile
, zerodata
, datalen
,
615 res
= unlink(testfile
);
620 res
= check_nonexist(testfile
);
628 static int test_utime(void)
631 time_t atime
= 987631200;
632 time_t mtime
= 123116400;
636 res
= create_file(testfile
, NULL
, 0);
642 res
= utime(testfile
, &utm
);
647 res
= check_times(testfile
, atime
, mtime
);
651 res
= unlink(testfile
);
656 res
= check_nonexist(testfile
);
664 static int test_create(void)
666 const char *data
= testdata
;
667 int datalen
= testdatalen
;
672 start_test("create");
674 fd
= creat(testfile
, 0644);
679 res
= write(fd
, data
, datalen
);
685 if (res
!= datalen
) {
686 ERROR("write is short: %u instead of %u", res
, datalen
);
695 res
= check_type(testfile
, S_IFREG
);
698 err
+= check_mode(testfile
, 0644);
699 err
+= check_nlink(testfile
, 1);
700 err
+= check_size(testfile
, datalen
);
701 err
+= check_data(testfile
, data
, 0, datalen
);
702 res
= unlink(testfile
);
707 res
= check_nonexist(testfile
);
717 static int test_create_unlink(void)
719 const char *data
= testdata
;
720 int datalen
= testdatalen
;
725 start_test("create+unlink");
727 fd
= open(testfile
, O_CREAT
| O_RDWR
| O_TRUNC
, 0644);
732 res
= unlink(testfile
);
738 res
= check_nonexist(testfile
);
741 res
= write(fd
, data
, datalen
);
747 if (res
!= datalen
) {
748 ERROR("write is short: %u instead of %u", res
, datalen
);
752 err
+= fcheck_type(fd
, S_IFREG
);
753 err
+= fcheck_mode(fd
, 0644);
754 err
+= fcheck_nlink(fd
, 0);
755 err
+= fcheck_size(fd
, datalen
);
756 err
+= fcheck_data(fd
, data
, 0, datalen
);
769 static int test_mknod(void)
776 res
= mknod(testfile
, 0644, 0);
781 res
= check_type(testfile
, S_IFREG
);
784 err
+= check_mode(testfile
, 0644);
785 err
+= check_nlink(testfile
, 1);
786 err
+= check_size(testfile
, 0);
787 res
= unlink(testfile
);
792 res
= check_nonexist(testfile
);
802 #define test_open(exist, flags, mode) do_test_open(exist, flags, #flags, mode)
804 static int do_test_open(int exist
, int flags
, const char *flags_str
, int mode
)
807 const char *data
= testdata
;
808 int datalen
= testdatalen
;
809 unsigned currlen
= 0;
815 start_test("open(%s, %s, 0%03o)", exist
? "+" : "-", flags_str
, mode
);
818 res
= create_file(testfile
, testdata2
, testdata2len
);
822 currlen
= testdata2len
;
825 fd
= open(testfile
, flags
, mode
);
826 if ((flags
& O_CREAT
) && (flags
& O_EXCL
) && exist
) {
828 ERROR("open should have failed");
831 } else if (errno
== EEXIST
)
834 if (!(flags
& O_CREAT
) && !exist
) {
836 ERROR("open should have failed");
839 } else if (errno
== ENOENT
)
850 err
+= check_type(testfile
, S_IFREG
);
852 err
+= check_mode(testfile
, 0644);
854 err
+= check_mode(testfile
, mode
);
855 err
+= check_nlink(testfile
, 1);
856 err
+= check_size(testfile
, currlen
);
857 if (exist
&& !(flags
& O_TRUNC
) && (mode
& 0400))
858 err
+= check_data(testfile
, testdata2
, 0, testdata2len
);
860 res
= write(fd
, data
, datalen
);
861 if ((flags
& O_ACCMODE
) != O_RDONLY
) {
865 } else if (res
!= datalen
) {
866 ERROR("write is short: %u instead of %u", res
, datalen
);
869 if (datalen
> (int) currlen
)
872 err
+= check_size(testfile
, currlen
);
875 err
+= check_data(testfile
, data
, 0, datalen
);
876 if (exist
&& !(flags
& O_TRUNC
) &&
877 testdata2len
> datalen
)
878 err
+= check_data(testfile
,
881 testdata2len
- datalen
);
886 ERROR("write should have failed");
888 } else if (errno
!= EBADF
) {
893 off
= lseek(fd
, SEEK_SET
, 0);
894 if (off
== (off_t
) -1) {
897 } else if (off
!= 0) {
898 ERROR("offset should have returned 0");
901 res
= read(fd
, buf
, sizeof(buf
));
902 if ((flags
& O_ACCMODE
) != O_WRONLY
) {
908 currlen
< sizeof(buf
) ? currlen
: sizeof(buf
);
909 if (res
!= readsize
) {
910 ERROR("read is short: %i instead of %u",
914 if ((flags
& O_ACCMODE
) != O_RDONLY
) {
915 err
+= check_buffer(buf
, data
, datalen
);
916 if (exist
&& !(flags
& O_TRUNC
) &&
917 testdata2len
> datalen
)
918 err
+= check_buffer(buf
+ datalen
,
920 testdata2len
- datalen
);
922 err
+= check_buffer(buf
, testdata2
,
928 ERROR("read should have failed");
930 } else if (errno
!= EBADF
) {
941 res
= unlink(testfile
);
946 res
= check_nonexist(testfile
);
957 #define test_open_acc(flags, mode, err) \
958 do_test_open_acc(flags, #flags, mode, err)
960 static int do_test_open_acc(int flags
, const char *flags_str
, int mode
, int err
)
962 const char *data
= testdata
;
963 int datalen
= testdatalen
;
967 start_test("open_acc(%s) mode: 0%03o error: '%s'", flags_str
, mode
,
970 res
= create_file(testfile
, data
, datalen
);
974 res
= chmod(testfile
, mode
);
980 res
= check_mode(testfile
, mode
);
984 fd
= open(testfile
, flags
);
992 ERROR("open should have failed");
1002 static int test_symlink(void)
1005 const char *data
= testdata
;
1006 int datalen
= testdatalen
;
1007 int linklen
= strlen(testfile
);
1011 start_test("symlink");
1012 res
= create_file(testfile
, data
, datalen
);
1017 res
= symlink(testfile
, testfile2
);
1022 res
= check_type(testfile2
, S_IFLNK
);
1025 err
+= check_mode(testfile2
, 0777);
1026 err
+= check_nlink(testfile2
, 1);
1027 res
= readlink(testfile2
, buf
, sizeof(buf
));
1032 if (res
!= linklen
) {
1033 ERROR("short readlink: %u instead of %u", res
, linklen
);
1036 if (memcmp(buf
, testfile
, linklen
) != 0) {
1037 ERROR("link mismatch");
1040 err
+= check_size(testfile2
, datalen
);
1041 err
+= check_data(testfile2
, data
, 0, datalen
);
1042 res
= unlink(testfile2
);
1047 res
= check_nonexist(testfile2
);
1057 static int test_link(void)
1059 const char *data
= testdata
;
1060 int datalen
= testdatalen
;
1065 res
= create_file(testfile
, data
, datalen
);
1070 res
= link(testfile
, testfile2
);
1075 res
= check_type(testfile2
, S_IFREG
);
1078 err
+= check_mode(testfile2
, 0644);
1079 err
+= check_nlink(testfile2
, 2);
1080 err
+= check_size(testfile2
, datalen
);
1081 err
+= check_data(testfile2
, data
, 0, datalen
);
1082 res
= unlink(testfile
);
1087 res
= check_nonexist(testfile
);
1091 err
+= check_nlink(testfile2
, 1);
1092 res
= unlink(testfile2
);
1097 res
= check_nonexist(testfile2
);
1107 static int test_rename_file(void)
1109 const char *data
= testdata
;
1110 int datalen
= testdatalen
;
1114 start_test("rename file");
1115 res
= create_file(testfile
, data
, datalen
);
1120 res
= rename(testfile
, testfile2
);
1125 res
= check_nonexist(testfile
);
1128 res
= check_type(testfile2
, S_IFREG
);
1131 err
+= check_mode(testfile2
, 0644);
1132 err
+= check_nlink(testfile2
, 1);
1133 err
+= check_size(testfile2
, datalen
);
1134 err
+= check_data(testfile2
, data
, 0, datalen
);
1135 res
= unlink(testfile2
);
1140 res
= check_nonexist(testfile2
);
1150 static int test_rename_dir(void)
1155 start_test("rename dir");
1156 res
= create_dir(testdir
, testdir_files
);
1161 res
= rename(testdir
, testdir2
);
1164 cleanup_dir(testdir
, testdir_files
, 1);
1167 res
= check_nonexist(testdir
);
1169 cleanup_dir(testdir
, testdir_files
, 1);
1172 res
= check_type(testdir2
, S_IFDIR
);
1174 cleanup_dir(testdir2
, testdir_files
, 1);
1177 err
+= check_mode(testdir2
, 0755);
1178 err
+= check_dir_contents(testdir2
, testdir_files
);
1179 err
+= cleanup_dir(testdir2
, testdir_files
, 0);
1180 res
= rmdir(testdir2
);
1185 res
= check_nonexist(testdir2
);
1195 static int test_mkfifo(void)
1200 start_test("mkfifo");
1202 res
= mkfifo(testfile
, 0644);
1207 res
= check_type(testfile
, S_IFIFO
);
1210 err
+= check_mode(testfile
, 0644);
1211 err
+= check_nlink(testfile
, 1);
1212 res
= unlink(testfile
);
1217 res
= check_nonexist(testfile
);
1227 static int test_mkdir(void)
1231 const char *dir_contents
[] = {NULL
};
1233 start_test("mkdir");
1235 res
= mkdir(testdir
, 0755);
1240 res
= check_type(testdir
, S_IFDIR
);
1243 err
+= check_mode(testdir
, 0755);
1244 err
+= check_nlink(testdir
, 2);
1245 err
+= check_dir_contents(testdir
, dir_contents
);
1246 res
= rmdir(testdir
);
1251 res
= check_nonexist(testdir
);
1261 int main(int argc
, char *argv
[])
1263 const char *basepath
;
1268 fprintf(stderr
, "usage: %s testdir\n", argv
[0]);
1272 assert(strlen(basepath
) < 512);
1273 if (basepath
[0] != '/') {
1274 fprintf(stderr
, "testdir must be an absolute path\n");
1278 sprintf(testfile
, "%s/testfile", basepath
);
1279 sprintf(testfile2
, "%s/testfile2", basepath
);
1280 sprintf(testdir
, "%s/testdir", basepath
);
1281 sprintf(testdir2
, "%s/testdir2", basepath
);
1282 err
+= test_create();
1283 err
+= test_create_unlink();
1284 err
+= test_mknod();
1285 err
+= test_symlink();
1287 err
+= test_mkfifo();
1288 err
+= test_mkdir();
1289 err
+= test_rename_file();
1290 err
+= test_rename_dir();
1291 err
+= test_utime();
1292 err
+= test_truncate(0);
1293 err
+= test_truncate(testdatalen
/ 2);
1294 err
+= test_truncate(testdatalen
);
1295 err
+= test_truncate(testdatalen
+ 100);
1296 err
+= test_ftruncate(0, 0600);
1297 err
+= test_ftruncate(testdatalen
/ 2, 0600);
1298 err
+= test_ftruncate(testdatalen
, 0600);
1299 err
+= test_ftruncate(testdatalen
+ 100, 0600);
1300 err
+= test_ftruncate(0, 0400);
1301 err
+= test_ftruncate(0, 0200);
1302 err
+= test_ftruncate(0, 0000);
1303 err
+= test_open(0, O_RDONLY
, 0);
1304 err
+= test_open(1, O_RDONLY
, 0);
1305 err
+= test_open(1, O_RDWR
, 0);
1306 err
+= test_open(1, O_WRONLY
, 0);
1307 err
+= test_open(0, O_RDWR
| O_CREAT
, 0600);
1308 err
+= test_open(1, O_RDWR
| O_CREAT
, 0600);
1309 err
+= test_open(0, O_RDWR
| O_CREAT
| O_TRUNC
, 0600);
1310 err
+= test_open(1, O_RDWR
| O_CREAT
| O_TRUNC
, 0600);
1311 err
+= test_open(0, O_RDONLY
| O_CREAT
, 0600);
1312 err
+= test_open(0, O_RDONLY
| O_CREAT
, 0400);
1313 err
+= test_open(0, O_RDONLY
| O_CREAT
, 0200);
1314 err
+= test_open(0, O_RDONLY
| O_CREAT
, 0000);
1315 err
+= test_open(0, O_WRONLY
| O_CREAT
, 0600);
1316 err
+= test_open(0, O_WRONLY
| O_CREAT
, 0400);
1317 err
+= test_open(0, O_WRONLY
| O_CREAT
, 0200);
1318 err
+= test_open(0, O_WRONLY
| O_CREAT
, 0000);
1319 err
+= test_open(0, O_RDWR
| O_CREAT
, 0400);
1320 err
+= test_open(0, O_RDWR
| O_CREAT
, 0200);
1321 err
+= test_open(0, O_RDWR
| O_CREAT
, 0000);
1322 err
+= test_open(0, O_RDWR
| O_CREAT
| O_EXCL
, 0600);
1323 err
+= test_open(1, O_RDWR
| O_CREAT
| O_EXCL
, 0600);
1324 err
+= test_open(0, O_RDWR
| O_CREAT
| O_EXCL
, 0000);
1325 err
+= test_open(1, O_RDWR
| O_CREAT
| O_EXCL
, 0000);
1326 err
+= test_open_acc(O_RDONLY
, 0600, 0);
1327 err
+= test_open_acc(O_WRONLY
, 0600, 0);
1328 err
+= test_open_acc(O_RDWR
, 0600, 0);
1329 err
+= test_open_acc(O_RDONLY
, 0400, 0);
1330 err
+= test_open_acc(O_RDONLY
| O_TRUNC
, 0400, EACCES
);
1331 err
+= test_open_acc(O_WRONLY
, 0400, EACCES
);
1332 err
+= test_open_acc(O_RDWR
, 0400, EACCES
);
1333 err
+= test_open_acc(O_RDONLY
, 0200, EACCES
);
1334 err
+= test_open_acc(O_WRONLY
, 0200, 0);
1335 err
+= test_open_acc(O_RDWR
, 0200, EACCES
);
1336 err
+= test_open_acc(O_RDONLY
, 0000, EACCES
);
1337 err
+= test_open_acc(O_WRONLY
, 0000, EACCES
);
1338 err
+= test_open_acc(O_RDWR
, 0000, EACCES
);
1346 fprintf(stderr
, "%i tests failed\n", -err
);