implement -R
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@10561 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
@@ -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).
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -49,14 +49,21 @@ RCSID("$Id$");
|
|||||||
|
|
||||||
#define sec_fprintf2 fprintf
|
#define sec_fprintf2 fprintf
|
||||||
#define sec_fflush fflush
|
#define sec_fflush fflush
|
||||||
void
|
static void list_files(FILE *out, const char **files, int n_files, int flags);
|
||||||
builtin_ls(FILE *out, const char *file);
|
static int parse_flags(const char *options);
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i = 1;
|
||||||
for(i = 1; i < argc; i++)
|
int flags;
|
||||||
builtin_ls(stdout, argv[i]);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -107,7 +114,10 @@ free_fileinfo(struct fileinfo *f)
|
|||||||
#define LS_DISP_LONG (1 << 8)
|
#define LS_DISP_LONG (1 << 8)
|
||||||
#define LS_DISP_COLUMN (2 << 8)
|
#define LS_DISP_COLUMN (2 << 8)
|
||||||
#define LS_DISP_CROSS (3 << 8)
|
#define LS_DISP_CROSS (3 << 8)
|
||||||
#define LS_IGNORE_DOTDIR (1 << 10)
|
#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
|
#ifndef S_ISTXT
|
||||||
#define S_ISTXT S_ISVTX
|
#define S_ISTXT S_ISVTX
|
||||||
@@ -121,19 +131,25 @@ free_fileinfo(struct fileinfo *f)
|
|||||||
#define S_ISLNK(mode) (((mode) & _S_IFMT) == S_IFLNK)
|
#define S_ISLNK(mode) (((mode) & _S_IFMT) == S_IFLNK)
|
||||||
#endif
|
#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
|
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];
|
char buf[128];
|
||||||
int file_type = 0;
|
int file_type = 0;
|
||||||
struct stat *st = &file->st;
|
struct stat *st = &file->st;
|
||||||
|
|
||||||
file->inode = st->st_ino;
|
file->inode = st->st_ino;
|
||||||
#ifdef S_BLKSIZE
|
file->bsize = block_convert(st->st_blocks);
|
||||||
file->bsize = st->st_blocks * S_BLKSIZE / 1024;
|
|
||||||
#else
|
|
||||||
file->bsize = st->st_blocks * 512 / 1024;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(S_ISDIR(st->st_mode)) {
|
if(S_ISDIR(st->st_mode)) {
|
||||||
file->mode[0] = 'd';
|
file->mode[0] = 'd';
|
||||||
@@ -252,7 +268,7 @@ make_fileinfo(const char *filename, struct fileinfo *file, int flags)
|
|||||||
buf[n] = '\0';
|
buf[n] = '\0';
|
||||||
file->link = strdup(buf);
|
file->link = strdup(buf);
|
||||||
} else
|
} else
|
||||||
warn("%s: readlink", filename);
|
sec_fprintf2(out, "readlink(%s): %s", filename, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,6 +465,12 @@ list_files(FILE *out, const char **files, int n_files, int flags)
|
|||||||
{
|
{
|
||||||
struct fileinfo *fi;
|
struct fileinfo *fi;
|
||||||
int i;
|
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));
|
fi = calloc(n_files, sizeof(*fi));
|
||||||
if (fi == NULL) {
|
if (fi == NULL) {
|
||||||
@@ -460,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));
|
sec_fprintf2(out, "%s: %s\r\n", files[i], strerror(errno));
|
||||||
fi[i].filename = NULL;
|
fi[i].filename = NULL;
|
||||||
} else {
|
} else {
|
||||||
if((flags & LS_DIRS) == 0 && S_ISDIR(fi[i].st.st_mode)) {
|
int include_in_list = 1;
|
||||||
if(n_files > 1)
|
total_blocks += block_convert(fi[i].st.st_blocks);
|
||||||
sec_fprintf2(out, "%s:\r\n", files[i]);
|
if(S_ISDIR(fi[i].st.st_mode)) {
|
||||||
list_dir(out, files[i], flags);
|
if(dirs == NULL)
|
||||||
} else {
|
dirs = calloc(n_files, sizeof(*dirs));
|
||||||
make_fileinfo(files[i], &fi[i], flags);
|
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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -522,7 +555,9 @@ list_files(FILE *out, const char **files, int n_files, int flags)
|
|||||||
max_inode = log10(max_inode);
|
max_inode = log10(max_inode);
|
||||||
max_bsize = log10(max_bsize);
|
max_bsize = log10(max_bsize);
|
||||||
max_n_link = log10(max_n_link);
|
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)
|
if(flags & LS_SORT_REVERSE)
|
||||||
for(i = n_files - 1; i >= 0; i--)
|
for(i = n_files - 1; i >= 0; i--)
|
||||||
print_file(out,
|
print_file(out,
|
||||||
@@ -554,6 +589,7 @@ list_files(FILE *out, const char **files, int n_files, int flags)
|
|||||||
} else if(DISP_MODE(flags) == LS_DISP_COLUMN ||
|
} else if(DISP_MODE(flags) == LS_DISP_COLUMN ||
|
||||||
DISP_MODE(flags) == LS_DISP_CROSS) {
|
DISP_MODE(flags) == LS_DISP_CROSS) {
|
||||||
int max_len = 0;
|
int max_len = 0;
|
||||||
|
int size_len = 0;
|
||||||
int num_files = n_files;
|
int num_files = n_files;
|
||||||
int columns;
|
int columns;
|
||||||
int j;
|
int j;
|
||||||
@@ -564,14 +600,30 @@ list_files(FILE *out, const char **files, int n_files, int flags)
|
|||||||
}
|
}
|
||||||
if(strlen(fi[i].filename) > max_len)
|
if(strlen(fi[i].filename) > max_len)
|
||||||
max_len = strlen(fi[i].filename);
|
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 */
|
if(num_files == 0)
|
||||||
max_len = 80 / columns;
|
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) {
|
if(DISP_MODE(flags) == LS_DISP_CROSS) {
|
||||||
for(i = 0, j = 0; i < n_files; i++) {
|
for(i = 0, j = 0; i < n_files; i++) {
|
||||||
if(fi[i].filename == NULL)
|
if(fi[i].filename == NULL)
|
||||||
continue;
|
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++;
|
j++;
|
||||||
if(j == columns) {
|
if(j == columns) {
|
||||||
sec_fprintf2(out, "\r\n");
|
sec_fprintf2(out, "\r\n");
|
||||||
@@ -579,7 +631,7 @@ list_files(FILE *out, const char **files, int n_files, int flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(j > 0)
|
if(j > 0)
|
||||||
sec_fprintf2(out, "\r\n");
|
sec_fprintf2(out, "\r\n");
|
||||||
} else {
|
} else {
|
||||||
int skip = (num_files + columns - 1) / columns;
|
int skip = (num_files + columns - 1) / columns;
|
||||||
j = 0;
|
j = 0;
|
||||||
@@ -587,7 +639,11 @@ list_files(FILE *out, const char **files, int n_files, int flags)
|
|||||||
for(j = i; j < n_files;) {
|
for(j = i; j < n_files;) {
|
||||||
while(j < n_files && fi[j].filename == NULL)
|
while(j < n_files && fi[j].filename == NULL)
|
||||||
j++;
|
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;
|
j += skip;
|
||||||
}
|
}
|
||||||
sec_fprintf2(out, "\r\n");
|
sec_fprintf2(out, "\r\n");
|
||||||
@@ -600,9 +656,24 @@ list_files(FILE *out, const char **files, int n_files, int flags)
|
|||||||
sec_fprintf2(out, "%s\r\n", fi[i].filename);
|
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++)
|
for(i = 0; i < n_files; i++)
|
||||||
free_fileinfo(&fi[i]);
|
free_fileinfo(&fi[i]);
|
||||||
free(fi);
|
free(fi);
|
||||||
|
if(dirs != NULL)
|
||||||
|
free(dirs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -615,6 +686,22 @@ free_files (char **files, int n)
|
|||||||
free (files);
|
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
|
static void
|
||||||
list_dir(FILE *out, const char *directory, int flags)
|
list_dir(FILE *out, const char *directory, int flags)
|
||||||
{
|
{
|
||||||
@@ -630,15 +717,8 @@ list_dir(FILE *out, const char *directory, int flags)
|
|||||||
while((ent = readdir(d)) != NULL) {
|
while((ent = readdir(d)) != NULL) {
|
||||||
void *tmp;
|
void *tmp;
|
||||||
|
|
||||||
if(ent->d_name[0] == '.') {
|
if(hide_file(ent->d_name, flags))
|
||||||
if (ent->d_name[1] == 0 && flags & LS_IGNORE_DOTDIR) /* Ignore . */
|
continue;
|
||||||
continue;
|
|
||||||
if (ent->d_name[1] == '.' && ent->d_name[2] == 0
|
|
||||||
&& flags & LS_IGNORE_DOTDIR) /* Ignore .. */
|
|
||||||
continue;
|
|
||||||
if (flags & LS_IGNORE_DOT)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
tmp = realloc(files, (n_files + 1) * sizeof(*files));
|
tmp = realloc(files, (n_files + 1) * sizeof(*files));
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
sec_fprintf2(out, "%s: out of memory\r\n", directory);
|
sec_fprintf2(out, "%s: out of memory\r\n", directory);
|
||||||
@@ -657,64 +737,84 @@ list_dir(FILE *out, const char *directory, int flags)
|
|||||||
++n_files;
|
++n_files;
|
||||||
}
|
}
|
||||||
closedir(d);
|
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
|
void
|
||||||
builtin_ls(FILE *out, const char *file)
|
builtin_ls(FILE *out, const char *file)
|
||||||
{
|
{
|
||||||
int flags = LS_SORT_NAME | LS_IGNORE_DOT | LS_IGNORE_DOTDIR | LS_DISP_LONG;
|
int flags;
|
||||||
|
|
||||||
if(*file == '-') {
|
if(*file == '-') {
|
||||||
const char *p;
|
flags = parse_flags(file);
|
||||||
for(p = file + 1; *p; p++) {
|
|
||||||
switch(*p) {
|
|
||||||
case '1':
|
|
||||||
flags = (flags & ~LS_DISP_MODE);
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
flags &= ~(LS_IGNORE_DOT | LS_IGNORE_DOTDIR);
|
|
||||||
break;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file = ".";
|
file = ".";
|
||||||
}
|
} else
|
||||||
|
flags = parse_flags("");
|
||||||
|
|
||||||
list_files(out, &file, 1, flags);
|
list_files(out, &file, 1, flags);
|
||||||
sec_fflush(out);
|
sec_fflush(out);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user