📄 ls.c
字号:
attach (path, dirname, name);
}
if (trace_links)
{
val = stat (path, &files[files_index].stat);
if (val < 0)
/* Perhaps a symbolically-linked to file doesn't exist; stat
the link instead. */
val = lstat (path, &files[files_index].stat);
}
else
val = lstat (path, &files[files_index].stat);
if (val < 0)
{
error (0, errno, "%s", path);
return 0;
}
#ifdef S_IFLNK
if ((files[files_index].stat.st_mode & S_IFMT) == S_IFLNK)
{
char *linkpath;
struct stat linkstats;
get_link_name (path, &files[files_index]);
linkpath = make_link_path (path, files[files_index].linkname);
/* Stat the file linked to; automatically trace it in non-long
listings, get its mode for the filetype indicator in long
listings. */
if (linkpath && lstat (linkpath, &linkstats) == 0)
{
if ((linkstats.st_mode & S_IFMT) == S_IFDIR
&& explicit_arg && format != long_format)
{
char *tempname;
/* Symbolic links to directories that are mentioned on the
command line are automatically traced if not being
listed as files. */
if (!immediate_dirs)
{
tempname = name;
name = linkpath;
linkpath = files[files_index].linkname;
files[files_index].linkname = tempname;
}
files[files_index].stat = linkstats;
}
else
files[files_index].linkmode = linkstats.st_mode;
}
if (linkpath)
free (linkpath);
}
#endif
switch (files[files_index].stat.st_mode & S_IFMT)
{
#ifdef S_IFLNK
case S_IFLNK:
files[files_index].filetype = symbolic_link;
break;
#endif
case S_IFDIR:
if (explicit_arg && !immediate_dirs)
files[files_index].filetype = arg_directory;
else
files[files_index].filetype = directory;
break;
default:
files[files_index].filetype = normal;
break;
}
blocks = convert_blocks (ST_NBLOCKS (files[files_index].stat),
kilobyte_blocks);
if (blocks >= 10000 && block_size_size < 5)
block_size_size = 5;
#ifndef MSDOS
if (blocks >= 100000 && block_size_size < 6)
block_size_size = 6;
if (blocks >= 1000000 && block_size_size < 7)
block_size_size = 7;
#endif /* not MSDOS */
}
else
blocks = 0;
files[files_index].name = copystring (name);
files_index++;
return blocks;
}
#ifdef S_IFLNK
/* Put the name of the file that `filename' is a symbolic link to
into the `linkname' field of `f'. */
void
get_link_name (filename, f)
char *filename;
struct file *f;
{
register char *linkbuf;
register int bufsiz = f->stat.st_size;
linkbuf = (char *) xmalloc (bufsiz + 1);
linkbuf[bufsiz] = 0;
if (readlink (filename, linkbuf, bufsiz) < 0)
{
error (0, errno, "%s", filename);
free (linkbuf);
}
else
f->linkname = linkbuf;
}
/* If `linkname' is a relative path and `path' contains one or more
leading directories, return `linkname' with those directories
prepended; otherwise, return a copy of `linkname'.
If `linkname' is zero, return zero. */
char *
make_link_path (path, linkname)
char *path;
char *linkname;
{
char *linkbuf;
int bufsiz;
if (linkname == 0)
return 0;
if (*linkname == '/')
return copystring (linkname);
/* The link is to a relative path. Prepend any leading path
in `path' to the link name. */
linkbuf = rindex (path, '/');
if (linkbuf == 0)
return copystring (linkname);
bufsiz = linkbuf - path + 1;
linkbuf = xmalloc (bufsiz + strlen (linkname) + 1);
strncpy (linkbuf, path, bufsiz);
strcpy (linkbuf + bufsiz, linkname);
return linkbuf;
}
#endif
/* 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)
char *dirname;
int recursive;
{
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);
}
else
{
path = (char *) xmalloc (strlen (files[i].name) + dirlen);
attach (path, dirname, files[i].name);
queue_directory (path, files[i].linkname);
free (path);
}
if (files[i].filetype == arg_directory)
free (files[i].name);
}
/* Now delete the directories from the table, compacting all the remaining
entries. */
for (i = 0, j = 0; i < files_index; i++)
if (files[i].filetype != arg_directory)
files[j++] = files[i];
files_index = j;
}
/* Return non-zero if `name' doesn't end in `.' or `..'
This is so we don't try to recurse on `././././. ...' */
int
is_not_dot_or_dotdot (name)
char *name;
{
char *t;
t = rindex (name, '/');
if (t)
name = t + 1;
if (name[0] == '.'
&& (name[1] == '\0'
|| (name[1] == '.' && name[2] == '\0')))
return 0;
return 1;
}
/* Sort the files now in the table. */
void
sort_files ()
{
int (*func) ();
switch (sort_type)
{
case sort_none:
return;
case sort_time:
switch (time_type)
{
case time_ctime:
func = sort_reverse ? rev_cmp_ctime : compare_ctime;
break;
case time_mtime:
func = sort_reverse ? rev_cmp_mtime : compare_mtime;
break;
case time_atime:
func = sort_reverse ? rev_cmp_atime : compare_atime;
break;
}
break;
case sort_name:
func = sort_reverse ? rev_cmp_name : compare_name;
break;
case sort_extension:
func = sort_reverse ? rev_cmp_extension : compare_extension;
break;
case sort_size:
func = sort_reverse ? rev_cmp_size : compare_size;
break;
}
qsort (files, files_index, sizeof (struct file), func);
}
/* Comparison routines for sorting the files. */
int
compare_ctime (file1, file2)
struct file *file1, *file2;
{
return longdiff (file2->stat.st_ctime, file1->stat.st_ctime);
}
int
rev_cmp_ctime (file2, file1)
struct file *file1, *file2;
{
return longdiff (file2->stat.st_ctime, file1->stat.st_ctime);
}
int
compare_mtime (file1, file2)
struct file *file1, *file2;
{
return longdiff (file2->stat.st_mtime, file1->stat.st_mtime);
}
int
rev_cmp_mtime (file2, file1)
struct file *file1, *file2;
{
return longdiff (file2->stat.st_mtime, file1->stat.st_mtime);
}
int
compare_atime (file1, file2)
struct file *file1, *file2;
{
return longdiff (file2->stat.st_atime, file1->stat.st_atime);
}
int
rev_cmp_atime (file2, file1)
struct file *file1, *file2;
{
return longdiff (file2->stat.st_atime, file1->stat.st_atime);
}
int
compare_size (file1, file2)
struct file *file1, *file2;
{
return longdiff (file2->stat.st_size, file1->stat.st_size);
}
int
rev_cmp_size (file2, file1)
struct file *file1, *file2;
{
return longdiff (file2->stat.st_size, file1->stat.st_size);
}
int
compare_name (file1, file2)
struct file *file1, *file2;
{
return strcmp (file1->name, file2->name);
}
int
rev_cmp_name (file2, file1)
struct file *file1, *file2;
{
return strcmp (file1->name, file2->name);
}
/* Compare file extensions. Files with no extension are `smallest'.
If extensions are the same, compare by filenames instead. */
int
compare_extension (file1, file2)
struct file *file1, *file2;
{
register char *base1, *base2;
register int cmp;
base1 = rindex (file1->name, '.');
base2 = rindex (file2->name, '.');
if (base1 == 0 && base2 == 0)
return strcmp (file1->name, file2->name);
if (base1 == 0)
return -1;
if (base2 == 0)
return 1;
cmp = strcmp (base1, base2);
if (cmp == 0)
return strcmp (file1->name, file2->name);
return cmp;
}
int
rev_cmp_extension (file2, file1)
struct file *file1, *file2;
{
register char *base1, *base2;
register int cmp;
base1 = rindex (file1->name, '.');
base2 = rindex (file2->name, '.');
if (base1 == 0 && base2 == 0)
return strcmp (file1->name, file2->name);
if (base1 == 0)
return -1;
if (base2 == 0)
return 1;
cmp = strcmp (base1, base2);
if (cmp == 0)
return strcmp (file1->name, file2->name);
return cmp;
}
/* List all the files now in the table. */
void
print_current_files ()
{
register int i;
switch (format)
{
case one_per_line:
for (i = 0; i < files_index; i++)
{
print_file_name_and_frills (files + i);
putchar ('\n');
}
break;
case many_per_line:
print_many_per_line ();
break;
case horizontal:
print_horizontal ();
break;
case with_commas:
print_with_commas ();
break;
case long_format:
for (i = 0; i < files_index; i++)
{
print_long_format (files + i);
putchar ('\n');
}
break;
}
}
void
print_long_format (f)
struct file *f;
{
char modebuf[20];
char timebuf[40];
long when;
mode_string (f->stat.st_mode, modebuf);
modebuf[10] = 0;
switch (time_type)
{
case time_ctime:
when = f->stat.st_ctime;
break;
case time_mtime:
when = f->stat.st_mtime;
break;
case time_atime:
when = f->stat.st_atime;
break;
}
strcpy (timebuf, ctime (&when));
if (current_time - when > 6L * 30L * 24L * 60L * 60L
|| current_time - when < 0L)
{
/* The file is fairly old or in the future.
POSIX says the cutoff is 6 months old;
approximate this by 6*30 days.
Show the year instead of the time of day. */
strcpy (timebuf + 11, timebuf + 19);
}
timebuf[16] = 0;
if (print_inode)
printf ("%6u ", f->stat.st_ino);
if (print_block_size)
printf ("%*u ", block_size_size, convert_blocks (ST_NBLOCKS (f->stat),
kilobyte_blocks));
/* The space between the mode and the number of links is the POSIX
"optional alternate access method flag". */
printf ("%s %3u ", modebuf, f->stat.st_nlink);
if (numeric_users)
printf ("%-8u ", (unsigned int) f->stat.st_uid);
else
printf ("%-8.8s ", getuser (f->stat.st_uid));
if (numeric_users)
printf ("%-8u ", (unsigned int) f->stat.st_gid);
else
printf ("%-8.8s ", getgroup (f->stat.st_gid));
#ifdef S_IFBLK
if ((f->stat.st_mode & S_IFMT) == S_IFCHR
|| (f->stat.st_mode & S_IFMT) == S_IFBLK)
#else /* not S_IFBLK */
if ((f->stat.st_mode & S_IFMT) == S_IFCHR)
#endif /* not S_IFBLK */
printf ("%3u, %3u ", major (f->stat.st_rdev), minor (f->stat.st_rdev));
else
printf ("%8lu ", f->stat.st_size);
printf ("%s ", timebuf + 4);
print_name_with_quoting (f->name);
if (f->filetype == symbolic_link)
{
if (f->linkname)
{
fputs (" -> ", stdout);
print_name_with_quoting (f->linkname);
if (indicator_style != none)
print_type_indicator (f->linkmode);
}
}
else if (indicator_style != none)
print_type_indicator (f->stat.st_mode);
}
void
print_name_with_quoting (p)
register char *p;
{
register unsigned char c;
if (quote_as_string)
putchar ('"');
while (c = *p++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -