1b528cefcSMark Murray /* 28373020dSJacques Vidrine * Copyright (c) 1999 - 2002 Kungliga Tekniska H�gskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of KTH nor the names of its contributors may be 18b528cefcSMark Murray * used to endorse or promote products derived from this software without 19b528cefcSMark Murray * specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 22b528cefcSMark Murray * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24b528cefcSMark Murray * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 25b528cefcSMark Murray * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26b528cefcSMark Murray * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27b528cefcSMark Murray * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28b528cefcSMark Murray * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29b528cefcSMark Murray * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30b528cefcSMark Murray * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31b528cefcSMark Murray * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 32b528cefcSMark Murray 335e9cd1aeSAssar Westerlund #ifndef TEST 34b528cefcSMark Murray #include "ftpd_locl.h" 35b528cefcSMark Murray 368373020dSJacques Vidrine RCSID("$Id: ls.c,v 1.25 2002/08/22 08:31:03 joda Exp $"); 375e9cd1aeSAssar Westerlund 385e9cd1aeSAssar Westerlund #else 395e9cd1aeSAssar Westerlund #include <stdio.h> 405e9cd1aeSAssar Westerlund #include <string.h> 415e9cd1aeSAssar Westerlund #include <stdlib.h> 425e9cd1aeSAssar Westerlund #include <time.h> 435e9cd1aeSAssar Westerlund #include <dirent.h> 445e9cd1aeSAssar Westerlund #include <sys/stat.h> 455e9cd1aeSAssar Westerlund #include <unistd.h> 465e9cd1aeSAssar Westerlund #include <pwd.h> 475e9cd1aeSAssar Westerlund #include <grp.h> 485e9cd1aeSAssar Westerlund #include <errno.h> 495e9cd1aeSAssar Westerlund 505e9cd1aeSAssar Westerlund #define sec_fprintf2 fprintf 515e9cd1aeSAssar Westerlund #define sec_fflush fflush 524137ff4cSJacques Vidrine static void list_files(FILE *out, const char **files, int n_files, int flags); 534137ff4cSJacques Vidrine static int parse_flags(const char *options); 544137ff4cSJacques Vidrine 555e9cd1aeSAssar Westerlund int 565e9cd1aeSAssar Westerlund main(int argc, char **argv) 575e9cd1aeSAssar Westerlund { 584137ff4cSJacques Vidrine int i = 1; 594137ff4cSJacques Vidrine int flags; 604137ff4cSJacques Vidrine if(argc > 1 && argv[1][0] == '-') { 614137ff4cSJacques Vidrine flags = parse_flags(argv[1]); 624137ff4cSJacques Vidrine i = 2; 634137ff4cSJacques Vidrine } else 644137ff4cSJacques Vidrine flags = parse_flags(NULL); 654137ff4cSJacques Vidrine 664137ff4cSJacques Vidrine list_files(stdout, (const char **)argv + i, argc - i, flags); 675e9cd1aeSAssar Westerlund return 0; 685e9cd1aeSAssar Westerlund } 695e9cd1aeSAssar Westerlund #endif 70b528cefcSMark Murray 71b528cefcSMark Murray struct fileinfo { 72b528cefcSMark Murray struct stat st; 73b528cefcSMark Murray int inode; 74b528cefcSMark Murray int bsize; 75b528cefcSMark Murray char mode[11]; 76b528cefcSMark Murray int n_link; 77b528cefcSMark Murray char *user; 78b528cefcSMark Murray char *group; 79b528cefcSMark Murray char *size; 80b528cefcSMark Murray char *major; 81b528cefcSMark Murray char *minor; 82b528cefcSMark Murray char *date; 83b528cefcSMark Murray char *filename; 84b528cefcSMark Murray char *link; 85b528cefcSMark Murray }; 86b528cefcSMark Murray 87b528cefcSMark Murray static void 88b528cefcSMark Murray free_fileinfo(struct fileinfo *f) 89b528cefcSMark Murray { 90b528cefcSMark Murray free(f->user); 91b528cefcSMark Murray free(f->group); 92b528cefcSMark Murray free(f->size); 93b528cefcSMark Murray free(f->major); 94b528cefcSMark Murray free(f->minor); 95b528cefcSMark Murray free(f->date); 96b528cefcSMark Murray free(f->filename); 97b528cefcSMark Murray free(f->link); 98b528cefcSMark Murray } 99b528cefcSMark Murray 1005e9cd1aeSAssar Westerlund #define LS_DIRS (1 << 0) 1015e9cd1aeSAssar Westerlund #define LS_IGNORE_DOT (1 << 1) 1025e9cd1aeSAssar Westerlund #define LS_SORT_MODE (3 << 2) 103b528cefcSMark Murray #define SORT_MODE(f) ((f) & LS_SORT_MODE) 1045e9cd1aeSAssar Westerlund #define LS_SORT_NAME (1 << 2) 1055e9cd1aeSAssar Westerlund #define LS_SORT_MTIME (2 << 2) 1065e9cd1aeSAssar Westerlund #define LS_SORT_SIZE (3 << 2) 1075e9cd1aeSAssar Westerlund #define LS_SORT_REVERSE (1 << 4) 108b528cefcSMark Murray 1095e9cd1aeSAssar Westerlund #define LS_SIZE (1 << 5) 1105e9cd1aeSAssar Westerlund #define LS_INODE (1 << 6) 1115e9cd1aeSAssar Westerlund #define LS_TYPE (1 << 7) 1125e9cd1aeSAssar Westerlund #define LS_DISP_MODE (3 << 8) 1135e9cd1aeSAssar Westerlund #define DISP_MODE(f) ((f) & LS_DISP_MODE) 1145e9cd1aeSAssar Westerlund #define LS_DISP_LONG (1 << 8) 1155e9cd1aeSAssar Westerlund #define LS_DISP_COLUMN (2 << 8) 1165e9cd1aeSAssar Westerlund #define LS_DISP_CROSS (3 << 8) 1174137ff4cSJacques Vidrine #define LS_SHOW_ALL (1 << 10) 1184137ff4cSJacques Vidrine #define LS_RECURSIVE (1 << 11) 1194137ff4cSJacques Vidrine #define LS_EXTRA_BLANK (1 << 12) 1204137ff4cSJacques Vidrine #define LS_SHOW_DIRNAME (1 << 13) 1214137ff4cSJacques Vidrine #define LS_DIR_FLAG (1 << 14) /* these files come via list_dir */ 122b528cefcSMark Murray 123b528cefcSMark Murray #ifndef S_ISTXT 124b528cefcSMark Murray #define S_ISTXT S_ISVTX 125b528cefcSMark Murray #endif 126b528cefcSMark Murray 1278373020dSJacques Vidrine #if !defined(_S_IFMT) && defined(S_IFMT) 1288373020dSJacques Vidrine #define _S_IFMT S_IFMT 1298373020dSJacques Vidrine #endif 1308373020dSJacques Vidrine 131b528cefcSMark Murray #ifndef S_ISSOCK 132b528cefcSMark Murray #define S_ISSOCK(mode) (((mode) & _S_IFMT) == S_IFSOCK) 133b528cefcSMark Murray #endif 134b528cefcSMark Murray 135b528cefcSMark Murray #ifndef S_ISLNK 136b528cefcSMark Murray #define S_ISLNK(mode) (((mode) & _S_IFMT) == S_IFLNK) 137b528cefcSMark Murray #endif 138b528cefcSMark Murray 1394137ff4cSJacques Vidrine static size_t 1404137ff4cSJacques Vidrine block_convert(size_t blocks) 1414137ff4cSJacques Vidrine { 1424137ff4cSJacques Vidrine #ifdef S_BLKSIZE 1434137ff4cSJacques Vidrine return blocks * S_BLKSIZE / 1024; 1444137ff4cSJacques Vidrine #else 1454137ff4cSJacques Vidrine return blocks * 512 / 1024; 1464137ff4cSJacques Vidrine #endif 1474137ff4cSJacques Vidrine } 1484137ff4cSJacques Vidrine 149b528cefcSMark Murray static void 1504137ff4cSJacques Vidrine make_fileinfo(FILE *out, const char *filename, struct fileinfo *file, int flags) 151b528cefcSMark Murray { 152b528cefcSMark Murray char buf[128]; 1535e9cd1aeSAssar Westerlund int file_type = 0; 154b528cefcSMark Murray struct stat *st = &file->st; 155b528cefcSMark Murray 156b528cefcSMark Murray file->inode = st->st_ino; 1574137ff4cSJacques Vidrine file->bsize = block_convert(st->st_blocks); 158b528cefcSMark Murray 1595e9cd1aeSAssar Westerlund if(S_ISDIR(st->st_mode)) { 160b528cefcSMark Murray file->mode[0] = 'd'; 1615e9cd1aeSAssar Westerlund file_type = '/'; 1625e9cd1aeSAssar Westerlund } 163b528cefcSMark Murray else if(S_ISCHR(st->st_mode)) 164b528cefcSMark Murray file->mode[0] = 'c'; 165b528cefcSMark Murray else if(S_ISBLK(st->st_mode)) 166b528cefcSMark Murray file->mode[0] = 'b'; 1675e9cd1aeSAssar Westerlund else if(S_ISREG(st->st_mode)) { 168b528cefcSMark Murray file->mode[0] = '-'; 1695e9cd1aeSAssar Westerlund if(st->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) 1705e9cd1aeSAssar Westerlund file_type = '*'; 1715e9cd1aeSAssar Westerlund } 1725e9cd1aeSAssar Westerlund else if(S_ISFIFO(st->st_mode)) { 173b528cefcSMark Murray file->mode[0] = 'p'; 1745e9cd1aeSAssar Westerlund file_type = '|'; 1755e9cd1aeSAssar Westerlund } 1765e9cd1aeSAssar Westerlund else if(S_ISLNK(st->st_mode)) { 177b528cefcSMark Murray file->mode[0] = 'l'; 1785e9cd1aeSAssar Westerlund file_type = '@'; 1795e9cd1aeSAssar Westerlund } 1805e9cd1aeSAssar Westerlund else if(S_ISSOCK(st->st_mode)) { 181b528cefcSMark Murray file->mode[0] = 's'; 1825e9cd1aeSAssar Westerlund file_type = '='; 1835e9cd1aeSAssar Westerlund } 184b528cefcSMark Murray #ifdef S_ISWHT 1855e9cd1aeSAssar Westerlund else if(S_ISWHT(st->st_mode)) { 186b528cefcSMark Murray file->mode[0] = 'w'; 1875e9cd1aeSAssar Westerlund file_type = '%'; 1885e9cd1aeSAssar Westerlund } 189b528cefcSMark Murray #endif 190b528cefcSMark Murray else 191b528cefcSMark Murray file->mode[0] = '?'; 192b528cefcSMark Murray { 193b528cefcSMark Murray char *x[] = { "---", "--x", "-w-", "-wx", 194b528cefcSMark Murray "r--", "r-x", "rw-", "rwx" }; 195b528cefcSMark Murray strcpy(file->mode + 1, x[(st->st_mode & S_IRWXU) >> 6]); 196b528cefcSMark Murray strcpy(file->mode + 4, x[(st->st_mode & S_IRWXG) >> 3]); 197b528cefcSMark Murray strcpy(file->mode + 7, x[(st->st_mode & S_IRWXO) >> 0]); 198b528cefcSMark Murray if((st->st_mode & S_ISUID)) { 199b528cefcSMark Murray if((st->st_mode & S_IXUSR)) 200b528cefcSMark Murray file->mode[3] = 's'; 201b528cefcSMark Murray else 202b528cefcSMark Murray file->mode[3] = 'S'; 203b528cefcSMark Murray } 204b528cefcSMark Murray if((st->st_mode & S_ISGID)) { 205b528cefcSMark Murray if((st->st_mode & S_IXGRP)) 206b528cefcSMark Murray file->mode[6] = 's'; 207b528cefcSMark Murray else 208b528cefcSMark Murray file->mode[6] = 'S'; 209b528cefcSMark Murray } 210b528cefcSMark Murray if((st->st_mode & S_ISTXT)) { 211b528cefcSMark Murray if((st->st_mode & S_IXOTH)) 212b528cefcSMark Murray file->mode[9] = 't'; 213b528cefcSMark Murray else 214b528cefcSMark Murray file->mode[9] = 'T'; 215b528cefcSMark Murray } 216b528cefcSMark Murray } 217b528cefcSMark Murray file->n_link = st->st_nlink; 218b528cefcSMark Murray { 219b528cefcSMark Murray struct passwd *pwd; 220b528cefcSMark Murray pwd = getpwuid(st->st_uid); 221b528cefcSMark Murray if(pwd == NULL) 222b528cefcSMark Murray asprintf(&file->user, "%u", (unsigned)st->st_uid); 223b528cefcSMark Murray else 224b528cefcSMark Murray file->user = strdup(pwd->pw_name); 225b528cefcSMark Murray } 226b528cefcSMark Murray { 227b528cefcSMark Murray struct group *grp; 228b528cefcSMark Murray grp = getgrgid(st->st_gid); 229b528cefcSMark Murray if(grp == NULL) 230b528cefcSMark Murray asprintf(&file->group, "%u", (unsigned)st->st_gid); 231b528cefcSMark Murray else 232b528cefcSMark Murray file->group = strdup(grp->gr_name); 233b528cefcSMark Murray } 234b528cefcSMark Murray 235b528cefcSMark Murray if(S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { 236b528cefcSMark Murray #if defined(major) && defined(minor) 237b528cefcSMark Murray asprintf(&file->major, "%u", (unsigned)major(st->st_rdev)); 238b528cefcSMark Murray asprintf(&file->minor, "%u", (unsigned)minor(st->st_rdev)); 239b528cefcSMark Murray #else 240b528cefcSMark Murray /* Don't want to use the DDI/DKI crap. */ 241b528cefcSMark Murray asprintf(&file->major, "%u", (unsigned)st->st_rdev); 242b528cefcSMark Murray asprintf(&file->minor, "%u", 0); 243b528cefcSMark Murray #endif 244b528cefcSMark Murray } else 245b528cefcSMark Murray asprintf(&file->size, "%lu", (unsigned long)st->st_size); 246b528cefcSMark Murray 247b528cefcSMark Murray { 248b528cefcSMark Murray time_t t = time(NULL); 2495e9cd1aeSAssar Westerlund time_t mtime = st->st_mtime; 2505e9cd1aeSAssar Westerlund struct tm *tm = localtime(&mtime); 2515e9cd1aeSAssar Westerlund if((t - mtime > 6*30*24*60*60) || 2525e9cd1aeSAssar Westerlund (mtime - t > 6*30*24*60*60)) 253b528cefcSMark Murray strftime(buf, sizeof(buf), "%b %e %Y", tm); 254b528cefcSMark Murray else 255b528cefcSMark Murray strftime(buf, sizeof(buf), "%b %e %H:%M", tm); 256b528cefcSMark Murray file->date = strdup(buf); 257b528cefcSMark Murray } 258b528cefcSMark Murray { 259b528cefcSMark Murray const char *p = strrchr(filename, '/'); 260b528cefcSMark Murray if(p) 261b528cefcSMark Murray p++; 262b528cefcSMark Murray else 263b528cefcSMark Murray p = filename; 2645e9cd1aeSAssar Westerlund if((flags & LS_TYPE) && file_type != 0) 2655e9cd1aeSAssar Westerlund asprintf(&file->filename, "%s%c", p, file_type); 2665e9cd1aeSAssar Westerlund else 267b528cefcSMark Murray file->filename = strdup(p); 268b528cefcSMark Murray } 269b528cefcSMark Murray if(S_ISLNK(st->st_mode)) { 270b528cefcSMark Murray int n; 271b528cefcSMark Murray n = readlink((char *)filename, buf, sizeof(buf)); 272b528cefcSMark Murray if(n >= 0) { 273b528cefcSMark Murray buf[n] = '\0'; 274b528cefcSMark Murray file->link = strdup(buf); 275b528cefcSMark Murray } else 2764137ff4cSJacques Vidrine sec_fprintf2(out, "readlink(%s): %s", filename, strerror(errno)); 277b528cefcSMark Murray } 278b528cefcSMark Murray } 279b528cefcSMark Murray 280b528cefcSMark Murray static void 281b528cefcSMark Murray print_file(FILE *out, 282b528cefcSMark Murray int flags, 283b528cefcSMark Murray struct fileinfo *f, 284b528cefcSMark Murray int max_inode, 285b528cefcSMark Murray int max_bsize, 286b528cefcSMark Murray int max_n_link, 287b528cefcSMark Murray int max_user, 288b528cefcSMark Murray int max_group, 289b528cefcSMark Murray int max_size, 290b528cefcSMark Murray int max_major, 291b528cefcSMark Murray int max_minor, 292b528cefcSMark Murray int max_date) 293b528cefcSMark Murray { 294b528cefcSMark Murray if(f->filename == NULL) 295b528cefcSMark Murray return; 296b528cefcSMark Murray 297b528cefcSMark Murray if(flags & LS_INODE) { 298b528cefcSMark Murray sec_fprintf2(out, "%*d", max_inode, f->inode); 299b528cefcSMark Murray sec_fprintf2(out, " "); 300b528cefcSMark Murray } 301b528cefcSMark Murray if(flags & LS_SIZE) { 302b528cefcSMark Murray sec_fprintf2(out, "%*d", max_bsize, f->bsize); 303b528cefcSMark Murray sec_fprintf2(out, " "); 304b528cefcSMark Murray } 305b528cefcSMark Murray sec_fprintf2(out, "%s", f->mode); 306b528cefcSMark Murray sec_fprintf2(out, " "); 307b528cefcSMark Murray sec_fprintf2(out, "%*d", max_n_link, f->n_link); 308b528cefcSMark Murray sec_fprintf2(out, " "); 309b528cefcSMark Murray sec_fprintf2(out, "%-*s", max_user, f->user); 310b528cefcSMark Murray sec_fprintf2(out, " "); 311b528cefcSMark Murray sec_fprintf2(out, "%-*s", max_group, f->group); 312b528cefcSMark Murray sec_fprintf2(out, " "); 313b528cefcSMark Murray if(f->major != NULL && f->minor != NULL) 314b528cefcSMark Murray sec_fprintf2(out, "%*s, %*s", max_major, f->major, max_minor, f->minor); 315b528cefcSMark Murray else 316b528cefcSMark Murray sec_fprintf2(out, "%*s", max_size, f->size); 317b528cefcSMark Murray sec_fprintf2(out, " "); 318b528cefcSMark Murray sec_fprintf2(out, "%*s", max_date, f->date); 319b528cefcSMark Murray sec_fprintf2(out, " "); 320b528cefcSMark Murray sec_fprintf2(out, "%s", f->filename); 321b528cefcSMark Murray if(f->link) 322b528cefcSMark Murray sec_fprintf2(out, " -> %s", f->link); 323b528cefcSMark Murray sec_fprintf2(out, "\r\n"); 324b528cefcSMark Murray } 325b528cefcSMark Murray 326b528cefcSMark Murray static int 327b528cefcSMark Murray compare_filename(struct fileinfo *a, struct fileinfo *b) 328b528cefcSMark Murray { 329b528cefcSMark Murray if(a->filename == NULL) 330b528cefcSMark Murray return 1; 331b528cefcSMark Murray if(b->filename == NULL) 332b528cefcSMark Murray return -1; 333b528cefcSMark Murray return strcmp(a->filename, b->filename); 334b528cefcSMark Murray } 335b528cefcSMark Murray 336b528cefcSMark Murray static int 337b528cefcSMark Murray compare_mtime(struct fileinfo *a, struct fileinfo *b) 338b528cefcSMark Murray { 339b528cefcSMark Murray if(a->filename == NULL) 340b528cefcSMark Murray return 1; 341b528cefcSMark Murray if(b->filename == NULL) 342b528cefcSMark Murray return -1; 3435e9cd1aeSAssar Westerlund return b->st.st_mtime - a->st.st_mtime; 344b528cefcSMark Murray } 345b528cefcSMark Murray 346b528cefcSMark Murray static int 347b528cefcSMark Murray compare_size(struct fileinfo *a, struct fileinfo *b) 348b528cefcSMark Murray { 349b528cefcSMark Murray if(a->filename == NULL) 350b528cefcSMark Murray return 1; 351b528cefcSMark Murray if(b->filename == NULL) 352b528cefcSMark Murray return -1; 3535e9cd1aeSAssar Westerlund return b->st.st_size - a->st.st_size; 354b528cefcSMark Murray } 355b528cefcSMark Murray 3568373020dSJacques Vidrine static int list_dir(FILE*, const char*, int); 357b528cefcSMark Murray 358b528cefcSMark Murray static int 359b528cefcSMark Murray log10(int num) 360b528cefcSMark Murray { 361b528cefcSMark Murray int i = 1; 362b528cefcSMark Murray while(num > 10) { 363b528cefcSMark Murray i++; 364b528cefcSMark Murray num /= 10; 365b528cefcSMark Murray } 366b528cefcSMark Murray return i; 367b528cefcSMark Murray } 368b528cefcSMark Murray 369b528cefcSMark Murray /* 370b528cefcSMark Murray * Operate as lstat but fake up entries for AFS mount points so we don't 371b528cefcSMark Murray * have to fetch them. 372b528cefcSMark Murray */ 373b528cefcSMark Murray 3745e9cd1aeSAssar Westerlund #ifdef KRB4 3755e9cd1aeSAssar Westerlund static int do_the_afs_dance = 1; 3765e9cd1aeSAssar Westerlund #endif 3775e9cd1aeSAssar Westerlund 378b528cefcSMark Murray static int 379b528cefcSMark Murray lstat_file (const char *file, struct stat *sb) 380b528cefcSMark Murray { 381b528cefcSMark Murray #ifdef KRB4 3825e9cd1aeSAssar Westerlund if (do_the_afs_dance && 3835e9cd1aeSAssar Westerlund k_hasafs() 384b528cefcSMark Murray && strcmp(file, ".") 3855e9cd1aeSAssar Westerlund && strcmp(file, "..") 3865e9cd1aeSAssar Westerlund && strcmp(file, "/")) 387b528cefcSMark Murray { 388b528cefcSMark Murray struct ViceIoctl a_params; 3895e9cd1aeSAssar Westerlund char *dir, *last; 390b528cefcSMark Murray char *path_bkp; 391b528cefcSMark Murray static ino_t ino_counter = 0, ino_last = 0; 392b528cefcSMark Murray int ret; 393b528cefcSMark Murray const int maxsize = 2048; 394b528cefcSMark Murray 395b528cefcSMark Murray path_bkp = strdup (file); 396b528cefcSMark Murray if (path_bkp == NULL) 397b528cefcSMark Murray return -1; 398b528cefcSMark Murray 399b528cefcSMark Murray a_params.out = malloc (maxsize); 400b528cefcSMark Murray if (a_params.out == NULL) { 401b528cefcSMark Murray free (path_bkp); 402b528cefcSMark Murray return -1; 403b528cefcSMark Murray } 404b528cefcSMark Murray 405b528cefcSMark Murray /* If path contains more than the filename alone - split it */ 406b528cefcSMark Murray 407b528cefcSMark Murray last = strrchr (path_bkp, '/'); 408b528cefcSMark Murray if (last != NULL) { 4095e9cd1aeSAssar Westerlund if(last[1] == '\0') 4105e9cd1aeSAssar Westerlund /* if path ended in /, replace with `.' */ 4115e9cd1aeSAssar Westerlund a_params.in = "."; 4125e9cd1aeSAssar Westerlund else 413b528cefcSMark Murray a_params.in = last + 1; 4145e9cd1aeSAssar Westerlund while(last > path_bkp && *--last == '/'); 4155e9cd1aeSAssar Westerlund if(*last != '/' || last != path_bkp) { 4165e9cd1aeSAssar Westerlund *++last = '\0'; 4175e9cd1aeSAssar Westerlund dir = path_bkp; 418b528cefcSMark Murray } else 4195e9cd1aeSAssar Westerlund /* we got to the start, so this must be the root dir */ 4205e9cd1aeSAssar Westerlund dir = "/"; 4215e9cd1aeSAssar Westerlund } else { 4225e9cd1aeSAssar Westerlund /* file is relative to cdir */ 4235e9cd1aeSAssar Westerlund dir = "."; 4245e9cd1aeSAssar Westerlund a_params.in = path_bkp; 4255e9cd1aeSAssar Westerlund } 426b528cefcSMark Murray 427b528cefcSMark Murray a_params.in_size = strlen (a_params.in) + 1; 428b528cefcSMark Murray a_params.out_size = maxsize; 429b528cefcSMark Murray 4305e9cd1aeSAssar Westerlund ret = k_pioctl (dir, VIOC_AFS_STAT_MT_PT, &a_params, 0); 431b528cefcSMark Murray free (a_params.out); 432b528cefcSMark Murray if (ret < 0) { 433b528cefcSMark Murray free (path_bkp); 434b528cefcSMark Murray 435b528cefcSMark Murray if (errno != EINVAL) 436b528cefcSMark Murray return ret; 437b528cefcSMark Murray else 438b528cefcSMark Murray /* if we get EINVAL this is probably not a mountpoint */ 439b528cefcSMark Murray return lstat (file, sb); 440b528cefcSMark Murray } 441b528cefcSMark Murray 442b528cefcSMark Murray /* 443b528cefcSMark Murray * wow this was a mountpoint, lets cook the struct stat 444b528cefcSMark Murray * use . as a prototype 445b528cefcSMark Murray */ 446b528cefcSMark Murray 4475e9cd1aeSAssar Westerlund ret = lstat (dir, sb); 448b528cefcSMark Murray free (path_bkp); 449b528cefcSMark Murray if (ret < 0) 450b528cefcSMark Murray return ret; 451b528cefcSMark Murray 452b528cefcSMark Murray if (ino_last == sb->st_ino) 453b528cefcSMark Murray ino_counter++; 454b528cefcSMark Murray else { 455b528cefcSMark Murray ino_last = sb->st_ino; 456b528cefcSMark Murray ino_counter = 0; 457b528cefcSMark Murray } 458b528cefcSMark Murray sb->st_ino += ino_counter; 459b528cefcSMark Murray sb->st_nlink = 3; 460b528cefcSMark Murray 461b528cefcSMark Murray return 0; 462b528cefcSMark Murray } 463b528cefcSMark Murray #endif /* KRB4 */ 464b528cefcSMark Murray return lstat (file, sb); 465b528cefcSMark Murray } 466b528cefcSMark Murray 4674137ff4cSJacques Vidrine #define IS_DOT_DOTDOT(X) ((X)[0] == '.' && ((X)[1] == '\0' || \ 4684137ff4cSJacques Vidrine ((X)[1] == '.' && (X)[2] == '\0'))) 4694137ff4cSJacques Vidrine 4708373020dSJacques Vidrine static int 471b528cefcSMark Murray list_files(FILE *out, const char **files, int n_files, int flags) 472b528cefcSMark Murray { 473b528cefcSMark Murray struct fileinfo *fi; 474b528cefcSMark Murray int i; 4754137ff4cSJacques Vidrine int *dirs = NULL; 4764137ff4cSJacques Vidrine size_t total_blocks = 0; 4774137ff4cSJacques Vidrine int n_print = 0; 4788373020dSJacques Vidrine int ret = 0; 4798373020dSJacques Vidrine 4808373020dSJacques Vidrine if(n_files == 0) 4818373020dSJacques Vidrine return 0; 4824137ff4cSJacques Vidrine 4834137ff4cSJacques Vidrine if(n_files > 1) 4844137ff4cSJacques Vidrine flags |= LS_SHOW_DIRNAME; 485b528cefcSMark Murray 486b528cefcSMark Murray fi = calloc(n_files, sizeof(*fi)); 487b528cefcSMark Murray if (fi == NULL) { 4888373020dSJacques Vidrine syslog(LOG_ERR, "out of memory"); 4898373020dSJacques Vidrine return -1; 490b528cefcSMark Murray } 491b528cefcSMark Murray for(i = 0; i < n_files; i++) { 492b528cefcSMark Murray if(lstat_file(files[i], &fi[i].st) < 0) { 493b528cefcSMark Murray sec_fprintf2(out, "%s: %s\r\n", files[i], strerror(errno)); 494b528cefcSMark Murray fi[i].filename = NULL; 495b528cefcSMark Murray } else { 4964137ff4cSJacques Vidrine int include_in_list = 1; 4974137ff4cSJacques Vidrine total_blocks += block_convert(fi[i].st.st_blocks); 4984137ff4cSJacques Vidrine if(S_ISDIR(fi[i].st.st_mode)) { 4994137ff4cSJacques Vidrine if(dirs == NULL) 5004137ff4cSJacques Vidrine dirs = calloc(n_files, sizeof(*dirs)); 5014137ff4cSJacques Vidrine if(dirs == NULL) { 5028373020dSJacques Vidrine syslog(LOG_ERR, "%s: %m", files[i]); 5038373020dSJacques Vidrine ret = -1; 5044137ff4cSJacques Vidrine goto out; 5054137ff4cSJacques Vidrine } 5064137ff4cSJacques Vidrine dirs[i] = 1; 5074137ff4cSJacques Vidrine if((flags & LS_DIRS) == 0) 5084137ff4cSJacques Vidrine include_in_list = 0; 5094137ff4cSJacques Vidrine } 5104137ff4cSJacques Vidrine if(include_in_list) { 5114137ff4cSJacques Vidrine make_fileinfo(out, files[i], &fi[i], flags); 5124137ff4cSJacques Vidrine n_print++; 513b528cefcSMark Murray } 514b528cefcSMark Murray } 515b528cefcSMark Murray } 516b528cefcSMark Murray switch(SORT_MODE(flags)) { 517b528cefcSMark Murray case LS_SORT_NAME: 518b528cefcSMark Murray qsort(fi, n_files, sizeof(*fi), 519b528cefcSMark Murray (int (*)(const void*, const void*))compare_filename); 520b528cefcSMark Murray break; 521b528cefcSMark Murray case LS_SORT_MTIME: 522b528cefcSMark Murray qsort(fi, n_files, sizeof(*fi), 523b528cefcSMark Murray (int (*)(const void*, const void*))compare_mtime); 524b528cefcSMark Murray break; 525b528cefcSMark Murray case LS_SORT_SIZE: 526b528cefcSMark Murray qsort(fi, n_files, sizeof(*fi), 527b528cefcSMark Murray (int (*)(const void*, const void*))compare_size); 528b528cefcSMark Murray break; 529b528cefcSMark Murray } 5305e9cd1aeSAssar Westerlund if(DISP_MODE(flags) == LS_DISP_LONG) { 531b528cefcSMark Murray int max_inode = 0; 532b528cefcSMark Murray int max_bsize = 0; 533b528cefcSMark Murray int max_n_link = 0; 534b528cefcSMark Murray int max_user = 0; 535b528cefcSMark Murray int max_group = 0; 536b528cefcSMark Murray int max_size = 0; 537b528cefcSMark Murray int max_major = 0; 538b528cefcSMark Murray int max_minor = 0; 539b528cefcSMark Murray int max_date = 0; 540b528cefcSMark Murray for(i = 0; i < n_files; i++) { 541b528cefcSMark Murray if(fi[i].filename == NULL) 542b528cefcSMark Murray continue; 543b528cefcSMark Murray if(fi[i].inode > max_inode) 544b528cefcSMark Murray max_inode = fi[i].inode; 545b528cefcSMark Murray if(fi[i].bsize > max_bsize) 546b528cefcSMark Murray max_bsize = fi[i].bsize; 547b528cefcSMark Murray if(fi[i].n_link > max_n_link) 548b528cefcSMark Murray max_n_link = fi[i].n_link; 549b528cefcSMark Murray if(strlen(fi[i].user) > max_user) 550b528cefcSMark Murray max_user = strlen(fi[i].user); 551b528cefcSMark Murray if(strlen(fi[i].group) > max_group) 552b528cefcSMark Murray max_group = strlen(fi[i].group); 553b528cefcSMark Murray if(fi[i].major != NULL && strlen(fi[i].major) > max_major) 554b528cefcSMark Murray max_major = strlen(fi[i].major); 555b528cefcSMark Murray if(fi[i].minor != NULL && strlen(fi[i].minor) > max_minor) 556b528cefcSMark Murray max_minor = strlen(fi[i].minor); 557b528cefcSMark Murray if(fi[i].size != NULL && strlen(fi[i].size) > max_size) 558b528cefcSMark Murray max_size = strlen(fi[i].size); 559b528cefcSMark Murray if(strlen(fi[i].date) > max_date) 560b528cefcSMark Murray max_date = strlen(fi[i].date); 561b528cefcSMark Murray } 562b528cefcSMark Murray if(max_size < max_major + max_minor + 2) 563b528cefcSMark Murray max_size = max_major + max_minor + 2; 564b528cefcSMark Murray else if(max_size - max_minor - 2 > max_major) 565b528cefcSMark Murray max_major = max_size - max_minor - 2; 566b528cefcSMark Murray max_inode = log10(max_inode); 567b528cefcSMark Murray max_bsize = log10(max_bsize); 568b528cefcSMark Murray max_n_link = log10(max_n_link); 569b528cefcSMark Murray 5704137ff4cSJacques Vidrine if(n_print > 0) 5714137ff4cSJacques Vidrine sec_fprintf2(out, "total %lu\r\n", (unsigned long)total_blocks); 572b528cefcSMark Murray if(flags & LS_SORT_REVERSE) 573b528cefcSMark Murray for(i = n_files - 1; i >= 0; i--) 574b528cefcSMark Murray print_file(out, 575b528cefcSMark Murray flags, 576b528cefcSMark Murray &fi[i], 577b528cefcSMark Murray max_inode, 578b528cefcSMark Murray max_bsize, 579b528cefcSMark Murray max_n_link, 580b528cefcSMark Murray max_user, 581b528cefcSMark Murray max_group, 582b528cefcSMark Murray max_size, 583b528cefcSMark Murray max_major, 584b528cefcSMark Murray max_minor, 585b528cefcSMark Murray max_date); 586b528cefcSMark Murray else 587b528cefcSMark Murray for(i = 0; i < n_files; i++) 588b528cefcSMark Murray print_file(out, 589b528cefcSMark Murray flags, 590b528cefcSMark Murray &fi[i], 591b528cefcSMark Murray max_inode, 592b528cefcSMark Murray max_bsize, 593b528cefcSMark Murray max_n_link, 594b528cefcSMark Murray max_user, 595b528cefcSMark Murray max_group, 596b528cefcSMark Murray max_size, 597b528cefcSMark Murray max_major, 598b528cefcSMark Murray max_minor, 599b528cefcSMark Murray max_date); 6005e9cd1aeSAssar Westerlund } else if(DISP_MODE(flags) == LS_DISP_COLUMN || 6015e9cd1aeSAssar Westerlund DISP_MODE(flags) == LS_DISP_CROSS) { 6025e9cd1aeSAssar Westerlund int max_len = 0; 6034137ff4cSJacques Vidrine int size_len = 0; 6045e9cd1aeSAssar Westerlund int num_files = n_files; 6055e9cd1aeSAssar Westerlund int columns; 6065e9cd1aeSAssar Westerlund int j; 6075e9cd1aeSAssar Westerlund for(i = 0; i < n_files; i++) { 6085e9cd1aeSAssar Westerlund if(fi[i].filename == NULL) { 6095e9cd1aeSAssar Westerlund num_files--; 6105e9cd1aeSAssar Westerlund continue; 6115e9cd1aeSAssar Westerlund } 6125e9cd1aeSAssar Westerlund if(strlen(fi[i].filename) > max_len) 6135e9cd1aeSAssar Westerlund max_len = strlen(fi[i].filename); 6144137ff4cSJacques Vidrine if(log10(fi[i].bsize) > size_len) 6154137ff4cSJacques Vidrine size_len = log10(fi[i].bsize); 6165e9cd1aeSAssar Westerlund } 6174137ff4cSJacques Vidrine if(num_files == 0) 6184137ff4cSJacques Vidrine goto next; 6194137ff4cSJacques Vidrine if(flags & LS_SIZE) { 6204137ff4cSJacques Vidrine columns = 80 / (size_len + 1 + max_len + 1); 6214137ff4cSJacques Vidrine max_len = 80 / columns - size_len - 1; 6224137ff4cSJacques Vidrine } else { 6235e9cd1aeSAssar Westerlund columns = 80 / (max_len + 1); /* get space between columns */ 6245e9cd1aeSAssar Westerlund max_len = 80 / columns; 6254137ff4cSJacques Vidrine } 6264137ff4cSJacques Vidrine if(flags & LS_SIZE) 6274137ff4cSJacques Vidrine sec_fprintf2(out, "total %lu\r\n", 6284137ff4cSJacques Vidrine (unsigned long)total_blocks); 6295e9cd1aeSAssar Westerlund if(DISP_MODE(flags) == LS_DISP_CROSS) { 6305e9cd1aeSAssar Westerlund for(i = 0, j = 0; i < n_files; i++) { 6315e9cd1aeSAssar Westerlund if(fi[i].filename == NULL) 6325e9cd1aeSAssar Westerlund continue; 6334137ff4cSJacques Vidrine if(flags & LS_SIZE) 6344137ff4cSJacques Vidrine sec_fprintf2(out, "%*u %-*s", size_len, fi[i].bsize, 6354137ff4cSJacques Vidrine max_len, fi[i].filename); 6364137ff4cSJacques Vidrine else 6375e9cd1aeSAssar Westerlund sec_fprintf2(out, "%-*s", max_len, fi[i].filename); 6385e9cd1aeSAssar Westerlund j++; 6395e9cd1aeSAssar Westerlund if(j == columns) { 6405e9cd1aeSAssar Westerlund sec_fprintf2(out, "\r\n"); 6415e9cd1aeSAssar Westerlund j = 0; 6425e9cd1aeSAssar Westerlund } 6435e9cd1aeSAssar Westerlund } 6445e9cd1aeSAssar Westerlund if(j > 0) 6455e9cd1aeSAssar Westerlund sec_fprintf2(out, "\r\n"); 6465e9cd1aeSAssar Westerlund } else { 6475e9cd1aeSAssar Westerlund int skip = (num_files + columns - 1) / columns; 6485e9cd1aeSAssar Westerlund j = 0; 6495e9cd1aeSAssar Westerlund for(i = 0; i < skip; i++) { 6505e9cd1aeSAssar Westerlund for(j = i; j < n_files;) { 6515e9cd1aeSAssar Westerlund while(j < n_files && fi[j].filename == NULL) 6525e9cd1aeSAssar Westerlund j++; 6534137ff4cSJacques Vidrine if(flags & LS_SIZE) 6544137ff4cSJacques Vidrine sec_fprintf2(out, "%*u %-*s", size_len, fi[j].bsize, 6554137ff4cSJacques Vidrine max_len, fi[j].filename); 6564137ff4cSJacques Vidrine else 6575e9cd1aeSAssar Westerlund sec_fprintf2(out, "%-*s", max_len, fi[j].filename); 6585e9cd1aeSAssar Westerlund j += skip; 6595e9cd1aeSAssar Westerlund } 6605e9cd1aeSAssar Westerlund sec_fprintf2(out, "\r\n"); 6615e9cd1aeSAssar Westerlund } 6625e9cd1aeSAssar Westerlund } 6635e9cd1aeSAssar Westerlund } else { 6645e9cd1aeSAssar Westerlund for(i = 0; i < n_files; i++) { 6655e9cd1aeSAssar Westerlund if(fi[i].filename == NULL) 6665e9cd1aeSAssar Westerlund continue; 6675e9cd1aeSAssar Westerlund sec_fprintf2(out, "%s\r\n", fi[i].filename); 6685e9cd1aeSAssar Westerlund } 6695e9cd1aeSAssar Westerlund } 6704137ff4cSJacques Vidrine next: 6714137ff4cSJacques Vidrine if(((flags & LS_DIRS) == 0 || (flags & LS_RECURSIVE)) && dirs != NULL) { 6724137ff4cSJacques Vidrine for(i = 0; i < n_files; i++) { 6734137ff4cSJacques Vidrine if(dirs[i]) { 6744137ff4cSJacques Vidrine const char *p = strrchr(files[i], '/'); 6754137ff4cSJacques Vidrine if(p == NULL) 6764137ff4cSJacques Vidrine p = files[i]; 6774137ff4cSJacques Vidrine else 6784137ff4cSJacques Vidrine p++; 6794137ff4cSJacques Vidrine if(!(flags & LS_DIR_FLAG) || !IS_DOT_DOTDOT(p)) { 6804137ff4cSJacques Vidrine if((flags & LS_SHOW_DIRNAME)) { 6814137ff4cSJacques Vidrine if ((flags & LS_EXTRA_BLANK)) 6824137ff4cSJacques Vidrine sec_fprintf2(out, "\r\n"); 6834137ff4cSJacques Vidrine sec_fprintf2(out, "%s:\r\n", files[i]); 6844137ff4cSJacques Vidrine } 6854137ff4cSJacques Vidrine list_dir(out, files[i], flags | LS_DIRS | LS_EXTRA_BLANK); 6864137ff4cSJacques Vidrine } 6874137ff4cSJacques Vidrine } 6884137ff4cSJacques Vidrine } 6894137ff4cSJacques Vidrine } 6904137ff4cSJacques Vidrine out: 691b528cefcSMark Murray for(i = 0; i < n_files; i++) 692b528cefcSMark Murray free_fileinfo(&fi[i]); 693b528cefcSMark Murray free(fi); 6944137ff4cSJacques Vidrine if(dirs != NULL) 6954137ff4cSJacques Vidrine free(dirs); 6968373020dSJacques Vidrine return ret; 697b528cefcSMark Murray } 698b528cefcSMark Murray 699b528cefcSMark Murray static void 700b528cefcSMark Murray free_files (char **files, int n) 701b528cefcSMark Murray { 702b528cefcSMark Murray int i; 703b528cefcSMark Murray 704b528cefcSMark Murray for (i = 0; i < n; ++i) 705b528cefcSMark Murray free (files[i]); 706b528cefcSMark Murray free (files); 707b528cefcSMark Murray } 708b528cefcSMark Murray 7094137ff4cSJacques Vidrine static int 7104137ff4cSJacques Vidrine hide_file(const char *filename, int flags) 7114137ff4cSJacques Vidrine { 7124137ff4cSJacques Vidrine if(filename[0] != '.') 7134137ff4cSJacques Vidrine return 0; 7144137ff4cSJacques Vidrine if((flags & LS_IGNORE_DOT)) 7154137ff4cSJacques Vidrine return 1; 7164137ff4cSJacques Vidrine if(filename[1] == '\0' || (filename[1] == '.' && filename[2] == '\0')) { 7174137ff4cSJacques Vidrine if((flags & LS_SHOW_ALL)) 7184137ff4cSJacques Vidrine return 0; 7194137ff4cSJacques Vidrine else 7204137ff4cSJacques Vidrine return 1; 7214137ff4cSJacques Vidrine } 7224137ff4cSJacques Vidrine return 0; 7234137ff4cSJacques Vidrine } 7244137ff4cSJacques Vidrine 7258373020dSJacques Vidrine static int 726b528cefcSMark Murray list_dir(FILE *out, const char *directory, int flags) 727b528cefcSMark Murray { 728b528cefcSMark Murray DIR *d = opendir(directory); 729b528cefcSMark Murray struct dirent *ent; 730b528cefcSMark Murray char **files = NULL; 731b528cefcSMark Murray int n_files = 0; 732b528cefcSMark Murray 733b528cefcSMark Murray if(d == NULL) { 7348373020dSJacques Vidrine syslog(LOG_ERR, "%s: %m", directory); 7358373020dSJacques Vidrine return -1; 736b528cefcSMark Murray } 737b528cefcSMark Murray while((ent = readdir(d)) != NULL) { 738b528cefcSMark Murray void *tmp; 739b528cefcSMark Murray 7404137ff4cSJacques Vidrine if(hide_file(ent->d_name, flags)) 741b528cefcSMark Murray continue; 742b528cefcSMark Murray tmp = realloc(files, (n_files + 1) * sizeof(*files)); 743b528cefcSMark Murray if (tmp == NULL) { 7448373020dSJacques Vidrine syslog(LOG_ERR, "%s: out of memory", directory); 745b528cefcSMark Murray free_files (files, n_files); 746b528cefcSMark Murray closedir (d); 7478373020dSJacques Vidrine return -1; 748b528cefcSMark Murray } 749b528cefcSMark Murray files = tmp; 750b528cefcSMark Murray asprintf(&files[n_files], "%s/%s", directory, ent->d_name); 751b528cefcSMark Murray if (files[n_files] == NULL) { 7528373020dSJacques Vidrine syslog(LOG_ERR, "%s: out of memory", directory); 753b528cefcSMark Murray free_files (files, n_files); 754b528cefcSMark Murray closedir (d); 7558373020dSJacques Vidrine return -1; 756b528cefcSMark Murray } 757b528cefcSMark Murray ++n_files; 758b528cefcSMark Murray } 759b528cefcSMark Murray closedir(d); 7608373020dSJacques Vidrine return list_files(out, (const char**)files, n_files, flags | LS_DIR_FLAG); 761b528cefcSMark Murray } 762b528cefcSMark Murray 7634137ff4cSJacques Vidrine static int 7644137ff4cSJacques Vidrine parse_flags(const char *options) 765b528cefcSMark Murray { 7664137ff4cSJacques Vidrine #ifdef TEST 7674137ff4cSJacques Vidrine int flags = LS_SORT_NAME | LS_IGNORE_DOT | LS_DISP_COLUMN; 7684137ff4cSJacques Vidrine #else 7695e9cd1aeSAssar Westerlund int flags = LS_SORT_NAME | LS_IGNORE_DOT | LS_DISP_LONG; 7704137ff4cSJacques Vidrine #endif 771b528cefcSMark Murray 772b528cefcSMark Murray const char *p; 7734137ff4cSJacques Vidrine if(options == NULL || *options != '-') 7744137ff4cSJacques Vidrine return flags; 7754137ff4cSJacques Vidrine for(p = options + 1; *p; p++) { 776b528cefcSMark Murray switch(*p) { 7775e9cd1aeSAssar Westerlund case '1': 7785e9cd1aeSAssar Westerlund flags = (flags & ~LS_DISP_MODE); 7795e9cd1aeSAssar Westerlund break; 780b528cefcSMark Murray case 'a': 7814137ff4cSJacques Vidrine flags |= LS_SHOW_ALL; 7824137ff4cSJacques Vidrine /*FALLTHROUGH*/ 783b528cefcSMark Murray case 'A': 784b528cefcSMark Murray flags &= ~LS_IGNORE_DOT; 785b528cefcSMark Murray break; 786b528cefcSMark Murray case 'C': 7875e9cd1aeSAssar Westerlund flags = (flags & ~LS_DISP_MODE) | LS_DISP_COLUMN; 788b528cefcSMark Murray break; 789b528cefcSMark Murray case 'd': 790b528cefcSMark Murray flags |= LS_DIRS; 791b528cefcSMark Murray break; 792b528cefcSMark Murray case 'f': 793b528cefcSMark Murray flags = (flags & ~LS_SORT_MODE); 794b528cefcSMark Murray break; 7955e9cd1aeSAssar Westerlund case 'F': 7965e9cd1aeSAssar Westerlund flags |= LS_TYPE; 7975e9cd1aeSAssar Westerlund break; 798b528cefcSMark Murray case 'i': 7995e9cd1aeSAssar Westerlund flags |= LS_INODE; 800b528cefcSMark Murray break; 801b528cefcSMark Murray case 'l': 8025e9cd1aeSAssar Westerlund flags = (flags & ~LS_DISP_MODE) | LS_DISP_LONG; 803b528cefcSMark Murray break; 8044137ff4cSJacques Vidrine case 'r': 8054137ff4cSJacques Vidrine flags |= LS_SORT_REVERSE; 8064137ff4cSJacques Vidrine break; 8074137ff4cSJacques Vidrine case 'R': 8084137ff4cSJacques Vidrine flags |= LS_RECURSIVE; 809b528cefcSMark Murray break; 810b528cefcSMark Murray case 's': 811b528cefcSMark Murray flags |= LS_SIZE; 812b528cefcSMark Murray break; 813b528cefcSMark Murray case 'S': 814b528cefcSMark Murray flags = (flags & ~LS_SORT_MODE) | LS_SORT_SIZE; 815b528cefcSMark Murray break; 8164137ff4cSJacques Vidrine case 't': 8174137ff4cSJacques Vidrine flags = (flags & ~LS_SORT_MODE) | LS_SORT_MTIME; 818b528cefcSMark Murray break; 8195e9cd1aeSAssar Westerlund case 'x': 8205e9cd1aeSAssar Westerlund flags = (flags & ~LS_DISP_MODE) | LS_DISP_CROSS; 8215e9cd1aeSAssar Westerlund break; 8224137ff4cSJacques Vidrine /* these are a bunch of unimplemented flags from BSD ls */ 8234137ff4cSJacques Vidrine case 'k': /* display sizes in kB */ 8244137ff4cSJacques Vidrine case 'c': /* last change time */ 8254137ff4cSJacques Vidrine case 'L': /* list symlink target */ 8264137ff4cSJacques Vidrine case 'm': /* stream output */ 8274137ff4cSJacques Vidrine case 'o': /* BSD file flags */ 8284137ff4cSJacques Vidrine case 'p': /* display / after directories */ 8294137ff4cSJacques Vidrine case 'q': /* print non-graphic characters */ 8304137ff4cSJacques Vidrine case 'u': /* use last access time */ 8314137ff4cSJacques Vidrine case 'T': /* display complete time */ 8324137ff4cSJacques Vidrine case 'W': /* include whiteouts */ 8334137ff4cSJacques Vidrine break; 834b528cefcSMark Murray } 835b528cefcSMark Murray } 8364137ff4cSJacques Vidrine return flags; 8374137ff4cSJacques Vidrine } 8384137ff4cSJacques Vidrine 8398373020dSJacques Vidrine int 8404137ff4cSJacques Vidrine builtin_ls(FILE *out, const char *file) 8414137ff4cSJacques Vidrine { 8424137ff4cSJacques Vidrine int flags; 8438373020dSJacques Vidrine int ret; 8444137ff4cSJacques Vidrine 8454137ff4cSJacques Vidrine if(*file == '-') { 8464137ff4cSJacques Vidrine flags = parse_flags(file); 847b528cefcSMark Murray file = "."; 8484137ff4cSJacques Vidrine } else 8494137ff4cSJacques Vidrine flags = parse_flags(""); 8504137ff4cSJacques Vidrine 8518373020dSJacques Vidrine ret = list_files(out, &file, 1, flags); 852b528cefcSMark Murray sec_fflush(out); 8538373020dSJacques Vidrine return ret; 854b528cefcSMark Murray } 855