Index: uspace/app/bdsh/cmds/modules/ls/ls.c
===================================================================
--- uspace/app/bdsh/cmds/modules/ls/ls.c	(revision 1e2629f9aff65706184989b3d1f58ea9b492a640)
+++ uspace/app/bdsh/cmds/modules/ls/ls.c	(revision ba63912e51ad2a68c560783e14e7e218b836b74d)
@@ -48,6 +48,20 @@
 #include "util.h"
 #include "entry.h"
-#include "ls.h"
 #include "cmds.h"
+
+/* Various values that can be returned by ls_scope() */
+#define LS_BOGUS 0
+#define LS_FILE  1
+#define LS_DIR   2
+
+/** Structure to represent a directory entry.
+ *
+ * Useful to keep together important informations
+ * for sorting directory entries.
+ */
+struct dir_elem_t {
+	char *name;
+	struct stat s;
+};
 
 static const char *cmdname = "ls";
@@ -59,28 +73,46 @@
 };
 
+/** Print an entry.
+ *
+ * ls_print currently does nothing more than print the entry.
+ * In the future, we will likely pass the absolute path, and
+ * some sort of ls_options structure that controls how each
+ * entry is printed and what is printed about it.
+ *
+ * Now we just print basic DOS style lists.
+ *
+ * @param de		Directory element.
+ */
+static void ls_print(struct dir_elem_t *de)
+{
+	if (de->s.is_file)
+		printf("%-40s\t%llu\n", de->name, (long long) de->s.size);
+	else if (de->s.is_directory)
+		printf("%-40s\t<dir>\n", de->name);
+	else
+		printf("%-40s\n", de->name);
+}
+
+
 /** Compare 2 directory elements.
  *
  * It compares 2 elements of a directory : a file is considered
- * as lower than a directory, and if they have the same type,
+ * as bigger than a directory, and if they have the same type,
  * they are compared alphabetically.
  *
  * @param a		Pointer to the structure of the first element.
  * @param b		Pointer to the structure of the second element.
- * @param arg	Pointer for an other and optionnal argument.
- *
- * @return		-1 if a < b,
- *				1 otherwise.
+ * @param arg		Pointer for an other and optionnal argument.
+ *
+ * @return		-1 if a < b, 1 otherwise.
  */
 static int ls_cmp(void *a, void *b, void *arg)
 {
-	int a_isdir = (*((struct dir_elem_t *)a)).isdir;
-	char * a_name = (*((struct dir_elem_t *)a)).name;
-	
-	int b_isdir = (*((struct dir_elem_t *)b)).isdir;
-	char * b_name = (*((struct dir_elem_t *)b)).name;
-	
-	if ((!a_isdir && b_isdir)
-		|| (((!b_isdir && !a_isdir) || (b_isdir && a_isdir))
-		&& str_cmp(a_name, b_name) < 0))
+	struct dir_elem_t *da = a;
+	struct dir_elem_t *db = b;
+	
+	if ((da->s.is_directory && db->s.is_file) ||
+	    ((da->s.is_directory == db->s.is_directory) &&
+	    str_cmp(da->name, db->name) < 0))
 		return -1;
 	else
@@ -100,152 +132,76 @@
 {
 	int alloc_blocks = 20;
-	int i = 0;
+	int i;
 	int nbdirs = 0;
-	int rc = 0;
-	char * buff = NULL;
-	struct dir_elem_t * tmp = NULL;
-	struct dir_elem_t * tosort = NULL;
-	struct dirent * dp = NULL;
-	struct stat s;
-	
-	if (! dirp)
+	int rc;
+	int len;
+	char *buff;
+	struct dir_elem_t *tmp;
+	struct dir_elem_t *tosort;
+	struct dirent *dp;
+	
+	if (!dirp)
 		return;
 
-	buff = (char *)malloc(PATH_MAX);
-	if (NULL == buff) {
+	buff = (char *) malloc(PATH_MAX);
+	if (!buff) {
 		cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
 		return;
 	}
-	memset(buff, 0, sizeof(buff));
-	
-	if (!sort) {
-		while ((dp = readdir(dirp))) {
-			memset(buff, 0, sizeof(buff));
-			/* Don't worry if inserting a double slash, this will be fixed by
-			 * absolutize() later with subsequent calls to open() or readdir() */
-			snprintf(buff, PATH_MAX - 1, "%s/%s", d, dp->d_name);
-			ls_print(dp->d_name, buff);
-		}
-
-		free(buff);
-
-		return;
-	}
-	
-	tosort = (struct dir_elem_t *)malloc(alloc_blocks*sizeof(struct dir_elem_t));
-	if (NULL == tosort) {
+	
+	tosort = (struct dir_elem_t *) malloc(alloc_blocks * sizeof(*tosort));
+	if (!tosort) {
 		cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
 		free(buff);
 		return;
 	}
-	memset(tosort, 0, sizeof(tosort));
 	
 	while ((dp = readdir(dirp))) {
-		nbdirs++;
-		
-		if (nbdirs > alloc_blocks) {
+		if (nbdirs + 1 > alloc_blocks) {
 			alloc_blocks += alloc_blocks;
 			
-			tmp = (struct dir_elem_t *)realloc(tosort,
-					alloc_blocks*sizeof(struct dir_elem_t));
-			if (NULL == tmp) {
+			tmp = (struct dir_elem_t *) realloc(tosort,
+			    alloc_blocks * sizeof(struct dir_elem_t));
+			if (!tmp) {
 				cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
-				for(i=0;i<(nbdirs-1);i++) {
-					free(tosort[i].name);
-				}
-				free(tosort);
-				free(buff);
-				return;
+				goto out;
 			}
-			
 			tosort = tmp;
 		}
 		
-		// fill the name field
-		tosort[nbdirs-1].name = (char *)malloc(str_length(dp->d_name)+1);
-		if (NULL == tosort[nbdirs-1].name) {
+		/* fill the name field */
+		tosort[nbdirs].name = (char *) malloc(str_length(dp->d_name) + 1);
+		if (!tosort[nbdirs].name) {
 			cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
-			for(i=0;i<(nbdirs-1);i++) {
-				free(tosort[i].name);
-			}
-			free(tosort);
-			free(buff);
-			return;
+			goto out;
 		}
 		
-		memset(tosort[nbdirs-1].name, 0, str_length(dp->d_name)+1);
-		str_cpy(tosort[nbdirs-1].name, str_length(dp->d_name)+1, dp->d_name);
-		
-		// fill the isdir field
-		memset(buff, 0, sizeof(buff));
-		snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[nbdirs-1].name);
-		
-		rc = stat(buff, &s);
+		str_cpy(tosort[nbdirs].name, str_length(dp->d_name) + 1, dp->d_name);
+		len = snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[nbdirs].name);
+		buff[len] = '\0';
+
+		rc = stat(buff, &tosort[nbdirs++].s);
 		if (rc != 0) {
 			printf("ls: skipping bogus node %s\n", buff);
 			printf("rc=%d\n", rc);
-			for(i=0;i<nbdirs;i++) {
-				free(tosort[i].name);
-			}
-			free(tosort);
-			free(buff);
-			return;
-		}
-		
-		tosort[nbdirs-1].isdir = s.is_directory ? 1 : 0;
-	}
-	
-	if (!qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t), ls_cmp, NULL)) {
-		printf("Sorting error.\n");
-	}
-	
-	for(i=0;i<nbdirs;i++) {
-		memset(buff, 0, sizeof(buff));
-		/* Don't worry if inserting a double slash, this will be fixed by
-		 * absolutize() later with subsequent calls to open() or readdir() */
-		snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[i].name);
-		ls_print(tosort[i].name, buff);
+			goto out;
+		}
+	}
+	
+	if (sort) {
+		if (!qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t),
+		    ls_cmp, NULL)) {
+			printf("Sorting error.\n");
+		}
+	}
+	
+	for (i = 0; i < nbdirs; i++)
+		ls_print(&tosort[i]);
+	
+out:
+	for(i = 0; i < nbdirs; i++)
 		free(tosort[i].name);
-	}
-	
 	free(tosort);
 	free(buff);
-
-	return;
-}
-
-/** Print an entry.
- *
- * ls_print currently does nothing more than print the entry.
- * In the future, we will likely pass the absolute path, and
- * some sort of ls_options structure that controls how each
- * entry is printed and what is printed about it.
- *
- * Now we just print basic DOS style lists.
- *
- * @param name		Name of the entry.
- * @param pathname	Path of the entry.
- */
-static void ls_print(const char *name, const char *pathname)
-{
-	struct stat s;
-	int rc;
-
-	rc = stat(pathname, &s);
-	if (rc != 0) {
-		/* Odd chance it was deleted from the time readdir() found it */
-		printf("ls: skipping bogus node %s\n", pathname);
-		printf("rc=%d\n", rc);
-		return;
-	}
-	
-	if (s.is_file)
-		printf("%-40s\t%llu\n", name, (long long) s.size);
-	else if (s.is_directory)
-		printf("%-40s\t<dir>\n", name);
-	else
-		printf("%-40s\n", name);
-
-	return;
 }
 
@@ -271,6 +227,5 @@
 {
 	unsigned int argc;
-	struct stat s;
-	char *buff;
+	struct dir_elem_t de;
 	DIR *dirp;
 	int c, opt_ind;
@@ -291,40 +246,40 @@
 	}
 	
-	int dir = (int)argc > optind ? (int)argc-1 : optind-1;
-	argc -= (optind-1);
-	
-	buff = (char *) malloc(PATH_MAX);
-	if (NULL == buff) {
+	int dir = (int) argc > optind ? (int) argc - 1 : optind - 1;
+	argc -= (optind - 1);
+	
+	de.name = (char *) malloc(PATH_MAX);
+	if (!de.name) {
 		cli_error(CL_ENOMEM, "%s: ", cmdname);
 		return CMD_FAILURE;
 	}
-	memset(buff, 0, sizeof(buff));
+	memset(de.name, 0, sizeof(PATH_MAX));
 	
 	if (argc == 1)
-		getcwd(buff, PATH_MAX);
+		getcwd(de.name, PATH_MAX);
 	else
-		str_cpy(buff, PATH_MAX, argv[dir]);
-	
-	if (stat(buff, &s)) {
-		cli_error(CL_ENOENT, buff);
-		free(buff);
+		str_cpy(de.name, PATH_MAX, argv[dir]);
+	
+	if (stat(de.name, &de.s)) {
+		cli_error(CL_ENOENT, de.name);
+		free(de.name);
 		return CMD_FAILURE;
 	}
 
-	if (s.is_file) {
-		ls_print(buff, buff);
+	if (de.s.is_file) {
+		ls_print(&de);
 	} else {
-		dirp = opendir(buff);
+		dirp = opendir(de.name);
 		if (!dirp) {
 			/* May have been deleted between scoping it and opening it */
-			cli_error(CL_EFAIL, "Could not stat %s", buff);
-			free(buff);
+			cli_error(CL_EFAIL, "Could not stat %s", de.name);
+			free(de.name);
 			return CMD_FAILURE;
 		}
-		ls_scan_dir(buff, dirp, sort);
+		ls_scan_dir(de.name, dirp, sort);
 		closedir(dirp);
 	}
 
-	free(buff);
+	free(de.name);
 
 	return CMD_SUCCESS;
