summaryrefslogtreecommitdiffstats
path: root/ls.c
diff options
context:
space:
mode:
Diffstat (limited to 'ls.c')
-rw-r--r--ls.c1055
1 files changed, 1055 insertions, 0 deletions
diff --git a/ls.c b/ls.c
new file mode 100644
index 0000000..2d093b7
--- /dev/null
+++ b/ls.c
@@ -0,0 +1,1055 @@
+/* $Header: /home/ksheff/src/e2tools/RCS/ls.c,v 0.8 2004/04/07 03:30:49 ksheff Exp $ */
+/*
+ * ls.c --- list directories
+ *
+ * Copyright (C) 1997 Theodore Ts'o. This file may be redistributed
+ * under the terms of the GNU Public License.
+ *
+ * Modified by Keith W. Sheffield <shefff@pobox.com> for inclusion with e2tools
+ */
+/*
+ * $Log: ls.c,v $
+ * Revision 0.8 2004/04/07 03:30:49 ksheff
+ * Updated usage string.
+ *
+ * Revision 0.7 2004/04/07 02:41:50 ksheff
+ * Modified to bracket files with an inode number of 0 with >< characters.
+ *
+ * Revision 0.6 2004/04/06 20:27:26 ksheff
+ * Modified to print "No files found!" for empty directories, corrected the
+ * directory name display, and fixed REGEX_OPT masking.
+ *
+ * Revision 0.5 2002/06/05 23:14:11 ksheff
+ * Fixed short display with respect to displaying the contents of multiple
+ * directories.
+ *
+ * Revision 0.4 2002/06/05 23:07:34 ksheff
+ * Allowed for multiple directory and file specifications. Added the -f
+ * option for no sorting.
+ *
+ * Revision 0.3 2002/06/03 23:00:51 ksheff
+ * Removed display code from directory iterator. A list of displayable files
+ * is now generated. This list can be sorted and displayed in a variety of
+ * ways. The -a, -c, -i, -r, and -t options are now accepted.
+ *
+ * Revision 0.2 2002/03/05 12:12:52 ksheff
+ * Removed setting optind for SCO.
+ *
+ * Revision 0.1 2002/02/27 04:46:21 ksheff
+ * initial revision
+ *
+ */
+
+
+#include "e2tools.h"
+#include "elist.h"
+#include <regex.h>
+
+/*
+ * list directory
+ */
+
+#define LONG_OPT 0x0001
+#define DELETED_OPT 0x0002
+#define REGEX_OPT 0x0004
+#define REVERSE_OPT 0x0008
+#define HIDDEN_OPT 0x0010
+#define CREATE_OPT 0x0020
+#define INODE_OPT 0x0040
+
+#define DIRECTORY_TYPE -1
+#define NORMAL_TYPE 0
+
+struct list_dir_struct
+{
+ int options;
+ regex_t *reg;
+ elist_t *files;
+};
+
+typedef struct list_file_struct
+{
+
+ char *name;
+ struct ext2_inode inode;
+ ext2_ino_t dir;
+ ext2_ino_t inode_num;
+ int entry;
+ long type;
+} ls_file_t;
+
+static const char *monstr[] =
+{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+static ext2_filsys fs;
+static int max_name_len = 0;
+
+static int
+list_dir_proc(ext2_ino_t dir, int entry, struct ext2_dir_entry *dirent,
+ int offset, int blocksize, char *buf, void *private);
+void
+free_ls_file_t(void *f);
+long
+do_list_dir(int argc, char *argv[]);
+void
+long_disp(ls_file_t *info, int *col, int options);
+void
+short_disp(ls_file_t *info, int *col, int options);
+int
+no_sort(void *n1, void *n2);
+int
+name_sort(void *n1, void *n2);
+int
+inode_sort(void *n1, void *n2);
+int
+mod_time_sort(void *n1, void *n2);
+int
+creat_time_sort(void *n1, void *n2);
+long
+add_ls_file(char *name, int namelen, ext2_ino_t dir, ext2_ino_t ino,
+ int entry, int type, struct list_dir_struct *ls);
+elist_t *
+remove_ls_dups(elist_t *list);
+
+/* Name: list_dir_proc()
+ *
+ * Description:
+ *
+ *
+ * Algorithm:
+ *
+ *
+ * Global Variables:
+ *
+ * None
+ *
+ * Arguments:
+ *
+ *
+ * Return Values:
+ *
+ *
+ * Author: Theodore Ts'o
+ * Date: 1997
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ * 02/27/02 K.Sheffield Modified for use with e2tools
+ */
+static int
+list_dir_proc(ext2_ino_t dir, int entry, struct ext2_dir_entry *dirent,
+ int offset, int blocksize, char *buf, void *private)
+{
+ struct ext2_inode inode;
+ char name[EXT2_NAME_LEN];
+ struct list_dir_struct *ls = (struct list_dir_struct *) private;
+ int thislen;
+
+ thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN) ?
+ (dirent->name_len & 0xFF) : EXT2_NAME_LEN;
+ strncpy(name, dirent->name, thislen);
+ name[thislen] = '\0';
+
+ /* skip hidden files unless we ask for them */
+ if (0 == (ls->options & HIDDEN_OPT) &&
+ name[0] == '.')
+ return(0);
+
+ if ((ls->options & REGEX_OPT) &&
+ regexec(ls->reg, name, 0, NULL, 0))
+ return(0);
+
+ return(add_ls_file(name, thislen, dir, dirent->inode, entry, NORMAL_TYPE,
+ ls));
+
+}
+
+/* Name: add_ls_file()
+ *
+ * Description:
+ *
+ *
+ * Algorithm:
+ *
+ *
+ * Global Variables:
+ *
+ * None
+ *
+ * Arguments:
+ *
+ *
+ * Return Values:
+ *
+ *
+ * Author: K.Sheffield
+ * Date: 02/27/2002
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ */
+long
+add_ls_file(char *name, int namelen, ext2_ino_t dir, ext2_ino_t ino,
+ int entry, int type, struct list_dir_struct *ls)
+{
+ ls_file_t *file_info;
+ elist_t *flist;
+
+ if (NULL == (file_info = calloc(sizeof(ls_file_t),1)))
+ {
+ perror("list_dir");
+ return(0);
+ }
+
+ file_info->dir = dir;
+
+ if (entry == DIRENT_DELETED_FILE)
+ file_info->inode_num = 0;
+ else
+ file_info->inode_num = ino;
+
+ file_info->entry = entry;
+ file_info->type = type;
+
+ if (file_info->inode_num)
+ {
+ if (read_inode(fs, file_info->inode_num, &file_info->inode))
+ {
+ free(file_info);
+ return 0;
+ }
+ }
+
+ if (name)
+ file_info->name = strdup(name);
+
+ if (NULL == (flist = elist_insert(ls->files, file_info)))
+ {
+ perror("list_dir");
+ free_ls_file_t(file_info);
+ return 0;
+ }
+ ls->files = flist;
+
+ if (max_name_len < namelen)
+ max_name_len = namelen;
+
+ return 0;
+}
+
+/* Name: free_ls_file_t()
+ *
+ * Description:
+ *
+ * This function is used to free an ls_file_t structure.
+ *
+ * Algorithm:
+ *
+ * Free the file's name if it is not NULL
+ * Free the ls_file_t structure
+ * Check to make sure the ls_file_t structure is not NULL
+ *
+ * Global Variables:
+ *
+ * None.
+ *
+ * Arguments:
+ *
+ * void *f; The structure to free
+ *
+ * Return Values:
+ *
+ * none
+ *
+ * Author: Keith W. Sheffield
+ * Date: 06/03/2002
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ *
+ */
+void free_ls_file_t(void *f)
+{
+ ls_file_t *n = (ls_file_t *) f;
+
+ if (n != NULL)
+ {
+ if (n->name != NULL)
+ free(n->name);
+ free(n);
+ }
+} /* end of free_ls_file_t */
+
+/* Name: do_list_dir()
+ *
+ * Description:
+ *
+ *
+ * Algorithm:
+ *
+ *
+ * Global Variables:
+ *
+ * None
+ *
+ * Arguments:
+ *
+ *
+ * Return Values:
+ *
+ *
+ * Author: Theodore Ts'o
+ * Date: 1997
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ * 02/27/02 K.Sheffield Modified for use with e2tools
+ * 04/06/04 K.Sheffield Modified to print "No Files Found!" for
+ * each empty directory. Corrected masking
+ * out REGEX_OPT.
+ */
+
+long
+do_list_dir(int argc, char *argv[])
+{
+ ext2_ino_t root;
+ ext2_ino_t cwd;
+ ext2_ino_t inode=0;
+ int retval;
+ int c;
+ int flags;
+ struct list_dir_struct ls;
+ char *fs_name;
+ char *last_fs_name;
+ char *path = NULL;
+ char *dup_path = NULL;
+ char *dir_name;
+ char *base_name;
+ int (*file_sort)(void *n1, void *n2) = name_sort;
+ void (*file_disp)(ls_file_t *n, int *col, int options) = short_disp;
+ elist_t *files=NULL;
+ int col=0;
+ ls_file_t *cur_file;
+ long last_type = 1;
+
+ memset(&ls, 0, sizeof(ls));
+
+ last_fs_name = NULL;
+#ifdef HAVE_OPTRESET
+ optreset = 1; /* Makes BSD getopt happy */
+#endif
+ while ((c = getopt (argc, argv, "acDd:filrt")) != EOF)
+ {
+ switch (c)
+ {
+ case 'a':
+ ls.options |= HIDDEN_OPT;
+ break;
+ case 'c':
+ ls.options |= CREATE_OPT;
+ break;
+ case 'l':
+ file_disp = long_disp;
+ break;
+ case 'D':
+ ls.options |= DELETED_OPT;
+ break;
+ case 'd':
+ fs_name = optarg;
+ if (NULL != (path = strchr(fs_name, ':')))
+ *path++ = '\0';
+ if ((retval = open_filesystem(fs_name, &fs, &root, 0)))
+ {
+ fputs(error_message(retval), stderr);
+ return(1);
+ }
+ last_fs_name = fs_name;
+ break;
+ case 'f':
+ file_sort = no_sort;
+ break;
+ case 't':
+ file_sort = mod_time_sort;
+ break;
+ case 'r':
+ ls.options |= REVERSE_OPT;
+ break;
+ case 'i':
+ file_sort = inode_sort;
+ ls.options |= INODE_OPT;
+ break;
+ }
+ }
+
+ if (argc <= optind)
+ {
+ fputs("Usage: e2ls [-acDfilrt][-d dir] file\n", stderr);
+ return(1);
+ }
+
+ if (ls.options & CREATE_OPT &&
+ (file_sort == mod_time_sort || file_disp != long_disp))
+ file_sort = creat_time_sort;
+
+ /* sort the remaining command line arguments */
+ qsort(argv+optind, argc-optind, sizeof(char *), my_strcmp);
+
+ for(c=optind;c<argc;c++)
+ {
+ fs_name = argv[c];
+
+ if (NULL != (path = strchr(fs_name, ':')))
+ *path++ = '\0';
+ else if (last_fs_name != NULL)
+ {
+ path = fs_name;
+ fs_name = last_fs_name;
+ }
+
+ /* keep a copy of the file path for later because get_file_parts() is
+ * destructive.
+ */
+
+ if (dup_path)
+ {
+ free(dup_path);
+ dup_path = NULL;
+ }
+
+ if (path)
+ dup_path = strdup(path);
+
+ if (last_fs_name == NULL || strcmp(last_fs_name, fs_name))
+ {
+ if (last_fs_name != NULL)
+ ext2fs_close(fs);
+
+ if ((retval = open_filesystem(fs_name, &fs, &root, 0)))
+ {
+ fputs(error_message(retval), stderr);
+ return(1);
+ }
+ last_fs_name = fs_name;
+ }
+
+ dir_name = NULL;
+ cwd = root;
+ ls.options &= (~REGEX_OPT);
+
+ if (path != NULL && *path != '\0')
+ {
+ if (get_file_parts(fs, root, path, &cwd, &dir_name, &base_name))
+ {
+ ext2fs_close(fs);
+ return(-1);
+ }
+
+ if (is_file_regexp(base_name))
+ {
+ if (NULL == (ls.reg = (regex_t *) make_regexp(base_name)))
+ {
+ fprintf(stderr,
+ "Error creating regular expression for %s\n",
+ base_name);
+ return(1);
+ }
+ ls.options |= REGEX_OPT;
+ inode = cwd;
+
+ }
+ /* check to see if the file name exists in the current directory
+ */
+ else if ((retval = ext2fs_namei(fs, cwd, cwd, base_name, &inode)))
+ {
+ fputs(error_message(retval), stderr);
+ ext2fs_close(fs);
+ return(1);
+ }
+ }
+ else
+ inode = root;
+
+ if(!dir_name)
+ dir_name = ".";
+
+ if (!inode)
+ continue;
+
+ flags = DIRENT_FLAG_INCLUDE_EMPTY;
+ if (ls.options & DELETED_OPT)
+ flags |= DIRENT_FLAG_INCLUDE_REMOVED;
+
+ if (retval = ext2fs_check_directory(fs, inode))
+ {
+ if (retval != EXT2_ET_NO_DIRECTORY)
+ {
+ fputs(error_message(retval), stderr);
+ ext2fs_close(fs);
+ return(1);
+ }
+
+ if(add_ls_file(dir_name, 0, cwd, 0, 0, DIRECTORY_TYPE, &ls))
+ {
+ fputs(error_message(retval), stderr);
+ ext2fs_close(fs);
+ return(1);
+ }
+
+ if(add_ls_file(base_name, strlen(base_name), cwd, inode, 0,
+ NORMAL_TYPE, &ls))
+ {
+ fputs(error_message(retval), stderr);
+ ext2fs_close(fs);
+ return(1);
+ }
+ }
+ else
+ {
+ if (ls.options & REGEX_OPT || path == NULL || *path == '\0')
+ path = dir_name;
+ else if (dup_path)
+ path = dup_path;
+
+
+ // if(add_ls_file((ls.options & REGEX_OPT) ? dir_name : path, 0, inode, 0,
+ if(add_ls_file(path, 0, inode, 0, 0, DIRECTORY_TYPE, &ls))
+ {
+ fputs(error_message(retval), stderr);
+ ext2fs_close(fs);
+ return(1);
+ }
+
+ retval = ext2fs_dir_iterate2(fs, inode, flags, 0, list_dir_proc,
+ &ls);
+ if (retval)
+ {
+ fputs(error_message(retval), stderr);
+ ext2fs_close(fs);
+ return(1);
+ }
+ }
+ }
+
+
+ elist_sort(ls.files, file_sort, ls.options & REVERSE_OPT);
+
+ ls.files = files = remove_ls_dups(ls.files);
+
+ if (files == NULL)
+ printf("No files found!");
+ else
+ {
+ while(files != NULL)
+ {
+ cur_file = (ls_file_t *)files->data;
+ if (cur_file->type == DIRECTORY_TYPE)
+ {
+ if (col > 0)
+ {
+ putchar('\n');
+ col = 0;
+ }
+ if (last_type == DIRECTORY_TYPE)
+ printf("No files found!\n");
+
+ printf("%s:", cur_file->name);
+ }
+ else
+ {
+ if (last_type == DIRECTORY_TYPE)
+ putchar('\n');
+ (file_disp)(cur_file, &col, ls.options);
+ }
+
+ last_type = cur_file->type;
+
+ files = files->next;
+ }
+ if (last_type == DIRECTORY_TYPE)
+ printf("No files found!");
+ }
+
+ putchar('\n');
+
+ elist_free(ls.files, free_ls_file_t);
+
+ ext2fs_close(fs);
+ return(0);
+}
+
+/* Name: long_disp()
+ *
+ * Description:
+ *
+ * This function displays a file's information for a long listing
+ *
+ * Algorithm:
+ *
+ * Generate the time string for the modification time
+ * Display the file's permission bits, owner, group, mod time, and name
+ *
+ * Global Variables:
+ *
+ * none
+ *
+ * Arguments:
+ *
+ * ls_file_t *info; The structure containing the file information
+ * int *col; The current column - unused
+ * int options; Options to ls
+ *
+ * Return Values:
+ *
+ * None
+ *
+ * Author: Keith W. Sheffield
+ * Date: 06/03/2002
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ * 06/06/02 K.Sheffield Increased file size width
+ * 04/06/04 K.Sheffield Modified to show entries with an inode of 0
+ * as deleted.
+ */
+void long_disp(ls_file_t *info, int *col, int options)
+{
+ char lbr, rbr;
+ char datestr[80];
+ time_t modtime;
+ struct tm *tm_p;
+
+
+ if (info->entry == DIRENT_DELETED_FILE ||
+ info->inode_num == 0)
+ {
+ lbr = '>';
+ rbr = '<';
+ }
+ else
+ {
+ lbr = rbr = ' ';
+ }
+
+
+ if (info->inode_num)
+ {
+ if (options & CREATE_OPT)
+ modtime = info->inode.i_ctime;
+ else
+ modtime = info->inode.i_mtime;
+ tm_p = localtime(&modtime);
+ sprintf(datestr, "%2d-%s-%4d %02d:%02d",
+ tm_p->tm_mday, monstr[tm_p->tm_mon],
+ 1900 + tm_p->tm_year, tm_p->tm_hour,
+ tm_p->tm_min);
+ }
+ else
+ strcpy(datestr, " ");
+
+ printf("%c%6u%c %6o %5d %5d ", lbr, info->inode_num, rbr,
+ info->inode.i_mode, info->inode.i_uid, info->inode.i_gid);
+ if (LINUX_S_ISDIR(info->inode.i_mode))
+ printf("%7d", info->inode.i_size);
+ else
+ printf("%7lld", info->inode.i_size |
+ ((__u64)info->inode.i_size_high << 32));
+ printf(" %s %s\n", datestr, info->name);
+
+} /* end of long_disp */
+
+
+/* Name: short_disp()
+ *
+ * Description:
+ *
+ * This function displays a file's information for a long listing
+ *
+ * Algorithm:
+ *
+ * Display the file's name at the appropriate column.
+ *
+ * Global Variables:
+ *
+ * none
+ *
+ * Arguments:
+ *
+ * ls_file_t *info; The structure containing the file information
+ * int *col; The current column
+ * int options; Options to ls
+ *
+ * Return Values:
+ *
+ * None
+ *
+ * Author: Keith W. Sheffield
+ * Date: 06/03/2002
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ * 04/06/04 K.Sheffield Modified to show entries with an inode of 0
+ * as deleted.
+ */
+void short_disp(ls_file_t *info, int *col, int options)
+{
+ char lbr, rbr;
+ char tmp[300];
+ int thislen;
+ static max_col_size = 0;
+
+ if (max_col_size == 0)
+ {
+ max_col_size = 80/(max_name_len + 2 + ((options & INODE_OPT) ? 8 : 0));
+ if (max_col_size == 0)
+ max_col_size = -1;
+ else
+ max_col_size = 80/max_col_size;
+ }
+
+
+ if (info->entry == DIRENT_DELETED_FILE ||
+ info->inode_num == 0)
+ {
+ lbr = '>';
+ rbr = '<';
+ }
+ else
+ {
+ lbr = 0;
+ rbr = ' ';
+ }
+
+ if (lbr == 0)
+ {
+ if (options & INODE_OPT)
+ sprintf(tmp, "%7d %s%c", info->inode_num, info->name, rbr);
+ else
+ sprintf(tmp, "%s%c", info->name, rbr);
+ }
+ else
+ {
+ if (options & INODE_OPT)
+ sprintf(tmp, "%7d %c%s%c", info->inode_num, lbr, info->name, rbr);
+ else
+ sprintf(tmp, "%c%s%c", lbr, info->name, rbr);
+ }
+
+ thislen = strlen(tmp);
+
+ if (*col + thislen > 80)
+ {
+ putchar('\n');
+ *col = 0;
+ }
+ thislen = max_col_size - thislen;
+ if (thislen < 0)
+ thislen = 0;
+
+ printf("%s%*.*s", tmp, thislen, thislen, "");
+ *col += max_col_size;
+}
+
+/* Name: no_sort()
+ *
+ * Description:
+ *
+ * This function sorts two ls_file_t structures by the file name
+ *
+ * Algorithm:
+ *
+ * Assign two ls_file_t pointers from the input void pointers
+ * Return the result of the comparison of the directories & type
+ *
+ * Global Variables:
+ *
+ * None
+ *
+ * Arguments:
+ *
+ * void *n1; The first node being compared
+ * void *n2; The second node being compared
+ *
+ * Return Values:
+ *
+ * >0 - n1 > n2
+ * =0 - n1 == n2
+ * <0 - n1 < n2
+ *
+ * Author: Keith W. Sheffield
+ * Date: 06/03/2002
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ *
+ */
+int no_sort(void *n1, void *n2)
+{
+ ls_file_t *f1 = *((ls_file_t **) n1);
+ ls_file_t *f2 = *((ls_file_t **) n2);
+ int retval;
+
+ return((retval = (f1->dir - f2->dir)) ? retval : (f1->type - f2->type));
+
+} /* end of name_sort */
+
+/* Name: name_sort()
+ *
+ * Description:
+ *
+ * This function sorts two ls_file_t structures by the file name
+ *
+ * Algorithm:
+ *
+ * Assign two ls_file_t pointers from the input void pointers
+ * Return the result of the comparison of the names
+ *
+ * Global Variables:
+ *
+ * None
+ *
+ * Arguments:
+ *
+ * void *n1; The first node being compared
+ * void *n2; The second node being compared
+ *
+ * Return Values:
+ *
+ * >0 - n1 > n2
+ * =0 - n1 == n2
+ * <0 - n1 < n2
+ *
+ * Author: Keith W. Sheffield
+ * Date: 06/03/2002
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ *
+ */
+int name_sort(void *n1, void *n2)
+{
+ ls_file_t *f1 = *((ls_file_t **) n1);
+ ls_file_t *f2 = *((ls_file_t **) n2);
+ int retval;
+
+ return((retval = (f1->dir - f2->dir)) ? retval :
+ ((retval = (f1->type - f2->type)) ? retval :
+ strcmp(f1->name, f2->name)));
+} /* end of name_sort */
+
+/* Name: inode_sort()
+ *
+ * Description:
+ *
+ * This function sorts two ls_file_t structures by the file inode number
+ *
+ * Algorithm:
+ *
+ * Assign two ls_file_t pointers from the input void pointers
+ * Return the result of the comparison of the inode numbers
+ *
+ * Global Variables:
+ *
+ * None
+ *
+ * Arguments:
+ *
+ * void *n1; The first node being compared
+ * void *n2; The second node being compared
+ *
+ * Return Values:
+ *
+ * >0 - n1 > n2
+ * =0 - n1 == n2
+ * <0 - n1 < n2
+ *
+ * Author: Keith W. Sheffield
+ * Date: 06/03/2002
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ *
+ */
+int inode_sort(void *n1, void *n2)
+{
+ ls_file_t *f1 = *((ls_file_t **) n1);
+ ls_file_t *f2 = *((ls_file_t **) n2);
+ int retval;
+
+ return((retval = (f1->dir - f2->dir)) ? retval :
+ ((retval = (f1->type - f2->type)) ? retval :
+ (f1->inode_num - f2->inode_num)));
+} /* end of inode_sort */
+
+/* Name: mod_time_sort()
+ *
+ * Description:
+ *
+ * This function sorts two ls_file_t structures by the file modification time
+ *
+ * Algorithm:
+ *
+ * Assign two ls_file_t pointers from the input void pointers
+ * Return the result of the comparison of the modification time
+ *
+ * Global Variables:
+ *
+ * None
+ *
+ * Arguments:
+ *
+ * void *n1; The first node being compared
+ * void *n2; The second node being compared
+ *
+ * Return Values:
+ *
+ * >0 - n1 > n2
+ * =0 - n1 == n2
+ * <0 - n1 < n2
+ *
+ * Author: Keith W. Sheffield
+ * Date: 06/03/2002
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ *
+ */
+int mod_time_sort(void *n1, void *n2)
+{
+ ls_file_t *f1 = *((ls_file_t **) n1);
+ ls_file_t *f2 = *((ls_file_t **) n2);
+ int retval;
+
+ return((retval = (f1->dir - f2->dir)) ? retval :
+ ((retval = (f1->type - f2->type)) ? retval :
+ (f2->inode.i_mtime - f1->inode.i_mtime)));
+
+} /* end of mod_time_sort */
+
+/* Name: creat_time_sort()
+ *
+ * Description:
+ *
+ * This function sorts two ls_file_t structures by the file creation time
+ *
+ * Algorithm:
+ *
+ * Assign two ls_file_t pointers from the input void pointers
+ * Return the result of the comparison of the creation time
+ *
+ * Global Variables:
+ *
+ * None
+ *
+ * Arguments:
+ *
+ * void *n1; The first node being compared
+ * void *n2; The second node being compared
+ *
+ * Return Values:
+ *
+ * >0 - n1 > n2
+ * =0 - n1 == n2
+ * <0 - n1 < n2
+ *
+ * Author: Keith W. Sheffield
+ * Date: 06/03/2002
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ *
+ */
+int creat_time_sort(void *n1, void *n2)
+{
+ ls_file_t *f1 = *((ls_file_t **) n1);
+ ls_file_t *f2 = *((ls_file_t **) n2);
+ int retval;
+
+ return((retval = (f1->dir - f2->dir)) ? retval :
+ ((retval = (f1->type - f2->type)) ? retval :
+ (f2->inode.i_ctime - f1->inode.i_ctime)));
+} /* end of creat_time_sort */
+
+/* Name: remove_ls_dups()
+ *
+ * Description:
+ *
+ * This function will remove the first directory node if it is the only one
+ * found. It will also remove bogus entries.
+ *
+ * Algorithm:
+ *
+ * For each node in the linked list
+ * If the current node has no data
+ * Remove it from the linked list
+ * If the current entry is a DIRECTORY_TYPE
+ * Increment the number of directories.
+ * Return the starting node in the linked list
+ *
+ * Global Variables:
+ *
+ * None.
+ *
+ * Arguments:
+ *
+ * elist *list; The linked list to process
+ *
+ * Return Values:
+ *
+ * The starting node in the linked list.
+ *
+ * Author: Keith W. Sheffield
+ * Date: 06/05/2002
+ *
+ * Modification History:
+ *
+ * MM/DD/YY Name Description
+ * 04/06/04 K.Sheffield Modified to just remove the first directory
+ * node if it is the only one found.
+ *
+ */
+elist_t * remove_ls_dups(elist_t *list)
+{
+ elist_t *start = list;
+ elist_t *next;
+ ls_file_t *cd;
+ ls_file_t *nd;
+ int cnt=0;
+
+ while(list != NULL)
+ {
+ cd = (ls_file_t *) list->data;
+ if (cd == NULL)
+ {
+ /* remove any empty nodes */
+ if (list == start)
+ start = list->next;
+ list = elist_delete(list, free_ls_file_t);
+ continue;
+ }
+ else if (cd->type == DIRECTORY_TYPE)
+ {
+ cnt++;
+ }
+ list = list->next;
+ }
+
+ /* if there is only one directory entry, delete it */
+ if (cnt == 1)
+ start = elist_delete(start, free_ls_file_t);
+
+ return(start);
+
+} /* end of remove_ls_dups */