Fix boolean_t/B_FALSE/B_TRUE compilation issue
[kopensolaris-gnu/glibc.git] / stdlib / test-canon.c
1 /* Test program for returning the canonical absolute name of a given file.
2    Copyright (C) 1996,1997,2000,2002,2004,2005,2006
3    Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by David Mosberger <davidm@azstarnet.com>.
6
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
11
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, write to the Free
19    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20    02111-1307 USA.  */
21
22 /* This file must be run from within a directory called "stdlib".  */
23
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <sys/param.h>
31
32 /* Prototype for our test function.  */
33 extern int do_test (int argc, char *argv[]);
34 #include <test-skeleton.c>
35
36 #ifndef PATH_MAX
37 # define PATH_MAX 4096
38 #endif
39 static char     cwd[PATH_MAX];
40 static size_t   cwd_len;
41
42 struct {
43   const char *  name;
44   const char *  value;
45 } symlinks[] = {
46   {"SYMLINK_LOOP",      "SYMLINK_LOOP"},
47   {"SYMLINK_1",         "."},
48   {"SYMLINK_2",         "//////./../../etc"},
49   {"SYMLINK_3",         "SYMLINK_1"},
50   {"SYMLINK_4",         "SYMLINK_2"},
51   {"SYMLINK_5",         "doesNotExist"},
52 };
53
54 struct {
55   const char * in, * out, * resolved;
56   int error;
57 } tests[] = {
58   /*  0 */
59   {"/",                                 "/"},
60   {"/////////////////////////////////", "/"},
61   {"/.././.././.././..///",             "/"},
62   {"/etc",                              "/etc"},
63   {"/etc/../etc",                       "/etc"},
64   /*  5 */
65   {"/doesNotExist/../etc",              0, "/doesNotExist", ENOENT},
66   {"./././././././././.",               "."},
67   {"/etc/.//doesNotExist",              0, "/etc/doesNotExist", ENOENT},
68   {"./doesExist",                       "./doesExist"},
69   {"./doesExist/",                      "./doesExist"},
70   /* 10 */
71   {"./doesExist/../doesExist",          "./doesExist"},
72   {"foobar",                            0, "./foobar", ENOENT},
73   {".",                                 "."},
74   {"./foobar",                          0, "./foobar", ENOENT},
75   {"SYMLINK_LOOP",                      0, "./SYMLINK_LOOP", ELOOP},
76   /* 15 */
77   {"./SYMLINK_LOOP",                    0, "./SYMLINK_LOOP", ELOOP},
78   {"SYMLINK_1",                         "."},
79   {"SYMLINK_1/foobar",                  0, "./foobar", ENOENT},
80   {"SYMLINK_2",                         "/etc"},
81   {"SYMLINK_3",                         "."},
82   /* 20 */
83   {"SYMLINK_4",                         "/etc"},
84   {"../stdlib/SYMLINK_1",               "."},
85   {"../stdlib/SYMLINK_2",               "/etc"},
86   {"../stdlib/SYMLINK_3",               "."},
87   {"../stdlib/SYMLINK_4",               "/etc"},
88   /* 25 */
89   {"./SYMLINK_5",                       0, "./doesNotExist", ENOENT},
90   {"SYMLINK_5",                         0, "./doesNotExist", ENOENT},
91   {"SYMLINK_5/foobar",                  0, "./doesNotExist", ENOENT},
92   {"doesExist/../../stdlib/doesExist",  "./doesExist"},
93   {"doesExist/.././../stdlib/.",        "."},
94   /* 30 */
95   {"./doesExist/someFile/",             0, "./doesExist/someFile", ENOTDIR},
96   {"./doesExist/someFile/..",           0, "./doesExist/someFile", ENOTDIR},
97 };
98
99
100 static int
101 check_path (const char * result, const char * expected)
102 {
103   int good;
104
105   if (!result)
106     return (expected == NULL);
107
108   if (!expected)
109     return 0;
110
111   if (expected[0] == '.' && (expected[1] == '/' || expected[1] == '\0'))
112     good = (strncmp (result, cwd, cwd_len) == 0
113             && strcmp (result + cwd_len, expected + 1) == 0);
114   else
115     good = (strcmp (expected, result) == 0);
116
117   return good;
118 }
119
120
121 int
122 do_test (int argc, char ** argv)
123 {
124   char * result;
125   int i, errors = 0;
126   char buf[PATH_MAX];
127
128   getcwd (cwd, sizeof(buf));
129   cwd_len = strlen (cwd);
130
131   errno = 0;
132   if (realpath (NULL, buf) != NULL || errno != EINVAL)
133     {
134       printf ("%s: expected return value NULL and errno set to EINVAL"
135               " for realpath(NULL,...)\n", argv[0]);
136       ++errors;
137     }
138
139 #if 0
140   /* This is now allowed.  The test is invalid.  */
141   errno = 0;
142   if (realpath ("/", NULL) != NULL || errno != EINVAL)
143     {
144       printf ("%s: expected return value NULL and errno set to EINVAL"
145               " for realpath(...,NULL)\n", argv[0]);
146       ++errors;
147     }
148 #endif
149
150   errno = 0;
151   if (realpath ("", buf) != NULL || errno != ENOENT)
152     {
153       printf ("%s: expected return value NULL and set errno to ENOENT"
154               " for realpath(\"\",...)\n", argv[0]);
155       ++errors;
156     }
157
158   for (i = 0; i < (int) (sizeof (symlinks) / sizeof (symlinks[0])); ++i)
159     symlink (symlinks[i].value, symlinks[i].name);
160
161   int has_dir = mkdir ("doesExist", 0777) == 0;
162
163   int fd = has_dir ? creat ("doesExist/someFile", 0777) : -1;
164
165   for (i = 0; i < (int) (sizeof (tests) / sizeof (tests[0])); ++i)
166     {
167       buf[0] = '\0';
168       result = realpath (tests[i].in, buf);
169
170       if (!check_path (result, tests[i].out))
171         {
172           printf ("%s: flunked test %d (expected `%s', got `%s')\n",
173                   argv[0], i, tests[i].out ? tests[i].out : "NULL",
174                   result ? result : "NULL");
175           ++errors;
176           continue;
177         }
178
179       if (!check_path (buf, tests[i].out ? tests[i].out : tests[i].resolved))
180         {
181           printf ("%s: flunked test %d (expected resolved `%s', got `%s')\n",
182                   argv[0], i, tests[i].out ? tests[i].out : tests[i].resolved,
183                   buf);
184           ++errors;
185           continue;
186         }
187
188       if (!tests[i].out && errno != tests[i].error)
189         {
190           printf ("%s: flunked test %d (expected errno %d, got %d)\n",
191                   argv[0], i, tests[i].error, errno);
192           ++errors;
193           continue;
194         }
195
196       char *result2 = realpath (tests[i].in, NULL);
197       if ((result2 == NULL && result != NULL)
198           || (result2 != NULL && strcmp (result, result2) != 0))
199         {
200           printf ("\
201 %s: realpath(..., NULL) produced different result than realpath(..., buf): '%s' vs '%s'\n",
202                   argv[0], result2, result);
203           ++errors;
204         }
205       free (result2);
206     }
207
208   getcwd (buf, sizeof(buf));
209   if (strcmp (buf, cwd))
210     {
211       printf ("%s: current working directory changed from %s to %s\n",
212               argv[0], cwd, buf);
213       ++errors;
214     }
215
216   if (fd >= 0)
217     {
218       close (fd);
219       unlink ("doesExist/someFile");
220     }
221
222   if (has_dir)
223     rmdir ("doesExist");
224
225   for (i = 0; i < (int) (sizeof (symlinks) / sizeof (symlinks[0])); ++i)
226     unlink (symlinks[i].name);
227
228   if (errors != 0)
229     {
230       printf ("%d errors.\n", errors);
231       return EXIT_FAILURE;
232     }
233
234   puts ("No errors.");
235   return EXIT_SUCCESS;
236 }