⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sfldir.c

📁 短小精悍的C语言标准函数库。提供450个以上的可移植的算法和工具代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
    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 + -