📄 ls.c
字号:
/* `dir', `vdir' and `ls' directory listing programs for GNU.
Copyright (C) 1985, 1988, 1989, 1990 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* MS-DOS port (c) 1990 by Thorsten Ohl, ohl@gnu.ai.mit.edu
This port is also distributed under the terms of the
GNU General Public License as published by the
Free Software Foundation.
Please note that this file is not identical to the
original GNU release, you should have received this
code as patch to the official release. */
#ifdef MSDOS
static char RCS_Id[] =
"$Header: e:/gnu/fileutil/RCS/ls.c 1.4.0.2 90/09/19 11:18:27 tho Exp $";
static char RCS_Revision[] = "$Revision: 1.4.0.2 $";
#define VERSION \
"GNU %s, Version %.*s (compiled %s %s for MS-DOS)\n", PROGNAME, \
(sizeof RCS_Revision - 14), (RCS_Revision + 11), __DATE__, __TIME__
#define COPYING \
"This is free software, distributed under the terms of the\n" \
"GNU General Public License. For details, see the file COPYING.\n"
#endif /* MSDOS */
/* If the macro MULTI_COL is defined,
the multi-column format is the default regardless
of the type of output device.
This is for the `dir' program.
If the macro LONG_FORMAT is defined,
the long format is the default regardless of the
type of output device.
This is for the `vdir' program.
If neither is defined,
the output format depends on whether the output
device is a terminal.
This is for the `ls' program. */
/* Written by Richard Stallman and David MacKenzie. */
#include <sys/types.h>
#ifdef _POSIX_SOURCE
#define S_IEXEC S_IXUSR
#else
#ifndef MSDOS
#include <sys/ioctl.h>
#endif /* not MSDOS */
#endif
#include <stdio.h>
#ifndef MSDOS
#include <grp.h>
#endif
#include <pwd.h>
#include <getopt.h>
#include "system.h"
/* Return an int indicating the result of comparing two longs. */
#ifdef INT_16_BITS
#define longdiff(a, b) ((a) < (b) ? -1 : (a) > (b) ? 1 : 0)
#else
#define longdiff(a, b) ((a) - (b))
#endif
#ifdef STDC_HEADERS
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#else
char *ctime ();
char *getenv ();
char *malloc ();
char *realloc ();
long time ();
extern int errno;
#endif
#ifdef MSDOS
#include <string.h>
#include <io.h>
#include <gnulib.h>
extern int glob_match (char *, char *, int);
extern void mode_string (unsigned short mode, char *str);
extern void main (int, char **);
extern int argmatch (char *, char **);
extern int decode_switches (int, char **);
extern void invalid_arg (char *, char *, int);
extern void queue_directory (char *, char *);
extern void print_dir (char *, char *);
extern void add_ignore_pattern (char *);
extern int file_interesting (struct direct *);
extern void clear_files (void);
extern int gobble_file (char *, int, char *);
extern void extract_dirs_from_files (char *, int);
extern int is_not_dot_or_dotdot (char *);
extern void sort_files (void);
extern int compare_ctime (struct file *, struct file *);
extern int rev_cmp_ctime (struct file *, struct file *);
extern int compare_mtime (struct file *, struct file *);
extern int rev_cmp_mtime (struct file *, struct file *);
extern int compare_atime (struct file *, struct file *);
extern int rev_cmp_atime (struct file *, struct file *);
extern int compare_size (struct file *, struct file *);
extern int rev_cmp_size (struct file *, struct file *);
extern int compare_name (struct file *, struct file *);
extern int rev_cmp_name (struct file *, struct file *);
extern int compare_extension (struct file *file1, struct file *file2);
extern int rev_cmp_extension (struct file *file1, struct file *file2);
extern void print_current_files (void);
extern void print_long_format (struct file *);
extern void print_name_with_quoting (char *);
extern void print_file_name_and_frills (struct file *);
extern void print_type_indicator (unsigned int);
extern int length_of_file_name_and_frills (struct file *);
extern void print_many_per_line (void);
extern void print_horizontal (void);
extern void print_with_commas (void);
extern char *getuser (unsigned short);
extern char *getgroup (unsigned short);
extern void indent (int, int);
extern char *copystring (char *);
extern void attach (char *, char *, char *);
extern char *basename (char *);
extern void usage (void);
#else /* not MSDOS */
struct group *getgrgid ();
struct passwd *getpwuid ();
int glob_match ();
void mode_string ();
char *copystring ();
char *getgroup ();
char *getuser ();
char *make_link_path ();
char *xmalloc ();
char *xrealloc ();
int argmatch ();
int compare_atime ();
int rev_cmp_atime ();
int compare_ctime ();
int rev_cmp_ctime ();
int compare_mtime ();
int rev_cmp_mtime ();
int compare_size ();
int rev_cmp_size ();
int compare_name ();
int rev_cmp_name ();
int compare_extension ();
int rev_cmp_extension ();
int decode_switches ();
int file_interesting ();
int gobble_file ();
int is_not_dot_or_dotdot ();
int length_of_file_name_and_frills ();
void add_ignore_pattern ();
void attach ();
void clear_files ();
void error ();
void extract_dirs_from_files ();
void get_link_name ();
void indent ();
void invalid_arg ();
void print_current_files ();
void print_dir ();
void print_file_name_and_frills ();
void print_horizontal ();
void print_long_format ();
void print_many_per_line ();
void print_name_with_quoting ();
void print_type_indicator ();
void print_with_commas ();
void queue_directory ();
void sort_files ();
void usage ();
#endif /* not MSDOS */
enum filetype
{
symbolic_link,
directory,
arg_directory, /* Directory given as command line arg. */
normal /* All others. */
};
struct file
{
/* The file name. */
char *name;
struct stat stat;
/* For symbolic link, name of the file linked to, otherwise zero. */
char *linkname;
/* For symbolic link and long listing, st_mode of file linked to, otherwise
zero. */
unsigned int linkmode;
enum filetype filetype;
};
/* The table of files in the current directory:
`files' points to a vector of `struct file', one per file.
`nfiles' is the number of elements space has been allocated for.
`files_index' is the number actually in use. */
/* Address of block containing the files that are described. */
struct file *files;
/* Length of block that `files' points to, measured in files. */
int nfiles;
/* Index of first unused in `files'. */
int files_index;
/* Record of one pending directory waiting to be listed. */
struct pending
{
char *name;
/* If the directory is actually the file pointed to by a symbolic link we
were told to list, `realname' will contain the name of the symbolic
link, otherwise zero. */
char *realname;
struct pending *next;
};
struct pending *pending_dirs;
/* Current time (seconds since 1970). When we are printing a file's time,
include the year if it is more than 6 months before this time. */
long current_time;
/* The number of digits to use for block sizes.
4, or more if needed for bigger numbers. */
int block_size_size;
/* The name the program was run with, stripped of any leading path. */
char *program_name;
/* Option flags */
/* long_format for lots of info, one per line.
one_per_line for just names, one per line.
many_per_line for just names, many per line, sorted vertically.
horizontal for just names, many per line, sorted horizontally.
with_commas for just names, many per line, separated by commas.
-l, -1, -C, -x and -m control this parameter. */
enum format
{
long_format, /* -l */
one_per_line, /* -1 */
many_per_line, /* -C */
horizontal, /* -x */
with_commas /* -m */
};
enum format format;
/* Type of time to print or sort by. Controlled by -c and -u. */
enum time_type
{
time_mtime, /* default */
time_ctime, /* -c */
time_atime /* -u */
};
enum time_type time_type;
/* The file characteristic to sort by. Controlled by -t, -S, -U, -X. */
enum sort_type
{
sort_none, /* -U */
sort_name, /* default */
sort_extension, /* -X */
sort_time, /* -t */
sort_size /* -S */
};
enum sort_type sort_type;
/* Direction of sort.
0 means highest first if numeric,
lowest first if alphabetic;
these are the defaults.
1 means the opposite order in each case. -r */
int sort_reverse;
/* Nonzero means print the user and group id's as numbers rather
than as names. -n */
int numeric_users;
/* Nonzero means mention the size in 512 byte blocks of each file. -s */
int print_block_size;
/* Nonzero means show file sizes in kilobytes instead of blocks
(the size of which is system-dependant). -k */
int kilobyte_blocks;
/* none means don't mention the type of files.
all means mention the types of all files.
not_programs means do so except for executables.
Controlled by -F and -p. */
enum indicator_style
{
none, /* default */
all, /* -F */
not_programs /* -p */
};
enum indicator_style indicator_style;
/* Nonzero means mention the inode number of each file. -i */
int print_inode;
/* Nonzero means when a symbolic link is found, display info on
the file linked to. -L */
int trace_links;
/* Nonzero means when a directory is found, display info on its
contents. -R */
int trace_dirs;
/* Nonzero means when an argument is a directory name, display info
on it itself. -d */
int immediate_dirs;
/* Nonzero means don't omit files whose names start with `.'. -A */
int all_files;
/* Nonzero means don't omit files `.' and `..'
This flag implies `all_files'. -a */
int really_all_files;
/* A linked list of shell-style globbing patterns. If a non-argument
file name matches any of these patterns, it is omitted.
Controlled by -I. Multiple -I options accumulate.
The -B option adds `*~' and `.*~' to this list. */
struct ignore_pattern
{
char *pattern;
struct ignore_pattern *next;
};
struct ignore_pattern *ignore_patterns;
/* Nonzero means quote nongraphic chars in file names. -b */
int quote_funny_chars;
/* Nonzero means output nongraphic chars in file names as `?'. -q */
int qmark_funny_chars;
/* Nonzero means output each file name using C syntax for a string.
Always accompanied by `quote_funny_chars'.
This mode, together with -x or -C or -m,
and without such frills as -F or -s,
is guaranteed to make it possible for a program receiving
the output to tell exactly what file names are present. -Q */
int quote_as_string;
/* The number of chars per hardware tab stop. -T */
int tabsize;
/* Nonzero means we are listing the working directory because no
non-option arguments were given. */
int dir_defaulted;
/* Nonzero means print each directory name before listing it. */
int print_dir_name;
/* The line length to use for breaking lines in many-per-line format.
Can be set with -w. */
int line_length;
/* If nonzero, the file listing format requires that stat be called on
each file. */
int format_needs_stat;
void
main (argc, argv)
int argc;
char **argv;
{
register int i;
register struct pending *thispend;
dir_defaulted = 1;
print_dir_name = 1;
pending_dirs = 0;
current_time = time ((long *) 0);
program_name = argv[0];
i = decode_switches (argc, argv);
format_needs_stat = sort_type == sort_time || sort_type == sort_size
|| format == long_format
|| trace_links || trace_dirs || indicator_style != none
|| print_block_size || print_inode;
nfiles = 100;
files = (struct file *) xmalloc (sizeof (struct file) * nfiles);
files_index = 0;
clear_files ();
if (i < argc)
dir_defaulted = 0;
#ifdef MSDOS
for (; i < argc; i++)
{
if (strlen (argv[i]) == 2 && argv[i][1] == ':')
{
/* The user wants the cwd on another drive. Help
DOS by appending a `.'! (This allows to stat()
the directory.) */
char *temp = (char *) xmalloc (4);
strcpy (temp, argv[i]);
strcat (temp, ".");
argv[i] = temp;
}
gobble_file (argv[i], 1, "");
}
#else /* not MSDOS */
for (; i < argc; i++)
gobble_file (argv[i], 1, "");
#endif /* not MSDOS */
if (dir_defaulted)
{
if (immediate_dirs)
gobble_file (".", 1, "");
else
queue_directory (".", 0);
}
if (files_index)
{
sort_files ();
if (!immediate_dirs)
extract_dirs_from_files ("", 0);
/* `files_index' might be zero now. */
}
if (files_index)
{
print_current_files ();
if (pending_dirs)
putchar ('\n');
}
else if (pending_dirs && pending_dirs->next == 0)
print_dir_name = 0;
while (pending_dirs)
{
thispend = pending_dirs;
pending_dirs = pending_dirs->next;
print_dir (thispend->name, thispend->realname);
free (thispend->name);
if (thispend->realname)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -