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