h_cwd.c revision 1.2.2.2 1 /* $NetBSD: h_cwd.c,v 1.2.2.2 2011/03/05 15:10:56 bouyer Exp $ */
2
3 /*-
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <sys/types.h>
31 #include <sys/stat.h>
32
33 #include <err.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <string.h>
37 #include <unistd.h>
38
39 static const char *prefix;
40 static size_t prefixlen;
41 static char buf[1024];
42 static char pwd[1024];
43
44 static const char *
45 makepath(const char *tail)
46 {
47
48 strcpy(buf, prefix);
49 if (prefix[prefixlen-1] != '/')
50 strcat(buf, "/");
51 strcat(buf, tail);
52
53 return buf;
54 }
55
56 static void
57 dochdir(const char *path, const char *errmsg)
58 {
59
60 if (chdir(path) == -1)
61 err(1, "%s", errmsg);
62 }
63
64 static void
65 dofchdir(const char *path, const char *errmsg)
66 {
67 int fd;
68
69 fd = open(path, O_RDONLY);
70 if (fd == -1)
71 err(1, "open %s", errmsg);
72 if (fchdir(fd) == -1)
73 err(1, "fchdir %s", errmsg);
74 close(fd);
75 }
76 static void (*thechdir)(const char *, const char *);
77
78 static void
79 simple(void)
80 {
81
82 thechdir(prefix, "chdir1");
83 if (getcwd(pwd, sizeof(pwd)) == NULL)
84 err(1, "getcwd1");
85 if (strcmp(pwd, prefix) != 0)
86 errx(1, "strcmp1");
87
88 if (mkdir("dir", 0777) == -1)
89 err(1, "mkdir2");
90 thechdir("dir", "chdir2");
91 if (getcwd(pwd, sizeof(pwd)) == NULL)
92 err(1, "getcwd2");
93 if (strcmp(pwd, makepath("dir")) != 0)
94 errx(1, "strcmp2");
95
96 if (mkdir("dir", 0777) == -1)
97 err(1, "mkdir3");
98 thechdir("dir", "chdir3");
99 if (getcwd(pwd, sizeof(pwd)) == NULL)
100 err(1, "getcwd3");
101 if (strcmp(pwd, makepath("dir/dir")) != 0)
102 errx(1, "strcmp3");
103
104 thechdir("..", "chdir4");
105 if (getcwd(pwd, sizeof(pwd)) == NULL)
106 err(1, "getcwd4");
107 if (strcmp(pwd, makepath("dir")) != 0)
108 errx(1, "strcmp4");
109
110
111 thechdir("../../../../../../..", "chdir5");
112 if (getcwd(pwd, sizeof(pwd)) == NULL)
113 err(1, "getcwd5");
114 if (strcmp(pwd, prefix) != 0)
115 errx(1, "strcmp5");
116
117 thechdir("/", "chdir6");
118 if (getcwd(pwd, sizeof(pwd)) == NULL)
119 err(1, "getcwd6");
120 if (strcmp(pwd, "/") != 0)
121 errx(1, "strcmp6");
122 }
123
124 static void
125 symlinktest(void)
126 {
127
128 thechdir(prefix, "chdir1");
129 if (mkdir("adir", 0777) == -1)
130 err(1, "mkdir1");
131 if (mkdir("anotherdir", 0777) == -1)
132 err(1, "mkdir2");
133
134 if (symlink("/adir", "anotherdir/lincthesink") == -1)
135 err(1, "symlink");
136
137 thechdir("anotherdir/lincthesink", "chdir2");
138 if (getcwd(pwd, sizeof(pwd)) == NULL)
139 err(1, "getcwd");
140 if (strcmp(pwd, makepath("adir")) != 0)
141 errx(1, "strcmp");
142 }
143
144 int
145 main(int argc, char *argv[])
146 {
147
148 if (argc != 4)
149 errx(1, "usage");
150
151 prefix = argv[1];
152 prefixlen = strlen(argv[1]);
153
154 if (strcmp(argv[3], "chdir") == 0)
155 thechdir = dochdir;
156 else if (strcmp(argv[3], "fchdir") == 0)
157 thechdir = dofchdir;
158 else
159 errx(1, "invalid chdir type");
160
161 if (strcmp(argv[2], "simple") == 0)
162 simple();
163 if (strcmp(argv[2], "symlink") == 0)
164 symlinktest();
165
166 return 0;
167 }
168