Add optional ls file sorting, thanks to a patch from
Sterling Huxley <sterling@europa.com> -Erik
This commit is contained in:
		@@ -7,8 +7,10 @@
 | 
				
			|||||||
	* syslogd can now log messages to a remote host -- patch thanks
 | 
						* syslogd can now log messages to a remote host -- patch thanks
 | 
				
			||||||
	    to Gyepi Sam <gyepi@praxis-sw.com>
 | 
						    to Gyepi Sam <gyepi@praxis-sw.com>
 | 
				
			||||||
	* Rewrite of 'tail' to make it simpler, smaller, and more robust.  
 | 
						* Rewrite of 'tail' to make it simpler, smaller, and more robust.  
 | 
				
			||||||
	    It now weighs only 2.25k (3k when full featured).  The code it
 | 
						    It now weighs only 2.25k (3k when full featured).  The code is
 | 
				
			||||||
	    much cleaner, thanks to "Allen Soard" <esp-software@mail.hypermart.net>
 | 
						    cleaner too, thanks to Allen Soard <esp-software@mail.hypermart.net>
 | 
				
			||||||
 | 
						* Add optional ls file sorting, thanks to a patch from 
 | 
				
			||||||
 | 
						    Sterling Huxley <sterling@europa.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	 -Erik Andersen
 | 
						 -Erik Andersen
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -161,6 +161,9 @@
 | 
				
			|||||||
// enable ls -p and -F
 | 
					// enable ls -p and -F
 | 
				
			||||||
#define BB_FEATURE_LS_FILETYPES
 | 
					#define BB_FEATURE_LS_FILETYPES
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					// sort the file names
 | 
				
			||||||
 | 
					#define BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
// enable ls -R
 | 
					// enable ls -R
 | 
				
			||||||
#define BB_FEATURE_LS_RECURSIVE
 | 
					#define BB_FEATURE_LS_RECURSIVE
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,6 +90,14 @@
 | 
				
			|||||||
