1214077Sgibbs/*
2214077Sgibbs * $NetBSD: ls.c,v 1.3 2009/07/20 04:59:03 kiyohara Exp $
3214077Sgibbs */
4214077Sgibbs
5214077Sgibbs/*-
6214077Sgibbs * Copyright (c) 1993
7214077Sgibbs *	The Regents of the University of California.  All rights reserved.
8214077Sgibbs * Copyright (c) 1996
9214077Sgibbs *	Matthias Drochner.  All rights reserved.
10214077Sgibbs *
11214077Sgibbs * Redistribution and use in source and binary forms, with or without
12214077Sgibbs * modification, are permitted provided that the following conditions
13214077Sgibbs * are met:
14214077Sgibbs * 1. Redistributions of source code must retain the above copyright
15214077Sgibbs *    notice, this list of conditions and the following disclaimer.
16214077Sgibbs * 2. Redistributions in binary form must reproduce the above copyright
17214077Sgibbs *    notice, this list of conditions and the following disclaimer in the
18214077Sgibbs *    documentation and/or other materials provided with the distribution.
19214077Sgibbs * 3. All advertising materials mentioning features or use of this software
20214077Sgibbs *    must display the following acknowledgement:
21214077Sgibbs *	This product includes software developed by the University of
22214077Sgibbs *	California, Berkeley and its contributors.
23214077Sgibbs * 4. Neither the name of the University nor the names of its contributors
24214077Sgibbs *    may be used to endorse or promote products derived from this software
25214077Sgibbs *    without specific prior written permission.
26214077Sgibbs *
27214077Sgibbs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28214077Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29214077Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30214077Sgibbs * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31214077Sgibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32214077Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33214077Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34214077Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35214077Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36214077Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37214077Sgibbs * SUCH DAMAGE.
38214077Sgibbs */
39214077Sgibbs
40214077Sgibbs#include <sys/cdefs.h>
41214077Sgibbs/* __FBSDID("$FreeBSD: src/sys/boot/common/ls.c,v 1.11 2003/08/25 23:30:41 obrien Exp $"); */
42214077Sgibbs
43214077Sgibbs
44214077Sgibbs#include <sys/param.h>
45214077Sgibbs#include <ufs/ufs/dinode.h>
46214077Sgibbs#include <ufs/ufs/dir.h>
47214077Sgibbs#include <sys/dirent.h>
48214077Sgibbs
49214077Sgibbs#include <lib/libsa/stand.h>
50214077Sgibbs#include <lib/libsa/loadfile.h>
51214077Sgibbs
52214077Sgibbs#include "bootstrap.h"
53214077Sgibbs
54214077Sgibbsstatic char typestr[] = "?fc?d?b? ?l?s?w";
55214077Sgibbs
56214077Sgibbsstatic int	ls_getdir(char **pathp);
57214077Sgibbs
58214077Sgibbsint
59214077Sgibbscommand_ls(int argc, char *argv[])
60214077Sgibbs{
61214077Sgibbs    int		fd;
62214077Sgibbs    struct stat	sb;
63214077Sgibbs    struct 	dirent *d;
64214077Sgibbs    char	*buf, *path;
65214077Sgibbs    char	lbuf[128];		/* one line */
66214077Sgibbs    int		result, ch;
67214077Sgibbs    int		verbose;
68214077Sgibbs
69214077Sgibbs    result = CMD_OK;
70214077Sgibbs    fd = -1;
71214077Sgibbs    verbose = 0;
72214077Sgibbs    optind = 1;
73214077Sgibbs    optreset = 1;
74214077Sgibbs    while ((ch = getopt(argc, argv, "l")) != -1) {
75214077Sgibbs	switch(ch) {
76214077Sgibbs	case 'l':
77214077Sgibbs	    verbose = 1;
78214077Sgibbs	    break;
79214077Sgibbs	case '?':
80214077Sgibbs	default:
81214077Sgibbs	    /* getopt has already reported an error */
82214077Sgibbs	    return(CMD_OK);
83214077Sgibbs	}
84214077Sgibbs    }
85214077Sgibbs    argv += (optind - 1);
86214077Sgibbs    argc -= (optind - 1);
87214077Sgibbs
88214077Sgibbs    if (argc < 2) {
89214077Sgibbs	path = "";
90214077Sgibbs    } else {
91214077Sgibbs	path = argv[1];
92214077Sgibbs    }
93214077Sgibbs
94214077Sgibbs    fd = ls_getdir(&path);
95214077Sgibbs    if (fd == -1) {
96214077Sgibbs	result = CMD_ERROR;
97214077Sgibbs	goto out;
98214077Sgibbs    }
99214077Sgibbs
100214077Sgibbs    pager_open();
101214077Sgibbs    pager_output(path);
102214077Sgibbs    pager_output("\n");
103214077Sgibbs
104214077Sgibbs    while ((d = readdirfd(fd)) != NULL) {
105214077Sgibbs/*	if (strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) { */
106214077Sgibbs	    if (verbose) {
107214077Sgibbs		size_t buflen;
108214077Sgibbs		/* stat the file, if possible */
109214077Sgibbs		sb.st_size = 0;
110214077Sgibbs		buflen = strlen(path) + strlen(d->d_name) + 2;
111214077Sgibbs		buf = alloc(buflen);
112214077Sgibbs		snprintf(buf, buflen, "%s/%s", path, d->d_name);
113214077Sgibbs		/* ignore return, could be symlink, etc. */
114214077Sgibbs		if (stat(buf, &sb))
115214077Sgibbs		    sb.st_size = 0;
116214077Sgibbs		free(buf);
117214077Sgibbs		snprintf(lbuf, sizeof(lbuf), " %c %8d %s\n", typestr[d->d_type],
118214077Sgibbs		    (int)sb.st_size, d->d_name);
119214077Sgibbs	    } else {
120214077Sgibbs	      snprintf(lbuf, sizeof(lbuf), " %c  %s\n", typestr[d->d_type],
121214077Sgibbs		  d->d_name);
122214077Sgibbs	    }
123214077Sgibbs	    if (pager_output(lbuf))
124214077Sgibbs		goto out;
125214077Sgibbs	    /*	} */
126214077Sgibbs    }
127214077Sgibbs out:
128214077Sgibbs    pager_close();
129214077Sgibbs    if (fd != -1)
130214077Sgibbs	close(fd);
131214077Sgibbs    if (path != NULL)
132214077Sgibbs	free(path);
133214077Sgibbs    return(result);
134214077Sgibbs}
135214077Sgibbs
136214077Sgibbs/*
137214077Sgibbs * Given (path) containing a vaguely reasonable path specification, return an fd
138214077Sgibbs * on the directory, and an allocated copy of the path to the directory.
139214077Sgibbs */
140214077Sgibbsstatic int
141214077Sgibbsls_getdir(char **pathp)
142214077Sgibbs{
143214077Sgibbs    struct stat	sb;
144214077Sgibbs    int		fd;
145214077Sgibbs    const char	*cp;
146214077Sgibbs    char	*path, *tail;
147214077Sgibbs
148214077Sgibbs    tail = NULL;
149214077Sgibbs    fd = -1;
150214077Sgibbs
151214077Sgibbs    /* one extra byte for a possible trailing slash required */
152214077Sgibbs    path = alloc(strlen(*pathp) + 2);
153214077Sgibbs    strcpy(path, *pathp);
154214077Sgibbs
155214077Sgibbs    /* Make sure the path is respectable to begin with */
156214077Sgibbs    if (archsw.arch_getdev(NULL, path, &cp)) {
157214077Sgibbs	command_seterr("bad path '%s'", path);
158214077Sgibbs	goto out;
159214077Sgibbs    }
160214077Sgibbs
161214077Sgibbs    /* If there's no path on the device, assume '/' */
162214077Sgibbs    if (*cp == 0)
163214077Sgibbs	strcat(path, "/");
164214077Sgibbs    fd = open(path, O_RDONLY);
165214077Sgibbs    if (fd < 0) {
166214077Sgibbs	command_seterr("open '%s' failed: %s", path, strerror(errno));
167214077Sgibbs	goto out;
168214077Sgibbs    }
169214077Sgibbs    if (fstat(fd, &sb) < 0) {
170214077Sgibbs	command_seterr("stat failed: %s", strerror(errno));
171214077Sgibbs	goto out;
172214077Sgibbs    }
173214077Sgibbs    if (!S_ISDIR(sb.st_mode)) {
174214077Sgibbs	command_seterr("%s: %s", path, strerror(ENOTDIR));
175214077Sgibbs	goto out;
176214077Sgibbs    }
177214077Sgibbs
178214077Sgibbs    *pathp = path;
179214077Sgibbs    return(fd);
180214077Sgibbs
181214077Sgibbs out:
182214077Sgibbs    free(path);
183214077Sgibbs    *pathp = NULL;
184214077Sgibbs    if (fd != -1)
185214077Sgibbs	close(fd);
186214077Sgibbs    return(-1);
187214077Sgibbs}
188214077Sgibbs