Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / native_client / tests / syscalls / syscalls.cc
1 /*
2  * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6
7 /*
8  * NaCl tests for simple syscalls
9  */
10
11 #include <dirent.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <limits.h>
15 #include <sched.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <unistd.h>
20
21 #include "native_client/src/include/nacl_assert.h"
22 #include "native_client/src/trusted/service_runtime/include/sys/nacl_syscalls.h"
23
24 #define PRINT_HEADER 0
25 #define TEXT_LINE_SIZE 1024
26
27 /*
28  * TODO(sbc): remove this test once these declarations get added to the prebuilt
29  * newlib toolchain
30  */
31 #ifndef __GLIBC__
32 extern "C" int gethostname(char *name, size_t len);
33 extern "C" int utimes(const char *filename, const struct timeval times[2]);
34 extern "C" int eaccess(const char *pathname, int mode);
35 #endif
36
37 /*
38  * function failed(testname, msg)
39  *   print failure message and exit with a return code of -1
40  */
41 bool failed(const char *testname, const char *msg) {
42   printf("TEST FAILED: %s: %s\n", testname, msg);
43   return false;
44 }
45
46 /*
47  * function passed(testname, msg)
48  *   print success message
49  */
50 bool passed(const char *testname, const char *msg) {
51   printf("TEST PASSED: %s: %s\n", testname, msg);
52   return true;
53 }
54
55 /*
56  * Split filename into basename and dirname.
57  * The argument is modified in place such that it
58  * becomes the dirname and the basename is returned.
59  */
60 static char *split_name(char *full_name) {
61   // Strip off the trailing filename
62   char *basename = strrchr(full_name, '/');
63   if (basename == NULL) {
64     basename = strrchr(full_name, '\\');
65     ASSERT_NE_MSG(basename, NULL, "test_file contains no dir seperator");
66     if (!basename)
67       return NULL;
68   }
69   basename[0] = '\0';
70   return basename + 1;
71 }
72
73 // In case a previous run of this test failed and left the file behind,
74 // remove the file first.
75 // TODO(mseaborn): It would be cleaner to create a guaranteed-empty temp
76 // directory instead of doing this.
77 static void ensure_file_is_absent(const char *filename) {
78   int result = unlink(filename);
79   if (result != 0) {
80     ASSERT_EQ(errno, ENOENT);
81   }
82 }
83
84 /*
85  * function test*()
86  *
87  *   Simple tests follow below.  Each test may call one or more
88  *   of the functions above.  They all have a boolean return value
89  *   to indicate success (all tests passed) or failure (one or more
90  *   tests failed)  Order matters - the parent should call
91  *   test1() before test2(), and so on.
92  */
93
94 bool test_sched_yield() {
95   if (sched_yield()) {
96     printf("sched_yield failed\n");
97     return false;
98   }
99   return true;
100 }
101
102 bool test_sysconf() {
103   // TODO(hamaji): Implement _SC_NPROCESSORS_ONLN for newlib based
104   // non-SFI mode. Note that this test works for unsandboxed mode.
105   if (NONSFI_MODE)
106     return true;
107   int rv;
108   rv = sysconf(_SC_NPROCESSORS_ONLN);
109   if (rv == -1) {
110     printf("failed to get nprocs\n");
111     return false;
112   }
113   if (rv < 1) {
114     printf("got strange number of processors: %d\n", rv);
115     return false;
116   }
117   // test sysconf on an invalid input.
118   rv = sysconf(-1);
119   if (rv != -1) {
120     printf("succeeded on unsupported\n");
121     return false;
122   }
123   return true;
124 }
125
126 // Simple test that chdir returns zero for '.'.  chdir gets more
127 // significant testing as part of the getcwd test.
128 bool test_chdir() {
129   int rtn = chdir(".");
130   ASSERT_EQ_MSG(rtn, 0, "chdir() failed");
131
132   return passed("test_chdir", "all");
133 }
134
135 bool test_mkdir_rmdir(const char *test_file) {
136   // Use a temporary direcotry name alongside the test_file which
137   // was passed in.
138   char dirname[PATH_MAX];
139   strncpy(dirname, test_file, PATH_MAX);
140   split_name(dirname);
141
142   ASSERT(strlen(dirname) + 6 < PATH_MAX);
143   strncat(dirname, "tmpdir", 6);
144
145   // Attempt to remove the directory in case it already exists
146   // from a previous test run.
147   if (rmdir(dirname) != 0)
148     ASSERT_EQ_MSG(errno, ENOENT, "rmdir() failed to cleanup existing dir");
149
150   char cwd[PATH_MAX];
151   char *cwd_rtn = getcwd(cwd, PATH_MAX);
152   ASSERT_EQ_MSG(cwd_rtn, cwd, "getcwd() failed");
153
154   int rtn = mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR);
155   ASSERT_EQ_MSG(rtn, 0, "mkdir() failed");
156
157   rtn = rmdir(dirname);
158   ASSERT_EQ_MSG(rtn, 0, "rmdir() failed");
159
160   rtn = rmdir("This file does not exist");
161   ASSERT_EQ_MSG(rtn, -1, "rmdir() failed to fail");
162   ASSERT_EQ_MSG(errno, ENOENT, "rmdir() failed to generate ENOENT");
163
164   return passed("test_mkdir_rmdir", "all");
165 }
166
167 bool test_getcwd() {
168   char dirname[PATH_MAX] = { '\0' };
169   char newdir[PATH_MAX] = { '\0' };
170   char parent[PATH_MAX] = { '\0' };
171
172   char *rtn = getcwd(dirname, PATH_MAX);
173   ASSERT_EQ_MSG(rtn, dirname, "getcwd() failed to return dirname");
174   ASSERT_NE_MSG(strlen(dirname), 0, "getcwd() failed to set valid dirname");
175
176   // Calculate parent folder.
177   strncpy(parent, dirname, PATH_MAX);
178   char *basename_start = strrchr(parent, '/');
179   if (basename_start == NULL) {
180     basename_start = strrchr(parent, '\\');
181     ASSERT_NE_MSG(basename_start, NULL, "test_file contains no dir seperator");
182   }
183   basename_start[0] = '\0';
184
185   int retcode = chdir("..");
186   ASSERT_EQ_MSG(retcode, 0, "chdir() failed");
187
188   rtn = getcwd(newdir, PATH_MAX);
189   ASSERT_EQ_MSG(rtn, newdir, "getcwd() failed");
190
191   ASSERT_MSG(strcmp(newdir, parent) == 0, "getcwd() failed after chdir");
192   retcode = chdir(dirname);
193   ASSERT_EQ_MSG(retcode, 0, "chdir() failed");
194
195   rtn = getcwd(dirname, 2);
196   ASSERT_EQ_MSG(rtn, NULL, "getcwd() failed to fail");
197   ASSERT_EQ_MSG(errno, ERANGE, "getcwd() failed to generate ERANGE");
198
199   return passed("test_getcwd", "all");
200 }
201
202 bool test_unlink(const char *test_file) {
203   int rtn;
204   struct stat buf;
205   char temp_file[PATH_MAX];
206   snprintf(temp_file, PATH_MAX, "%s.tmp_unlink", test_file);
207   temp_file[PATH_MAX - 1] = '\0';
208
209   int fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
210   ASSERT_MSG(fd >= 0, "open() failed");
211
212   rtn = close(fd);
213   ASSERT_EQ_MSG(rtn, 0, "close() failed");
214
215   rtn = stat(temp_file, &buf);
216   ASSERT_EQ_MSG(rtn, 0, "stat() failed");
217
218   rtn = unlink(temp_file);
219   ASSERT_EQ_MSG(rtn, 0, "unlink() failed");
220
221   rtn = stat(temp_file, &buf);
222   ASSERT_NE_MSG(rtn, 0, "unlink() failed to remove file");
223
224   rtn = unlink(temp_file);
225   ASSERT_NE_MSG(rtn, 0, "unlink() failed to fail");
226
227   return passed("test_unlink", "all");
228 }
229
230 bool test_rename(const char *test_file) {
231   int rtn;
232   struct stat buf;
233   char filename1[PATH_MAX];
234   char filename2[PATH_MAX];
235   snprintf(filename1, PATH_MAX, "%s.tmp1", test_file);
236   snprintf(filename2, PATH_MAX, "%s.tmp2", test_file);
237
238   // Create a test file and verify that we can stat() it.
239   int fd = open(filename1, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
240   ASSERT_MSG(fd >= 0, "open() failed");
241   rtn = close(fd);
242   ASSERT_EQ_MSG(rtn, 0, "close() failed");
243
244   rtn = stat(filename1, &buf);
245   ASSERT_EQ_MSG(rtn, 0, "stat() failed");
246
247   // Rename the test file and verify that the old file is no
248   // longer stat()-able.
249   rtn = rename(filename1, filename2);
250   ASSERT_EQ_MSG(rtn, 0, "rename() failed");
251
252   rtn = stat(filename2, &buf);
253   ASSERT_EQ_MSG(rtn, 0, "stat() of new file failed");
254
255   rtn = stat(filename1, &buf);
256   ASSERT_NE_MSG(rtn, 0, "stat() of old name should fail after rename");
257
258   ASSERT_EQ(remove(filename2), 0);
259   return passed("test_rename", "all");
260 }
261
262 bool test_link(const char *test_file) {
263   struct stat buf;
264   struct stat buf_orig;
265   char link_filename[PATH_MAX];
266   char target_filename[PATH_MAX];
267   snprintf(target_filename, PATH_MAX, "%s.target", test_file);
268   snprintf(link_filename, PATH_MAX, "%s.link", test_file);
269
270   ensure_file_is_absent(target_filename);
271   ensure_file_is_absent(link_filename);
272
273   // Create link target with some dummy data
274   int fd = open(target_filename, O_WRONLY | O_CREAT, S_IRWXU);
275   ASSERT(fd >= 0);
276   ASSERT_EQ(write(fd, "123", 3), 3);
277   ASSERT_EQ(close(fd), 0);
278
279   int rtn = link(target_filename, link_filename);
280   if (rtn != 0 && errno == ENOSYS) {
281     // If we get ENOSYS, assume we are on Windows, where link() is expected
282     // to fail.
283     return passed("test_link", "all");
284   }
285   ASSERT_EQ(rtn, 0);
286
287   // Verify that the new file is a regular file and that changes to it are
288   // mirrored in the original file.
289   ASSERT_EQ(stat(link_filename, &buf), 0);
290   ASSERT_EQ(stat(target_filename, &buf_orig), 0);
291   ASSERT(S_ISREG(buf.st_mode));
292   ASSERT(S_ISREG(buf_orig.st_mode));
293
294   ASSERT_EQ(buf_orig.st_size, 3);
295   ASSERT_EQ(buf_orig.st_size, buf.st_size);
296
297   // Write some bytes to the new file
298   fd = open(link_filename, O_WRONLY);
299   ASSERT(fd >= 0);
300   ASSERT_EQ(write(fd, "test", 4), 4);
301   ASSERT_EQ(close(fd), 0);
302
303   // Verify that the two files are still the same size
304   ASSERT_EQ(stat(link_filename, &buf), 0);
305   ASSERT_EQ(stat(target_filename, &buf_orig), 0);
306   ASSERT(S_ISREG(buf.st_mode));
307   ASSERT(S_ISREG(buf_orig.st_mode));
308   ASSERT_EQ(buf_orig.st_size, buf.st_size);
309   ASSERT_EQ(buf_orig.st_size, 4);
310
311   ASSERT_EQ(remove(link_filename), 0);
312   ASSERT_EQ(remove(target_filename), 0);
313   return passed("test_link", "all");
314 }
315
316 // This tests symlink/readlink and lstat.
317 bool test_symlinks(const char *test_file) {
318   char dirname[PATH_MAX];
319   char link_filename[PATH_MAX];
320   struct stat buf;
321
322   // Test that lstat of the test_file works
323   ASSERT_EQ(lstat(test_file, &buf), 0);
324   ASSERT_EQ(S_ISREG(buf.st_mode), 1);
325
326   // Split filename into basename and dirname.
327   strncpy(dirname, test_file, PATH_MAX);
328   char *basename = split_name(dirname);
329
330   snprintf(link_filename, PATH_MAX, "%s.link", test_file);
331
332   ensure_file_is_absent(link_filename);
333
334   // Create this link
335   int rtn = symlink(basename, link_filename);
336   if (rtn != 0 && errno == ENOSYS) {
337     // If we get ENOSYS, assume we are on Windows, where symlink() and
338     // readlink() are expected to fail.
339     return passed("test_symlinks", "all");
340   }
341   ASSERT_EQ(rtn, 0);
342
343   // Check the lstat() and stat of the link
344   ASSERT_EQ(lstat(link_filename, &buf), 0);
345   ASSERT_NE_MSG(S_ISLNK(buf.st_mode), 0, "lstat of link failed to be ISLNK");
346   ASSERT_EQ_MSG(S_ISREG(buf.st_mode), 0, "lstat of link should not be ISREG");
347
348   ASSERT_EQ(stat(link_filename, &buf), 0);
349   ASSERT_EQ_MSG(S_ISLNK(buf.st_mode), 0, "stat of symlink should not ISLNK");
350   ASSERT_NE_MSG(S_ISREG(buf.st_mode), 0, "stat of symlink should report ISREG");
351
352   // Test readlink().
353   char link_dest[PATH_MAX];
354   memset(link_dest, 0x77, sizeof(link_dest));
355   ssize_t result = readlink(link_filename, link_dest, sizeof(link_dest));
356   ASSERT_EQ(result, (ssize_t) strlen(basename));
357   ASSERT_EQ(memcmp(link_dest, basename, result), 0);
358   // readlink() should not write a null terminator.
359   ASSERT_EQ(link_dest[result], 0x77);
360
361   // Test readlink() with a truncated result.
362   memset(link_dest, 0x77, sizeof(link_dest));
363   result = readlink(link_filename, link_dest, 1);
364   ASSERT_EQ(result, 1);
365   ASSERT_EQ(link_dest[0], basename[0]);
366   // The rest of the buffer should not be modified.
367   for (size_t i = 1; i < sizeof(link_dest); ++i)
368     ASSERT_EQ(link_dest[i], 0x77);
369
370   // calling symlink again should yield EEXIST.
371   ASSERT_EQ(symlink(test_file, link_filename), -1);
372   ASSERT_EQ(errno, EEXIST);
373   ASSERT_EQ(remove(link_filename), 0);
374
375   return passed("test_symlinks", "all");
376 }
377
378 bool test_chmod(const char *test_file) {
379   struct stat buf;
380   char temp_file[PATH_MAX];
381   snprintf(temp_file, PATH_MAX, "%s.tmp_chmod", test_file);
382
383   int fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
384   ASSERT(fd >= 0);
385   ASSERT_EQ(close(fd), 0);
386
387   ASSERT_EQ(stat(temp_file, &buf), 0);
388   ASSERT_EQ(buf.st_mode & ~S_IFMT, S_IRUSR | S_IWUSR);
389
390   // change the file to readonly and verify the change
391   ASSERT_EQ(chmod(temp_file, S_IRUSR), 0);
392   ASSERT_EQ(stat(temp_file, &buf), 0);
393   ASSERT_EQ(buf.st_mode & ~S_IFMT, S_IRUSR);
394   ASSERT(open(temp_file, O_WRONLY) < 0);
395
396   ASSERT_EQ(remove(temp_file), 0);
397   return passed("test_chmod", "all");
398 }
399
400 static void test_access_call(const char *path, int mode, int expected_result) {
401   ASSERT_EQ(access(path, mode), expected_result);
402   ASSERT_EQ(eaccess(path, mode), expected_result);
403 }
404
405 bool test_access(const char *test_file) {
406   char temp_access[PATH_MAX];
407   snprintf(temp_access, PATH_MAX, "%s.tmp_access", test_file);
408
409   test_access_call(test_file, F_OK, 0);
410   test_access_call(test_file, R_OK, 0);
411   test_access_call(test_file, W_OK, 0);
412
413   test_access_call(temp_access, F_OK, -1);
414   test_access_call(temp_access, R_OK, -1);
415   test_access_call(temp_access, W_OK, -1);
416
417   /*
418    * We can't test the X bit here since it's not consistent across platforms.
419    * On win32 there is no equivalent so we always return true.  On Mac/Linux
420    * the underlying X bit is reported.
421    */
422   // test_access_call(test_file, X_OK, -1);
423   // test_access_call(temp_access, X_OK, -1);
424
425   // Create a read-only file
426   int fd = open(temp_access, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR);
427   ASSERT(fd > 0);
428   ASSERT_EQ(close(fd), 0);
429
430   test_access_call(temp_access, F_OK, 0);
431   test_access_call(temp_access, R_OK, 0);
432   test_access_call(temp_access, W_OK, -1);
433   ASSERT_EQ(remove(temp_access), 0);
434
435   return passed("test_access", "all");
436 }
437
438 bool test_utimes(const char *test_file) {
439   // TODO(mseaborn): Implement utimes for unsandboxed mode.
440   if (NONSFI_MODE)
441     return true;
442   struct timeval times[2];
443   // utimes() is currently not implemented and should always
444   // fail with ENOSYS
445   ASSERT_EQ(utimes("dummy", times), -1);
446   ASSERT_EQ(errno, ENOSYS);
447   return passed("test_utimes", "all");
448 }
449
450 bool test_truncate(const char *test_file) {
451   char temp_file[PATH_MAX];
452   snprintf(temp_file, PATH_MAX, "%s.tmp_truncate", test_file);
453
454   char buffer[100];
455   char read_buffer[200];
456   struct stat buf;
457   for (size_t i = 0; i < sizeof(buffer); i++)
458     buffer[i] = i;
459
460   // Write 100 sequential chars to the test file.
461   int fd = open(temp_file, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
462   ASSERT(fd >= 0);
463   ASSERT_EQ(100, write(fd, buffer, 100));
464   ASSERT_EQ(0, close(fd));
465
466   ASSERT_EQ(stat(temp_file, &buf), 0);
467   ASSERT_EQ(buf.st_size, 100);
468
469   // truncate the file beyond its current length
470   ASSERT_EQ(truncate(temp_file, 200), 0);
471   ASSERT_EQ(stat(temp_file, &buf), 0);
472   ASSERT_EQ(buf.st_size, 200);
473
474   // Verify the new content, which should not be 100
475   // bytes of sequential chars and 100 bytes of '\0'
476   fd = open(temp_file, O_RDONLY);
477   ASSERT(fd >= 0);
478   ASSERT_EQ(read(fd, read_buffer, 200), 200);
479   ASSERT_EQ(memcmp(read_buffer, buffer, 100), 0);
480   for (int i = 100; i < 200; i++)
481     ASSERT_EQ(read_buffer[i], 0);
482   ASSERT_EQ(0, close(fd));
483
484   // Now truncate the file to a size smaller than the
485   // original
486   ASSERT_EQ(truncate(temp_file, 50), 0);
487   ASSERT_EQ(stat(temp_file, &buf), 0);
488   ASSERT_EQ(buf.st_size, 50);
489
490   fd = open(temp_file, O_RDONLY);
491   ASSERT(fd >= 0);
492   ASSERT_EQ(read(fd, read_buffer, 50), 50);
493   ASSERT_EQ(memcmp(read_buffer, buffer, 50), 0);
494   ASSERT_EQ(0, close(fd));
495
496   ASSERT_EQ(remove(temp_file), 0);
497   return passed("test_truncate", "all");
498 }
499
500 // open() returns the new file descriptor, or -1 if an error occurred
501 bool test_open(const char *test_file) {
502   int fd;
503   const char *testname = "test_open";
504
505   // file OK, flag OK
506   fd = open(test_file, O_RDONLY);
507   if (fd == -1)
508     return failed(testname, "open(test_file, O_RDONLY)");
509   close(fd);
510
511   errno = 0;
512   // file does not exist, flags OK
513   fd = open("testdata/file_none.txt", O_RDONLY);
514   if (fd != -1)
515     return failed(testname, "open(testdata/file_none.txt, O_RDONLY)");
516   // no such file or directory
517   if (ENOENT != errno)
518     return failed(testname, "ENOENT != errno");
519   close(fd);
520
521   // file OK, flags OK, mode OK
522   fd = open(test_file, O_WRONLY, S_IRUSR);
523   if (fd == -1)
524     return failed(testname, "open(test_file, O_WRONLY, S_IRUSR)");
525   close(fd);
526
527   // too many args
528   fd = open(test_file, O_RDWR, S_IRUSR, O_APPEND);
529   if (fd == -1)
530     return failed(testname, "open(test_file, O_RDWR, S_IRUSR, O_APPEND)");
531   close(fd);
532
533   // directory OK
534   fd = open(".", O_RDONLY);
535   if (fd == -1)
536     return failed(testname, "open(., O_RDONLY)");
537   close(fd);
538
539   errno = 0;
540   // directory does not exist
541   fd = open("nosuchdir", O_RDONLY);
542   if (fd != -1)
543     return failed(testname, "open(nosuchdir, O_RDONLY)");
544   // no such file or directory
545   if (ENOENT != errno)
546     return failed(testname, "ENOENT != errno");
547   close(fd);
548
549   return passed(testname, "all");
550 }
551
552 bool test_stat(const char *test_file) {
553   struct stat buf;
554
555   // Test incoming test_file for read and write permission.
556   ASSERT_EQ(stat(test_file, &buf), 0);
557   ASSERT_MSG(buf.st_mode & S_IRUSR, "stat() failed to report S_IRUSR");
558   ASSERT_MSG(buf.st_mode & S_IWUSR, "stat() failed to report S_IWUSR");
559
560   // Test fstat and compare the result with the result of stat.
561   int fd = open(test_file, O_RDONLY);
562   ASSERT_NE(fd, -1);
563   struct stat buf2;
564   int rc = fstat(fd, &buf2);
565   ASSERT_EQ(rc, 0);
566   ASSERT_EQ(buf.st_dev, buf2.st_dev);
567   ASSERT_EQ(buf.st_mode, buf2.st_mode);
568   ASSERT_EQ(buf.st_nlink, buf2.st_nlink);
569   ASSERT_EQ(buf.st_uid, buf2.st_uid);
570   ASSERT_EQ(buf.st_gid, buf2.st_gid);
571   ASSERT_EQ(buf.st_rdev, buf2.st_rdev);
572   ASSERT_EQ(buf.st_size, buf2.st_size);
573   ASSERT_EQ(buf.st_blksize, buf2.st_blksize);
574   ASSERT_EQ(buf.st_blocks, buf2.st_blocks);
575   // Do not check st_atime as it seems to be updated by open or fstat
576   // on Windows.
577   ASSERT_EQ(buf.st_mtime, buf2.st_mtime);
578   ASSERT_EQ(buf.st_ctime, buf2.st_ctime);
579   rc = close(fd);
580   ASSERT_EQ(rc, 0);
581
582   // An invalid fstat call.
583   errno = 0;
584   ASSERT_EQ(fstat(-1, &buf2), -1);
585   ASSERT_EQ(errno, EBADF);
586
587   // Test a new read-only file
588   // The current unlink() implemenation in the sel_ldr for Windows
589   // doesn't support removing read-only files.
590   // TODO(sbc): enable this part of the test once this gets fixed.
591 #if 0
592   char buffer[PATH_MAX];
593   snprintf(buffer, PATH_MAX, "%s.readonly", test_file);
594   buffer[PATH_MAX - 1] = '\0';
595   unlink(buffer);
596   ASSERT_EQ(stat(buffer, &buf), -1);
597   int fd = open(buffer, O_RDWR | O_CREAT, S_IRUSR);
598   ASSERT_NE(fd, -1);
599   ASSERT_EQ(close(fd), 0);
600   ASSERT_EQ(stat(buffer, &buf), 0);
601   ASSERT_MSG(buf.st_mode & S_IRUSR, "stat() failed to report S_IRUSR");
602   ASSERT_MSG(!(buf.st_mode & S_IWUSR), "S_IWUSR report for a read-only file");
603 #endif
604
605   // Windows doesn't support the concept of write only files,
606   // so we can't test this case.
607
608   return passed("test_stat", "all");
609 }
610
611 // close() returns 0 on success, -1 on error
612 bool test_close(const char *test_file) {
613   int fd;
614   int ret_val;
615   const char *testname = "test_close";
616
617   // file OK
618   fd = open(test_file, O_RDWR);
619   if (fd == -1)
620     return failed(testname, "open(test_file, O_RDWR)");
621   ret_val = close(fd);
622   if (ret_val == -1)
623     return failed(testname, "close(test_file, O_RDWR)");
624
625   // file OK
626   fd = open(test_file, O_RDWR);
627   if (fd == -1)
628     return failed(testname, "open(test_file, O_RDWR)");
629   // close on wrong fd not OK
630   errno = 0;
631   ret_val = close(fd+1);
632   if (ret_val != -1)
633     return failed(testname, "close(fd+1)");
634   // bad file number
635   if (EBADF != errno)
636     return failed(testname, "EBADF != errno");
637   ret_val = close(fd);
638   if (ret_val == -1)
639     return failed(testname, "close(test_file, O_RDWR)");
640
641   // file not OK
642   fd = open("file_none.txt", O_WRONLY);
643   if (fd != -1)
644     return failed(testname, "open(file_none.txt, O_WRONLY)");
645   errno = 0;
646   ret_val = close(fd);
647   if (ret_val == 0)
648     return failed(testname, "close(file_none.txt, O_WRONLY)");
649   // bad file number
650   if (EBADF != errno)
651     return failed(testname, "EBADF != errno");
652
653   // directory OK
654   // Linux's open() (unsandboxed) does not allow O_RDWR on a directory.
655   // TODO(mseaborn): sel_ldr should reject O_RDWR on a directory too.
656   if (!NONSFI_MODE) {
657     fd = open(".", O_RDWR);
658     if (fd == -1)
659       return failed(testname, "open(., O_RDWR)");
660     ret_val = close(fd);
661     if (ret_val == -1)
662       return failed(testname, "close(., O_RDWR)");
663   }
664
665   // directory not OK
666   fd = open("nosuchdir", O_RDWR);
667   if (fd != -1)
668     return failed(testname, "open(nosuchdir, O_RDWR)");
669   errno = 0;
670   ret_val = close(fd);
671   if (ret_val == 0)
672     return failed(testname, "close(nosuchdir, O_RDWR)");
673   // bad file number
674   if (EBADF != errno)
675     return failed(testname, "EBADF != errno");
676
677   return passed(testname, "all");
678 }
679
680 // read() returns the number of bytes read on success (0 indicates end
681 // of file), -1 on error
682 bool test_read(const char *test_file) {
683   int fd;
684   int ret_val;
685   char out_char[5];
686   const char *testname = "test_read";
687
688   fd = open(test_file, O_RDONLY);
689   if (fd == -1)
690     return failed(testname, "open(test_file, O_RDONLY)");
691
692   // fd OK, buffer OK, count OK
693   ret_val = read(fd, out_char, 1);
694   if (ret_val == -1)
695     return failed(testname, "read(fd, out_char, 1)");
696
697   errno = 0;
698   // fd not OK, buffer OK, count OK
699   ret_val = read(-1, out_char, 1);
700   if (ret_val != -1)
701     return failed(testname, "read(-1, out_char, 1)");
702   // bad file number
703   if (EBADF != errno)
704     return failed(testname, "EBADF != errno");
705
706   errno = 0;
707   // fd OK, buffer OK, count not OK
708   // Linux's read() (unsandboxed) does not reject this buffer size.
709   if (!NONSFI_MODE) {
710     ret_val = read(fd, out_char, -1);
711     if (ret_val != -1)
712       return failed(testname, "read(fd, out_char, -1)");
713     // bad address
714     ASSERT_EQ(errno, EFAULT);
715     if (EFAULT != errno)
716       return failed(testname, "EFAULT != errno");
717   }
718
719   errno = 0;
720   // fd not OK, buffer OK, count not OK
721   ret_val = read(-1, out_char, -1);
722   if (ret_val != -1)
723     return failed(testname, "read(-1, out_char, -1)");
724   // bad descriptor
725   if (NONSFI_MODE) {
726     // Under qemu-arm, this read() call returns EFAULT.
727     if (EBADF != errno && EFAULT != errno)
728       return failed(testname, "errno is not EBADF or EFAULT");
729   } else {
730     if (EBADF != errno)
731       return failed(testname, "EBADF != errno");
732   }
733
734   // fd OK, buffer OK, count 0
735   ret_val = read(fd, out_char, 0);
736   if (ret_val != 0)
737     return failed(testname, "read(fd, out_char, 0)");
738
739   // read 10, but only 3 are left
740   ret_val = read(fd, out_char, 10);
741   if (ret_val != 4)
742     return failed(testname, "read(fd, out_char, 10)");
743
744   // EOF
745   ret_val = read(fd, out_char, 10);
746   if (ret_val != 0)
747     return failed(testname, "read(fd, out_char, 10)");
748
749   close(fd);
750   return passed(testname, "all");
751 }
752
753 // write() returns the number of bytes written on success, -1 on error
754 bool test_write(const char *test_file) {
755   int fd;
756   int ret_val;
757   char out_char[] = "12";
758   const char *testname = "test_write";
759
760   fd = open(test_file, O_WRONLY);
761   if (fd == -1)
762     return failed(testname, "open(test_file, O_WRONLY)");
763
764   // all params OK
765   ret_val = write(fd, out_char, 2);
766   if (ret_val != 2)
767     return failed(testname, "write(fd, out_char, 2)");
768
769   errno = 0;
770   // invalid count
771   // Linux's write() (unsandboxed) does not reject this buffer size.
772   if (!NONSFI_MODE) {
773     ret_val = write(fd, out_char, -1);
774     if (ret_val != -1)
775       return failed(testname, "write(fd, out_char, -1)");
776     // bad address
777     if (EFAULT != errno)
778       return failed(testname, "EFAULT != errno");
779   }
780
781   errno = 0;
782   // invalid fd
783   ret_val = write(-1, out_char, 2);
784   if (ret_val != -1)
785     return failed(testname, "write(-1, out_char, 2)");
786   // bad address
787   if (EBADF != errno)
788     return failed(testname, "EBADF != errno");
789
790   close(fd);
791   return passed(testname, "all");
792 }
793
794 // lseek returns the resulting offset location in bytes from the
795 // beginning of the file, -1 on error
796 bool test_lseek(const char *test_file) {
797   int fd;
798   int ret_val;
799   char out_char;
800   const char *testname = "test_lseek";
801
802   fd = open(test_file, O_RDWR);
803   if (fd == -1)
804     return failed(testname, "open(test_file, O_RDWR)");
805
806   ret_val = lseek(fd, 2, SEEK_SET);
807   if (ret_val != 2)
808     return failed(testname, "lseek(fd, 2, SEEK_SET)");
809
810   errno = 0;
811   ret_val = lseek(-1, 1, SEEK_SET);
812   if (ret_val != -1)
813     return failed(testname, "lseek(-1, 1, SEEK_SET)");
814   // bad file number
815   if (EBADF != errno)
816     return failed(testname, "EBADF != errno");
817
818   ret_val = read(fd, &out_char, 1);
819   if ((ret_val != 1) || (out_char != '3'))
820     return failed(testname, "read(fd, &out_char, 1) #1");
821
822   ret_val = lseek(fd, 1, SEEK_CUR);
823   if (ret_val != 4)
824     return failed(testname, "lseek(fd, 1, SEEK_CUR)");
825
826   ret_val = read(fd, &out_char, 1);
827   if ((ret_val != 1) || (out_char != '5'))
828     return failed(testname, "read(fd, &out_char, 1) #2");
829
830   ret_val = lseek(fd, -1, SEEK_CUR);
831   if (ret_val != 4)
832     return failed(testname, "lseek(fd, -1, SEEK_CUR)");
833
834   ret_val = read(fd, &out_char, 1);
835   if ((ret_val != 1) || (out_char != '5'))
836     return failed(testname, "read(fd, &out_char, 1) #3");
837
838   ret_val = lseek(fd, -2, SEEK_END);
839   if (ret_val != 3)
840     return failed(testname, "lseek(fd, -2, SEEK_END)");
841
842   ret_val = read(fd, &out_char, 1);
843   if ((ret_val != 1) || (out_char != '4'))
844     return failed(testname, "read(fd, &out_char, 1) #4");
845
846   ret_val = lseek(fd, 4, SEEK_END);
847   // lseek allows for positioning beyond the EOF
848   if (ret_val != 9)
849     return failed(testname, "lseek(fd, 4, SEEK_END)");
850
851   ret_val = lseek(fd, 4, SEEK_SET);
852   if (ret_val != 4)
853     return failed(testname, "lseek(fd, 4, SEEK_SET)");
854
855   errno = 0;
856   ret_val = lseek(fd, 4, SEEK_END + 3);
857   if (ret_val != -1)
858     return failed(testname, "lseek(fd, 4, SEEK_END + 3)");
859   // invalid argument
860   if (EINVAL != errno)
861     return failed(testname, "EINVAL != errno");
862
863   errno = 0;
864   ret_val = lseek(fd, -40, SEEK_SET);
865   if (ret_val != -1)
866     return failed(testname, "lseek(fd, -40, SEEK_SET)");
867   // invalid argument
868   if (EINVAL != errno)
869     return failed(testname, "EINVAL != errno");
870
871   ret_val = read(fd, &out_char, 1);
872   if ((ret_val != 1) || (out_char == '4'))
873     return failed(testname, "read(fd, &out_char, 1) #5");
874
875   close(fd);
876   return passed(testname, "all");
877 }
878
879 bool test_readdir(const char *test_file) {
880   // TODO(mseaborn): Implement listing directories for unsandboxed mode.
881   if (NONSFI_MODE)
882     return true;
883
884   // Read the directory containing the test file
885
886   // Split filename into basename and dirname.
887   char dirname[PATH_MAX];
888   strncpy(dirname, test_file, PATH_MAX);
889   char *basename = split_name(dirname);
890
891   // Read the directory listing and verify that the test_file is
892   // present.
893   int found = 0;
894   DIR *d = opendir(dirname);
895   ASSERT_NE_MSG(d, NULL, "opendir failed");
896   int count = 0;
897   struct dirent *ent;
898   while (1) {
899     ent = readdir(d);
900     if (!ent)
901       break;
902     if (!strcmp(ent->d_name, basename))
903       found = 1;
904     count++;
905   }
906   ASSERT_EQ_MSG(1, found, "failed to find test file in directory listing");
907
908   // Rewind directory and verify that the number of elements
909   // matches the previous count.
910   rewinddir(d);
911   while (readdir(d))
912     count--;
913   ASSERT_EQ_MSG(0, count, "readdir after rewinddir was inconsistent");
914
915   ASSERT_EQ(0, closedir(d));
916   return passed("test_readdir", "all");
917 }
918
919 // isatty returns 1 for TTY descriptors and 0 on error (setting errno)
920 bool test_isatty(const char *test_file) {
921   // TODO(mseaborn): Implement isatty() for unsandboxed mode.
922   // We need to write two if-statements two avoid clang's warning.
923   if (NONSFI_MODE)
924     if (TESTS_USE_IRT)
925       return true;
926
927   // TODO(sbc): isatty() in glibc is not yet hooked up to the IRT
928   // interfaces. Remove this conditional once this gets addressed:
929   // https://code.google.com/p/nativeclient/issues/detail?id=3709
930 #if defined(__GLIBC__)
931   return true;
932 #endif
933
934   // Open a regular file that check that it is not a tty.
935   int fd = open(test_file, O_RDONLY);
936   ASSERT_NE_MSG(fd, -1, "open() failed");
937   errno = 0;
938   ASSERT_EQ_MSG(isatty(fd), 0, "isatty returned non-zero");
939   ASSERT_EQ_MSG(errno, ENOTTY, "isatty failed to set errno to ENOTTY");
940   close(fd);
941
942   // Verify that isatty() on closed file returns 0 and sets errno to EBADF
943   errno = 0;
944   ASSERT_EQ_MSG(isatty(fd), 0, "isatty returned non-zero");
945   ASSERT_EQ_MSG(errno, EBADF, "isatty failed to set errno to EBADF");
946
947   // On Linux opening /dev/ptmx always returns a TTY file descriptor.
948   fd = open("/dev/ptmx", O_RDWR);
949   if (fd >= 0) {
950     errno = 0;
951     ASSERT_EQ(isatty(fd), 1);
952     ASSERT_EQ(errno, 0);
953     close(fd);
954   }
955
956   return passed("test_isatty", "all");
957 }
958
959 /*
960  * Not strictly speaking a syscall, but we have a 'fake' implementation
961  * that we want to test.
962  */
963 bool test_gethostname() {
964   char hostname[256];
965   ASSERT_EQ(gethostname(hostname, 1), -1);
966 #ifdef __GLIBC__
967   // glibc only provides a stub gethostbyname() that returns
968   // ENOSYS in all cases.
969   ASSERT_EQ(errno, ENOSYS);
970 #else
971   ASSERT_EQ(errno, ENAMETOOLONG);
972
973   errno = 0;
974   ASSERT_EQ(gethostname(hostname, 256), 0);
975   ASSERT_EQ(errno, 0);
976   ASSERT_EQ(strcmp(hostname, "naclhost"), 0);
977 #endif
978   return passed("test_gethostname", "all");
979 }
980
981 /*
982  * function testSuite()
983  *
984  *   Run through a complete sequence of file tests.
985  *
986  * returns true if all tests succeed.  false if one or more fail.
987  */
988
989 bool testSuite(const char *test_file) {
990   bool ret = true;
991   // The order of executing these tests matters!
992   ret &= test_sched_yield();
993   ret &= test_sysconf();
994   ret &= test_stat(test_file);
995   ret &= test_open(test_file);
996   ret &= test_close(test_file);
997   ret &= test_read(test_file);
998   ret &= test_write(test_file);
999   ret &= test_lseek(test_file);
1000   ret &= test_readdir(test_file);
1001   ret &= test_gethostname();
1002 // glibc support for calling syscalls directly, without the IRT, is limited
1003 // so we skip certain tests in this case.
1004 #if !defined(__GLIBC__) || TESTS_USE_IRT
1005   ret &= test_unlink(test_file);
1006   ret &= test_chdir();
1007   ret &= test_mkdir_rmdir(test_file);
1008   ret &= test_getcwd();
1009   ret &= test_mkdir_rmdir(test_file);
1010   ret &= test_isatty(test_file);
1011   ret &= test_rename(test_file);
1012   ret &= test_link(test_file);
1013   ret &= test_symlinks(test_file);
1014   ret &= test_chmod(test_file);
1015   ret &= test_access(test_file);
1016 #endif
1017 // TODO(sbc): remove this restriction once glibc's truncate calls
1018 // is hooked up to the IRT dev-filename-0.2 interface:
1019 // https://code.google.com/p/nativeclient/issues/detail?id=3709
1020 #if !defined(__GLIBC__)
1021   ret &= test_truncate(test_file);
1022 #endif
1023   ret &= test_utimes(test_file);
1024   return ret;
1025 }
1026
1027 /*
1028  * main entry point.
1029  *
1030  * run all tests and call system exit with appropriate value
1031  *   0 - success, all tests passed.
1032  *  -1 - one or more tests failed.
1033  */
1034
1035 int main(const int argc, const char *argv[]) {
1036   bool passed;
1037
1038   if (argc != 2) {
1039     printf("Please specify the test file name\n");
1040     exit(-1);
1041   }
1042   // run the full test suite
1043   passed = testSuite(argv[1]);
1044
1045   if (passed) {
1046     printf("All tests PASSED\n");
1047     exit(0);
1048   } else {
1049     printf("One or more tests FAILED\n");
1050     exit(-1);
1051   }
1052 }