1521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o/*
2521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * ls.c --- list directories
3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
4521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * Copyright (C) 1997 Theodore Ts'o.  This file may be redistributed
5521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * under the terms of the GNU Public License.
6521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o */
7521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
8521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#include <stdio.h>
9521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#include <unistd.h>
10521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#include <stdlib.h>
11521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#include <ctype.h>
12521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#include <string.h>
13521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#include <time.h>
14521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#ifdef HAVE_ERRNO_H
15521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#include <errno.h>
16521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#endif
17521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#include <sys/types.h>
18e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o#ifdef HAVE_GETOPT_H
19e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o#include <getopt.h>
20efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#else
21e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'oextern int optind;
22e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'oextern char *optarg;
23e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o#endif
24521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
25521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#include "debugfs.h"
26521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
27521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o/*
28521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * list directory
29521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o */
30521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
31521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#define LONG_OPT	0x0001
32e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o#define DELETED_OPT	0x0002
33d056b99191c87a68dc73ef01817169fb8f50afbdTheodore Ts'o#define PARSE_OPT	0x0004
34521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
35521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'ostruct list_dir_struct {
36521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	FILE	*f;
37521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	int	col;
38521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	int	options;
39521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o};
40521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
41521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'ostatic const char *monstr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
42521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o				"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
43efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
44544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic int list_dir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
45e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			 int	entry,
46e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			 struct ext2_dir_entry *dirent,
47544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			 int	offset EXT2FS_ATTR((unused)),
48544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			 int	blocksize EXT2FS_ATTR((unused)),
49544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			 char	*buf EXT2FS_ATTR((unused)),
50e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			 void	*private)
51521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o{
52521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	struct ext2_inode	inode;
53e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	ext2_ino_t		ino;
54521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	struct tm		*tm_p;
55521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	time_t			modtime;
56b772900b4bcff407c883b7bd8419af56be0a9823Brian Behlendorf	char			name[EXT2_NAME_LEN + 1];
57e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	char			tmp[EXT2_NAME_LEN + 16];
58521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	char			datestr[80];
59e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	char			lbr, rbr;
60e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	int			thislen;
61521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	struct list_dir_struct *ls = (struct list_dir_struct *) private;
62521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	thislen = dirent->name_len & 0xFF;
64521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	strncpy(name, dirent->name, thislen);
65521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	name[thislen] = '\0';
66e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	ino = dirent->inode;
67e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o
68e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	if (entry == DIRENT_DELETED_FILE) {
69e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		lbr = '<';
70e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		rbr = '>';
71e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		ino = 0;
72e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	} else {
73e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		lbr = rbr = ' ';
74e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	}
75d056b99191c87a68dc73ef01817169fb8f50afbdTheodore Ts'o	if (ls->options & PARSE_OPT) {
76e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ino) {
77e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (debugfs_read_inode(ino, &inode, name))
78e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				return 0;
79e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		} else
80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			memset(&inode, 0, sizeof(struct ext2_inode));
81d056b99191c87a68dc73ef01817169fb8f50afbdTheodore Ts'o		fprintf(ls->f,"/%u/%06o/%d/%d/%s/",ino,inode.i_mode,inode.i_uid, inode.i_gid,name);
82d056b99191c87a68dc73ef01817169fb8f50afbdTheodore Ts'o		if (LINUX_S_ISDIR(inode.i_mode))
83d056b99191c87a68dc73ef01817169fb8f50afbdTheodore Ts'o			fprintf(ls->f, "/");
84d056b99191c87a68dc73ef01817169fb8f50afbdTheodore Ts'o		else
85e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			fprintf(ls->f, "%lld/", EXT2_I_SIZE(&inode));
86d056b99191c87a68dc73ef01817169fb8f50afbdTheodore Ts'o		fprintf(ls->f, "\n");
87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	} else if (ls->options & LONG_OPT) {
88e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		if (ino) {
89e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			if (debugfs_read_inode(ino, &inode, name))
90682720a41b70cbe5291b524184983712124035b2Theodore Ts'o				return 0;
91e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			modtime = inode.i_mtime;
92e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			tm_p = localtime(&modtime);
93e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			sprintf(datestr, "%2d-%s-%4d %02d:%02d",
94e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o				tm_p->tm_mday, monstr[tm_p->tm_mon],
95e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o				1900 + tm_p->tm_year, tm_p->tm_hour,
96e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o				tm_p->tm_min);
97e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		} else {
98e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			strcpy(datestr, "                 ");
99e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			memset(&inode, 0, sizeof(struct ext2_inode));
100e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		}
101fa7c30276c2b3ff06ddfa6ac0067a753bfbe0d21Theodore Ts'o		fprintf(ls->f, "%c%6u%c %6o (%d)  %5d  %5d   ", lbr, ino, rbr,
102f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o			inode.i_mode, dirent->name_len >> 8,
1035113a6e32b298671c86ae7da097bcd24540cebc9Eric Sandeen			inode_uid(inode), inode_gid(inode));
104e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		if (LINUX_S_ISDIR(inode.i_mode))
105e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			fprintf(ls->f, "%5d", inode.i_size);
106e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		else
107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			fprintf(ls->f, "%5llu", EXT2_I_SIZE(&inode));
108e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		fprintf (ls->f, " %s %s\n", datestr, name);
109e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	} else {
110e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		sprintf(tmp, "%c%u%c (%d) %s   ", lbr, dirent->inode, rbr,
111e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			dirent->rec_len, name);
112e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		thislen = strlen(tmp);
113e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o
114e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		if (ls->col + thislen > 80) {
115e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			fprintf(ls->f, "\n");
116e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			ls->col = 0;
117e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		}
118e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		fprintf(ls->f, "%s", tmp);
119e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		ls->col += thislen;
120e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	}
121521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	return 0;
122521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o}
123521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
124521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'ovoid do_list_dir(int argc, char *argv[])
125521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o{
126b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o	ext2_ino_t	inode;
127b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o	int		retval;
128e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	int		c;
129e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	int		flags;
130521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	struct list_dir_struct ls;
131efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
132521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	ls.options = 0;
133521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	if (check_fs_open(argv[0]))
134521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o		return;
135521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
13688494bb6d440f703db98b6cc4452f63d7aa392b9Theodore Ts'o	reset_getopt();
137d056b99191c87a68dc73ef01817169fb8f50afbdTheodore Ts'o	while ((c = getopt (argc, argv, "dlp")) != EOF) {
138e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		switch (c) {
139e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		case 'l':
140e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			ls.options |= LONG_OPT;
141e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			break;
142e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		case 'd':
143e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			ls.options |= DELETED_OPT;
144e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o			break;
145d056b99191c87a68dc73ef01817169fb8f50afbdTheodore Ts'o		case 'p':
146d056b99191c87a68dc73ef01817169fb8f50afbdTheodore Ts'o			ls.options |= PARSE_OPT;
147d056b99191c87a68dc73ef01817169fb8f50afbdTheodore Ts'o			break;
14849c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o		default:
14949c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o			goto print_usage;
150e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		}
151e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	}
152e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o
153e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	if (argc > optind+1) {
15449c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o	print_usage:
155d056b99191c87a68dc73ef01817169fb8f50afbdTheodore Ts'o		com_err(0, 0, "Usage: ls [-l] [-d] [-p] file");
156e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		return;
157521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	}
158521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
159e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	if (argc == optind)
160521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o		inode = cwd;
161521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	else
162e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		inode = string_to_inode(argv[optind]);
163521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	if (!inode)
164521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o		return;
165521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
166521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	ls.f = open_pager();
167521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	ls.col = 0;
168e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	flags = DIRENT_FLAG_INCLUDE_EMPTY;
169e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	if (ls.options & DELETED_OPT)
170e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o		flags |= DIRENT_FLAG_INCLUDE_REMOVED;
171e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o
172e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o	retval = ext2fs_dir_iterate2(current_fs, inode, flags,
173521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o				    0, list_dir_proc, &ls);
174521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	fprintf(ls.f, "\n");
175521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	close_pager(ls.f);
176521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	if (retval)
1779b9a780f5a5823865f62f0c9fd194d262f63a06fTheodore Ts'o		com_err(argv[1], retval, 0);
178521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
179521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o	return;
180521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o}
181521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
182521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o
183