source: trunk/libtransmission/file-test.c

Last change on this file was 14721, checked in by jordan, 5 years ago

fix a handful of minor compiler warnings, mostly in the unit tests, eg field width shortening or implicit signed/unsigned conversions

  • Property svn:keywords set to Date Rev Author Id
File size: 42.0 KB
Line 
1/*
2 * This file Copyright (C) 2013-2014 Mnemosyne LLC
3 *
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 * $Id: file-test.c 14721 2016-03-29 03:04:54Z mikedld $
8 */
9
10#include <string.h>
11
12#ifndef _WIN32
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <unistd.h>
16#else
17 #include <windows.h>
18#endif
19
20#include "transmission.h"
21#include "error.h"
22#include "file.h"
23
24#include "libtransmission-test.h"
25
26#ifndef _WIN32
27 #define NATIVE_PATH_SEP "/"
28#else
29 #define NATIVE_PATH_SEP "\\"
30#endif
31
32static tr_session * session;
33
34static char *
35create_test_dir (const char * name)
36{
37  char * const test_dir = tr_buildPath (tr_sessionGetConfigDir (session), name, NULL);
38  tr_sys_dir_create (test_dir, 0, 0777, NULL);
39  return test_dir;
40}
41
42static bool
43create_symlink (const char * dst_path, const char * src_path, bool dst_is_dir)
44{
45#ifndef _WIN32
46
47  (void) dst_is_dir;
48
49  return symlink (src_path, dst_path) != -1;
50
51#else
52
53  wchar_t * wide_src_path;
54  wchar_t * wide_dst_path;
55  bool ret = false;
56
57  wide_src_path = tr_win32_utf8_to_native (src_path, -1);
58  wide_dst_path = tr_win32_utf8_to_native (dst_path, -1);
59
60  ret = CreateSymbolicLinkW (wide_dst_path, wide_src_path,
61                             dst_is_dir ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0);
62
63  tr_free (wide_dst_path);
64  tr_free (wide_src_path);
65
66  return ret;
67
68#endif
69}
70
71static bool
72create_hardlink (const char * dst_path, const char * src_path)
73{
74#ifndef _WIN32
75
76  return link (src_path, dst_path) != -1;
77
78#else
79
80  wchar_t * wide_src_path = tr_win32_utf8_to_native (src_path, -1);
81  wchar_t * wide_dst_path = tr_win32_utf8_to_native (dst_path, -1);
82
83  bool ret = CreateHardLinkW (wide_dst_path, wide_src_path, NULL);
84
85  tr_free (wide_dst_path);
86  tr_free (wide_src_path);
87
88  return ret;
89
90#endif
91}
92
93static void
94clear_path_info (tr_sys_path_info * info)
95{
96  info->type = (tr_sys_path_type_t) -1;
97  info->size = (uint64_t) -1;
98  info->last_modified_at = (time_t) -1;
99}
100
101static bool
102path_contains_no_symlinks (const char * path)
103{
104  const char * p = path;
105
106  while (*p != '\0')
107    {
108      tr_sys_path_info info;
109      char * pathPart;
110      const char * slashPos = strchr (p, '/');
111
112#ifdef _WIN32
113
114      const char * backslashPos = strchr (p, '\\');
115      if (slashPos == NULL || (backslashPos != NULL && backslashPos < slashPos))
116        slashPos = backslashPos;
117
118#endif
119
120      if (slashPos == NULL)
121        slashPos = p + strlen (p) - 1;
122
123      pathPart = tr_strndup (path, (size_t)(slashPos - path + 1));
124
125      if (!tr_sys_path_get_info (pathPart, TR_SYS_PATH_NO_FOLLOW, &info, NULL) ||
126          (info.type != TR_SYS_PATH_IS_FILE && info.type != TR_SYS_PATH_IS_DIRECTORY))
127        {
128          tr_free (pathPart);
129          return false;
130        }
131
132      tr_free (pathPart);
133
134      p = slashPos + 1;
135    }
136
137  return true;
138}
139
140static bool
141validate_permissions (const char   * path,
142                      unsigned int   permissions)
143{
144#ifndef _WIN32
145
146  struct stat sb;
147  return stat (path, &sb) != -1 && (sb.st_mode & 0777) == permissions;
148
149#else
150
151  (void) path;
152  (void) permissions;
153
154  /* No UNIX permissions on Windows */
155  return true;
156
157#endif
158}
159
160static int
161test_get_info (void)
162{
163  char * const test_dir = create_test_dir (__FUNCTION__);
164  tr_sys_path_info info;
165  tr_sys_file_t fd;
166  tr_error * err = NULL;
167  char * path1, * path2;
168  time_t t;
169
170  path1 = tr_buildPath (test_dir, "a", NULL);
171  path2 = tr_buildPath (test_dir, "b", NULL);
172
173  /* Can't get info of non-existent file/directory */
174  check (!tr_sys_path_get_info (path1, 0, &info, &err));
175  check (err != NULL);
176  tr_error_clear (&err);
177
178  t = time (NULL);
179  libtest_create_file_with_string_contents (path1, "test");
180
181  /* Good file info */
182  clear_path_info (&info);
183  check (tr_sys_path_get_info (path1, 0, &info, &err));
184  check (err == NULL);
185  check_int_eq (TR_SYS_PATH_IS_FILE, info.type);
186  check_uint_eq (4, info.size);
187  check (info.last_modified_at >= t && info.last_modified_at <= time (NULL));
188
189  /* Good file info (by handle) */
190  fd = tr_sys_file_open (path1, TR_SYS_FILE_READ, 0, NULL);
191  clear_path_info (&info);
192  check (tr_sys_file_get_info (fd, &info, &err));
193  check (err == NULL);
194  check_int_eq (TR_SYS_PATH_IS_FILE, info.type);
195  check_uint_eq (4, info.size);
196  check (info.last_modified_at >= t && info.last_modified_at <= time (NULL));
197  tr_sys_file_close (fd, NULL);
198
199  tr_sys_path_remove (path1, NULL);
200
201  /* Good directory info */
202  t = time (NULL);
203  tr_sys_dir_create (path1, 0, 0777, NULL);
204  clear_path_info (&info);
205  check (tr_sys_path_get_info (path1, 0, &info, &err));
206  check (err == NULL);
207  check_int_eq (TR_SYS_PATH_IS_DIRECTORY, info.type);
208  check (info.size != (uint64_t) -1);
209  check (info.last_modified_at >= t && info.last_modified_at <= time (NULL));
210  tr_sys_path_remove (path1, NULL);
211
212  if (create_symlink (path1, path2, false))
213    {
214      /* Can't get info of non-existent file/directory */
215      check (!tr_sys_path_get_info (path1, 0, &info, &err));
216      check (err != NULL);
217      tr_error_clear (&err);
218
219      t = time (NULL);
220      libtest_create_file_with_string_contents (path2, "test");
221
222      /* Good file info */
223      clear_path_info (&info);
224      check (tr_sys_path_get_info (path1, 0, &info, &err));
225      check (err == NULL);
226      check_int_eq (TR_SYS_PATH_IS_FILE, info.type);
227      check_uint_eq (4, info.size);
228      check (info.last_modified_at >= t && info.last_modified_at <= time (NULL));
229
230      /* Good file info (by handle) */
231      fd = tr_sys_file_open (path1, TR_SYS_FILE_READ, 0, NULL);
232      clear_path_info (&info);
233      check (tr_sys_file_get_info (fd, &info, &err));
234      check (err == NULL);
235      check_int_eq (TR_SYS_PATH_IS_FILE, info.type);
236      check_uint_eq (4, info.size);
237      check (info.last_modified_at >= t && info.last_modified_at <= time (NULL));
238      tr_sys_file_close (fd, NULL);
239
240      tr_sys_path_remove (path2, NULL);
241
242      /* Good directory info */
243      t = time (NULL);
244      tr_sys_dir_create (path2, 0, 0777, NULL);
245      clear_path_info (&info);
246      check (tr_sys_path_get_info (path1, 0, &info, &err));
247      check (err == NULL);
248      check_int_eq (TR_SYS_PATH_IS_DIRECTORY, info.type);
249      check (info.size != (uint64_t) -1);
250      check (info.last_modified_at >= t && info.last_modified_at <= time (NULL));
251
252      tr_sys_path_remove (path2, NULL);
253      tr_sys_path_remove (path1, NULL);
254    }
255  else
256    {
257      fprintf (stderr, "WARNING: [%s] unable to run symlink tests\n", __FUNCTION__);
258    }
259
260  tr_free (path2);
261  tr_free (path1);
262
263  tr_free (test_dir);
264  return 0;
265}
266
267static int
268test_path_exists (void)
269{
270  char * const test_dir = create_test_dir (__FUNCTION__);
271  tr_error * err = NULL;
272  char * path1, * path2;
273
274  path1 = tr_buildPath (test_dir, "a", NULL);
275  path2 = tr_buildPath (test_dir, "b", NULL);
276
277  /* Non-existent file does not exist */
278  check (!tr_sys_path_exists (path1, &err));
279  check (err == NULL);
280
281  /* Create file and see that it exists */
282  libtest_create_file_with_string_contents (path1, "test");
283  check (tr_sys_path_exists (path1, &err));
284  check (err == NULL);
285
286  tr_sys_path_remove (path1, NULL);
287
288  /* Create directory and see that it exists */
289  tr_sys_dir_create (path1, 0, 0777, NULL);
290  check (tr_sys_path_exists (path1, &err));
291  check (err == NULL);
292
293  tr_sys_path_remove (path1, NULL);
294
295  if (create_symlink (path1, path2, false))
296    {
297      /* Non-existent file does not exist (via symlink) */
298      check (!tr_sys_path_exists (path1, &err));
299      check (err == NULL);
300
301      /* Create file and see that it exists (via symlink) */
302      libtest_create_file_with_string_contents (path2, "test");
303      check (tr_sys_path_exists (path1, &err));
304      check (err == NULL);
305
306      tr_sys_path_remove (path2, NULL);
307
308      /* Create directory and see that it exists (via symlink) */
309      tr_sys_dir_create (path2, 0, 0777, NULL);
310      check (tr_sys_path_exists (path1, &err));
311      check (err == NULL);
312
313      tr_sys_path_remove (path2, NULL);
314      tr_sys_path_remove (path1, NULL);
315    }
316  else
317    {
318      fprintf (stderr, "WARNING: [%s] unable to run symlink tests\n", __FUNCTION__);
319    }
320
321  tr_free (path2);
322  tr_free (path1);
323
324  tr_free (test_dir);
325  return 0;
326}
327
328static int
329test_path_is_relative (void)
330{
331  check (tr_sys_path_is_relative (""));
332  check (tr_sys_path_is_relative ("."));
333  check (tr_sys_path_is_relative (".."));
334  check (tr_sys_path_is_relative ("x"));
335  check (tr_sys_path_is_relative ("\\"));
336  check (tr_sys_path_is_relative (":"));
337
338#ifdef _WIN32
339
340  check (tr_sys_path_is_relative ("/"));
341  check (tr_sys_path_is_relative ("\\x"));
342  check (tr_sys_path_is_relative ("/x"));
343  check (tr_sys_path_is_relative ("\\x\\y"));
344  check (tr_sys_path_is_relative ("/x/y"));
345  check (tr_sys_path_is_relative ("C:x"));
346  check (tr_sys_path_is_relative ("C:x\\y"));
347  check (tr_sys_path_is_relative ("C:x/y"));
348
349  check (!tr_sys_path_is_relative ("\\\\"));
350  check (!tr_sys_path_is_relative ("//"));
351  check (!tr_sys_path_is_relative ("\\\\x"));
352  check (!tr_sys_path_is_relative ("//x"));
353  check (!tr_sys_path_is_relative ("\\\\x\\y"));
354  check (!tr_sys_path_is_relative ("//x/y"));
355  check (!tr_sys_path_is_relative ("\\\\.\\x"));
356  check (!tr_sys_path_is_relative ("//./x"));
357
358  check (!tr_sys_path_is_relative ("a:"));
359  check (!tr_sys_path_is_relative ("a:\\"));
360  check (!tr_sys_path_is_relative ("a:/"));
361  check (!tr_sys_path_is_relative ("Z:"));
362  check (!tr_sys_path_is_relative ("Z:\\"));
363  check (!tr_sys_path_is_relative ("Z:/"));
364
365#else /* _WIN32 */
366
367  check (!tr_sys_path_is_relative ("/"));
368  check (!tr_sys_path_is_relative ("/x"));
369  check (!tr_sys_path_is_relative ("/x/y"));
370  check (!tr_sys_path_is_relative ("//x"));
371
372#endif /* _WIN32 */
373
374  return 0;
375}
376
377static int
378test_path_is_same (void)
379{
380  char * const test_dir = create_test_dir (__FUNCTION__);
381  tr_error * err = NULL;
382  char * path1, * path2, * path3;
383
384  path1 = tr_buildPath (test_dir, "a", NULL);
385  path2 = tr_buildPath (test_dir, "b", NULL);
386  path3 = tr_buildPath (path2, "c", NULL);
387
388  /* Two non-existent files are not the same */
389  check (!tr_sys_path_is_same (path1, path1, &err));
390  check (err == NULL);
391  check (!tr_sys_path_is_same (path1, path2, &err));
392  check (err == NULL);
393
394  /* Two same files are the same */
395  libtest_create_file_with_string_contents (path1, "test");
396  check (tr_sys_path_is_same (path1, path1, &err));
397  check (err == NULL);
398
399  /* Existent and non-existent files are not the same */
400  check (!tr_sys_path_is_same (path1, path2, &err));
401  check (err == NULL);
402  check (!tr_sys_path_is_same (path2, path1, &err));
403  check (err == NULL);
404
405  /* Two separate files (even with same content) are not the same */
406  libtest_create_file_with_string_contents (path2, "test");
407  check (!tr_sys_path_is_same (path1, path2, &err));
408  check (err == NULL);
409
410  tr_sys_path_remove (path1, NULL);
411
412  /* Two same directories are the same */
413  tr_sys_dir_create (path1, 0, 0777, NULL);
414  check (tr_sys_path_is_same (path1, path1, &err));
415  check (err == NULL);
416
417  /* File and directory are not the same */
418  check (!tr_sys_path_is_same (path1, path2, &err));
419  check (err == NULL);
420  check (!tr_sys_path_is_same (path2, path1, &err));
421  check (err == NULL);
422
423  tr_sys_path_remove (path2, NULL);
424
425  /* Two separate directories are not the same */
426  tr_sys_dir_create (path2, 0, 0777, NULL);
427  check (!tr_sys_path_is_same (path1, path2, &err));
428  check (err == NULL);
429
430  tr_sys_path_remove (path1, NULL);
431  tr_sys_path_remove (path2, NULL);
432
433  if (create_symlink (path1, ".", true))
434    {
435      /* Directory and symlink pointing to it are the same */
436      check (tr_sys_path_is_same (path1, test_dir, &err));
437      check (err == NULL);
438      check (tr_sys_path_is_same (test_dir, path1, &err));
439      check (err == NULL);
440
441      /* Non-existent file and symlink are not the same */
442      check (!tr_sys_path_is_same (path1, path2, &err));
443      check (err == NULL);
444      check (!tr_sys_path_is_same (path2, path1, &err));
445      check (err == NULL);
446
447      /* Symlinks pointing to different directories are not the same */
448      create_symlink (path2, "..", true);
449      check (!tr_sys_path_is_same (path1, path2, &err));
450      check (err == NULL);
451      check (!tr_sys_path_is_same (path2, path1, &err));
452      check (err == NULL);
453
454      tr_sys_path_remove (path2, NULL);
455
456      /* Symlinks pointing to same directory are the same */
457      create_symlink (path2, ".", true);
458      check (tr_sys_path_is_same (path1, path2, &err));
459      check (err == NULL);
460
461      tr_sys_path_remove (path2, NULL);
462
463      /* Directory and symlink pointing to another directory are not the same */
464      tr_sys_dir_create (path2, 0, 0777, NULL);
465      check (!tr_sys_path_is_same (path1, path2, &err));
466      check (err == NULL);
467      check (!tr_sys_path_is_same (path2, path1, &err));
468      check (err == NULL);
469
470      /* Symlinks pointing to same directory are the same */
471      create_symlink (path3, "..", true);
472      check (tr_sys_path_is_same (path1, path3, &err));
473      check (err == NULL);
474
475      tr_sys_path_remove (path1, NULL);
476
477      /* File and symlink pointing to directory are not the same */
478      libtest_create_file_with_string_contents (path1, "test");
479      check (!tr_sys_path_is_same (path1, path3, &err));
480      check (err == NULL);
481      check (!tr_sys_path_is_same (path3, path1, &err));
482      check (err == NULL);
483
484      tr_sys_path_remove (path3, NULL);
485
486      /* File and symlink pointing to same file are the same */
487      create_symlink (path3, path1, false);
488      check (tr_sys_path_is_same (path1, path3, &err));
489      check (err == NULL);
490      check (tr_sys_path_is_same (path3, path1, &err));
491      check (err == NULL);
492
493      /* Symlinks pointing to non-existent files are not the same */
494      tr_sys_path_remove (path1, NULL);
495      create_symlink (path1, "missing", false);
496      tr_sys_path_remove (path3, NULL);
497      create_symlink (path3, "missing", false);
498      check (!tr_sys_path_is_same (path1, path3, &err));
499      check (err == NULL);
500      check (!tr_sys_path_is_same (path3, path1, &err));
501      check (err == NULL);
502
503      tr_sys_path_remove (path3, NULL);
504
505      /* Symlinks pointing to same non-existent file are not the same */
506      create_symlink (path3, ".." NATIVE_PATH_SEP "missing", false);
507      check (!tr_sys_path_is_same (path1, path3, &err));
508      check (err == NULL);
509      check (!tr_sys_path_is_same (path3, path1, &err));
510      check (err == NULL);
511
512      /* Non-existent file and symlink pointing to non-existent file are not the same */
513      tr_sys_path_remove (path3, NULL);
514      check (!tr_sys_path_is_same (path1, path3, &err));
515      check (err == NULL);
516      check (!tr_sys_path_is_same (path3, path1, &err));
517      check (err == NULL);
518
519      tr_sys_path_remove (path2, NULL);
520      tr_sys_path_remove (path1, NULL);
521    }
522  else
523    {
524      fprintf (stderr, "WARNING: [%s] unable to run symlink tests\n", __FUNCTION__);
525    }
526
527  tr_free (path3);
528  path3 = tr_buildPath (test_dir, "c", NULL);
529
530  libtest_create_file_with_string_contents (path1, "test");
531
532  if (create_hardlink (path2, path1))
533    {
534      /* File and hardlink to it are the same */
535      check (tr_sys_path_is_same (path1, path2, &err));
536      check (err == NULL);
537
538      /* Two hardlinks to the same file are the same */
539      create_hardlink (path3, path2);
540      check (tr_sys_path_is_same (path2, path3, &err));
541      check (err == NULL);
542      check (tr_sys_path_is_same (path1, path3, &err));
543      check (err == NULL);
544
545      tr_sys_path_remove (path2, NULL);
546
547      check (tr_sys_path_is_same (path1, path3, &err));
548      check (err == NULL);
549
550      tr_sys_path_remove (path3, NULL);
551
552      /* File and hardlink to another file are not the same */
553      libtest_create_file_with_string_contents (path3, "test");
554      create_hardlink (path2, path3);
555      check (!tr_sys_path_is_same (path1, path2, &err));
556      check (err == NULL);
557      check (!tr_sys_path_is_same (path2, path1, &err));
558      check (err == NULL);
559
560      tr_sys_path_remove (path3, NULL);
561      tr_sys_path_remove (path2, NULL);
562    }
563  else
564    {
565      fprintf (stderr, "WARNING: [%s] unable to run hardlink tests\n", __FUNCTION__);
566    }
567
568  if (create_symlink (path2, path1, false) && create_hardlink (path3, path1))
569    {
570      check (tr_sys_path_is_same (path2, path3, &err));
571      check (err == NULL);
572    }
573  else
574    {
575      fprintf (stderr, "WARNING: [%s] unable to run combined symlink and hardlink tests\n", __FUNCTION__);
576    }
577
578  tr_sys_path_remove (path3, NULL);
579  tr_sys_path_remove (path2, NULL);
580  tr_sys_path_remove (path1, NULL);
581
582  tr_free (path3);
583  tr_free (path2);
584  tr_free (path1);
585
586  tr_free (test_dir);
587  return 0;
588}
589
590static int
591test_path_resolve (void)
592{
593  char * const test_dir = create_test_dir (__FUNCTION__);
594  tr_error * err = NULL;
595  char * path1, * path2;
596
597  path1 = tr_buildPath (test_dir, "a", NULL);
598  path2 = tr_buildPath (test_dir, "b", NULL);
599
600  libtest_create_file_with_string_contents (path1, "test");
601  if (create_symlink (path2, path1, false))
602    {
603      char * tmp;
604
605      tmp = tr_sys_path_resolve (path2, &err);
606      check (tmp != NULL);
607      check (err == NULL);
608      check (path_contains_no_symlinks (tmp));
609      tr_free (tmp);
610
611      tr_sys_path_remove (path1, NULL);
612      tr_sys_dir_create (path1, 0, 0755, NULL);
613
614      tmp = tr_sys_path_resolve (path2, &err);
615      check (tmp != NULL);
616      check (err == NULL);
617      check (path_contains_no_symlinks (tmp));
618      tr_free (tmp);
619    }
620  else
621    {
622      fprintf (stderr, "WARNING: [%s] unable to run symlink tests\n", __FUNCTION__);
623    }
624
625  tr_sys_path_remove (path2, NULL);
626  tr_sys_path_remove (path1, NULL);
627
628  tr_free (path2);
629  tr_free (path1);
630
631  tr_free (test_dir);
632  return 0;
633}
634
635struct xname_test_data
636{
637  const char * input;
638  const char * output;
639};
640
641static int
642test_path_xname (const struct xname_test_data * data,
643                 size_t                         data_size,
644                 char *                      (* func) (const char *, tr_error **))
645{
646  for (size_t i = 0; i < data_size; ++i)
647    {
648      tr_error * err = NULL;
649      char * name = func (data[i].input, &err);
650
651      if (data[i].output != NULL)
652        {
653          check (name != NULL);
654          check (err == NULL);
655          check_streq (data[i].output, name);
656          tr_free (name);
657        }
658      else
659        {
660          check (name == NULL);
661          check (err != NULL);
662          tr_error_clear (&err);
663        }
664    }
665
666  return 0;
667}
668
669static int
670test_path_basename_dirname (void)
671{
672  const struct xname_test_data common_xname_tests[] =
673  {
674    { "/", "/" },
675    { "", "." },
676#ifdef _WIN32
677    { "\\", "/" },
678    /* Invalid paths */
679    { "\\\\\\", NULL },
680    { "123:" , NULL },
681    /* Reserved characters */
682    { "<", NULL },
683    { ">", NULL },
684    { ":", NULL },
685    { "\"", NULL },
686    { "|", NULL },
687    { "?", NULL },
688    { "*", NULL },
689    { "a\\<", NULL },
690    { "a\\>", NULL },
691    { "a\\:", NULL },
692    { "a\\\"", NULL },
693    { "a\\|", NULL },
694    { "a\\?", NULL },
695    { "a\\*", NULL },
696    { "c:\\a\\b<c\\d", NULL },
697    { "c:\\a\\b>c\\d", NULL },
698    { "c:\\a\\b:c\\d", NULL },
699    { "c:\\a\\b\"c\\d", NULL },
700    { "c:\\a\\b|c\\d", NULL },
701    { "c:\\a\\b?c\\d", NULL },
702    { "c:\\a\\b*c\\d", NULL }
703#else
704    { "////", "/" }
705#endif
706  };
707
708  if (test_path_xname (common_xname_tests, sizeof (common_xname_tests) / sizeof (*common_xname_tests), tr_sys_path_basename) != 0)
709    return 1;
710  if (test_path_xname (common_xname_tests, sizeof (common_xname_tests) / sizeof (*common_xname_tests), tr_sys_path_dirname) != 0)
711    return 1;
712
713  const struct xname_test_data basename_tests[] =
714  {
715    { "a", "a" },
716    { "aa", "aa" },
717    { "/aa", "aa" },
718    { "/a/b/c", "c" },
719    { "/a/b/c/", "c" },
720#ifdef _WIN32
721    { "c:\\a\\b\\c", "c" },
722    { "c:", "/" },
723    { "c:/", "/" },
724    { "c:\\", "/" },
725    { "c:a/b", "b" },
726    { "c:a", "a" },
727    { "\\\\a\\b\\c", "c" },
728    { "//a/b", "b" },
729    { "//1.2.3.4/b", "b" },
730    { "\\\\a", "a" },
731    { "\\\\1.2.3.4", "1.2.3.4" },
732    { "\\", "/" },
733    { "\\a", "a" }
734#endif
735  };
736
737  if (test_path_xname (basename_tests, sizeof (basename_tests) / sizeof (*basename_tests), tr_sys_path_basename) != 0)
738    return 1;
739
740  const struct xname_test_data dirname_tests[] =
741  {
742    { "/a/b/c", "/a/b" },
743    { "a/b/c", "a/b" },
744    { "a/b/c/", "a/b" },
745    { "a", "." },
746    { "a/", "." },
747#ifdef _WIN32
748    { "C:\\a/b\\c", "C:\\a/b" },
749    { "C:\\a/b\\c\\", "C:\\a/b" },
750    { "C:\\a/b", "C:\\a" },
751    { "C:/a", "C:" },
752    { "C:", "C:" },
753    { "C:/", "C:" },
754    { "C:\\", "C:" },
755    { "c:a/b", "c:a" },
756    { "c:a", "c:." },
757    { "c:.", "c:." },
758    { "\\\\a\\b\\c", "\\\\a\\b" },
759    { "\\\\a\\b\\c/", "\\\\a\\b" },
760    { "//a/b", "//a" },
761    { "//1.2.3.4/b", "//1.2.3.4" },
762    { "\\\\a", "\\\\" },
763    { "\\\\1.2.3.4", "\\\\" },
764    { "\\\\", "\\\\" },
765    { "a/b\\c", "a/b" }
766#endif
767  };
768
769  if (test_path_xname (dirname_tests, sizeof (dirname_tests) / sizeof (*dirname_tests), tr_sys_path_dirname) != 0)
770    return 1;
771
772  /* TODO: is_same (dirname (x) + '/' + basename (x), x) */
773
774  return 0;
775}
776
777static int
778test_path_rename (void)
779{
780  char * const test_dir = create_test_dir (__FUNCTION__);
781  tr_error * err = NULL;
782  char * path1, * path2, * path3;
783
784  path1 = tr_buildPath (test_dir, "a", NULL);
785  path2 = tr_buildPath (test_dir, "b", NULL);
786  path3 = tr_buildPath (path2, "c", NULL);
787
788  libtest_create_file_with_string_contents (path1, "test");
789
790  /* Preconditions */
791  check (tr_sys_path_exists (path1, NULL));
792  check (!tr_sys_path_exists (path2, NULL));
793
794  /* Forward rename works */
795  check (tr_sys_path_rename (path1, path2, &err));
796  check (!tr_sys_path_exists (path1, NULL));
797  check (tr_sys_path_exists (path2, NULL));
798  check (err == NULL);
799
800  /* Backward rename works */
801  check (tr_sys_path_rename (path2, path1, &err));
802  check (tr_sys_path_exists (path1, NULL));
803  check (!tr_sys_path_exists (path2, NULL));
804  check (err == NULL);
805
806  /* Another backward rename [of non-existent file] does not work */
807  check (!tr_sys_path_rename (path2, path1, &err));
808  check (err != NULL);
809  tr_error_clear (&err);
810
811  /* Rename to file which couldn't be created does not work */
812  check (!tr_sys_path_rename (path1, path3, &err));
813  check (err != NULL);
814  tr_error_clear (&err);
815
816  /* Rename of non-existent file does not work */
817  check (!tr_sys_path_rename (path3, path2, &err));
818  check (err != NULL);
819  tr_error_clear (&err);
820
821  libtest_create_file_with_string_contents (path2, "test");
822
823  /* Renaming file does overwrite existing file */
824  check (tr_sys_path_rename (path2, path1, &err));
825  check (err == NULL);
826
827  tr_sys_dir_create (path2, 0, 0777, NULL);
828
829  /* Renaming file does not overwrite existing directory, and vice versa */
830  check (!tr_sys_path_rename (path1, path2, &err));
831  check (err != NULL);
832  tr_error_clear (&err);
833  check (!tr_sys_path_rename (path2, path1, &err));
834  check (err != NULL);
835  tr_error_clear (&err);
836
837  tr_sys_path_remove (path2, NULL);
838
839  tr_free (path3);
840  path3 = tr_buildPath (test_dir, "c", NULL);
841
842  if (create_symlink (path2, path1, false))
843    {
844      /* Preconditions */
845      check (tr_sys_path_exists (path2, NULL));
846      check (!tr_sys_path_exists (path3, NULL));
847      check (tr_sys_path_is_same (path1, path2, NULL));
848
849      /* Rename of symlink works, files stay the same */
850      check (tr_sys_path_rename (path2, path3, &err));
851      check (err == NULL);
852      check (!tr_sys_path_exists (path2, NULL));
853      check (tr_sys_path_exists (path3, NULL));
854      check (tr_sys_path_is_same (path1, path3, NULL));
855
856      tr_sys_path_remove (path3, NULL);
857    }
858  else
859    {
860      fprintf (stderr, "WARNING: [%s] unable to run symlink tests\n", __FUNCTION__);
861    }
862
863  if (create_hardlink (path2, path1))
864    {
865      /* Preconditions */
866      check (tr_sys_path_exists (path2, NULL));
867      check (!tr_sys_path_exists (path3, NULL));
868      check (tr_sys_path_is_same (path1, path2, NULL));
869
870      /* Rename of hardlink works, files stay the same */
871      check (tr_sys_path_rename (path2, path3, &err));
872      check (err == NULL);
873      check (!tr_sys_path_exists (path2, NULL));
874      check (tr_sys_path_exists (path3, NULL));
875      check (tr_sys_path_is_same (path1, path3, NULL));
876
877      tr_sys_path_remove (path3, NULL);
878    }
879  else
880    {
881      fprintf (stderr, "WARNING: [%s] unable to run hardlink tests\n", __FUNCTION__);
882    }
883
884  tr_sys_path_remove (path1, NULL);
885
886  tr_free (path3);
887  tr_free (path2);
888  tr_free (path1);
889
890  tr_free (test_dir);
891  return 0;
892}
893
894static int
895test_path_remove (void)
896{
897  char * const test_dir = create_test_dir (__FUNCTION__);
898  tr_error * err = NULL;
899  char * path1, * path2, * path3;
900
901  path1 = tr_buildPath (test_dir, "a", NULL);
902  path2 = tr_buildPath (test_dir, "b", NULL);
903  path3 = tr_buildPath (path2, "c", NULL);
904
905  /* Can't remove non-existent file/directory */
906  check (!tr_sys_path_exists (path1, NULL));
907  check (!tr_sys_path_remove (path1, &err));
908  check (err != NULL);
909  check (!tr_sys_path_exists (path1, NULL));
910  tr_error_clear (&err);
911
912  /* Removing file works */
913  libtest_create_file_with_string_contents (path1, "test");
914  check (tr_sys_path_exists (path1, NULL));
915  check (tr_sys_path_remove (path1, &err));
916  check (err == NULL);
917  check (!tr_sys_path_exists (path1, NULL));
918
919  /* Removing empty directory works */
920  tr_sys_dir_create (path1, 0, 0777, NULL);
921  check (tr_sys_path_exists (path1, NULL));
922  check (tr_sys_path_remove (path1, &err));
923  check (err == NULL);
924  check (!tr_sys_path_exists (path1, NULL));
925
926  /* Removing non-empty directory fails */
927  tr_sys_dir_create (path2, 0, 0777, NULL);
928  libtest_create_file_with_string_contents (path3, "test");
929  check (tr_sys_path_exists (path2, NULL));
930  check (tr_sys_path_exists (path3, NULL));
931  check (!tr_sys_path_remove (path2, &err));
932  check (err != NULL);
933  check (tr_sys_path_exists (path2, NULL));
934  check (tr_sys_path_exists (path3, NULL));
935  tr_error_clear (&err);
936
937  tr_sys_path_remove (path3, NULL);
938  tr_sys_path_remove (path2, NULL);
939
940  tr_free (path3);
941  tr_free (path2);
942  tr_free (path1);
943
944  tr_free (test_dir);
945  return 0;
946}
947
948static int
949test_file_open (void)
950{
951  char * const test_dir = create_test_dir (__FUNCTION__);
952  tr_error * err = NULL;
953  char * path1;
954  tr_sys_file_t fd;
955  uint64_t n;
956  tr_sys_path_info info;
957
958  path1 = tr_buildPath (test_dir, "a", NULL);
959
960  /* Can't open non-existent file */
961  check (!tr_sys_path_exists (path1, NULL));
962  check (tr_sys_file_open (path1, TR_SYS_FILE_READ, 0600, &err) == TR_BAD_SYS_FILE);
963  check (err != NULL);
964  check (!tr_sys_path_exists (path1, NULL));
965  tr_error_clear (&err);
966  check (tr_sys_file_open (path1, TR_SYS_FILE_WRITE, 0600, &err) == TR_BAD_SYS_FILE);
967  check (err != NULL);
968  check (!tr_sys_path_exists (path1, NULL));
969  tr_error_clear (&err);
970
971  /* Can't open directory */
972  tr_sys_dir_create (path1, 0, 0777, NULL);
973#ifdef _WIN32
974  /* This works on *NIX */
975  check (tr_sys_file_open (path1, TR_SYS_FILE_READ, 0600, &err) == TR_BAD_SYS_FILE);
976  check (err != NULL);
977  tr_error_clear (&err);
978#endif
979  check (tr_sys_file_open (path1, TR_SYS_FILE_WRITE, 0600, &err) == TR_BAD_SYS_FILE);
980  check (err != NULL);
981  tr_error_clear (&err);
982
983  tr_sys_path_remove (path1, NULL);
984
985  /* Can create non-existent file */
986  fd = tr_sys_file_open (path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0640, &err);
987  check (fd != TR_BAD_SYS_FILE);
988  check (err == NULL);
989  tr_sys_file_close (fd, NULL);
990  check (tr_sys_path_exists (path1, NULL));
991  check (validate_permissions (path1, 0640));
992
993  /* Can open existing file */
994  check (tr_sys_path_exists (path1, NULL));
995  fd = tr_sys_file_open (path1, TR_SYS_FILE_READ, 0600, &err);
996  check (fd != TR_BAD_SYS_FILE);
997  check (err == NULL);
998  tr_sys_file_close (fd, NULL);
999  fd = tr_sys_file_open (path1, TR_SYS_FILE_WRITE, 0600, &err);
1000  check (fd != TR_BAD_SYS_FILE);
1001  check (err == NULL);
1002  tr_sys_file_close (fd, NULL);
1003
1004  tr_sys_path_remove (path1, NULL);
1005  libtest_create_file_with_string_contents (path1, "test");
1006
1007  /* Can't create new file if it already exists */
1008  fd = tr_sys_file_open (path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE_NEW, 0640, &err);
1009  check (fd == TR_BAD_SYS_FILE);
1010  check (err != NULL);
1011  tr_error_clear (&err);
1012  tr_sys_path_get_info (path1, TR_SYS_PATH_NO_FOLLOW, &info, NULL);
1013  check_uint_eq (4, info.size);
1014
1015  /* Pointer is at the end of file */
1016  tr_sys_path_get_info (path1, TR_SYS_PATH_NO_FOLLOW, &info, NULL);
1017  check_uint_eq (4, info.size);
1018  fd = tr_sys_file_open (path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_APPEND, 0600, &err);
1019  check (fd != TR_BAD_SYS_FILE);
1020  check (err == NULL);
1021  tr_sys_file_write (fd, "s", 1, NULL, NULL); /* On *NIX, pointer is positioned on each write but not initially */
1022  tr_sys_file_seek (fd, 0, TR_SEEK_CUR, &n, NULL);
1023  check_uint_eq (5, n);
1024  tr_sys_file_close (fd, NULL);
1025
1026  /* File gets truncated */
1027  tr_sys_path_get_info (path1, TR_SYS_PATH_NO_FOLLOW, &info, NULL);
1028  check_uint_eq (5, info.size);
1029  fd = tr_sys_file_open (path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_TRUNCATE, 0600, &err);
1030  check (fd != TR_BAD_SYS_FILE);
1031  check (err == NULL);
1032  tr_sys_file_get_info (fd, &info, NULL);
1033  check_uint_eq (0, info.size);
1034  tr_sys_file_close (fd, NULL);
1035  tr_sys_path_get_info (path1, TR_SYS_PATH_NO_FOLLOW, &info, NULL);
1036  check_uint_eq (0, info.size);
1037
1038  /* TODO: symlink and hardlink tests */
1039
1040  tr_sys_path_remove (path1, NULL);
1041
1042  tr_free (path1);
1043
1044  tr_free (test_dir);
1045  return 0;
1046}
1047
1048static int
1049test_file_read_write_seek (void)
1050{
1051  char * const test_dir = create_test_dir (__FUNCTION__);
1052  tr_error * err = NULL;
1053  char * path1;
1054  tr_sys_file_t fd;
1055  uint64_t n;
1056  char buf[100];
1057
1058  path1 = tr_buildPath (test_dir, "a", NULL);
1059
1060  fd = tr_sys_file_open (path1, TR_SYS_FILE_READ | TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, NULL);
1061
1062  check (tr_sys_file_seek (fd, 0, TR_SEEK_CUR, &n, &err));
1063  check (err == NULL);
1064  check_uint_eq (0, n);
1065
1066  check (tr_sys_file_write (fd, "test", 4, &n, &err));
1067  check (err == NULL);
1068  check_uint_eq (4, n);
1069
1070  check (tr_sys_file_seek (fd, 0, TR_SEEK_CUR, &n, &err));
1071  check (err == NULL);
1072  check_uint_eq (4, n);
1073
1074  check (tr_sys_file_seek (fd, 0, TR_SEEK_SET, &n, &err));
1075  check (err == NULL);
1076  check_uint_eq (0, n);
1077
1078  check (tr_sys_file_read (fd, buf, sizeof (buf), &n, &err));
1079  check (err == NULL);
1080  check_uint_eq (4, n);
1081
1082  check_int_eq (0, memcmp (buf, "test", 4));
1083
1084  check (tr_sys_file_seek (fd, -3, TR_SEEK_CUR, &n, &err));
1085  check (err == NULL);
1086  check_uint_eq (1, n);
1087
1088  check (tr_sys_file_write (fd, "E", 1, &n, &err));
1089  check (err == NULL);
1090  check_uint_eq (1, n);
1091
1092  check (tr_sys_file_seek (fd, -2, TR_SEEK_CUR, &n, &err));
1093  check (err == NULL);
1094  check_uint_eq (0, n);
1095
1096  check (tr_sys_file_read (fd, buf, sizeof (buf), &n, &err));
1097  check (err == NULL);
1098  check_uint_eq (4, n);
1099
1100  check_int_eq (0, memcmp (buf, "tEst", 4));
1101
1102  check (tr_sys_file_seek (fd, 0, TR_SEEK_END, &n, &err));
1103  check (err == NULL);
1104  check_uint_eq (4, n);
1105
1106  check (tr_sys_file_write (fd, " ok", 3, &n, &err));
1107  check (err == NULL);
1108  check_uint_eq (3, n);
1109
1110  check (tr_sys_file_seek (fd, 0, TR_SEEK_SET, &n, &err));
1111  check (err == NULL);
1112  check_uint_eq (0, n);
1113
1114  check (tr_sys_file_read (fd, buf, sizeof (buf), &n, &err));
1115  check (err == NULL);
1116  check_uint_eq (7, n);
1117
1118  check_int_eq (0, memcmp (buf, "tEst ok", 7));
1119
1120  check (tr_sys_file_write_at (fd, "-", 1, 4, &n, &err));
1121  check (err == NULL);
1122  check_uint_eq (1, n);
1123
1124  check (tr_sys_file_read_at (fd, buf, 5, 2, &n, &err));
1125  check (err == NULL);
1126  check_uint_eq (5, n);
1127
1128  check_int_eq (0, memcmp (buf, "st-ok", 5));
1129
1130  tr_sys_file_close (fd, NULL);
1131
1132  tr_sys_path_remove (path1, NULL);
1133
1134  tr_free (path1);
1135
1136  tr_free (test_dir);
1137  return 0;
1138}
1139
1140static int
1141test_file_truncate (void)
1142{
1143  char * const test_dir = create_test_dir (__FUNCTION__);
1144  tr_error * err = NULL;
1145  char * path1;
1146  tr_sys_file_t fd;
1147  tr_sys_path_info info;
1148
1149  path1 = tr_buildPath (test_dir, "a", NULL);
1150
1151  fd = tr_sys_file_open (path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, NULL);
1152
1153  check (tr_sys_file_truncate (fd, 10, &err));
1154  check (err == NULL);
1155  tr_sys_file_get_info (fd, &info, NULL);
1156  check_uint_eq (10, info.size);
1157
1158  check (tr_sys_file_truncate (fd, 20, &err));
1159  check (err == NULL);
1160  tr_sys_file_get_info (fd, &info, NULL);
1161  check_uint_eq (20, info.size);
1162
1163  check (tr_sys_file_truncate (fd, 0, &err));
1164  check (err == NULL);
1165  tr_sys_file_get_info (fd, &info, NULL);
1166  check_uint_eq (0, info.size);
1167
1168  check (tr_sys_file_truncate (fd, 50, &err));
1169  check (err == NULL);
1170
1171  tr_sys_file_close (fd, NULL);
1172
1173  tr_sys_path_get_info (path1, 0, &info, NULL);
1174  check_uint_eq (50, info.size);
1175
1176  fd = tr_sys_file_open (path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, NULL);
1177
1178  check (tr_sys_file_truncate (fd, 25, &err));
1179  check (err == NULL);
1180
1181  tr_sys_file_close (fd, NULL);
1182
1183  tr_sys_path_get_info (path1, 0, &info, NULL);
1184  check_uint_eq (25, info.size);
1185
1186  tr_sys_path_remove (path1, NULL);
1187
1188  tr_free (path1);
1189
1190  tr_free (test_dir);
1191  return 0;
1192}
1193
1194static int
1195test_file_preallocate (void)
1196{
1197  char * const test_dir = create_test_dir (__FUNCTION__);
1198  tr_error * err = NULL;
1199  char * path1;
1200  tr_sys_file_t fd;
1201  tr_sys_path_info info;
1202
1203  path1 = tr_buildPath (test_dir, "a", NULL);
1204
1205  fd = tr_sys_file_open (path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, NULL);
1206
1207  if (tr_sys_file_preallocate (fd, 50, 0, &err))
1208    {
1209      check (err == NULL);
1210      tr_sys_file_get_info (fd, &info, NULL);
1211      check_uint_eq (50, info.size);
1212    }
1213  else
1214    {
1215      check (err != NULL);
1216      fprintf (stderr, "WARNING: [%s] unable to preallocate file (full): %s (%d)\n", __FUNCTION__, err->message, err->code);
1217      tr_error_clear (&err);
1218    }
1219
1220  tr_sys_file_close (fd, NULL);
1221
1222  tr_sys_path_remove (path1, NULL);
1223
1224  fd = tr_sys_file_open (path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, NULL);
1225
1226  if (tr_sys_file_preallocate (fd, 500 * 1024 * 1024, TR_SYS_FILE_PREALLOC_SPARSE, &err))
1227    {
1228      check (err == NULL);
1229      tr_sys_file_get_info (fd, &info, NULL);
1230      check_uint_eq (500 * 1024 * 1024, info.size);
1231    }
1232  else
1233    {
1234      check (err != NULL);
1235      fprintf (stderr, "WARNING: [%s] unable to preallocate file (sparse): %s (%d)\n", __FUNCTION__, err->message, err->code);
1236      tr_error_clear (&err);
1237    }
1238
1239  tr_sys_file_close (fd, NULL);
1240
1241  tr_sys_path_remove (path1, NULL);
1242
1243  tr_free (path1);
1244
1245  tr_free (test_dir);
1246  return 0;
1247}
1248
1249static int
1250test_file_map (void)
1251{
1252  char * const test_dir = create_test_dir (__FUNCTION__);
1253  tr_error * err = NULL;
1254  char * path1;
1255  tr_sys_file_t fd;
1256  char * view;
1257
1258  path1 = tr_buildPath (test_dir, "a", NULL);
1259
1260  libtest_create_file_with_string_contents (path1, "test");
1261
1262  fd = tr_sys_file_open (path1, TR_SYS_FILE_READ | TR_SYS_FILE_WRITE, 0600, NULL);
1263
1264  view = tr_sys_file_map_for_reading (fd, 0, 4, &err);
1265  check (view != NULL);
1266  check (err == NULL);
1267
1268  check_int_eq (0, memcmp (view, "test", 4));
1269
1270  tr_sys_file_write_at (fd, "E", 1, 1, NULL, NULL);
1271
1272  check_int_eq (0, memcmp (view, "tEst", 4));
1273
1274  check (tr_sys_file_unmap (view, 4, &err));
1275  check (err == NULL);
1276
1277  tr_sys_file_close (fd, NULL);
1278
1279  tr_sys_path_remove (path1, NULL);
1280
1281  tr_free (path1);
1282
1283  tr_free (test_dir);
1284  return 0;
1285}
1286
1287static int
1288test_file_utilities (void)
1289{
1290  char * const test_dir = create_test_dir (__FUNCTION__);
1291  tr_error * err = NULL;
1292  char * path1;
1293  tr_sys_file_t fd;
1294  char buffer[16];
1295
1296  path1 = tr_buildPath (test_dir, "a", NULL);
1297
1298  libtest_create_file_with_string_contents (path1, "a\nbc\r\ndef\nghij\r\n\n\nklmno\r");
1299
1300  fd = tr_sys_file_open (path1, TR_SYS_FILE_READ, 0, NULL);
1301
1302  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1303  check (err == NULL);
1304  check_streq ("a", buffer);
1305  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1306  check (err == NULL);
1307  check_streq ("bc", buffer);
1308  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1309  check (err == NULL);
1310  check_streq ("def", buffer);
1311  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1312  check (err == NULL);
1313  check_streq ("ghij", buffer);
1314  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1315  check (err == NULL);
1316  check_streq ("", buffer);
1317  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1318  check (err == NULL);
1319  check_streq ("", buffer);
1320  check (tr_sys_file_read_line (fd, buffer, 4, &err));
1321  check (err == NULL);
1322  check_streq ("klmn", buffer);
1323  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1324  check (err == NULL);
1325  check_streq ("o", buffer);
1326  check (!tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1327  check (err == NULL);
1328  check_streq ("o", buffer); /* on EOF, buffer stays unchanged */
1329
1330  tr_sys_file_close (fd, NULL);
1331
1332  fd = tr_sys_file_open (path1, TR_SYS_FILE_READ | TR_SYS_FILE_WRITE | TR_SYS_FILE_TRUNCATE, 0, NULL);
1333
1334  check (tr_sys_file_write_line (fd, "p", &err));
1335  check (err == NULL);
1336  check (tr_sys_file_write_line (fd, "", &err));
1337  check (err == NULL);
1338  check (tr_sys_file_write_line (fd, "qr", &err));
1339  check (err == NULL);
1340  check (tr_sys_file_write_fmt (fd, "s%cu\r\n", &err, 't'));
1341  check (err == NULL);
1342  check (tr_sys_file_write_line (fd, "", &err));
1343  check (err == NULL);
1344  check (tr_sys_file_write_line (fd, "", &err));
1345  check (err == NULL);
1346  check (tr_sys_file_write_fmt (fd, "v%sy%d", &err, "wx", 2));
1347  check (err == NULL);
1348
1349  tr_sys_file_seek (fd, 0, TR_SEEK_SET, NULL, NULL);
1350
1351  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1352  check (err == NULL);
1353  check_streq ("p", buffer);
1354  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1355  check (err == NULL);
1356  check_streq ("", buffer);
1357  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1358  check (err == NULL);
1359  check_streq ("qr", buffer);
1360  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1361  check (err == NULL);
1362  check_streq ("stu", buffer);
1363  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1364  check (err == NULL);
1365  check_streq ("", buffer);
1366  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1367  check (err == NULL);
1368  check_streq ("", buffer);
1369  check (tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1370  check (err == NULL);
1371  check_streq ("vwxy2", buffer);
1372  check (!tr_sys_file_read_line (fd, buffer, sizeof (buffer) / sizeof (*buffer), &err));
1373  check (err == NULL);
1374  check_streq ("vwxy2", buffer); /* on EOF, buffer stays unchanged */
1375
1376  tr_sys_file_close (fd, NULL);
1377
1378  tr_sys_path_remove (path1, NULL);
1379
1380  tr_free (path1);
1381
1382  tr_free (test_dir);
1383  return 0;
1384}
1385
1386static int
1387test_dir_create (void)
1388{
1389  char * const test_dir = create_test_dir (__FUNCTION__);
1390  tr_error * err = NULL;
1391  char * path1, * path2;
1392
1393  path1 = tr_buildPath (test_dir, "a", NULL);
1394  path2 = tr_buildPath (path1, "b", NULL);
1395
1396  /* Can create directory which has parent */
1397  check (tr_sys_dir_create (path1, 0, 0700, &err));
1398  check (err == NULL);
1399  check (tr_sys_path_exists (path1, NULL));
1400  check (validate_permissions (path1, 0700));
1401
1402  tr_sys_path_remove (path1, NULL);
1403  libtest_create_file_with_string_contents (path1, "test");
1404
1405  /* Can't create directory where file already exists */
1406  check (!tr_sys_dir_create (path1, 0, 0700, &err));
1407  check (err != NULL);
1408  tr_error_clear (&err);
1409  check (!tr_sys_dir_create (path1, TR_SYS_DIR_CREATE_PARENTS, 0700, &err));
1410  check (err != NULL);
1411  tr_error_clear (&err);
1412
1413  tr_sys_path_remove (path1, NULL);
1414
1415  /* Can't create directory which has no parent */
1416  check (!tr_sys_dir_create (path2, 0, 0700, &err));
1417  check (err != NULL);
1418  check (!tr_sys_path_exists (path2, NULL));
1419  tr_error_clear (&err);
1420
1421  /* Can create directory with parent directories */
1422  check (tr_sys_dir_create (path2, TR_SYS_DIR_CREATE_PARENTS, 0751, &err));
1423  check (err == NULL);
1424  check (tr_sys_path_exists (path1, NULL));
1425  check (tr_sys_path_exists (path2, NULL));
1426  check (validate_permissions (path1, 0751));
1427  check (validate_permissions (path2, 0751));
1428
1429  /* Can create existing directory (no-op) */
1430  check (tr_sys_dir_create (path1, 0, 0700, &err));
1431  check (err == NULL);
1432  check (tr_sys_dir_create (path1, TR_SYS_DIR_CREATE_PARENTS, 0700, &err));
1433  check (err == NULL);
1434
1435  tr_sys_path_remove (path2, NULL);
1436  tr_sys_path_remove (path1, NULL);
1437
1438  tr_free (path2);
1439  tr_free (path1);
1440
1441  tr_free (test_dir);
1442  return 0;
1443}
1444
1445static int
1446test_dir_read_impl (const char * path,
1447                      bool       * have1,
1448                      bool       * have2)
1449{
1450  tr_error * err = NULL;
1451  tr_sys_dir_t dd;
1452  const char * name;
1453
1454  *have1 = *have2 = false;
1455
1456  dd = tr_sys_dir_open (path, &err);
1457  check (dd != TR_BAD_SYS_DIR);
1458  check (err == NULL);
1459
1460  while ((name = tr_sys_dir_read_name (dd, &err)) != NULL)
1461    {
1462      check (err == NULL);
1463
1464      if (strcmp (name, ".") == 0 || strcmp (name, "..") == 0)
1465        continue;
1466
1467      if (strcmp (name, "a") == 0)
1468        *have1 = true;
1469      else if (strcmp (name, "b") == 0)
1470        *have2 = true;
1471      else
1472        check (false);
1473    }
1474
1475  check (err == NULL);
1476
1477  check (tr_sys_dir_close (dd, &err));
1478  check (err == NULL);
1479
1480  return 0;
1481}
1482
1483static int
1484test_dir_read (void)
1485{
1486  char * const test_dir = create_test_dir (__FUNCTION__);
1487  char * path1, * path2;
1488  bool have1, have2;
1489
1490  path1 = tr_buildPath (test_dir, "a", NULL);
1491  path2 = tr_buildPath (test_dir, "b", NULL);
1492
1493  if (test_dir_read_impl (test_dir, &have1, &have2) != 0)
1494    return 1;
1495  check (!have1);
1496  check (!have2);
1497
1498  libtest_create_file_with_string_contents (path1, "test");
1499
1500  if (test_dir_read_impl (test_dir, &have1, &have2) != 0)
1501    return 1;
1502  check (have1);
1503  check (!have2);
1504
1505  libtest_create_file_with_string_contents (path2, "test");
1506
1507  if (test_dir_read_impl (test_dir, &have1, &have2) != 0)
1508    return 1;
1509  check (have1);
1510  check (have2);
1511
1512  tr_sys_path_remove (path1, NULL);
1513
1514  if (test_dir_read_impl (test_dir, &have1, &have2) != 0)
1515    return 1;
1516  check (!have1);
1517  check (have2);
1518
1519  tr_free (path2);
1520  tr_free (path1);
1521
1522  tr_free (test_dir);
1523  return 0;
1524}
1525
1526int
1527main (void)
1528{
1529  const testFunc tests[] =
1530    {
1531      test_get_info,
1532      test_path_exists,
1533      test_path_is_relative,
1534      test_path_is_same,
1535      test_path_resolve,
1536      test_path_basename_dirname,
1537      test_path_rename,
1538      test_path_remove,
1539      test_file_open,
1540      test_file_read_write_seek,
1541      test_file_truncate,
1542      test_file_preallocate,
1543      test_file_map,
1544      test_file_utilities,
1545      test_dir_create,
1546      test_dir_read
1547    };
1548  int ret;
1549
1550  /* init the session */
1551  session = libttest_session_init (NULL);
1552
1553  ret = runTests (tests, NUM_TESTS (tests));
1554
1555  if (ret == 0)
1556    libttest_session_close (session);
1557
1558  return ret;
1559}
Note: See TracBrowser for help on using the repository browser.