Correct BSD License clause numbering from 1-2-4 to 1-2-3.
[dragonfly.git] / sys / boot / common / ls.c
1 /*
2  * $NetBSD: ls.c,v 1.3 1997/06/13 13:48:47 drochner Exp $
3  */
4
5 /*-
6  * Copyright (c) 1993
7  *      The Regents of the University of California.  All rights reserved.
8  * Copyright (c) 1996
9  *      Matthias Drochner.  All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * $FreeBSD: src/sys/boot/common/ls.c,v 1.11 2003/08/25 23:30:41 obrien Exp $
36  * $DragonFly: src/sys/boot/common/ls.c,v 1.5 2008/09/02 17:21:12 dillon Exp $
37  */
38
39 #include <sys/param.h>
40 #include <ufs/ufs/dinode.h>
41 #include <ufs/ufs/dir.h>
42
43 #include <stand.h>
44 #include <string.h>
45
46 #include "bootstrap.h"
47
48 static char typestr[] = "?fc?d?b? ?l?s?w";
49
50 static int      ls_getdir(char **pathp);
51
52 COMMAND_SET(ls, "ls", "list files", command_ls);
53
54 static int
55 command_ls(int argc, char *argv[])
56 {
57     int         fd;
58     struct stat sb;
59     struct      dirent *d;
60     char        *buf, *path;
61     char        lbuf[128];              /* one line */
62     int         result, ch;
63     int         verbose;
64         
65     result = CMD_OK;
66     fd = -1;
67     verbose = 0;
68     optind = 1;
69     optreset = 1;
70     while ((ch = getopt(argc, argv, "l")) != -1) {
71         switch(ch) {
72         case 'l':
73             verbose = 1;
74             break;
75         case '?':
76         default:
77             /* getopt has already reported an error */
78             return(CMD_OK);
79         }
80     }
81     argv += (optind - 1);
82     argc -= (optind - 1);
83
84     if (argc < 2) {
85         path = "";
86     } else {
87         path = argv[1];
88     }
89
90     fd = ls_getdir(&path);
91     if (fd == -1) {
92         result = CMD_ERROR;
93         goto out;
94     }
95     pager_open();
96     pager_output(path);
97     pager_output("\n");
98
99     while ((d = readdirfd(fd)) != NULL) {
100         if (strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) {
101             if (verbose) {
102                 /* stat the file, if possible */
103                 sb.st_size = 0;
104                 buf = malloc(strlen(path) + strlen(d->d_name) + 2);
105                 sprintf(buf, "%s/%s", path, d->d_name);
106                 /* ignore return, could be symlink, etc. */
107                 if (rel_stat(buf, &sb))
108                     sb.st_size = 0;
109                 free(buf);
110                 sprintf(lbuf, " %c %8d %s\n", typestr[d->d_type],
111                     (int)sb.st_size, d->d_name);
112             } else {
113                 sprintf(lbuf, " %c  %s\n", typestr[d->d_type], d->d_name);
114             }
115             if (pager_output(lbuf))
116                 goto out;
117         }
118     }
119  out:
120     pager_close();
121     if (fd != -1)
122         close(fd);
123     if (path != NULL)
124         free(path);
125     return(result);
126 }
127
128 /*
129  * Given (path) containing a vaguely reasonable path specification, return an fd
130  * on the directory, and an allocated copy of the path to the directory.
131  */
132 static int
133 ls_getdir(char **pathp)
134 {
135     struct stat sb;
136     int         fd;
137     const char  *cp;
138     char        *path;
139
140     fd = -1;
141
142     /* one extra byte for a possible trailing slash required */
143     path = malloc(strlen(*pathp) + 2);
144     strcpy(path, *pathp);
145
146     /* Make sure the path is respectable to begin with */
147     if (archsw.arch_getdev(NULL, path, &cp)) {
148         sprintf(command_errbuf, "bad path '%s'", path);
149         goto out;
150     }
151     
152     fd = rel_open(cp, NULL, O_RDONLY);
153     if (fd < 0) {
154         sprintf(command_errbuf, "open '%s' failed: %s", path, strerror(errno));
155         goto out;
156     }
157     if (fstat(fd, &sb) < 0) {
158         sprintf(command_errbuf, "stat failed: %s", strerror(errno));
159         goto out;
160     }
161     if (!S_ISDIR(sb.st_mode)) {
162         sprintf(command_errbuf, "%s: %s", path, strerror(ENOTDIR));
163         goto out;
164     }
165
166     *pathp = path;
167     return(fd);
168
169  out:
170     free(path);
171     *pathp = NULL;
172     if (fd != -1)
173         close(fd);
174     return(-1);
175 }