OSDN Git Service

Replace FSF snail mail address with URLs
[uclinux-h8/uClibc.git] / test / 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, see
19    <http://www.gnu.org/licenses/>.  */
20
21 /* This file must be run from within a directory called "stdlib".  */
22
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <sys/param.h>
30 #include <sys/stat.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;
56   const char * retval; /* what realpath should return */
57   const char * retbuf; /* what realpath should store in buf */
58   /* if both of the above are NULL, we won't check for result,
59    * it's undefined */
60   int error; /* expected errno value */
61 } tests[] = {
62   /*  0 */
63   {"/",                                 "/"},
64   {"/////////////////////////////////", "/"},
65   {"/.././.././.././..///",             "/"},
66   {"/etc",                              "/etc"},
67   {"/etc/../etc",                       "/etc"},
68   /*  5 */
69   {"/doesNotExist/../etc",              0, "/doesNotExist", ENOENT},
70   {"./././././././././.",               "."},
71   {"/etc/.//doesNotExist",              0, "/etc/doesNotExist", ENOENT},
72   {"./doesExist",                       "./doesExist"},
73   {"./doesExist/",                      "./doesExist"},
74   /* 10 */
75   {"./doesExist/../doesExist",          "./doesExist"},
76   {"foobar",                            0, "./foobar", ENOENT},
77   {".",                                 "."},
78   {"./foobar",                          0, "./foobar", ENOENT},
79   {"SYMLINK_LOOP",                      0, 0, ELOOP},
80   /* 15 */
81   {"./SYMLINK_LOOP",                    0, 0, ELOOP},
82   {"SYMLINK_1",                         "."},
83   {"SYMLINK_1/foobar",                  0, "./foobar", ENOENT},
84   {"SYMLINK_2",                         "/etc"},
85   {"SYMLINK_3",                         "."},
86   /* 20 */
87   {"SYMLINK_4",                         "/etc"},
88   {"../stdlib/SYMLINK_1",               "."},
89   {"../stdlib/SYMLINK_2",               "/etc"},
90   {"../stdlib/SYMLINK_3",               "."},
91   {"../stdlib/SYMLINK_4",               "/etc"},
92   /* 25 */
93   {"./SYMLINK_5",                       0, "./doesNotExist", ENOENT},
94   {"SYMLINK_5",                         0, "./doesNotExist", ENOENT},
95   {"SYMLINK_5/foobar",                  0, "./doesNotExist", ENOENT},
96   {"doesExist/../../stdlib/doesExist",  "./doesExist"},
97   {"doesExist/.././../stdlib/.",        "."},
98 #ifndef __UCLIBC__
99   /* we dont check for ENOTDIR in readlink() which causes failures to
100    * propogate up to realpath() ... so disable for now ... */
101   /* 30 */
102   {"./doesExist/someFile/",             0, "./doesExist/someFile", ENOTDIR},
103   {"./doesExist/someFile/..",           0, "./doesExist/someFile", ENOTDIR},
104 #endif
105 };
106
107
108 static int
109 check_path (const char * result, const char * expected)
110 {
111   int good;
112
113   if (!result)
114     return (expected == NULL);
115
116   if (!expected)
117     return 0;
118
119   if (expected[0] == '.' && (expected[1] == '/' || expected[1] == '\0'))
120     good = (strncmp (result, cwd, cwd_len) == 0
121             && strcmp (result + cwd_len, expected + 1) == 0);
122   else
123     good = (strcmp (expected, result) == 0);
124
125   return good;
126 }
127
128
129 int
130 do_test (int argc, char ** argv)
131 {
132   char * result;
133   int i, errors = 0;
134   char buf[PATH_MAX];
135
136   getcwd (cwd, sizeof(buf));
137   cwd_len = strlen (cwd);
138
139 #ifndef __UCLIBC__
140   /* we choose to crash in uClibc when given a NULL */
141   errno = 0;
142   if (realpath (NULL, buf) != 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 #if 0
151   /* This is now allowed.  The test is invalid.  */
152   errno = 0;
153   if (realpath ("/", NULL) != NULL || errno != EINVAL)
154     {
155       printf ("%s: expected return value NULL and errno set to EINVAL"
156               " for realpath(...,NULL)\n", argv[0]);
157       ++errors;
158     }
159 #endif
160
161   errno = 0;
162   if (realpath ("", buf) != NULL || errno != ENOENT)
163     {
164       printf ("%s: expected return value NULL and set errno to ENOENT"
165               " for realpath(\"\",...)\n", argv[0]);
166       ++errors;
167     }
168
169   for (i = 0; i < (int) (sizeof (symlinks) / sizeof (symlinks[0])); ++i)
170     symlink (symlinks[i].value, symlinks[i].name);
171
172   int has_dir = mkdir ("doesExist", 0777) == 0;
173
174   int fd = has_dir ? creat ("doesExist/someFile", 0777) : -1;
175
176   for (i = 0; i < (int) (sizeof (tests) / sizeof (tests[0])); ++i)
177     {
178       buf[0] = '\0';
179       errno = 0;
180       result = realpath (tests[i].in, buf);
181
182       if (!check_path (result, tests[i].retval))
183         {
184           printf ("%s: flunked test %d (expected `%s', got `%s')\n",
185                   argv[0], i, tests[i].retval ? tests[i].retval : "NULL",
186                   result ? result : "NULL");
187           ++errors;
188           continue;
189         }
190
191       if (result && !check_path (buf, tests[i].retval ? tests[i].retval : tests[i].retbuf))
192         {
193           printf ("%s: flunked test %d (expected resolved `%s', got `%s')\n",
194                   argv[0], i, tests[i].retval ? tests[i].retval : tests[i].retbuf,
195                   buf);
196           ++errors;
197           continue;
198         }
199
200       if (errno != tests[i].error)
201         {
202           printf ("%s: flunked test %d (expected errno %d, got %d)\n",
203                   argv[0], i, tests[i].error, errno);
204           ++errors;
205           continue;
206         }
207
208 #ifndef __UCLIBC__
209       /* we choose to crash in uClibc when given a NULL */
210       char *result2 = realpath (tests[i].in, NULL);
211       if ((result2 == NULL && result != NULL)
212           || (result2 != NULL && strcmp (result, result2) != 0))
213         {
214           printf ("\
215 %s: realpath(..., NULL) produced different result than realpath(..., buf): '%s' vs '%s'\n",
216                   argv[0], result2, result);
217           ++errors;
218         }
219       free (result2);
220 #endif
221     }
222
223   getcwd (buf, sizeof(buf));
224   if (strcmp (buf, cwd))
225     {
226       printf ("%s: current working directory changed from %s to %s\n",
227               argv[0], cwd, buf);
228       ++errors;
229     }
230
231   if (fd >= 0)
232     {
233       close (fd);
234       unlink ("doesExist/someFile");
235     }
236
237   if (has_dir)
238     rmdir ("doesExist");
239
240   for (i = 0; i < (int) (sizeof (symlinks) / sizeof (symlinks[0])); ++i)
241     unlink (symlinks[i].name);
242
243   if (errors != 0)
244     {
245       printf ("%d errors.\n", errors);
246       return EXIT_FAILURE;
247     }
248
249   puts ("No errors.");
250   return EXIT_SUCCESS;
251 }