1 /* 2 * Copyright (c) 2008 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 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 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $DragonFly: src/sys/boot/common/rel_open.c,v 1.2 2008/09/04 17:30:52 swildner Exp $ 35 */ 36 37 #include <stand.h> 38 #include <string.h> 39 #include "bootstrap.h" 40 41 char *DirBase; 42 43 COMMAND_SET(cd, "cd", "Change directory", command_chdir); 44 COMMAND_SET(optcd, "optcd", 45 "Change directory; ignore exit status", command_optchdir); 46 47 int 48 command_chdir(int ac, char **av) 49 { 50 int result; 51 52 if (ac == 1) { 53 result = chdir(getenv("base")); 54 } else if (ac == 2) { 55 result = chdir(av[1]); 56 } else { 57 sprintf(command_errbuf, "usage: cd [<directory>]"); 58 result = CMD_ERROR; 59 } 60 return result; 61 } 62 63 int 64 command_optchdir(int ac, char **av) 65 { 66 if (ac == 1) { 67 chdir(getenv("base")); 68 } else if (ac == 2) { 69 chdir(av[1]); 70 } else { 71 sprintf(command_errbuf, "usage: optcd [<directory>]"); 72 } 73 return(CMD_OK); 74 } 75 76 int 77 chdir(const char *path) 78 { 79 struct stat st; 80 char *base; 81 char *p; 82 char *b; 83 char *s; 84 char *w; 85 int len; 86 int dlen; 87 int res; 88 89 if (DirBase == NULL) 90 DirBase = strdup("/"); 91 92 len = strlen(path); 93 if (path[0] == '/') { 94 base = malloc(len + 2); /* room for trailing / */ 95 bcopy(path, base, len + 1); 96 } else { 97 while (len && path[len-1] == '/') 98 --len; 99 dlen = strlen(DirBase); 100 base = malloc(dlen + len + 2); /* room for trailing / */ 101 bcopy(DirBase, base, dlen); 102 bcopy(path, base + dlen, len); 103 base[dlen + len] = 0; 104 } 105 106 if (stat(base, &st) == 0 && S_ISDIR(st.st_mode)) { 107 p = b = w = s = base; 108 while (*s) { 109 if (*s == '/') { 110 if (s - b == 2 && b[0] == '.' && b[1] == '.') { 111 w = p; 112 } else { 113 p = b; 114 b = s + 1; 115 } 116 while (s[1] == '/') 117 ++s; 118 } 119 *w = *s; 120 ++w; 121 ++s; 122 } 123 if (s - b == 2 && b[0] == '.' && b[1] == '.') 124 w = p; 125 while (w > base && w[-1] == '/') 126 --w; 127 *w++ = '/'; 128 *w = 0; 129 130 if (DirBase) 131 free(DirBase); 132 DirBase = base; 133 res = CMD_OK; 134 } else { 135 free(base); 136 sprintf(command_errbuf, "Unable to find directory"); 137 res = CMD_ERROR; 138 } 139 return (res); 140 } 141 142 COMMAND_SET(pwd, "pwd", "Get current directory", command_pwd); 143 144 int 145 command_pwd(int ac, char **av) 146 { 147 printf("%s\n", DirBase ? DirBase : "/"); 148 return(0); 149 } 150 151 int 152 rel_open(const char *path, char **abspathp, int flags) 153 { 154 int fd; 155 char *ptr; 156 157 if (DirBase == NULL) 158 DirBase = strdup("/"); 159 160 if (path[0] != '/') { 161 ptr = malloc(strlen(DirBase) + strlen(path) + 1); 162 sprintf(ptr, "%s%s", DirBase, path); 163 fd = open(ptr, flags); 164 if (abspathp && fd >= 0) { 165 *abspathp = ptr; 166 } else if (abspathp) { 167 *abspathp = NULL; 168 free(ptr); 169 } else { 170 free(ptr); 171 } 172 } else { 173 fd = open(path, flags); 174 if (abspathp && fd >= 0) { 175 *abspathp = strdup(path); 176 } else if (abspathp) { 177 *abspathp = NULL; 178 } 179 } 180 return(fd); 181 } 182 183 int 184 rel_stat(const char *path, struct stat *st) 185 { 186 char *ptr; 187 int res; 188 189 if (DirBase == NULL) 190 DirBase = strdup("/"); 191 192 if (path[0] != '/') { 193 ptr = malloc(strlen(DirBase) + strlen(path) + 1); 194 sprintf(ptr, "%s%s", DirBase, path); 195 res = stat(ptr, st); 196 free(ptr); 197 } else { 198 res = stat(path, st); 199 } 200 return(res); 201 } 202