1479ab7f0SSascha Wildner /*
2479ab7f0SSascha Wildner * Copyright (c) 2008 The DragonFly Project. All rights reserved.
3479ab7f0SSascha Wildner *
4479ab7f0SSascha Wildner * This code is derived from software contributed to The DragonFly Project
5479ab7f0SSascha Wildner * by Matthew Dillon <dillon@backplane.com>
6479ab7f0SSascha Wildner *
7479ab7f0SSascha Wildner * Redistribution and use in source and binary forms, with or without
8479ab7f0SSascha Wildner * modification, are permitted provided that the following conditions
9479ab7f0SSascha Wildner * are met:
10479ab7f0SSascha Wildner *
11479ab7f0SSascha Wildner * 1. Redistributions of source code must retain the above copyright
12479ab7f0SSascha Wildner * notice, this list of conditions and the following disclaimer.
13479ab7f0SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
14479ab7f0SSascha Wildner * notice, this list of conditions and the following disclaimer in
15479ab7f0SSascha Wildner * the documentation and/or other materials provided with the
16479ab7f0SSascha Wildner * distribution.
17479ab7f0SSascha Wildner * 3. Neither the name of The DragonFly Project nor the names of its
18479ab7f0SSascha Wildner * contributors may be used to endorse or promote products derived
19479ab7f0SSascha Wildner * from this software without specific, prior written permission.
20479ab7f0SSascha Wildner *
21479ab7f0SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22479ab7f0SSascha Wildner * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23479ab7f0SSascha Wildner * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24479ab7f0SSascha Wildner * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25479ab7f0SSascha Wildner * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26479ab7f0SSascha Wildner * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27479ab7f0SSascha Wildner * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28479ab7f0SSascha Wildner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29479ab7f0SSascha Wildner * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30479ab7f0SSascha Wildner * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31479ab7f0SSascha Wildner * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32479ab7f0SSascha Wildner * SUCH DAMAGE.
33479ab7f0SSascha Wildner *
34479ab7f0SSascha Wildner * $DragonFly: src/sys/boot/common/rel_open.c,v 1.2 2008/09/04 17:30:52 swildner Exp $
35479ab7f0SSascha Wildner */
36479ab7f0SSascha Wildner
37479ab7f0SSascha Wildner #include <stand.h>
38479ab7f0SSascha Wildner #include <string.h>
39d5ee8190SAaron LI
40479ab7f0SSascha Wildner #include "bootstrap.h"
41479ab7f0SSascha Wildner
42479ab7f0SSascha Wildner char *DirBase;
43479ab7f0SSascha Wildner
44479ab7f0SSascha Wildner COMMAND_SET(cd, "cd", "Change directory", command_chdir);
45479ab7f0SSascha Wildner
46d5ee8190SAaron LI static int
command_chdir(int ac,char ** av)47479ab7f0SSascha Wildner command_chdir(int ac, char **av)
48479ab7f0SSascha Wildner {
49479ab7f0SSascha Wildner int result;
50479ab7f0SSascha Wildner
51479ab7f0SSascha Wildner if (ac == 1) {
52479ab7f0SSascha Wildner result = chdir(getenv("base"));
53479ab7f0SSascha Wildner } else if (ac == 2) {
54479ab7f0SSascha Wildner result = chdir(av[1]);
55479ab7f0SSascha Wildner } else {
56479ab7f0SSascha Wildner sprintf(command_errbuf, "usage: cd [<directory>]");
57479ab7f0SSascha Wildner result = CMD_ERROR;
58479ab7f0SSascha Wildner }
59479ab7f0SSascha Wildner return result;
60479ab7f0SSascha Wildner }
61479ab7f0SSascha Wildner
62d5ee8190SAaron LI COMMAND_SET(optcd, "optcd",
63d5ee8190SAaron LI "Change directory; ignore exit status", command_optchdir);
64d5ee8190SAaron LI
65d5ee8190SAaron LI static int
command_optchdir(int ac,char ** av)66479ab7f0SSascha Wildner command_optchdir(int ac, char **av)
67479ab7f0SSascha Wildner {
68479ab7f0SSascha Wildner if (ac == 1) {
69479ab7f0SSascha Wildner chdir(getenv("base"));
70479ab7f0SSascha Wildner } else if (ac == 2) {
71479ab7f0SSascha Wildner chdir(av[1]);
72479ab7f0SSascha Wildner } else {
73479ab7f0SSascha Wildner sprintf(command_errbuf, "usage: optcd [<directory>]");
74479ab7f0SSascha Wildner }
75479ab7f0SSascha Wildner return(CMD_OK);
76479ab7f0SSascha Wildner }
77479ab7f0SSascha Wildner
78479ab7f0SSascha Wildner int
chdir(const char * path)79479ab7f0SSascha Wildner chdir(const char *path)
80479ab7f0SSascha Wildner {
81479ab7f0SSascha Wildner struct stat st;
82479ab7f0SSascha Wildner char *base;
83479ab7f0SSascha Wildner char *p;
84479ab7f0SSascha Wildner char *b;
85479ab7f0SSascha Wildner char *s;
86479ab7f0SSascha Wildner char *w;
87479ab7f0SSascha Wildner int len;
88479ab7f0SSascha Wildner int dlen;
89479ab7f0SSascha Wildner int res;
90479ab7f0SSascha Wildner
91479ab7f0SSascha Wildner if (DirBase == NULL)
92479ab7f0SSascha Wildner DirBase = strdup("/");
93479ab7f0SSascha Wildner
94479ab7f0SSascha Wildner len = strlen(path);
95479ab7f0SSascha Wildner if (path[0] == '/') {
96479ab7f0SSascha Wildner base = malloc(len + 2); /* room for trailing / */
97479ab7f0SSascha Wildner bcopy(path, base, len + 1);
98479ab7f0SSascha Wildner } else {
99479ab7f0SSascha Wildner while (len && path[len-1] == '/')
100479ab7f0SSascha Wildner --len;
101479ab7f0SSascha Wildner dlen = strlen(DirBase);
102479ab7f0SSascha Wildner base = malloc(dlen + len + 2); /* room for trailing / */
103479ab7f0SSascha Wildner bcopy(DirBase, base, dlen);
104479ab7f0SSascha Wildner bcopy(path, base + dlen, len);
105479ab7f0SSascha Wildner base[dlen + len] = 0;
106479ab7f0SSascha Wildner }
107479ab7f0SSascha Wildner
108479ab7f0SSascha Wildner if (stat(base, &st) == 0 && S_ISDIR(st.st_mode)) {
109479ab7f0SSascha Wildner p = b = w = s = base;
110479ab7f0SSascha Wildner while (*s) {
111479ab7f0SSascha Wildner if (*s == '/') {
112479ab7f0SSascha Wildner if (s - b == 2 && b[0] == '.' && b[1] == '.') {
113479ab7f0SSascha Wildner w = p;
114479ab7f0SSascha Wildner } else {
115479ab7f0SSascha Wildner p = b;
116479ab7f0SSascha Wildner b = s + 1;
117479ab7f0SSascha Wildner }
118479ab7f0SSascha Wildner while (s[1] == '/')
119479ab7f0SSascha Wildner ++s;
120479ab7f0SSascha Wildner }
121479ab7f0SSascha Wildner *w = *s;
122479ab7f0SSascha Wildner ++w;
123479ab7f0SSascha Wildner ++s;
124479ab7f0SSascha Wildner }
125479ab7f0SSascha Wildner if (s - b == 2 && b[0] == '.' && b[1] == '.')
126479ab7f0SSascha Wildner w = p;
127479ab7f0SSascha Wildner while (w > base && w[-1] == '/')
128479ab7f0SSascha Wildner --w;
129479ab7f0SSascha Wildner *w++ = '/';
130479ab7f0SSascha Wildner *w = 0;
131479ab7f0SSascha Wildner
132479ab7f0SSascha Wildner if (DirBase)
133479ab7f0SSascha Wildner free(DirBase);
134479ab7f0SSascha Wildner DirBase = base;
135479ab7f0SSascha Wildner res = CMD_OK;
136479ab7f0SSascha Wildner } else {
137479ab7f0SSascha Wildner free(base);
138479ab7f0SSascha Wildner sprintf(command_errbuf, "Unable to find directory");
139479ab7f0SSascha Wildner res = CMD_ERROR;
140479ab7f0SSascha Wildner }
141479ab7f0SSascha Wildner return (res);
142479ab7f0SSascha Wildner }
143479ab7f0SSascha Wildner
144479ab7f0SSascha Wildner COMMAND_SET(pwd, "pwd", "Get current directory", command_pwd);
145479ab7f0SSascha Wildner
146d5ee8190SAaron LI static int
command_pwd(int ac,char ** av)147479ab7f0SSascha Wildner command_pwd(int ac, char **av)
148479ab7f0SSascha Wildner {
149479ab7f0SSascha Wildner printf("%s\n", DirBase ? DirBase : "/");
150479ab7f0SSascha Wildner return(0);
151479ab7f0SSascha Wildner }
152479ab7f0SSascha Wildner
153479ab7f0SSascha Wildner int
rel_open(const char * path,char ** abspathp,int flags)154479ab7f0SSascha Wildner rel_open(const char *path, char **abspathp, int flags)
155479ab7f0SSascha Wildner {
156479ab7f0SSascha Wildner int fd;
157479ab7f0SSascha Wildner char *ptr;
158479ab7f0SSascha Wildner
159479ab7f0SSascha Wildner if (DirBase == NULL)
160479ab7f0SSascha Wildner DirBase = strdup("/");
161479ab7f0SSascha Wildner
162479ab7f0SSascha Wildner if (path[0] != '/') {
163479ab7f0SSascha Wildner ptr = malloc(strlen(DirBase) + strlen(path) + 1);
164479ab7f0SSascha Wildner sprintf(ptr, "%s%s", DirBase, path);
165479ab7f0SSascha Wildner fd = open(ptr, flags);
166479ab7f0SSascha Wildner if (abspathp && fd >= 0) {
167479ab7f0SSascha Wildner *abspathp = ptr;
168479ab7f0SSascha Wildner } else if (abspathp) {
169479ab7f0SSascha Wildner *abspathp = NULL;
170479ab7f0SSascha Wildner free(ptr);
171479ab7f0SSascha Wildner } else {
172479ab7f0SSascha Wildner free(ptr);
173479ab7f0SSascha Wildner }
174479ab7f0SSascha Wildner } else {
175479ab7f0SSascha Wildner fd = open(path, flags);
176479ab7f0SSascha Wildner if (abspathp && fd >= 0) {
177479ab7f0SSascha Wildner *abspathp = strdup(path);
178479ab7f0SSascha Wildner } else if (abspathp) {
179479ab7f0SSascha Wildner *abspathp = NULL;
180479ab7f0SSascha Wildner }
181479ab7f0SSascha Wildner }
182479ab7f0SSascha Wildner return(fd);
183479ab7f0SSascha Wildner }
184479ab7f0SSascha Wildner
185479ab7f0SSascha Wildner int
rel_stat(const char * path,struct stat * st)186479ab7f0SSascha Wildner rel_stat(const char *path, struct stat *st)
187479ab7f0SSascha Wildner {
188479ab7f0SSascha Wildner char *ptr;
189479ab7f0SSascha Wildner int res;
190479ab7f0SSascha Wildner
191479ab7f0SSascha Wildner if (DirBase == NULL)
192479ab7f0SSascha Wildner DirBase = strdup("/");
193479ab7f0SSascha Wildner
194479ab7f0SSascha Wildner if (path[0] != '/') {
195479ab7f0SSascha Wildner ptr = malloc(strlen(DirBase) + strlen(path) + 1);
196479ab7f0SSascha Wildner sprintf(ptr, "%s%s", DirBase, path);
197479ab7f0SSascha Wildner res = stat(ptr, st);
198479ab7f0SSascha Wildner free(ptr);
199479ab7f0SSascha Wildner } else {
200479ab7f0SSascha Wildner res = stat(path, st);
201479ab7f0SSascha Wildner }
202479ab7f0SSascha Wildner return(res);
203479ab7f0SSascha Wildner }
204*34f6038dSAaron LI
205*34f6038dSAaron LI /*
206*34f6038dSAaron LI * Return the root path of (path) with the "/boot" prefix prepended if
207*34f6038dSAaron LI * not present. This is required by the kernel after bootstrap, e.g.,
208*34f6038dSAaron LI * kldstat(), preload_delete_name().
209*34f6038dSAaron LI */
210*34f6038dSAaron LI char *
rel_rootpath(const char * path)211*34f6038dSAaron LI rel_rootpath(const char *path)
212*34f6038dSAaron LI {
213*34f6038dSAaron LI char *rootpath;
214*34f6038dSAaron LI
215*34f6038dSAaron LI if (DirBase == NULL)
216*34f6038dSAaron LI DirBase = strdup("/");
217*34f6038dSAaron LI
218*34f6038dSAaron LI if (strncmp(path, "/boot/", sizeof("/boot/")-1) == 0) {
219*34f6038dSAaron LI rootpath = strdup(path);
220*34f6038dSAaron LI } else if (path[0] == '/') {
221*34f6038dSAaron LI rootpath = malloc(strlen(path) + sizeof("/boot"));
222*34f6038dSAaron LI sprintf(rootpath, "/boot%s", path);
223*34f6038dSAaron LI } else {
224*34f6038dSAaron LI rootpath = malloc(strlen(DirBase) + strlen(path) +
225*34f6038dSAaron LI sizeof("/boot"));
226*34f6038dSAaron LI sprintf(rootpath, "/boot%s%s", DirBase, path);
227*34f6038dSAaron LI }
228*34f6038dSAaron LI
229*34f6038dSAaron LI return (rootpath);
230*34f6038dSAaron LI }
231