#define MINOR(dev) ((dev)&0xff)
 | 
					#define MINOR(dev) ((dev)&0xff)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
					struct dnode {				/* the basic node */
 | 
				
			||||||
 | 
						char *name;				/* the dir entry name */
 | 
				
			||||||
 | 
						char *fullname;			/* the dir entry name */
 | 
				
			||||||
 | 
						struct stat dstat;		/* the file stat info */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					typedef struct dnode dnode_t;
 | 
				
			||||||
 | 
					#endif 
 | 
				
			||||||
static unsigned char display_fmt = FMT_AUTO;
 | 
					static unsigned char display_fmt = FMT_AUTO;
 | 
				
			||||||
static unsigned short opts = 0;
 | 
					static unsigned short opts = 0;
 | 
				
			||||||
static unsigned short column = 0;
 | 
					static unsigned short column = 0;
 | 
				
			||||||
@@ -328,6 +336,48 @@ static void list_single(const char *name, struct stat *info,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
					void shellsort(struct dnode *dn[], int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct dnode *temp;
 | 
				
			||||||
 | 
					    int gap, i, j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* shell short the array */
 | 
				
			||||||
 | 
					    for (gap= size/2; gap>0; gap /=2) {
 | 
				
			||||||
 | 
					        for (i=gap; i<size; i++) {
 | 
				
			||||||
 | 
					            for (j= i-gap; j>=0; j-=gap) {
 | 
				
			||||||
 | 
					                if (strcmp(dn[j]->name, dn[j+gap]->name) <= 0)
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                temp= dn[j];
 | 
				
			||||||
 | 
					                dn[j]= dn[j+gap];
 | 
				
			||||||
 | 
					                dn[j+gap]= temp;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void showdnodes(struct dnode *dn[], int nfiles)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int nf, nc;
 | 
				
			||||||
 | 
						int ncols, fpc, i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ncols= (int)(terminal_width / (column_width + COLUMN_GAP));
 | 
				
			||||||
 | 
						/* files per column.  The +1 means the last col is shorter than others */
 | 
				
			||||||
 | 
						fpc= (nfiles / ncols) + 1;
 | 
				
			||||||
 | 
						for (nf=0; nf<fpc; nf++) {
 | 
				
			||||||
 | 
							for (nc=0; nc<ncols; nc++) {
 | 
				
			||||||
 | 
								/* reach into the array based on the column and row */
 | 
				
			||||||
 | 
								i= (nc * fpc) + nf;
 | 
				
			||||||
 | 
								if (i >= nfiles) {
 | 
				
			||||||
 | 
									newline();
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									list_single(dn[i]->name, &dn[i]->dstat, dn[i]->fullname);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 **
 | 
					 **
 | 
				
			||||||
 ** List the given file or directory, expanding a directory
 | 
					 ** List the given file or directory, expanding a directory
 | 
				
			||||||
@@ -341,6 +391,11 @@ static int list_item(const char *name)
 | 
				
			|||||||
	DIR *dir;
 | 
						DIR *dir;
 | 
				
			||||||
	struct dirent *entry;
 | 
						struct dirent *entry;
 | 
				
			||||||
	char fullname[BUFSIZ + 1], *fnend;
 | 
						char fullname[BUFSIZ + 1], *fnend;
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
						int ni=0, nfiles=0;
 | 
				
			||||||
 | 
						struct dnode **dnp;
 | 
				
			||||||
 | 
						dnode_t *cur;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (lstat(name, &info))
 | 
						if (lstat(name, &info))
 | 
				
			||||||
		goto listerr;
 | 
							goto listerr;
 | 
				
			||||||
@@ -369,6 +424,18 @@ static int list_item(const char *name)
 | 
				
			|||||||
	column_width = 0;
 | 
						column_width = 0;
 | 
				
			||||||
	while ((entry = readdir(dir)) != NULL) {
 | 
						while ((entry = readdir(dir)) != NULL) {
 | 
				
			||||||
		short w = strlen(entry->d_name);
 | 
							short w = strlen(entry->d_name);
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
							const char *en = entry->d_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (en[0] == '.') {
 | 
				
			||||||
 | 
								if (!en[1] || (en[1] == '.' && !en[2])) {	/* . or .. */
 | 
				
			||||||
 | 
									if (!(opts & DISP_DOT))
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
								} else if (!(opts & DISP_HIDDEN))
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							nfiles++;	/* count how many files there will be */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (column_width < w)
 | 
							if (column_width < w)
 | 
				
			||||||
			column_width = w;
 | 
								column_width = w;
 | 
				
			||||||
@@ -381,6 +448,12 @@ static int list_item(const char *name)
 | 
				
			|||||||
	if (!dir)
 | 
						if (!dir)
 | 
				
			||||||
		goto listerr;
 | 
							goto listerr;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
						/* now that we know how many files there are
 | 
				
			||||||
 | 
						 * allocate memory for an array to hold dnode pointers
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						dnp= (struct dnode **)calloc((size_t)nfiles, (size_t)(sizeof(struct dnode *)));
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* List the contents */
 | 
						/* List the contents */
 | 
				
			||||||
@@ -402,11 +475,24 @@ static int list_item(const char *name)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		/* FIXME: avoid stat if not required */
 | 
							/* FIXME: avoid stat if not required */
 | 
				
			||||||
		strcpy(fnend, entry->d_name);
 | 
							strcpy(fnend, entry->d_name);
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
							/* allocate memory for a node and memory for the file name */
 | 
				
			||||||
 | 
							cur= (struct dnode *)malloc(sizeof(struct dnode));
 | 
				
			||||||
 | 
							cur->fullname= strcpy((char *)malloc(strlen(fullname)+1), fullname);
 | 
				
			||||||
 | 
							cur->name= cur->fullname + (int)(fnend - fullname) ;
 | 
				
			||||||
 | 
							lstat(fullname, &cur->dstat);   /* get file stat info into node */
 | 
				
			||||||
 | 
							dnp[ni++]= cur;   /* save pointer to node in array */
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
		if (lstat(fullname, &info))
 | 
							if (lstat(fullname, &info))
 | 
				
			||||||
			goto direrr;		/* (shouldn't fail) */
 | 
								goto direrr;		/* (shouldn't fail) */
 | 
				
			||||||
		list_single(entry->d_name, &info, fullname);
 | 
							list_single(entry->d_name, &info, fullname);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	closedir(dir);
 | 
						closedir(dir);
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
						shellsort(dnp, nfiles);
 | 
				
			||||||
 | 
						showdnodes(dnp, nfiles);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts & DISP_DIRNAME) {      /* separate the directory */
 | 
						if (opts & DISP_DIRNAME) {      /* separate the directory */
 | 
				
			||||||
		if (column) {
 | 
							if (column) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										86
									
								
								ls.c
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								ls.c
									
									
									
									
									
								
							@@ -90,6 +90,14 @@
 | 
				
			|||||||
#define MINOR(dev) ((dev)&0xff)
 | 
					#define MINOR(dev) ((dev)&0xff)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
					struct dnode {				/* the basic node */
 | 
				
			||||||
 | 
						char *name;				/* the dir entry name */
 | 
				
			||||||
 | 
						char *fullname;			/* the dir entry name */
 | 
				
			||||||
 | 
						struct stat dstat;		/* the file stat info */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					typedef struct dnode dnode_t;
 | 
				
			||||||
 | 
					#endif 
 | 
				
			||||||
static unsigned char display_fmt = FMT_AUTO;
 | 
					static unsigned char display_fmt = FMT_AUTO;
 | 
				
			||||||
static unsigned short opts = 0;
 | 
					static unsigned short opts = 0;
 | 
				
			||||||
static unsigned short column = 0;
 | 
					static unsigned short column = 0;
 | 
				
			||||||
@@ -328,6 +336,48 @@ static void list_single(const char *name, struct stat *info,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
					void shellsort(struct dnode *dn[], int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct dnode *temp;
 | 
				
			||||||
 | 
					    int gap, i, j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* shell short the array */
 | 
				
			||||||
 | 
					    for (gap= size/2; gap>0; gap /=2) {
 | 
				
			||||||
 | 
					        for (i=gap; i<size; i++) {
 | 
				
			||||||
 | 
					            for (j= i-gap; j>=0; j-=gap) {
 | 
				
			||||||
 | 
					                if (strcmp(dn[j]->name, dn[j+gap]->name) <= 0)
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                temp= dn[j];
 | 
				
			||||||
 | 
					                dn[j]= dn[j+gap];
 | 
				
			||||||
 | 
					                dn[j+gap]= temp;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void showdnodes(struct dnode *dn[], int nfiles)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int nf, nc;
 | 
				
			||||||
 | 
						int ncols, fpc, i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ncols= (int)(terminal_width / (column_width + COLUMN_GAP));
 | 
				
			||||||
 | 
						/* files per column.  The +1 means the last col is shorter than others */
 | 
				
			||||||
 | 
						fpc= (nfiles / ncols) + 1;
 | 
				
			||||||
 | 
						for (nf=0; nf<fpc; nf++) {
 | 
				
			||||||
 | 
							for (nc=0; nc<ncols; nc++) {
 | 
				
			||||||
 | 
								/* reach into the array based on the column and row */
 | 
				
			||||||
 | 
								i= (nc * fpc) + nf;
 | 
				
			||||||
 | 
								if (i >= nfiles) {
 | 
				
			||||||
 | 
									newline();
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									list_single(dn[i]->name, &dn[i]->dstat, dn[i]->fullname);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 **
 | 
					 **
 | 
				
			||||||
 ** List the given file or directory, expanding a directory
 | 
					 ** List the given file or directory, expanding a directory
 | 
				
			||||||
@@ -341,6 +391,11 @@ static int list_item(const char *name)
 | 
				
			|||||||
	DIR *dir;
 | 
						DIR *dir;
 | 
				
			||||||
	struct dirent *entry;
 | 
						struct dirent *entry;
 | 
				
			||||||
	char fullname[BUFSIZ + 1], *fnend;
 | 
						char fullname[BUFSIZ + 1], *fnend;
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
						int ni=0, nfiles=0;
 | 
				
			||||||
 | 
						struct dnode **dnp;
 | 
				
			||||||
 | 
						dnode_t *cur;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (lstat(name, &info))
 | 
						if (lstat(name, &info))
 | 
				
			||||||
		goto listerr;
 | 
							goto listerr;
 | 
				
			||||||
@@ -369,6 +424,18 @@ static int list_item(const char *name)
 | 
				
			|||||||
	column_width = 0;
 | 
						column_width = 0;
 | 
				
			||||||
	while ((entry = readdir(dir)) != NULL) {
 | 
						while ((entry = readdir(dir)) != NULL) {
 | 
				
			||||||
		short w = strlen(entry->d_name);
 | 
							short w = strlen(entry->d_name);
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
							const char *en = entry->d_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (en[0] == '.') {
 | 
				
			||||||
 | 
								if (!en[1] || (en[1] == '.' && !en[2])) {	/* . or .. */
 | 
				
			||||||
 | 
									if (!(opts & DISP_DOT))
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
								} else if (!(opts & DISP_HIDDEN))
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							nfiles++;	/* count how many files there will be */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (column_width < w)
 | 
							if (column_width < w)
 | 
				
			||||||
			column_width = w;
 | 
								column_width = w;
 | 
				
			||||||
@@ -381,6 +448,12 @@ static int list_item(const char *name)
 | 
				
			|||||||
	if (!dir)
 | 
						if (!dir)
 | 
				
			||||||
		goto listerr;
 | 
							goto listerr;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
						/* now that we know how many files there are
 | 
				
			||||||
 | 
						 * allocate memory for an array to hold dnode pointers
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						dnp= (struct dnode **)calloc((size_t)nfiles, (size_t)(sizeof(struct dnode *)));
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* List the contents */
 | 
						/* List the contents */
 | 
				
			||||||
@@ -402,11 +475,24 @@ static int list_item(const char *name)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		/* FIXME: avoid stat if not required */
 | 
							/* FIXME: avoid stat if not required */
 | 
				
			||||||
		strcpy(fnend, entry->d_name);
 | 
							strcpy(fnend, entry->d_name);
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
							/* allocate memory for a node and memory for the file name */
 | 
				
			||||||
 | 
							cur= (struct dnode *)malloc(sizeof(struct dnode));
 | 
				
			||||||
 | 
							cur->fullname= strcpy((char *)malloc(strlen(fullname)+1), fullname);
 | 
				
			||||||
 | 
							cur->name= cur->fullname + (int)(fnend - fullname) ;
 | 
				
			||||||
 | 
							lstat(fullname, &cur->dstat);   /* get file stat info into node */
 | 
				
			||||||
 | 
							dnp[ni++]= cur;   /* save pointer to node in array */
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
		if (lstat(fullname, &info))
 | 
							if (lstat(fullname, &info))
 | 
				
			||||||
			goto direrr;		/* (shouldn't fail) */
 | 
								goto direrr;		/* (shouldn't fail) */
 | 
				
			||||||
		list_single(entry->d_name, &info, fullname);
 | 
							list_single(entry->d_name, &info, fullname);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	closedir(dir);
 | 
						closedir(dir);
 | 
				
			||||||
 | 
					#ifdef BB_FEATURE_LS_SORTFILES
 | 
				
			||||||
 | 
						shellsort(dnp, nfiles);
 | 
				
			||||||
 | 
						showdnodes(dnp, nfiles);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts & DISP_DIRNAME) {      /* separate the directory */
 | 
						if (opts & DISP_DIRNAME) {      /* separate the directory */
 | 
				
			||||||
		if (column) {
 | 
							if (column) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user