📄 sfldir.c
字号:
the UNIX 'ls -l' command. Returns a static buffer that contains the
the formatted string. If the full argument is TRUE, adds cosmetic
hints to indicate the file type; for instance '/' if the file is a
directory, '*' if it is executable.
---------------------------------------------------------------------[>]-*/
char *
format_dir (
DIRST *dir,
Bool full)
{
static char
buffer [LINE_MAX]; /* Formatted directory entry */
ASSERT (dir != NULL);
snprintf (buffer, sizeof (buffer),
"%s %3d %-8.8s %-8.8s %8ld %s %s",
format_mode (dir),
dir-> file_nlink,
dir-> owner,
dir-> group,
(long) dir-> file_size,
format_time (dir),
format_name (dir, full)
);
return (buffer);
}
/* -------------------------------------------------------------------------
* format_mode -- internal
*
* Returns a static string holding the ASCII representation of the UNIX-ish
* permission bits for the directory entry specified.
*/
static char *
format_mode (
DIRST *dir)
{
static char
buffer [11], /* duuugggooo + null */
*bufptr; /* Pointer into buffer */
dbyte
mode = dir-> file_mode; /* File mode bits */
int
field; /* User, group, other */
bufptr = buffer;
*bufptr++ = ((mode & S_IFDIR) ? 'd' : '-');
for (field = 0; field < 3; field++)
{
*bufptr++ = ((mode & (S_IREAD >> (field * 3))) ? 'r' : '-');
*bufptr++ = ((mode & (S_IWRITE >> (field * 3))) ? 'w' : '-');
*bufptr = ((mode & (S_IEXEC >> (field * 3))) ? 'x' : '-');
#if (defined (S_ISUID))
if (field == 0 && (mode & S_ISUID))
*bufptr = (*bufptr == 'x' ? 's' : 'S');
else
if (field == 1 && (mode & S_ISGID))
*bufptr = (*bufptr == 'x' ? 's' : 'S');
# if (defined (S_ISVTX))
else
if (field == 2 && (mode & S_ISVTX))
*bufptr = (*bufptr == 'x' ? 't' : 'T');
# endif
#endif
++bufptr;
}
*bufptr = '\0';
return (buffer);
}
/* -------------------------------------------------------------------------
* format_name -- internal
*
* Returns a static string holding the cleaned-up filename for the directory
* entry specified. Replaces any control characters by an octal string
* and appends '/' if the entry is a directory, or '*' if it is executable,
* if the full argument is TRUE.
*/
static char *
format_name (DIRST *dir, Bool full)
{
static char
buffer [NAME_MAX + 1],
*fromptr,
*bufptr;
bufptr = buffer;
for (fromptr = dir-> file_name; *fromptr; bufptr++, fromptr++)
{
*bufptr = *fromptr;
if ((byte) *bufptr < ' ')
{
sprintf (bufptr, "\\%03o", (byte) *fromptr);
bufptr += strlen (bufptr) - 1;
}
}
if (full)
{
if (dir-> file_mode & S_IFDIR)
*bufptr++ = '/';
else
if (dir-> file_mode & S_IEXEC)
*bufptr++ = '*';
}
*bufptr = '\0';
return (buffer);
}
/* -------------------------------------------------------------------------
* format_time -- internal
*
* Returns a static string holding the ASCII representation of the date and
* time for the specified directory entry. The format of the date and time
* depends on whether the file is older than 6 months, roughly:
*
* Oct 9 1995 if older than 6 months
* Jan 12 09:55 if not older than 6 months
*/
static char *
format_time (DIRST *dir)
{
static char
buffer [13], /* Returned string */
*months = "Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec";
static time_t
six_months_ago = 0;
struct tm
*file_time;
if (six_months_ago == 0)
six_months_ago = get_six_months_ago ();
file_time = safe_localtime (&dir-> file_time);
strncpy (buffer, months + file_time-> tm_mon * 4, 4);
if (dir-> file_time < six_months_ago
|| dir-> file_time > time (NULL))
snprintf (buffer + 3, sizeof (buffer) - 3,
" %2d %4d", file_time-> tm_mday,
file_time-> tm_year + 1900);
else
snprintf (buffer + 3, sizeof (buffer) - 3,
" %2d %02d:%02d", file_time-> tm_mday,
file_time-> tm_hour,
file_time-> tm_min);
return (buffer);
}
/* -------------------------------------------------------------------------
* get_six_months_ago -- internal
*
* Returns system clock 6 months ago.
*/
static time_t
get_six_months_ago ()
{
int
count,
year,
month;
long
days;
time_t
time_val;
struct tm
*time_now;
time_val = time (NULL);
time_now = safe_localtime (&time_val);
month = time_now-> tm_mon + 1;
year = time_now-> tm_year;
days = 0;
for (count = 0; count < 6; count++)
{
if (--month < 1) /* Start with last month */
{
month = 12;
year--;
}
switch (month)
{
case 2: /* Feb */
days += leap_year (year)? 29: 28;
break;
case 1: /* Jan */
case 3: /* Mar */
case 5: /* May */
case 7: /* Jul */
case 8: /* Aug */
case 10: /* Oct */
case 12: /* Dec */
days++;
case 4: /* Apr */
case 6: /* Jun */
case 9: /* Sep */
case 11: /* Nov */
days += 30;
}
}
/* 60 * 60 * 24 = 86400 sec / day */
return (time (NULL) - (long) (86400L * days));
}
/* ---------------------------------------------------------------------[<]-
Function: fix_dir
Synopsis:
Converts all strings in the DIRST into permenant values, by allocating
heap memory for each string. You must call this function if you intend
to keep a set of DIRSTs, for searching or sorting. You do not need to
call fix_dir() if you handle each call to read_dir() independently.
If you use fix_dir(), you must call free_dir() for each DIRST when you
terminate. Returns 0 if okay, -1 if there was insufficient memory or
another fatal error.
---------------------------------------------------------------------[>]-*/
int
fix_dir (DIRST *dir)
{
char
*owner,
*group,
*file_name;
/* Allocate each string */
owner = mem_strdup (dir-> owner);
group = mem_strdup (dir-> group);
file_name = mem_strdup (dir-> file_name);
/* If all okay, assign new strings and indicate everything okay */
if (owner && group && file_name)
{
dir-> owner = owner;
dir-> group = group;
dir-> file_name = file_name;
dir-> _fixed = TRUE;
return (0);
}
else
{
/* Otherwise patch things back the way they were */
if (owner)
mem_free (owner);
if (group)
mem_free (group);
if (file_name)
mem_free (file_name);
return (-1);
}
}
/* ---------------------------------------------------------------------[<]-
Function: free_dir
Synopsis:
Frees all strings used in the DIRST. You should call this function to
free space allocated by fix_dir(). If you try to call free_dir() for a
DIRST that was not fixed, you will get an error feedback, and (if you
compiled with DEBUG defined) an assertion fault. Returns 0 if okay,
-1 if there was an error. After a call to free_dir(), do not try to
access the strings in DIRST; they are all set to point to an empty
string.
---------------------------------------------------------------------[>]-*/
int
free_dir (DIRST *dir)
{
static char
*empty = "";
ASSERT (dir-> _fixed);
if (dir-> _fixed)
{
/* Free allocated strings */
mem_free (dir-> owner);
mem_free (dir-> group);
mem_free (dir-> file_name);
/* Now point the strings to an empty string */
dir-> owner = empty;
dir-> group = empty;
dir-> file_name = empty;
/* And mark the DIRST as no longer 'fixed' */
dir-> _fixed = FALSE;
return (0);
}
else
return (-1);
}
/* ---------------------------------------------------------------------[<]-
Function: load_dir_list
Synopsis:
Loads and sorts the contents of a directory. Returns a NODE pointer to
a linked list containing the directory entries. Each node is a FILEINFO
structure (mapped onto a NODE structure for purposes of manipulating the
linked list). You can ask for the directory list to be sorted in various
ways; in this case subdirectory entries are always sorted first. To
specify the sort order you pass a string consisting of one or more of
these characters, which are then used in order:
<TABLE>
n Sort by ascending name.
N Sort by descending name.
x Sort by ascending extension.
X Sort by descending extension.
t Sort by ascending time and date.
T Sort by descending time and date.
s Sort by ascending size.
S Sort by descending size.
</TABLE>
If the sort string is NULL, no sort is carried out.
---------------------------------------------------------------------[>]-*/
NODE *
load_dir_list (
const char *dir_name,
const char *sort)
{
NODE
*file_list; /* File list head */
DIRST
dir;
Bool
rc;
int
nbr_files = 0;
file_list = mem_alloc (sizeof (NODE));
if (!file_list)
return (NULL);
node_reset (file_list); /* Initialise file list */
/* Load directory */
rc = open_dir (&dir, dir_name);
while (rc)
{
add_dir_list (file_list, &dir);
nbr_files++;
rc = read_dir (&dir);
}
close_dir (&dir);
if (sort && nbr_files > 1)
sort_dir_list (file_list, sort);
return (file_list);
}
/* ---------------------------------------------------------------------[<]-
Function: free_dir_list
Synopsis:
Frees all FILELIST blocks in the specified linked list.
---------------------------------------------------------------------[>]-*/
void
free_dir_list (NODE *file_list)
{
ASSERT (file_list);
while (file_list-> next != file_list)
{
free_dir (&((FILEINFO *) file_list-> next)-> dir);
node_destroy (file_list-> next);
}
mem_free (file_list);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -