[BusyBox-cvs] busybox/fileutils ls.c,1.94,1.95

Glenn McGrath bug1 at busybox.net
Mon Jan 6 01:11:53 UTC 2003


Update of /var/cvs/busybox/fileutils
In directory winder:/tmp/cvs-serv22143/fileutils

Modified Files:
	ls.c 
Log Message:
Correct column width for tab completion and ls


Index: ls.c
===================================================================
RCS file: /var/cvs/busybox/fileutils/ls.c,v
retrieving revision 1.94
retrieving revision 1.95
diff -u -d -r1.94 -r1.95
--- ls.c	28 Nov 2002 11:27:24 -0000	1.94
+++ ls.c	6 Jan 2003 01:11:49 -0000	1.95
@@ -43,11 +43,9 @@
 
 enum {
 	TERMINAL_WIDTH = 80,	/* use 79 if terminal has linefold bug */
-	COLUMN_WIDTH = 14,	/* default if AUTOWIDTH not defined */
 	COLUMN_GAP = 2,		/* includes the file type char */
 };
 
-
 /************************************************************************/
 
 #include <sys/types.h>
@@ -167,7 +165,7 @@
 };
 typedef struct dnode dnode_t;
 
-static struct dnode **list_dir(char *);
+static struct dnode **list_dir(const char *);
 static struct dnode **dnalloc(int);
 static int list_single(struct dnode *);
 
@@ -186,14 +184,12 @@
 static unsigned int follow_links = FALSE;
 #endif
 
-static unsigned short column = 0;
-
 #ifdef CONFIG_FEATURE_AUTOWIDTH
 static unsigned short terminal_width = TERMINAL_WIDTH;
-static unsigned short column_width = COLUMN_WIDTH;
 static unsigned short tabstops = COLUMN_GAP;
 #else
-static unsigned short column_width = COLUMN_WIDTH;
+#define tabstops COLUMN_GAP
+#define terminal_width TERMINAL_WIDTH
 #endif
 
 static int status = EXIT_SUCCESS;
@@ -202,35 +198,31 @@
 static unsigned long ls_disp_hr = 0;
 #endif
 
-static int my_stat(struct dnode *cur)
+static struct dnode *my_stat(char *fullname, char *name)
 {
+	struct stat dstat;
+	struct dnode *cur;
+
 #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
 	if (follow_links) {
-		if (stat(cur->fullname, &cur->dstat)) {
-			perror_msg("%s", cur->fullname);
+		if (stat(fullname, &dstat)) {
+			perror_msg("%s", fullname);
 			status = EXIT_FAILURE;
-			free(cur->fullname);
-			free(cur);
-			return -1;
+			return 0;
 		}
 	} else
 #endif
-	if (lstat(cur->fullname, &cur->dstat)) {
-		perror_msg("%s", cur->fullname);
+	if (lstat(fullname, &dstat)) {
+		perror_msg("%s", fullname);
 		status = EXIT_FAILURE;
-		free(cur->fullname);
-		free(cur);
-		return -1;
-	}
 	return 0;
-}
-
-static void newline(void)
-{
-	if (column > 0) {
-		putchar('\n');
-		column = 0;
 	}
+
+	cur = (struct dnode *) xmalloc(sizeof(struct dnode));
+	cur->fullname = fullname;
+	cur->name = name;
+	cur->dstat = dstat;
+	return cur;
 }
 
 /*----------------------------------------------------------------------*/
@@ -239,7 +231,6 @@
 {
 	/* Check wheter the file is existing (if so, color it red!) */
 	if (errno == ENOENT) {
-		errno = 0;
 		return '\037';
 	}
 	if (LIST_EXEC && S_ISREG(mode)
@@ -272,24 +263,6 @@
 #endif
 
 /*----------------------------------------------------------------------*/
-static void nexttabstop(void)
-{
-	static short nexttab = 0;
-	int n = 0;
-
-	if (column > 0) {
-		n = nexttab - column;
-		if (n < 1)
-			n = 1;
-		while (n--) {
-			putchar(' ');
-			column++;
-		}
-	}
-	nexttab = column + column_width + COLUMN_GAP;
-}
-
-/*----------------------------------------------------------------------*/
 static int is_subdir(struct dnode *dn)
 {
 	return (S_ISDIR(dn->dstat.st_mode) && strcmp(dn->name, ".") != 0 &&
@@ -437,7 +410,11 @@
 		cmp = 1;
 	if (dif == 0) {
 		/* sort by name- may be a tie_breaker for time or size cmp */
+#ifdef CONFIG_LOCALE_SUPPORT
+		dif = strcoll(d1->name, d2->name);
+#else
 		dif = strcmp(d1->name, d2->name);
+#endif
 		if (dif > 0)
 			cmp = 1;
 		if (dif < 0)
@@ -479,46 +456,40 @@
 static void showfiles(struct dnode **dn, int nfiles)
 {
 	int i, ncols, nrows, row, nc;
-
-#ifdef CONFIG_FEATURE_AUTOWIDTH
-	int len;
-#endif
+	int column = 0;
+	int nexttab = 0;
+	int column_width = 0; /* for STYLE_LONG and STYLE_SINGLE not used */
 
 	if (dn == NULL || nfiles < 1)
 		return;
 
-#ifdef CONFIG_FEATURE_AUTOWIDTH
+	switch (style_fmt) {
+	case STYLE_LONG:        /* one record per line, extended info */
+	case STYLE_SINGLE:      /* one record per line */
+		ncols = 1;
+		break;
+	default:
 	/* find the longest file name-  use that as the column width */
-	column_width = 0;
 	for (i = 0; i < nfiles; i++) {
-		len = strlen(dn[i]->name) +
+			int len = strlen(dn[i]->name) +
 			((list_fmt & LIST_INO) ? 8 : 0) +
 			((list_fmt & LIST_BLOCKS) ? 5 : 0);
 		if (column_width < len)
 			column_width = len;
 	}
-	ncols = (int) (terminal_width / (column_width + COLUMN_GAP));
-#else
-	ncols = TERMINAL_WIDTH;
-#endif
-	switch (style_fmt) {
-	case STYLE_LONG:	/* one record per line, extended info */
-	case STYLE_SINGLE:	/* one record per line */
-		ncols = 1;
-		break;
+		column_width += tabstops;
+		ncols = (int) (terminal_width / column_width);
 	}
 
 	if (ncols > 1) {
 		nrows = nfiles / ncols;
+		if ((nrows * ncols) < nfiles)
+			nrows++;                /* round up fractionals */
 	} else {
 		nrows = nfiles;
 		ncols = 1;
 	}
-	if ((nrows * ncols) < nfiles)
-		nrows++;		/* round up fractionals */
 
-	if (nrows > nfiles)
-		nrows = nfiles;
 	for (row = 0; row < nrows; row++) {
 		for (nc = 0; nc < ncols; nc++) {
 			/* reach into the array based on the column and row */
@@ -526,11 +497,19 @@
 			if (disp_opts & DISP_ROWS)
 				i = (row * ncols) + nc;	/* display across row */
 			if (i < nfiles) {
-				nexttabstop();
-				list_single(dn[i]);
+				if (column > 0) {
+					nexttab -= column;
+					while (nexttab--) {
+						putchar(' ');
+						column++;
+					}
 			}
+				nexttab = column + column_width;
+				column += list_single(dn[i]);
 		}
-		newline();
+		}
+		putchar('\n');
+		column = 0;
 	}
 }
 
@@ -580,7 +559,7 @@
 }
 
 /*----------------------------------------------------------------------*/
-static struct dnode **list_dir(char *path)
+static struct dnode **list_dir(const char *path)
 {
 	struct dnode *dn, *cur, **dnp;
 	struct dirent *entry;
@@ -599,18 +578,21 @@
 		return (NULL);	/* could not open the dir */
 	}
 	while ((entry = readdir(dir)) != NULL) {
+		char *fullname;
+
 		/* are we going to list the file- it may be . or .. or a hidden file */
-		if ((strcmp(entry->d_name, ".") == 0) && !(disp_opts & DISP_DOT))
-			continue;
-		if ((strcmp(entry->d_name, "..") == 0) && !(disp_opts & DISP_DOT))
+		if (entry->d_name[0] == '.') {
+			if ((entry->d_name[1] == 0 || (
+				entry->d_name[1] == '.'
+				&& entry->d_name[2] == 0))
+					&& !(disp_opts & DISP_DOT))
 			continue;
-		if ((entry->d_name[0] == '.') && !(disp_opts & DISP_HIDDEN))
+			if (!(disp_opts & DISP_HIDDEN))
 			continue;
-		cur = (struct dnode *) xmalloc(sizeof(struct dnode));
-		cur->fullname = concat_path_file(path, entry->d_name);
-		cur->name = cur->fullname +
-			(strlen(cur->fullname) - strlen(entry->d_name));
-		if (my_stat(cur))
+		}
+		fullname = concat_path_file(path, entry->d_name);
+		cur = my_stat(fullname, strrchr(fullname, '/') + 1);
+		if (!cur)
 			continue;
 		cur->next = dn;
 		dn = cur;
@@ -621,7 +603,7 @@
 	/* now that we know how many files there are
 	   ** allocate memory for an array to hold dnode pointers
 	 */
-	if (nfiles < 1)
+	if (dn == NULL)
 		return (NULL);
 	dnp = dnalloc(nfiles);
 	for (i = 0, cur = dn; i < nfiles; i++) {
@@ -635,10 +617,10 @@
 /*----------------------------------------------------------------------*/
 static int list_single(struct dnode *dn)
 {
-	int i;
+	int i, column = 0;
 
 #ifdef CONFIG_FEATURE_LS_USERNAME
-	char scratch[BUFSIZ + 1];
+	char scratch[16];
 #endif
 #ifdef CONFIG_FEATURE_LS_TIMESTAMPS
 	char *filetime;
@@ -649,7 +631,7 @@
 	char append;
 #endif
 
-	if (dn == NULL || dn->fullname == NULL)
+	if (dn->fullname == NULL)
 		return (0);
 
 #ifdef CONFIG_FEATURE_LS_TIMESTAMPS
@@ -667,29 +649,20 @@
 	for (i = 0; i <= 31; i++) {
 		switch (list_fmt & (1 << i)) {
 		case LIST_INO:
-			printf("%7ld ", (long int) dn->dstat.st_ino);
-			column += 8;
+			column += printf("%7ld ", (long int) dn->dstat.st_ino);
 			break;
 		case LIST_BLOCKS:
-#ifdef CONFIG_FEATURE_HUMAN_READABLE
-			printf("%6s ", make_human_readable_str(dn->dstat.st_blocks >> 1,
-					KILOBYTE, (ls_disp_hr == TRUE) ? 0 : KILOBYTE));
-#else
 #if _FILE_OFFSET_BITS == 64
-			printf("%4lld ", dn->dstat.st_blocks >> 1);
+			column += printf("%4lld ", dn->dstat.st_blocks >> 1);
 #else
-			printf("%4ld ", dn->dstat.st_blocks >> 1);
-#endif
+			column += printf("%4ld ", dn->dstat.st_blocks >> 1);
 #endif
-			column += 5;
 			break;
 		case LIST_MODEBITS:
-			printf("%-10s ", (char *) mode_string(dn->dstat.st_mode));
-			column += 10;
+			column += printf("%-10s ", (char *) mode_string(dn->dstat.st_mode));
 			break;
 		case LIST_NLINKS:
-			printf("%4ld ", (long) dn->dstat.st_nlink);
-			column += 10;
+			column += printf("%4ld ", (long) dn->dstat.st_nlink);
 			break;
 		case LIST_ID_NAME:
 #ifdef CONFIG_FEATURE_LS_USERNAME
@@ -701,29 +674,28 @@
 			break;
 #endif
 		case LIST_ID_NUMERIC:
-			printf("%-8d %-8d", dn->dstat.st_uid, dn->dstat.st_gid);
-			column += 17;
+			column += printf("%-8d %-8d", dn->dstat.st_uid, dn->dstat.st_gid);
 			break;
 		case LIST_SIZE:
 		case LIST_DEV:
 			if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) {
-				printf("%4d, %3d ", (int) MAJOR(dn->dstat.st_rdev),
+				column += printf("%4d, %3d ", (int) MAJOR(dn->dstat.st_rdev),
 					   (int) MINOR(dn->dstat.st_rdev));
 			} else {
 #ifdef CONFIG_FEATURE_HUMAN_READABLE
 				if (ls_disp_hr == TRUE) {
-					printf("%8s ", make_human_readable_str(dn->dstat.st_size, 1, 0));
+					column += printf("%9s ",
+							make_human_readable_str(dn->dstat.st_size, 1, 0));
 				} else
 #endif
 				{
 #if _FILE_OFFSET_BITS == 64
-					printf("%9lld ", (long long) dn->dstat.st_size);
+					column += printf("%9lld ", (long long) dn->dstat.st_size);
 #else
-					printf("%9ld ", dn->dstat.st_size);
+					column += printf("%9ld ", dn->dstat.st_size);
 #endif
 				}
 			}
-			column += 10;
 			break;
 #ifdef CONFIG_FEATURE_LS_TIMESTAMPS
 		case LIST_FULLTIME:
@@ -752,13 +724,12 @@
 					   fgcolor(info.st_mode));
 			}
 #endif
-			printf("%s", dn->name);
+			column += printf("%s", dn->name);
 #ifdef CONFIG_FEATURE_LS_COLOR
 			if (show_color) {
 				printf("\033[0m");
 			}
 #endif
-			column += strlen(dn->name);
 			break;
 		case LIST_SYMLINK:
 			if (S_ISLNK(dn->dstat.st_mode)) {
@@ -778,13 +749,12 @@
 							   fgcolor(info.st_mode));
 					}
 #endif
-					printf("%s", lpath);
+					column += printf("%s", lpath) + 4;
 #ifdef CONFIG_FEATURE_LS_COLOR
 					if (show_color) {
 						printf("\033[0m");
 					}
 #endif
-					column += strlen(lpath) + 4;
 					free(lpath);
 				}
 			}
@@ -800,7 +770,7 @@
 		}
 	}
 
-	return (0);
+	return column;
 }
 
 /*----------------------------------------------------------------------*/
@@ -830,8 +800,6 @@
 #endif
 #ifdef CONFIG_FEATURE_AUTOWIDTH
 	ioctl(fileno(stdout), TIOCGWINSZ, &win);
-	if (win.ws_row > 4)
-		column_width = win.ws_row - 2;
 	if (win.ws_col > 0)
 		terminal_width = win.ws_col - 1;
 #endif
@@ -1025,10 +993,10 @@
 	/* stuff the command line file names into an dnode array */
 	dn = NULL;
 	for (oi = 0; oi < ac; oi++) {
-		cur = (struct dnode *) xmalloc(sizeof(struct dnode));
-		cur->fullname = xstrdup(av[oi]);
-		cur->name = cur->fullname;
-		if (my_stat(cur))
+		char *fullname = xstrdup(av[oi]);
+
+		cur = my_stat(fullname, fullname);
+		if (!cur)
 			continue;
 		cur->next = dn;
 		dn = cur;




More information about the busybox-cvs mailing list