diff options
author | Vincent Labrecque <vincent@cvs.openbsd.org> | 2003-05-08 21:04:18 +0000 |
---|---|---|
committer | Vincent Labrecque <vincent@cvs.openbsd.org> | 2003-05-08 21:04:18 +0000 |
commit | 06d47a94407f97c7758d872cd76157b79c5cf8a6 (patch) | |
tree | 86d312612fe0eaf6d1af26634397d03d5d8617b0 | |
parent | 92123554d19cb1b6fc10adb7a5118fc02e564f19 (diff) |
multiple readlink() calls that forgot the -1...
ok millert
-rw-r--r-- | gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.c | 2 | ||||
-rw-r--r-- | gnu/usr.sbin/mkhybrid/src/rock.c | 4 | ||||
-rw-r--r-- | gnu/usr.sbin/mkhybrid/src/tree.c | 4 | ||||
-rw-r--r-- | kerberosIV/src/appl/ftp/ftpd/ls.c | 464 | ||||
-rw-r--r-- | kerberosV/src/appl/ftp/ftpd/ls.c | 270 |
5 files changed, 560 insertions, 184 deletions
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.c index ee8da85d810..40fa3826bac 100644 --- a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.c +++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.c @@ -274,7 +274,7 @@ PRIVATE void LYListFmtParse ARGS5( *buf = '\0'; #ifdef S_IFLNK if (c != 'A' && S_ISLNK(st.st_mode) && - (len = readlink(file, tmp, sizeof(tmp))) >= 0) { + (len = readlink(file, tmp, sizeof(tmp) - 1)) >= 0) { PUTS(" -> "); tmp[len] = '\0'; PUTS(tmp); diff --git a/gnu/usr.sbin/mkhybrid/src/rock.c b/gnu/usr.sbin/mkhybrid/src/rock.c index bc7a5aef338..6eecfe5bef6 100644 --- a/gnu/usr.sbin/mkhybrid/src/rock.c +++ b/gnu/usr.sbin/mkhybrid/src/rock.c @@ -19,7 +19,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: rock.c,v 1.1 2000/10/10 20:40:21 beck Exp $"; +static char rcsid[] ="$Id: rock.c,v 1.2 2003/05/08 21:04:17 vincent Exp $"; #include <stdlib.h> @@ -338,7 +338,7 @@ int deep_opt; int lenpos, lenval, j0, j1; int nchar; unsigned char * cpnt, *cpnt1; - nchar = readlink(whole_name, (char *)symlink_buff, sizeof(symlink_buff)); + nchar = readlink(whole_name, (char *)symlink_buff, sizeof(symlink_buff)-1); symlink_buff[nchar < 0 ? 0 : nchar] = 0; nchar = strlen((char *) symlink_buff); set_733(s_entry->isorec.size, 0); diff --git a/gnu/usr.sbin/mkhybrid/src/tree.c b/gnu/usr.sbin/mkhybrid/src/tree.c index 2b302197299..db5d93f0176 100644 --- a/gnu/usr.sbin/mkhybrid/src/tree.c +++ b/gnu/usr.sbin/mkhybrid/src/tree.c @@ -20,7 +20,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: tree.c,v 1.1 2000/10/10 20:40:21 beck Exp $"; +static char rcsid[] ="$Id: tree.c,v 1.2 2003/05/08 21:04:17 vincent Exp $"; /* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ @@ -1572,7 +1572,7 @@ FDECL3(insert_file_entry,struct directory *, this_dir, case S_IFLNK: nchar = readlink(whole_path, (char *)symlink_buff, - sizeof(symlink_buff)); + sizeof(symlink_buff)-1); symlink_buff[nchar < 0 ? 0 : nchar] = 0; sprintf(buffer,"L\t%s\t%s\n", s_entry->name, symlink_buff); diff --git a/kerberosIV/src/appl/ftp/ftpd/ls.c b/kerberosIV/src/appl/ftp/ftpd/ls.c index 9bb92442b98..a43ea6ce5b2 100644 --- a/kerberosIV/src/appl/ftp/ftpd/ls.c +++ b/kerberosIV/src/appl/ftp/ftpd/ls.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Kungliga Tekniska Högskolan + * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -30,9 +30,43 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifndef TEST #include "ftpd_locl.h" -RCSID("$KTH: ls.c,v 1.13 1999/11/20 20:49:41 assar Exp $"); +RCSID("$KTH: ls.c,v 1.23 2001/09/14 11:32:52 joda Exp $"); + +#else +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include <dirent.h> +#include <sys/stat.h> +#include <unistd.h> +#include <pwd.h> +#include <grp.h> +#include <errno.h> + +#define sec_fprintf2 fprintf +#define sec_fflush fflush +static void list_files(FILE *out, const char **files, int n_files, int flags); +static int parse_flags(const char *options); + +int +main(int argc, char **argv) +{ + int i = 1; + int flags; + if(argc > 1 && argv[1][0] == '-') { + flags = parse_flags(argv[1]); + i = 2; + } else + flags = parse_flags(NULL); + + list_files(stdout, (const char **)argv + i, argc - i, flags); + return 0; +} +#endif struct fileinfo { struct stat st; @@ -50,17 +84,41 @@ struct fileinfo { char *link; }; -#define LS_DIRS 1 -#define LS_IGNORE_DOT 2 -#define LS_SORT_MODE 12 -#define SORT_MODE(f) ((f) & LS_SORT_MODE) -#define LS_SORT_NAME 4 -#define LS_SORT_MTIME 8 -#define LS_SORT_SIZE 12 -#define LS_SORT_REVERSE 16 +static void +free_fileinfo(struct fileinfo *f) +{ + free(f->user); + free(f->group); + free(f->size); + free(f->major); + free(f->minor); + free(f->date); + free(f->filename); + free(f->link); +} -#define LS_SIZE 32 -#define LS_INODE 64 +#define LS_DIRS (1 << 0) +#define LS_IGNORE_DOT (1 << 1) +#define LS_SORT_MODE (3 << 2) +#define SORT_MODE(f) ((f) & LS_SORT_MODE) +#define LS_SORT_NAME (1 << 2) +#define LS_SORT_MTIME (2 << 2) +#define LS_SORT_SIZE (3 << 2) +#define LS_SORT_REVERSE (1 << 4) + +#define LS_SIZE (1 << 5) +#define LS_INODE (1 << 6) +#define LS_TYPE (1 << 7) +#define LS_DISP_MODE (3 << 8) +#define DISP_MODE(f) ((f) & LS_DISP_MODE) +#define LS_DISP_LONG (1 << 8) +#define LS_DISP_COLUMN (2 << 8) +#define LS_DISP_CROSS (3 << 8) +#define LS_SHOW_ALL (1 << 10) +#define LS_RECURSIVE (1 << 11) +#define LS_EXTRA_BLANK (1 << 12) +#define LS_SHOW_DIRNAME (1 << 13) +#define LS_DIR_FLAG (1 << 14) /* these files come via list_dir */ #ifndef S_ISTXT #define S_ISTXT S_ISVTX @@ -74,36 +132,56 @@ struct fileinfo { #define S_ISLNK(mode) (((mode) & _S_IFMT) == S_IFLNK) #endif +static size_t +block_convert(size_t blocks) +{ +#ifdef S_BLKSIZE + return blocks * S_BLKSIZE / 1024; +#else + return blocks * 512 / 1024; +#endif +} + static void -make_fileinfo(const char *filename, struct fileinfo *file, int flags) +make_fileinfo(FILE *out, const char *filename, struct fileinfo *file, int flags) { char buf[128]; + int file_type = 0; struct stat *st = &file->st; file->inode = st->st_ino; -#ifdef S_BLKSIZE - file->bsize = st->st_blocks * S_BLKSIZE / 1024; -#else - file->bsize = st->st_blocks * 512 / 1024; -#endif + file->bsize = block_convert(st->st_blocks); - if(S_ISDIR(st->st_mode)) + if(S_ISDIR(st->st_mode)) { file->mode[0] = 'd'; + file_type = '/'; + } else if(S_ISCHR(st->st_mode)) file->mode[0] = 'c'; else if(S_ISBLK(st->st_mode)) file->mode[0] = 'b'; - else if(S_ISREG(st->st_mode)) + else if(S_ISREG(st->st_mode)) { file->mode[0] = '-'; - else if(S_ISFIFO(st->st_mode)) + if(st->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) + file_type = '*'; + } + else if(S_ISFIFO(st->st_mode)) { file->mode[0] = 'p'; - else if(S_ISLNK(st->st_mode)) + file_type = '|'; + } + else if(S_ISLNK(st->st_mode)) { file->mode[0] = 'l'; - else if(S_ISSOCK(st->st_mode)) + file_type = '@'; + } + else if(S_ISSOCK(st->st_mode)) { file->mode[0] = 's'; + file_type = '='; + } #ifdef S_ISWHT - else if(S_ISWHT(st->st_mode)) + else if(S_ISWHT(st->st_mode)) { file->mode[0] = 'w'; + file_type = '%'; + } #endif else file->mode[0] = '?'; @@ -164,9 +242,10 @@ make_fileinfo(const char *filename, struct fileinfo *file, int flags) { time_t t = time(NULL); - struct tm *tm = localtime(&st->st_mtime); - if((t - st->st_mtime > 6*30*24*60*60) || - (st->st_mtime - t > 6*30*24*60*60)) + time_t mtime = st->st_mtime; + struct tm *tm = localtime(&mtime); + if((t - mtime > 6*30*24*60*60) || + (mtime - t > 6*30*24*60*60)) strftime(buf, sizeof(buf), "%b %e %Y", tm); else strftime(buf, sizeof(buf), "%b %e %H:%M", tm); @@ -178,16 +257,19 @@ make_fileinfo(const char *filename, struct fileinfo *file, int flags) p++; else p = filename; - file->filename = strdup(p); + if((flags & LS_TYPE) && file_type != 0) + asprintf(&file->filename, "%s%c", p, file_type); + else + file->filename = strdup(p); } if(S_ISLNK(st->st_mode)) { int n; - n = readlink((char *)filename, buf, sizeof(buf)); + n = readlink((char *)filename, buf, sizeof(buf) - 1); if(n >= 0) { buf[n] = '\0'; file->link = strdup(buf); } else - warn("%s: readlink", filename); + sec_fprintf2(out, "readlink(%s): %s", filename, strerror(errno)); } } @@ -254,7 +336,7 @@ compare_mtime(struct fileinfo *a, struct fileinfo *b) return 1; if(b->filename == NULL) return -1; - return a->st.st_mtime - b->st.st_mtime; + return b->st.st_mtime - a->st.st_mtime; } static int @@ -264,7 +346,7 @@ compare_size(struct fileinfo *a, struct fileinfo *b) return 1; if(b->filename == NULL) return -1; - return a->st.st_size - b->st.st_size; + return b->st.st_size - a->st.st_size; } static void @@ -286,16 +368,22 @@ log10(int num) * have to fetch them. */ +#ifdef KRB4 +static int do_the_afs_dance = 1; +#endif + static int lstat_file (const char *file, struct stat *sb) { #ifdef KRB4 - if (k_hasafs() + if (do_the_afs_dance && + k_hasafs() && strcmp(file, ".") - && strcmp(file, "..")) + && strcmp(file, "..") + && strcmp(file, "/")) { struct ViceIoctl a_params; - char *last; + char *dir, *last; char *path_bkp; static ino_t ino_counter = 0, ino_last = 0; int ret; @@ -315,16 +403,28 @@ lstat_file (const char *file, struct stat *sb) last = strrchr (path_bkp, '/'); if (last != NULL) { - *last = '\0'; - a_params.in = last + 1; - } else - a_params.in = (char *)file; + if(last[1] == '\0') + /* if path ended in /, replace with `.' */ + a_params.in = "."; + else + a_params.in = last + 1; + while(last > path_bkp && *--last == '/'); + if(*last != '/' || last != path_bkp) { + *++last = '\0'; + dir = path_bkp; + } else + /* we got to the start, so this must be the root dir */ + dir = "/"; + } else { + /* file is relative to cdir */ + dir = "."; + a_params.in = path_bkp; + } a_params.in_size = strlen (a_params.in) + 1; a_params.out_size = maxsize; - ret = k_pioctl (last ? path_bkp : "." , - VIOC_AFS_STAT_MT_PT, &a_params, 0); + ret = k_pioctl (dir, VIOC_AFS_STAT_MT_PT, &a_params, 0); free (a_params.out); if (ret < 0) { free (path_bkp); @@ -341,7 +441,7 @@ lstat_file (const char *file, struct stat *sb) * use . as a prototype */ - ret = lstat (path_bkp, sb); + ret = lstat (dir, sb); free (path_bkp); if (ret < 0) return ret; @@ -361,11 +461,20 @@ lstat_file (const char *file, struct stat *sb) return lstat (file, sb); } +#define IS_DOT_DOTDOT(X) ((X)[0] == '.' && ((X)[1] == '\0' || \ + ((X)[1] == '.' && (X)[2] == '\0'))) + static void -list_files(FILE *out, char **files, int n_files, int flags) +list_files(FILE *out, const char **files, int n_files, int flags) { struct fileinfo *fi; int i; + int *dirs = NULL; + size_t total_blocks = 0; + int n_print = 0; + + if(n_files > 1) + flags |= LS_SHOW_DIRNAME; fi = calloc(n_files, sizeof(*fi)); if (fi == NULL) { @@ -377,12 +486,23 @@ list_files(FILE *out, char **files, int n_files, int flags) sec_fprintf2(out, "%s: %s\r\n", files[i], strerror(errno)); fi[i].filename = NULL; } else { - if((flags & LS_DIRS) == 0 && S_ISDIR(fi[i].st.st_mode)) { - if(n_files > 1) - sec_fprintf2(out, "%s:\r\n", files[i]); - list_dir(out, files[i], flags); - } else { - make_fileinfo(files[i], &fi[i], flags); + int include_in_list = 1; + total_blocks += block_convert(fi[i].st.st_blocks); + if(S_ISDIR(fi[i].st.st_mode)) { + if(dirs == NULL) + dirs = calloc(n_files, sizeof(*dirs)); + if(dirs == NULL) { + sec_fprintf2(out, "%s: %s\r\n", + files[i], strerror(errno)); + goto out; + } + dirs[i] = 1; + if((flags & LS_DIRS) == 0) + include_in_list = 0; + } + if(include_in_list) { + make_fileinfo(out, files[i], &fi[i], flags); + n_print++; } } } @@ -400,7 +520,7 @@ list_files(FILE *out, char **files, int n_files, int flags) (int (*)(const void*, const void*))compare_size); break; } - { + if(DISP_MODE(flags) == LS_DISP_LONG) { int max_inode = 0; int max_bsize = 0; int max_n_link = 0; @@ -439,7 +559,9 @@ list_files(FILE *out, char **files, int n_files, int flags) max_inode = log10(max_inode); max_bsize = log10(max_bsize); max_n_link = log10(max_n_link); - + + if(n_print > 0) + sec_fprintf2(out, "total %lu\r\n", (unsigned long)total_blocks); if(flags & LS_SORT_REVERSE) for(i = n_files - 1; i >= 0; i--) print_file(out, @@ -468,7 +590,102 @@ list_files(FILE *out, char **files, int n_files, int flags) max_major, max_minor, max_date); + } else if(DISP_MODE(flags) == LS_DISP_COLUMN || + DISP_MODE(flags) == LS_DISP_CROSS) { + int max_len = 0; + int size_len = 0; + int num_files = n_files; + int columns; + int j; + for(i = 0; i < n_files; i++) { + if(fi[i].filename == NULL) { + num_files--; + continue; + } + if(strlen(fi[i].filename) > max_len) + max_len = strlen(fi[i].filename); + if(log10(fi[i].bsize) > size_len) + size_len = log10(fi[i].bsize); + } + if(num_files == 0) + goto next; + if(flags & LS_SIZE) { + columns = 80 / (size_len + 1 + max_len + 1); + max_len = 80 / columns - size_len - 1; + } else { + columns = 80 / (max_len + 1); /* get space between columns */ + max_len = 80 / columns; + } + if(flags & LS_SIZE) + sec_fprintf2(out, "total %lu\r\n", + (unsigned long)total_blocks); + if(DISP_MODE(flags) == LS_DISP_CROSS) { + for(i = 0, j = 0; i < n_files; i++) { + if(fi[i].filename == NULL) + continue; + if(flags & LS_SIZE) + sec_fprintf2(out, "%*u %-*s", size_len, fi[i].bsize, + max_len, fi[i].filename); + else + sec_fprintf2(out, "%-*s", max_len, fi[i].filename); + j++; + if(j == columns) { + sec_fprintf2(out, "\r\n"); + j = 0; + } + } + if(j > 0) + sec_fprintf2(out, "\r\n"); + } else { + int skip = (num_files + columns - 1) / columns; + j = 0; + for(i = 0; i < skip; i++) { + for(j = i; j < n_files;) { + while(j < n_files && fi[j].filename == NULL) + j++; + if(flags & LS_SIZE) + sec_fprintf2(out, "%*u %-*s", size_len, fi[j].bsize, + max_len, fi[j].filename); + else + sec_fprintf2(out, "%-*s", max_len, fi[j].filename); + j += skip; + } + sec_fprintf2(out, "\r\n"); + } + } + } else { + for(i = 0; i < n_files; i++) { + if(fi[i].filename == NULL) + continue; + sec_fprintf2(out, "%s\r\n", fi[i].filename); + } + } + next: + if(((flags & LS_DIRS) == 0 || (flags & LS_RECURSIVE)) && dirs != NULL) { + for(i = 0; i < n_files; i++) { + if(dirs[i]) { + const char *p = strrchr(files[i], '/'); + if(p == NULL) + p = files[i]; + else + p++; + if(!(flags & LS_DIR_FLAG) || !IS_DOT_DOTDOT(p)) { + if((flags & LS_SHOW_DIRNAME)) { + if ((flags & LS_EXTRA_BLANK)) + sec_fprintf2(out, "\r\n"); + sec_fprintf2(out, "%s:\r\n", files[i]); + } + list_dir(out, files[i], flags | LS_DIRS | LS_EXTRA_BLANK); + } + } + } } + out: + for(i = 0; i < n_files; i++) + free_fileinfo(&fi[i]); + free(fi); + if(dirs != NULL) + free(dirs); } static void @@ -481,6 +698,22 @@ free_files (char **files, int n) free (files); } +static int +hide_file(const char *filename, int flags) +{ + if(filename[0] != '.') + return 0; + if((flags & LS_IGNORE_DOT)) + return 1; + if(filename[1] == '\0' || (filename[1] == '.' && filename[2] == '\0')) { + if((flags & LS_SHOW_ALL)) + return 0; + else + return 1; + } + return 0; +} + static void list_dir(FILE *out, const char *directory, int flags) { @@ -496,14 +729,8 @@ list_dir(FILE *out, const char *directory, int flags) while((ent = readdir(d)) != NULL) { void *tmp; - if(ent->d_name[0] == '.') { - if (flags & LS_IGNORE_DOT) - continue; - if (ent->d_name[1] == 0) /* Ignore . */ - continue; - if (ent->d_name[1] == '.' && ent->d_name[2] == 0) /* Ignore .. */ - continue; - } + if(hide_file(ent->d_name, flags)) + continue; tmp = realloc(files, (n_files + 1) * sizeof(*files)); if (tmp == NULL) { sec_fprintf2(out, "%s: out of memory\r\n", directory); @@ -522,51 +749,96 @@ list_dir(FILE *out, const char *directory, int flags) ++n_files; } closedir(d); - list_files(out, files, n_files, flags | LS_DIRS); + list_files(out, (const char**)files, n_files, flags | LS_DIR_FLAG); +} + +static int +parse_flags(const char *options) +{ +#ifdef TEST + int flags = LS_SORT_NAME | LS_IGNORE_DOT | LS_DISP_COLUMN; +#else + int flags = LS_SORT_NAME | LS_IGNORE_DOT | LS_DISP_LONG; +#endif + + const char *p; + if(options == NULL || *options != '-') + return flags; + for(p = options + 1; *p; p++) { + switch(*p) { + case '1': + flags = (flags & ~LS_DISP_MODE); + break; + case 'a': + flags |= LS_SHOW_ALL; + /*FALLTHROUGH*/ + case 'A': + flags &= ~LS_IGNORE_DOT; + break; + case 'C': + flags = (flags & ~LS_DISP_MODE) | LS_DISP_COLUMN; + break; + case 'd': + flags |= LS_DIRS; + break; + case 'f': + flags = (flags & ~LS_SORT_MODE); + break; + case 'F': + flags |= LS_TYPE; + break; + case 'i': + flags |= LS_INODE; + break; + case 'l': + flags = (flags & ~LS_DISP_MODE) | LS_DISP_LONG; + break; + case 'r': + flags |= LS_SORT_REVERSE; + break; + case 'R': + flags |= LS_RECURSIVE; + break; + case 's': + flags |= LS_SIZE; + break; + case 'S': + flags = (flags & ~LS_SORT_MODE) | LS_SORT_SIZE; + break; + case 't': + flags = (flags & ~LS_SORT_MODE) | LS_SORT_MTIME; + break; + case 'x': + flags = (flags & ~LS_DISP_MODE) | LS_DISP_CROSS; + break; + /* these are a bunch of unimplemented flags from BSD ls */ + case 'k': /* display sizes in kB */ + case 'c': /* last change time */ + case 'L': /* list symlink target */ + case 'm': /* stream output */ + case 'o': /* BSD file flags */ + case 'p': /* display / after directories */ + case 'q': /* print non-graphic characters */ + case 'u': /* use last access time */ + case 'T': /* display complete time */ + case 'W': /* include whiteouts */ + break; + } + } + return flags; } void builtin_ls(FILE *out, const char *file) { - int flags = LS_SORT_NAME; + int flags; if(*file == '-') { - const char *p; - for(p = file + 1; *p; p++) { - switch(*p) { - case 'a': - case 'A': - flags &= ~LS_IGNORE_DOT; - break; - case 'C': - break; - case 'd': - flags |= LS_DIRS; - break; - case 'f': - flags = (flags & ~LS_SORT_MODE); - break; - case 'i': - flags |= flags | LS_INODE; - break; - case 'l': - break; - case 't': - flags = (flags & ~LS_SORT_MODE) | LS_SORT_MTIME; - break; - case 's': - flags |= LS_SIZE; - break; - case 'S': - flags = (flags & ~LS_SORT_MODE) | LS_SORT_SIZE; - break; - case 'r': - flags |= LS_SORT_REVERSE; - break; - } - } + flags = parse_flags(file); file = "."; - } + } else + flags = parse_flags(""); + list_files(out, &file, 1, flags); sec_fflush(out); } diff --git a/kerberosV/src/appl/ftp/ftpd/ls.c b/kerberosV/src/appl/ftp/ftpd/ls.c index 0c3e9a5c2b5..fff33b4c8a6 100644 --- a/kerberosV/src/appl/ftp/ftpd/ls.c +++ b/kerberosV/src/appl/ftp/ftpd/ls.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan + * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #ifndef TEST #include "ftpd_locl.h" -RCSID("$KTH: ls.c,v 1.20 2001/01/25 01:33:15 joda Exp $"); +RCSID("$KTH: ls.c,v 1.22 2001/08/26 10:02:24 joda Exp $"); #else #include <stdio.h> @@ -49,14 +49,21 @@ RCSID("$KTH: ls.c,v 1.20 2001/01/25 01:33:15 joda Exp $"); #define sec_fprintf2 fprintf #define sec_fflush fflush -void -builtin_ls(FILE *out, const char *file); +static void list_files(FILE *out, const char **files, int n_files, int flags); +static int parse_flags(const char *options); + int main(int argc, char **argv) { - int i; - for(i = 1; i < argc; i++) - builtin_ls(stdout, argv[i]); + int i = 1; + int flags; + if(argc > 1 && argv[1][0] == '-') { + flags = parse_flags(argv[1]); + i = 2; + } else + flags = parse_flags(NULL); + + list_files(stdout, (const char **)argv + i, argc - i, flags); return 0; } #endif @@ -107,6 +114,10 @@ free_fileinfo(struct fileinfo *f) #define LS_DISP_LONG (1 << 8) #define LS_DISP_COLUMN (2 << 8) #define LS_DISP_CROSS (3 << 8) +#define LS_SHOW_ALL (1 << 10) +#define LS_RECURSIVE (1 << 11) +#define LS_EXTRA_BLANK (1 << 12) +#define LS_SHOW_DIRNAME (1 << 13) #ifndef S_ISTXT #define S_ISTXT S_ISVTX @@ -120,19 +131,25 @@ free_fileinfo(struct fileinfo *f) #define S_ISLNK(mode) (((mode) & _S_IFMT) == S_IFLNK) #endif +static size_t +block_convert(size_t blocks) +{ +#ifdef S_BLKSIZE + return blocks * S_BLKSIZE / 1024; +#else + return blocks * 512 / 1024; +#endif +} + static void -make_fileinfo(const char *filename, struct fileinfo *file, int flags) +make_fileinfo(FILE *out, const char *filename, struct fileinfo *file, int flags) { char buf[128]; int file_type = 0; struct stat *st = &file->st; file->inode = st->st_ino; -#ifdef S_BLKSIZE - file->bsize = st->st_blocks * S_BLKSIZE / 1024; -#else - file->bsize = st->st_blocks * 512 / 1024; -#endif + file->bsize = block_convert(st->st_blocks); if(S_ISDIR(st->st_mode)) { file->mode[0] = 'd'; @@ -246,12 +263,12 @@ make_fileinfo(const char *filename, struct fileinfo *file, int flags) } if(S_ISLNK(st->st_mode)) { int n; - n = readlink((char *)filename, buf, sizeof(buf)); + n = readlink((char *)filename, buf, sizeof(buf) - 1); if(n >= 0) { buf[n] = '\0'; file->link = strdup(buf); } else - warn("%s: readlink", filename); + sec_fprintf2(out, "readlink(%s): %s", filename, strerror(errno)); } } @@ -448,6 +465,12 @@ list_files(FILE *out, const char **files, int n_files, int flags) { struct fileinfo *fi; int i; + int *dirs = NULL; + size_t total_blocks = 0; + int n_print = 0; + + if(n_files > 1) + flags |= LS_SHOW_DIRNAME; fi = calloc(n_files, sizeof(*fi)); if (fi == NULL) { @@ -459,12 +482,23 @@ list_files(FILE *out, const char **files, int n_files, int flags) sec_fprintf2(out, "%s: %s\r\n", files[i], strerror(errno)); fi[i].filename = NULL; } else { - if((flags & LS_DIRS) == 0 && S_ISDIR(fi[i].st.st_mode)) { - if(n_files > 1) - sec_fprintf2(out, "%s:\r\n", files[i]); - list_dir(out, files[i], flags); - } else { - make_fileinfo(files[i], &fi[i], flags); + int include_in_list = 1; + total_blocks += block_convert(fi[i].st.st_blocks); + if(S_ISDIR(fi[i].st.st_mode)) { + if(dirs == NULL) + dirs = calloc(n_files, sizeof(*dirs)); + if(dirs == NULL) { + sec_fprintf2(out, "%s: %s\r\n", + files[i], strerror(errno)); + goto out; + } + dirs[i] = 1; + if((flags & LS_DIRS) == 0) + include_in_list = 0; + } + if(include_in_list) { + make_fileinfo(out, files[i], &fi[i], flags); + n_print++; } } } @@ -521,7 +555,9 @@ list_files(FILE *out, const char **files, int n_files, int flags) max_inode = log10(max_inode); max_bsize = log10(max_bsize); max_n_link = log10(max_n_link); - + + if(n_print > 0) + sec_fprintf2(out, "total %lu\r\n", (unsigned long)total_blocks); if(flags & LS_SORT_REVERSE) for(i = n_files - 1; i >= 0; i--) print_file(out, @@ -553,6 +589,7 @@ list_files(FILE *out, const char **files, int n_files, int flags) } else if(DISP_MODE(flags) == LS_DISP_COLUMN || DISP_MODE(flags) == LS_DISP_CROSS) { int max_len = 0; + int size_len = 0; int num_files = n_files; int columns; int j; @@ -563,14 +600,30 @@ list_files(FILE *out, const char **files, int n_files, int flags) } if(strlen(fi[i].filename) > max_len) max_len = strlen(fi[i].filename); + if(log10(fi[i].bsize) > size_len) + size_len = log10(fi[i].bsize); } - columns = 80 / (max_len + 1); /* get space between columns */ - max_len = 80 / columns; + if(num_files == 0) + goto next; + if(flags & LS_SIZE) { + columns = 80 / (size_len + 1 + max_len + 1); + max_len = 80 / columns - size_len - 1; + } else { + columns = 80 / (max_len + 1); /* get space between columns */ + max_len = 80 / columns; + } + if(flags & LS_SIZE) + sec_fprintf2(out, "total %lu\r\n", + (unsigned long)total_blocks); if(DISP_MODE(flags) == LS_DISP_CROSS) { for(i = 0, j = 0; i < n_files; i++) { if(fi[i].filename == NULL) continue; - sec_fprintf2(out, "%-*s", max_len, fi[i].filename); + if(flags & LS_SIZE) + sec_fprintf2(out, "%*u %-*s", size_len, fi[i].bsize, + max_len, fi[i].filename); + else + sec_fprintf2(out, "%-*s", max_len, fi[i].filename); j++; if(j == columns) { sec_fprintf2(out, "\r\n"); @@ -578,7 +631,7 @@ list_files(FILE *out, const char **files, int n_files, int flags) } } if(j > 0) - sec_fprintf2(out, "\r\n"); + sec_fprintf2(out, "\r\n"); } else { int skip = (num_files + columns - 1) / columns; j = 0; @@ -586,7 +639,11 @@ list_files(FILE *out, const char **files, int n_files, int flags) for(j = i; j < n_files;) { while(j < n_files && fi[j].filename == NULL) j++; - sec_fprintf2(out, "%-*s", max_len, fi[j].filename); + if(flags & LS_SIZE) + sec_fprintf2(out, "%*u %-*s", size_len, fi[j].bsize, + max_len, fi[j].filename); + else + sec_fprintf2(out, "%-*s", max_len, fi[j].filename); j += skip; } sec_fprintf2(out, "\r\n"); @@ -599,9 +656,24 @@ list_files(FILE *out, const char **files, int n_files, int flags) sec_fprintf2(out, "%s\r\n", fi[i].filename); } } + next: + if(((flags & LS_DIRS) == 0 || (flags & LS_RECURSIVE)) && dirs != NULL) { + for(i = 0; i < n_files; i++) + if(dirs[i]) { + if((flags & LS_SHOW_DIRNAME)) { + if ((flags & LS_EXTRA_BLANK)) + sec_fprintf2(out, "\r\n"); + sec_fprintf2(out, "%s:\r\n", files[i]); + } + list_dir(out, files[i], flags | LS_DIRS | LS_EXTRA_BLANK); + } + } + out: for(i = 0; i < n_files; i++) free_fileinfo(&fi[i]); free(fi); + if(dirs != NULL) + free(dirs); } static void @@ -614,6 +686,22 @@ free_files (char **files, int n) free (files); } +static int +hide_file(const char *filename, int flags) +{ + if(filename[0] != '.') + return 0; + if((flags & LS_IGNORE_DOT)) + return 1; + if(filename[1] == '\0' || (filename[1] == '.' && filename[2] == '\0')) { + if((flags & LS_SHOW_ALL)) + return 0; + else + return 1; + } + return 0; +} + static void list_dir(FILE *out, const char *directory, int flags) { @@ -629,14 +717,8 @@ list_dir(FILE *out, const char *directory, int flags) while((ent = readdir(d)) != NULL) { void *tmp; - if(ent->d_name[0] == '.') { - if (flags & LS_IGNORE_DOT) - continue; - if (ent->d_name[1] == 0) /* Ignore . */ - continue; - if (ent->d_name[1] == '.' && ent->d_name[2] == 0) /* Ignore .. */ - continue; - } + if(hide_file(ent->d_name, flags)) + continue; tmp = realloc(files, (n_files + 1) * sizeof(*files)); if (tmp == NULL) { sec_fprintf2(out, "%s: out of memory\r\n", directory); @@ -655,62 +737,84 @@ list_dir(FILE *out, const char *directory, int flags) ++n_files; } closedir(d); - list_files(out, (const char**)files, n_files, flags | LS_DIRS); + list_files(out, (const char**)files, n_files, flags); +} + +static int +parse_flags(const char *options) +{ +#ifdef TEST + int flags = LS_SORT_NAME | LS_IGNORE_DOT | LS_DISP_COLUMN; +#else + int flags = LS_SORT_NAME | LS_IGNORE_DOT | LS_DISP_LONG; +#endif + + const char *p; + if(options == NULL || *options != '-') + return flags; + for(p = options + 1; *p; p++) { + switch(*p) { + case '1': + flags = (flags & ~LS_DISP_MODE); + break; + case 'a': + flags |= LS_SHOW_ALL; + /*FALLTHROUGH*/ + case 'A': + flags &= ~LS_IGNORE_DOT; + break; + case 'C': + flags = (flags & ~LS_DISP_MODE) | LS_DISP_COLUMN; + break; + case 'd': + flags |= LS_DIRS; + break; + case 'f': + flags = (flags & ~LS_SORT_MODE); + break; + case 'F': + flags |= LS_TYPE; + break; + case 'i': + flags |= LS_INODE; + break; + case 'l': + flags = (flags & ~LS_DISP_MODE) | LS_DISP_LONG; + break; + case 't': + flags = (flags & ~LS_SORT_MODE) | LS_SORT_MTIME; + break; + case 's': + flags |= LS_SIZE; + break; + case 'S': + flags = (flags & ~LS_SORT_MODE) | LS_SORT_SIZE; + break; + case 'r': + flags |= LS_SORT_REVERSE; + break; + case 'R': + flags |= LS_RECURSIVE; + break; + case 'x': + flags = (flags & ~LS_DISP_MODE) | LS_DISP_CROSS; + break; + } + } + return flags; } void builtin_ls(FILE *out, const char *file) { - int flags = LS_SORT_NAME | LS_IGNORE_DOT | LS_DISP_LONG; + int flags; if(*file == '-') { - const char *p; - for(p = file + 1; *p; p++) { - switch(*p) { - case '1': - flags = (flags & ~LS_DISP_MODE); - break; - case 'a': - case 'A': - flags &= ~LS_IGNORE_DOT; - break; - case 'C': - flags = (flags & ~LS_DISP_MODE) | LS_DISP_COLUMN; - break; - case 'd': - flags |= LS_DIRS; - break; - case 'f': - flags = (flags & ~LS_SORT_MODE); - break; - case 'F': - flags |= LS_TYPE; - break; - case 'i': - flags |= LS_INODE; - break; - case 'l': - flags = (flags & ~LS_DISP_MODE) | LS_DISP_LONG; - break; - case 't': - flags = (flags & ~LS_SORT_MODE) | LS_SORT_MTIME; - break; - case 's': - flags |= LS_SIZE; - break; - case 'S': - flags = (flags & ~LS_SORT_MODE) | LS_SORT_SIZE; - break; - case 'r': - flags |= LS_SORT_REVERSE; - break; - case 'x': - flags = (flags & ~LS_DISP_MODE) | LS_DISP_CROSS; - break; - } - } + flags = parse_flags(file); file = "."; - } + } else + flags = parse_flags(""); + list_files(out, &file, 1, flags); sec_fflush(out); } |