xref: /dflybsd-src/stand/boot/common/rel_open.c (revision 34f6038d8e05d03acda52bf11979c6c2afe7b5ea)
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