1 /* $NetBSD: h_cwd.c,v 1.3 2012/04/17 09:23:21 jruoho 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 <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39
40 static const char *prefix;
41 static size_t prefixlen;
42 static char buf[1024];
43 static char pwd[1024];
44
45 static const char *
makepath(const char * tail)46 makepath(const char *tail)
47 {
48
49 strcpy(buf, prefix);
50 if (prefix[prefixlen-1] != '/')
51 strcat(buf, "/");
52 strcat(buf, tail);
53
54 return buf;
55 }
56
57 static void
dochdir(const char * path,const char * errmsg)58 dochdir(const char *path, const char *errmsg)
59 {
60
61 if (chdir(path) == -1)
62 err(EXIT_FAILURE, "%s", errmsg);
63 }
64
65 static void
dofchdir(const char * path,const char * errmsg)66 dofchdir(const char *path, const char *errmsg)
67 {
68 int fd;
69
70 fd = open(path, O_RDONLY);
71 if (fd == -1)
72 err(EXIT_FAILURE, "open %s", errmsg);
73 if (fchdir(fd) == -1)
74 err(EXIT_FAILURE, "fchdir %s", errmsg);
75 close(fd);
76 }
77 static void (*thechdir)(const char *, const char *);
78
79 static void
simple(void)80 simple(void)
81 {
82
83 thechdir(prefix, "chdir1");
84 if (getcwd(pwd, sizeof(pwd)) == NULL)
85 err(EXIT_FAILURE, "getcwd1");
86 if (strcmp(pwd, prefix) != 0)
87 errx(EXIT_FAILURE, "strcmp1");
88
89 if (mkdir("dir", 0777) == -1)
90 err(EXIT_FAILURE, "mkdir2");
91 thechdir("dir", "chdir2");
92 if (getcwd(pwd, sizeof(pwd)) == NULL)
93 err(EXIT_FAILURE, "getcwd2");
94 if (strcmp(pwd, makepath("dir")) != 0)
95 errx(EXIT_FAILURE, "strcmp2");
96
97 if (mkdir("dir", 0777) == -1)
98 err(EXIT_FAILURE, "mkdir3");
99 thechdir("dir", "chdir3");
100 if (getcwd(pwd, sizeof(pwd)) == NULL)
101 err(EXIT_FAILURE, "getcwd3");
102 if (strcmp(pwd, makepath("dir/dir")) != 0)
103 errx(EXIT_FAILURE, "strcmp3");
104
105 thechdir("..", "chdir4");
106 if (getcwd(pwd, sizeof(pwd)) == NULL)
107 err(EXIT_FAILURE, "getcwd4");
108 if (strcmp(pwd, makepath("dir")) != 0)
109 errx(EXIT_FAILURE, "strcmp4");
110
111
112 thechdir("../../../../../../..", "chdir5");
113 if (getcwd(pwd, sizeof(pwd)) == NULL)
114 err(EXIT_FAILURE, "getcwd5");
115 if (strcmp(pwd, prefix) != 0)
116 errx(EXIT_FAILURE, "strcmp5");
117
118 thechdir("/", "chdir6");
119 if (getcwd(pwd, sizeof(pwd)) == NULL)
120 err(EXIT_FAILURE, "getcwd6");
121 if (strcmp(pwd, "/") != 0)
122 errx(EXIT_FAILURE, "strcmp6");
123 }
124
125 static void
symlinktest(void)126 symlinktest(void)
127 {
128
129 thechdir(prefix, "chdir1");
130 if (mkdir("adir", 0777) == -1)
131 err(EXIT_FAILURE, "mkdir1");
132 if (mkdir("anotherdir", 0777) == -1)
133 err(EXIT_FAILURE, "mkdir2");
134
135 if (symlink("/adir", "anotherdir/lincthesink") == -1)
136 err(EXIT_FAILURE, "symlink");
137
138 thechdir("anotherdir/lincthesink", "chdir2");
139 if (getcwd(pwd, sizeof(pwd)) == NULL)
140 err(EXIT_FAILURE, "getcwd");
141 if (strcmp(pwd, makepath("adir")) != 0)
142 errx(EXIT_FAILURE, "strcmp");
143 }
144
145 int
main(int argc,char * argv[])146 main(int argc, char *argv[])
147 {
148
149 if (argc != 4)
150 errx(1, "usage");
151
152 prefix = argv[1];
153 prefixlen = strlen(argv[1]);
154
155 if (strcmp(argv[3], "chdir") == 0)
156 thechdir = dochdir;
157 else if (strcmp(argv[3], "fchdir") == 0)
158 thechdir = dofchdir;
159 else
160 errx(EXIT_FAILURE, "invalid chdir type");
161
162 if (strcmp(argv[2], "simple") == 0)
163 simple();
164 if (strcmp(argv[2], "symlink") == 0)
165 symlinktest();
166
167 return EXIT_SUCCESS;
168 }
169