138465Smsmith/*
2119483Sobrien * $NetBSD: ls.c,v 1.3 1997/06/13 13:48:47 drochner Exp $
338465Smsmith */
438465Smsmith
5119483Sobrien/*-
638465Smsmith * Copyright (c) 1993
738465Smsmith *	The Regents of the University of California.  All rights reserved.
838465Smsmith * Copyright (c) 1996
938465Smsmith *	Matthias Drochner.  All rights reserved.
1038465Smsmith *
1138465Smsmith * Redistribution and use in source and binary forms, with or without
1238465Smsmith * modification, are permitted provided that the following conditions
1338465Smsmith * are met:
1438465Smsmith * 1. Redistributions of source code must retain the above copyright
1538465Smsmith *    notice, this list of conditions and the following disclaimer.
1638465Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1738465Smsmith *    notice, this list of conditions and the following disclaimer in the
1838465Smsmith *    documentation and/or other materials provided with the distribution.
1938465Smsmith * 3. All advertising materials mentioning features or use of this software
2038465Smsmith *    must display the following acknowledgement:
2138465Smsmith *	This product includes software developed by the University of
2238465Smsmith *	California, Berkeley and its contributors.
2338465Smsmith * 4. Neither the name of the University nor the names of its contributors
2438465Smsmith *    may be used to endorse or promote products derived from this software
2538465Smsmith *    without specific prior written permission.
2638465Smsmith *
2738465Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2838465Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2938465Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3038465Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3138465Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3238465Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3338465Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3438465Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3538465Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3638465Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3738465Smsmith * SUCH DAMAGE.
3838465Smsmith */
3938465Smsmith
40119483Sobrien#include <sys/cdefs.h>
41119483Sobrien__FBSDID("$FreeBSD: stable/11/stand/common/ls.c 329099 2018-02-10 04:37:44Z kevans $");
4238465Smsmith
4338465Smsmith#include <sys/param.h>
4438465Smsmith#include <ufs/ufs/dinode.h>
4538465Smsmith#include <ufs/ufs/dir.h>
4638465Smsmith
4738465Smsmith#include <stand.h>
4840106Smsmith#include <string.h>
4938465Smsmith
5038465Smsmith#include "bootstrap.h"
5138465Smsmith
5238465Smsmithstatic char typestr[] = "?fc?d?b? ?l?s?w";
5338465Smsmith
5440106Smsmithstatic int	ls_getdir(char **pathp);
5540106Smsmith
5638465SmsmithCOMMAND_SET(ls, "ls", "list files", command_ls);
5738465Smsmith
5838465Smsmithstatic int
5938465Smsmithcommand_ls(int argc, char *argv[])
6038465Smsmith{
6138465Smsmith    int		fd;
6238465Smsmith    struct stat	sb;
63329099Skevans    struct	dirent *d;
6440106Smsmith    char	*buf, *path;
6540106Smsmith    char	lbuf[128];		/* one line */
6638465Smsmith    int		result, ch;
6738465Smsmith    int		verbose;
68329099Skevans
6940106Smsmith    result = CMD_OK;
7040106Smsmith    fd = -1;
7138465Smsmith    verbose = 0;
7238465Smsmith    optind = 1;
7342512Smsmith    optreset = 1;
7438465Smsmith    while ((ch = getopt(argc, argv, "l")) != -1) {
75329099Skevans	switch (ch) {
7638465Smsmith	case 'l':
7738465Smsmith	    verbose = 1;
7838465Smsmith	    break;
7938465Smsmith	case '?':
8038465Smsmith	default:
8138465Smsmith	    /* getopt has already reported an error */
82329099Skevans	    return (CMD_OK);
8338465Smsmith	}
8438465Smsmith    }
8538465Smsmith    argv += (optind - 1);
8638465Smsmith    argc -= (optind - 1);
8738465Smsmith
8838465Smsmith    if (argc < 2) {
8940106Smsmith	path = "";
9038465Smsmith    } else {
9138465Smsmith	path = argv[1];
9238465Smsmith    }
9338465Smsmith
94329099Skevans    if (stat(path, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
95329099Skevans	if (verbose) {
96329099Skevans	    printf(" %c %8d %s\n",
97329099Skevans		typestr[sb.st_mode >> 12],
98329099Skevans		(int)sb.st_size, path);
99329099Skevans	} else {
100329099Skevans	    printf(" %c  %s\n",
101329099Skevans		typestr[sb.st_mode >> 12], path);
102329099Skevans	}
103329099Skevans	return (CMD_OK);
104329099Skevans    }
105329099Skevans
10640106Smsmith    fd = ls_getdir(&path);
10740106Smsmith    if (fd == -1) {
10840106Smsmith	result = CMD_ERROR;
10940106Smsmith	goto out;
11040106Smsmith    }
11138465Smsmith    pager_open();
11238465Smsmith    pager_output(path);
11338465Smsmith    pager_output("\n");
11438465Smsmith
11559767Sjlemon    while ((d = readdirfd(fd)) != NULL) {
11659767Sjlemon	if (strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) {
117329099Skevans	    if (d->d_type == 0 || verbose) {
11859767Sjlemon		/* stat the file, if possible */
11959767Sjlemon		sb.st_size = 0;
120329099Skevans		sb.st_mode = 0;
12159767Sjlemon		buf = malloc(strlen(path) + strlen(d->d_name) + 2);
122329099Skevans		if (buf != NULL) {
123329099Skevans		    sprintf(buf, "%s/%s", path, d->d_name);
124329099Skevans		    /* ignore return, could be symlink, etc. */
125329099Skevans		    if (stat(buf, &sb)) {
126329099Skevans			sb.st_size = 0;
127329099Skevans			sb.st_mode = 0;
128329099Skevans		    }
129329099Skevans		    free(buf);
130329099Skevans		}
131329099Skevans	    }
132329099Skevans	    if (verbose) {
133329099Skevans		snprintf(lbuf, sizeof(lbuf), " %c %8d %s\n",
134329099Skevans		    typestr[d->d_type? d->d_type:sb.st_mode >> 12],
13559767Sjlemon		    (int)sb.st_size, d->d_name);
13659767Sjlemon	    } else {
137329099Skevans		snprintf(lbuf, sizeof(lbuf), " %c  %s\n",
138329099Skevans		    typestr[d->d_type? d->d_type:sb.st_mode >> 12], d->d_name);
13938465Smsmith	    }
14059767Sjlemon	    if (pager_output(lbuf))
14159767Sjlemon		goto out;
14238465Smsmith	}
14338465Smsmith    }
14438465Smsmith out:
14538465Smsmith    pager_close();
14640106Smsmith    if (fd != -1)
14740106Smsmith	close(fd);
148329099Skevans    free(path);		/* ls_getdir() did allocate path */
149329099Skevans    return (result);
15038465Smsmith}
15140106Smsmith
15240106Smsmith/*
15340106Smsmith * Given (path) containing a vaguely reasonable path specification, return an fd
15440106Smsmith * on the directory, and an allocated copy of the path to the directory.
15540106Smsmith */
15640106Smsmithstatic int
15740106Smsmithls_getdir(char **pathp)
15840106Smsmith{
15940106Smsmith    struct stat	sb;
16040106Smsmith    int		fd;
16140215Speter    const char	*cp;
162316318Sngie    char	*path;
16340106Smsmith
16440106Smsmith    fd = -1;
16540106Smsmith
16640106Smsmith    /* one extra byte for a possible trailing slash required */
16740106Smsmith    path = malloc(strlen(*pathp) + 2);
168329099Skevans    if (path == NULL) {
169329099Skevans	snprintf(command_errbuf, sizeof (command_errbuf),
170329099Skevans	    "out of memory");
171329099Skevans	goto out;
172329099Skevans    }
17340106Smsmith    strcpy(path, *pathp);
17440106Smsmith
17540106Smsmith    /* Make sure the path is respectable to begin with */
17640106Smsmith    if (archsw.arch_getdev(NULL, path, &cp)) {
177329010Skevans	snprintf(command_errbuf, sizeof(command_errbuf),
178329010Skevans	    "bad path '%s'", path);
17940106Smsmith	goto out;
18040106Smsmith    }
181329099Skevans
18240106Smsmith    /* If there's no path on the device, assume '/' */
18340106Smsmith    if (*cp == 0)
18440106Smsmith	strcat(path, "/");
18540106Smsmith
18640106Smsmith    fd = open(path, O_RDONLY);
18740106Smsmith    if (fd < 0) {
188329010Skevans	snprintf(command_errbuf, sizeof(command_errbuf),
189329010Skevans	    "open '%s' failed: %s", path, strerror(errno));
19040106Smsmith	goto out;
19140106Smsmith    }
19240106Smsmith    if (fstat(fd, &sb) < 0) {
193329010Skevans	snprintf(command_errbuf, sizeof(command_errbuf),
194329010Skevans	    "stat failed: %s", strerror(errno));
19540106Smsmith	goto out;
19640106Smsmith    }
19740106Smsmith    if (!S_ISDIR(sb.st_mode)) {
198329010Skevans	snprintf(command_errbuf, sizeof(command_errbuf),
199329010Skevans	    "%s: %s", path, strerror(ENOTDIR));
20040106Smsmith	goto out;
20140106Smsmith    }
20240106Smsmith
20340106Smsmith    *pathp = path;
204329099Skevans    return (fd);
20540106Smsmith
20640106Smsmith out:
20740106Smsmith    free(path);
20840106Smsmith    *pathp = NULL;
20940106Smsmith    if (fd != -1)
21040106Smsmith	close(fd);
211329099Skevans    return (-1);
21240106Smsmith}
213