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 * 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 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 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 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 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 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