summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Labrecque <vincent@cvs.openbsd.org>2003-05-08 21:04:18 +0000
committerVincent Labrecque <vincent@cvs.openbsd.org>2003-05-08 21:04:18 +0000
commit06d47a94407f97c7758d872cd76157b79c5cf8a6 (patch)
tree86d312612fe0eaf6d1af26634397d03d5d8617b0
parent92123554d19cb1b6fc10adb7a5118fc02e564f19 (diff)
multiple readlink() calls that forgot the -1...
ok millert
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.c2
-rw-r--r--gnu/usr.sbin/mkhybrid/src/rock.c4
-rw-r--r--gnu/usr.sbin/mkhybrid/src/tree.c4
-rw-r--r--kerberosIV/src/appl/ftp/ftpd/ls.c464
-rw-r--r--kerberosV/src/appl/ftp/ftpd/ls.c270
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);
}