📄 cfls.c
字号:
numeric_users = 1;
break;
case 'p':
indicator_style = not_programs;
break;
case 'q':
qmark_funny_chars = 1;
quote_funny_chars = 0;
break;
case 'r':
sort_reverse = 1;
break;
case 's':
print_block_size = 1;
break;
case 't':
sort_type = sort_time;
break;
case 'u':
time_type = time_atime;
break;
case 'w':
line_length = atoi (optarg);
if (line_length < 1)
error (1, 0, "invalid line width: %s", optarg);
break;
case 'x':
format = horizontal;
break;
case 'A':
all_files = 1;
break;
case 'B':
add_ignore_pattern ("*~");
add_ignore_pattern (".*~");
break;
case 'C':
format = many_per_line;
break;
case 'F':
indicator_style = all;
break;
case 'I':
add_ignore_pattern (optarg);
break;
case 'L':
trace_links = 1;
break;
case 'N':
quote_funny_chars = 0;
qmark_funny_chars = 0;
break;
case 'Q':
quote_as_string = 1;
quote_funny_chars = 1;
qmark_funny_chars = 0;
break;
case 'R':
trace_dirs = 1;
break;
case 'S':
sort_type = sort_size;
break;
case 'T':
tabsize = atoi (optarg);
if (tabsize < 1)
error (1, 0, "invalid tab size: %s", optarg);
break;
case 'U':
sort_type = sort_none;
break;
case 'X':
sort_type = sort_extension;
break;
case '1':
format = one_per_line;
break;
case 10: /* +sort */
longind = argmatch (optarg, sort_args);
if (longind < 0)
{
invalid_arg ("sort type", optarg, longind);
usage ();
}
sort_type = sort_types[longind];
break;
case 11: /* +time */
longind = argmatch (optarg, time_args);
if (longind < 0)
{
invalid_arg ("time type", optarg, longind);
usage ();
}
time_type = time_types[longind];
break;
case 12: /* +format */
longind = argmatch (optarg, format_args);
if (longind < 0)
{
invalid_arg ("format type", optarg, longind);
usage ();
}
format = formats[longind];
break;
default:
usage ();
}
}
return optind;
}
/* Request that the directory named `name' have its contents listed later.
If `realname' is nonzero, it will be used instead of `name' when the
directory name is printed. This allows symbolic links to directories
to be treated as regular directories but still be listed under their
real names. */
void
queue_directory (name, realname, thispend)
char *name;
char *realname;
struct pending *thispend;
{
struct pending *new;
new = (struct pending *) xmalloc (sizeof (struct pending));
new->next = pending_dirs;
pending_dirs = new;
new->name = copystring (name);
if (realname)
new->realname = copystring (realname);
else
new->realname = NULL;
if(thispend)
new->list_patterns = thispend->list_patterns;
else
new->list_patterns = NULL;
}
/* Read directory `name', and list the files in it.
If `realname' is nonzero, print its name instead of `name';
this is used for symbolic links to directories. */
void
print_dir (thispend)
struct pending *thispend;
{
register void *reading;
CFDIRENT *next;
register long total_blocks = 0;
char *name;
char *realname;
errno = 0;
name = thispend->name;
realname = thispend->realname;
reading = opendir (name);
if (!reading)
{
#ifdef PCDOS
errno = 2;/* it seems to have a small vocabulary, so ENOENT */
#endif
error (0, errno, "%s", name);
return;
}
/* Read the directory entries, and insert the subfiles into the `files'
table. */
clear_files ();
while (next = (void*)readdir (reading))
{
if (file_interesting (next, thispend))
total_blocks += gobble_file (next->d_name, 0, name, next);
}
closedir (reading);
/* Sort the directory contents. */
sort_files ();
/* If any member files are subdirectories, perhaps they should have their
contents listed rather than being mentioned here as files. */
if (trace_dirs)
extract_dirs_from_files (name, 1, thispend);
if (print_dir_name)
{
if (realname)
printf ("%s:\n", realname);
else
printf ("%s:\n", name);
}
#ifndef PCDOS
if (format == long_format || print_block_size)
printf ("total %u\n", total_blocks);
#endif
if (files_index)
print_current_files ();
#ifdef PCDOS
if(format == long_format || format == many_per_line || print_block_size)
{
printf ("\t%d file(s)\t", files_index);
if(print_block_size)
printf ("%lu blocks allocated\n", total_blocks);
else
printf ("%lu blocks used\n", total_blocks);
}
#endif
if (pending_dirs)
putchar ('\n');
}
/* Add `pattern' to the list of patterns for which files that match are
listed. */
void
add_list_pattern (pattern)
char *pattern;
{
register struct ignore_pattern *list;
list = (struct ignore_pattern *) xmalloc (sizeof (struct ignore_pattern));
list->pattern = pattern;
/* Add it to the head of the linked list. */
list->next = pending_dirs->list_patterns;
pending_dirs->list_patterns = list;
}
/* Add `pattern' to the list of patterns for which files that match are
not listed. */
void
add_ignore_pattern (pattern)
char *pattern;
{
register struct ignore_pattern *ignore;
ignore = (struct ignore_pattern *) xmalloc (sizeof (struct ignore_pattern));
ignore->pattern = pattern;
/* Add it to the head of the linked list. */
ignore->next = ignore_patterns;
ignore_patterns = ignore;
}
/* Return nonzero if the file in `next' should be listed. */
int
file_interesting (dirp, thispend)
register CFDIRENT *dirp;
register struct pending *thispend;
{
register struct ignore_pattern *ignore;
/* exclude files which match the ignore_pattern list */
for (ignore = ignore_patterns; ignore; ignore = ignore->next)
if (glob_match (ignore->pattern, dirp->d_name, 1))
return 0;
/* include files which match the list_pattern list */
for (ignore = thispend->list_patterns; ignore; ignore = ignore->next)
{
if (glob_match (ignore->pattern, dirp->d_name, 1))
goto file_maybe_ok;
}
if(thispend->list_patterns) return 0;
file_maybe_ok:
if (really_all_files
|| dirp->d_name[0] != '.'
|| (all_files
&& dirp->d_name[1] != '\0'
&& (dirp->d_name[1] != '.' || dirp->d_name[2] != '\0')))
return 1;
return 0;
}
/* Enter and remove entries in the table `files'. */
/* Empty the table of files. */
void
clear_files ()
{
register int i;
for (i = 0; i < files_index; i++)
{
free (files[i].name);
if (files[i].linkname)
free (files[i].linkname);
}
files_index = 0;
block_size_size = 3;
}
/* Add a file to the current table of files.
Verify that the file exists, and print an error message if it does not.
Return the number of blocks that the file occupies. */
long
gobble_file (name, explicit_arg, dirname, dirp)
char *name;
int explicit_arg;
char *dirname;
CFDIRENT *dirp;
{
long blocks;
register int val;
register char *path;
struct file *f;
int printable;
if (files_index == nfiles)
{
nfiles *= 2;
files = (struct file *) xrealloc (files, sizeof (struct file) * nfiles);
}
f = &files[files_index];
f->linkname = NULL;
f->linkmode = 0;
if(!dirp)
printable = 1;
else printable = is_printable(name, dirp->d_namlen);
if (explicit_arg && printable && if_pattern(name))
{/* The shell passed a pattern which needs globbing locally */
char ch, *pat;
if(path = rindex(name, '/'))
{
pat = path+1;
if(path == name || path[-1] == ':')
++path;
ch = *path;
*path = '\0';
if( ((pending_dirs) ? (strcmp(pending_dirs->name, name)) : 1))
queue_directory (name, NULL, NULL);
*path = ch;
add_list_pattern(pat);
return 0;
}
if(name[1] == ':')
{/* e.g. b:*.h */
ch = name[2];
name[2] = '\0';
if( ((pending_dirs) ? (strcmp(pending_dirs->name, name)) : 1))
queue_directory (name, NULL, NULL);
name[2] = ch;
add_list_pattern(&name[2]);
return 0;
}
else
{
if(!pending_dirs)
queue_directory ("./", NULL, NULL);
add_list_pattern(name);
return 0;
}
return 0;
}
blocks = 0;
if (explicit_arg || format_needs_stat)
{
LSTAT *sp = &f->stats;
if(dirp)
{
sp->st_mode = dirp->d_mode;
sp->st_size = dirp->d_bytesused;
sp->st_alloc = dirp->d_bytesalloc;
sp->st_mtime = dirp->d_mtime;
sp->st_ctime = dirp->d_ctime;
sp->st_atime = sp->st_mtime;
sp->st_ino = dirp->d_ino;
if(sp->st_mode & (M_HASHDIR|M_TREEDIR))
sp->st_mode |= S_IFDIR;
else sp->st_mode |= S_IFREG;
} else {
CFSTAT s;
cfstat(name, &s);
sp->st_mode = s.st_mode;
sp->st_size = s.st_size;
sp->st_alloc = s.st_size;
sp->st_mtime = s.st_mtime;
sp->st_ctime = s.st_ctime;
sp->st_atime = s.st_atime;
sp->st_ino = s.st_ino;
if(sp->st_mode & (M_HASHDIR|M_TREEDIR))
sp->st_mode |= S_IFDIR;
else sp->st_mode |= S_IFREG;
}
settype:
switch (sp->st_mode & S_IFMT)
{
case S_IFDIR:
if (explicit_arg && !immediate_dirs)
f->filetype = arg_directory;
else
f->filetype = directory;
break;
default:
f->filetype = normal;
break;
}
blocks = (long)convert_blocks(ST_NBLOCKS(sp), kilobyte_blocks);
if(blocks >= 1000 && block_size_size < 4)
block_size_size = 4;
if(blocks >= 10000 && block_size_size < 5)
block_size_size = 5;
if(blocks >= 100000 && block_size_size < 6)
block_size_size = 6;
if(blocks >= 1000000 && block_size_size < 7)
block_size_size = 7;
}
if(dirp)
{
if(is_printable(dirp->d_name, dirp->d_namlen))
{
f->name = xmalloc(dirp->d_namlen+1);
memcpy(f->name, dirp->d_name, dirp->d_namlen+1);
f->namlen = dirp->d_namlen;
} else {/* print a tidbit of the key, in hex */
f->name = xmalloc(16);
f->namlen = cfsprintf(f->name, "0x%x", *((long *)dirp->d_name));
}
} else {
f->namlen = strlen(name);
f->name = xmalloc(f->namlen+1);
strcpy(f->name, name);
}
files_index++;
return blocks;
}
/* Remove any entries from `files' that are for directories,
and queue them to be listed as directories instead.
`dirname' is the prefix to prepend to each dirname
to make it correct relative to ls's working dir.
`recursive' is nonzero if we should not treat `.' and `..' as dirs.
This is desirable when processing directories recursively. */
void
extract_dirs_from_files (dirname, recursive, thispend)
char *dirname;
int recursive;
struct pending *thispend;
{
register int i, j;
register char *path;
int dirlen;
dirlen = strlen (dirname) + 2;
/* Queue the directories last one first, because queueing reverses the
order. */
for (i = files_index - 1; i >= 0; i--)
if ((files[i].filetype == directory || files[i].filetype == arg_directory)
&& (!recursive || is_not_dot_or_dotdot (files[i].name)))
{
if (files[i].name[0] == '/' || dirname[0] == 0)
{
queue_directory (files[i].name, files[i].linkname, thispend);
}
else
{
path = (char *) xmalloc (strlen (files[i].name) + dirlen);
attach (path, dirname, files[i].name);
queue_directory (path, files[i].linkname, thispend);
free (path);
}
if ( files[i].filetype == arg_directory
|| (files[i].filetype == directory && thispend->list_patterns))
free (files[i].name);
}
/* Now delete the directories from the table, compacting all the remaining
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -