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
40static const char *prefix;
41static size_t prefixlen;
42static char buf[1024];
43static char pwd[1024];
44
45static const char *
46makepath(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
57static void
58dochdir(const char *path, const char *errmsg)
59{
60
61	if (chdir(path) == -1)
62		err(EXIT_FAILURE, "%s", errmsg);
63}
64
65static void
66dofchdir(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}
77static void (*thechdir)(const char *, const char *);
78
79static void
80simple(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
125static void
126symlinktest(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
145int
146main(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