Hi,

On Sat, Mar 24, 2012 at 9:33 PM, Jakub Jermar <[email protected]> wrote:

> Line 115
> Is it really necessary to use all three dir_list, dir_listp and tmp to
> realloc dir_list?
>

I have modified the corresponding hunk. Please check it again, and advise
me if it's still not the desired way to do things.


> Lines 117, 174, 177
> The proper way to break the long line is to use tabs to get to the same
> indentation level as the previous line and then add four spaces.
>
> Line 156
> Here you are wrongly using spaces instead of tabs.
>
> Line 164
> There are some extra spaces instead of a tab.
>
> Line 191
> Spaces instead of tabs.
>

Oh, this is troublesome. I had messed up my vimrc file a few days ago in a
system crash, which caused all this problem. I am sorry for the trouble.

I have also fixed the missing spaces between if/switch and opening
parenthesis and indentation of case labels.

Line 357
> The static declarations IMHO should not go to the .h file, but rather to
> the .c file.
>

I have moved them to ls.c file. But, please have a look at rm/rm.h file,
where static declarations are done.

I have set up a bazaar branch. The diff can be seen at
http://bazaar.launchpad.net/~vivek-cs-iitr/vivekp/mainline/revision/1441.
The corresponding branch can be cloned as:
bzr branch lp:~vivek-cs-iitr/vivekp/mainline HelenOS

I am new to bazaar, but i have prior experience with other VCS. Please tell
me if it's not the right way of using bazaar.

I have also attached the patch file in this mail. Any suggestions are very
welcome. If the patch is not acceptable at all, i can start all over again.

Thanks,
Vivek Prakash
=== modified file 'uspace/app/bdsh/cmds/modules/ls/ls.c'
--- uspace/app/bdsh/cmds/modules/ls/ls.c	2011-07-19 20:04:59 +0000
+++ uspace/app/bdsh/cmds/modules/ls/ls.c	2012-03-24 20:41:16 +0000
@@ -41,35 +41,40 @@
 #include <str.h>
 #include <sort.h>
 
+#include "ls.h"
 #include "errors.h"
 #include "config.h"
 #include "util.h"
 #include "entry.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 information
- * for sorting directory entries.
- */
-struct dir_elem_t {
-	char *name;
-	struct stat s;
-};
-
 static const char *cmdname = "ls";
 
+static ls_job_t ls;
+
 static struct option const long_options[] = {
 	{ "help", no_argument, 0, 'h' },
 	{ "unsort", no_argument, 0, 'u' },
+	{ "recursive", no_argument, 0, 'R' },
 	{ 0, 0, 0, 0 }
 };
 
+/* Prototypes for the ls command, excluding entry points. */
+static unsigned int ls_start(ls_job_t *);
+static void ls_print(struct dir_elem_t *);
+static int ls_cmp(void *, void *, void *);
+static signed int ls_scan_dir(const char *, DIR *, struct dir_elem_t **);
+static unsigned int ls_recursive(const char *, DIR *);
+static unsigned int ls_scope(const char *, struct dir_elem_t *);
+
+static unsigned int ls_start(ls_job_t *ls)
+{
+	ls->recursive = 0;
+	ls->sort = 1;
+
+	return 1;
+}
+
 /** Print an entry.
  *
  * ls_print currently does nothing more than print the entry.
@@ -91,7 +96,6 @@
 		printf("%-40s\n", de->name);
 }
 
-
 /** Compare 2 directory elements.
  *
  * It compares 2 elements of a directory : a file is considered
@@ -126,7 +130,8 @@
  * @param sort	1 if the output must be sorted,
  *				0 otherwise.
  */
-static void ls_scan_dir(const char *d, DIR *dirp, int sort)
+static signed int ls_scan_dir(const char *d, DIR *dirp, 
+    struct dir_elem_t **dir_list_ptr)
 {
 	int alloc_blocks = 20;
 	int i;
@@ -139,19 +144,19 @@
 	struct dirent *dp;
 	
 	if (!dirp)
-		return;
+		return -1;
 
 	buff = (char *) malloc(PATH_MAX);
 	if (!buff) {
 		cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
-		return;
+		return -1;
 	}
 	
 	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;
+		return -1;
 	}
 	
 	while ((dp = readdir(dirp))) {
@@ -186,7 +191,7 @@
 		}
 	}
 	
-	if (sort) {
+	if (ls.sort) {
 		if (!qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t),
 		    ls_cmp, NULL)) {
 			printf("Sorting error.\n");
@@ -195,12 +200,112 @@
 	
 	for (i = 0; i < nbdirs; i++)
 		ls_print(&tosort[i]);
+
+	/* Populate the directory list. */
+	if (ls.recursive) {
+		tmp = (struct dir_elem_t *) realloc(*dir_list_ptr, 
+		    nbdirs * sizeof(struct dir_elem_t));
+		if (!tmp) {
+			cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
+			goto out;
+		} 
+		*dir_list_ptr = tmp;
+
+		for (i = 0; i < nbdirs; i++) {
+			(*dir_list_ptr)[i].name = str_dup(tosort[i].name);
+			if (!(*dir_list_ptr)[i].name) {
+				cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
+				goto out;
+			}
+		}
+	}
 	
 out:
 	for(i = 0; i < nbdirs; i++)
 		free(tosort[i].name);
 	free(tosort);
 	free(buff);
+
+	return nbdirs;
+}
+
+/** Visit a directory recursively.
+ *
+ * ls_recursive visits all the subdirectories recursively and
+ * prints the files and directories in them.
+ *
+ * @param path	Path the current directory being visited.
+ * @param dirp	Directory stream.
+ */
+static unsigned int ls_recursive(const char *path, DIR *dirp)
+{
+	int i, nbdirs, ret;
+	unsigned int scope;
+	char *subdir_path;
+	DIR *subdirp;
+	struct dir_elem_t *dir_list;
+	
+	const char * const trailing_slash = "/";
+
+	dir_list = (struct dir_elem_t *) malloc(sizeof(struct dir_elem_t));
+
+	printf("\n%s:\n", path);
+
+	nbdirs = ls_scan_dir(path, dirp, &dir_list); 
+	if (nbdirs == -1)
+		return CMD_FAILURE;
+
+	subdir_path = (char *) malloc(PATH_MAX);
+
+	for (i = 0; i < nbdirs; ++i) {
+		memset(subdir_path, 0, PATH_MAX);
+
+		if (str_size(subdir_path) + str_size(path) + 1 <= PATH_MAX)
+			str_append(subdir_path, PATH_MAX, path);
+		if (path[str_size(path)-1] != '/' &&
+		    str_size(subdir_path) + str_size(trailing_slash) + 1 <= PATH_MAX)
+			str_append(subdir_path, PATH_MAX, trailing_slash);
+		if (str_size(subdir_path) +
+		    str_size(dir_list[i].name) + 1 <= PATH_MAX)
+			str_append(subdir_path, PATH_MAX, dir_list[i].name);
+
+		scope = ls_scope(subdir_path, &dir_list[i]);
+		switch (scope) {
+		case LS_FILE:
+			break;
+		case LS_DIR:
+			subdirp = opendir(subdir_path);
+			if (!subdirp) {
+				/* May have been deleted between scoping it and opening it */
+				cli_error(CL_EFAIL, "Could not stat %s", dir_list[i].name);
+				return CMD_FAILURE;
+			}
+
+			ret = ls_recursive(subdir_path, subdirp);
+			if (ret == CMD_FAILURE)
+				return CMD_FAILURE;
+			break;
+		case LS_BOGUS:
+			return CMD_FAILURE;
+		}	
+	}
+   
+	return CMD_SUCCESS; 
+}
+
+static unsigned int ls_scope(const char *path, struct dir_elem_t *de)
+{
+	if (stat(path, &de->s)) {
+		cli_error(CL_ENOENT, path);
+		return LS_BOGUS;
+	}
+
+	if (de->s.is_file)
+		return LS_FILE;
+	else if (de->s.is_directory)
+		return LS_DIR;
+
+	return LS_BOGUS;
 }
 
 void help_cmd_ls(unsigned int level)
@@ -214,7 +319,8 @@
 		"If not path is given, the current working directory is used.\n"
 		"Options:\n"
 		"  -h, --help       A short option summary\n"
-		"  -u, --unsort     Do not sort directory entries\n",
+		"  -u, --unsort     Do not sort directory entries\n"
+		"  -R, --recursive  List subdirectories recursively\n",
 		cmdname);
 	}
 
@@ -227,18 +333,27 @@
 	struct dir_elem_t de;
 	DIR *dirp;
 	int c, opt_ind;
-	int sort = 1;
+	int ret = 0;
+	unsigned int scope;
+
+	if (!ls_start(&ls)) {
+		cli_error(CL_EFAIL, "%s: Could not initialize", cmdname);
+		return CMD_FAILURE;
+	}
 
 	argc = cli_count_args(argv);
 	
 	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
-		c = getopt_long(argc, argv, "hu", long_options, &opt_ind);
+		c = getopt_long(argc, argv, "huR", long_options, &opt_ind);
 		switch (c) {
 		case 'h':
 			help_cmd_ls(HELP_LONG);
 			return CMD_SUCCESS;
 		case 'u':
-			sort = 0;
+			ls.sort = 0;
+			break;
+		case 'R':
+			ls.recursive = 1;
 			break;
 		}
 	}
@@ -250,22 +365,19 @@
 		cli_error(CL_ENOMEM, "%s: ", cmdname);
 		return CMD_FAILURE;
 	}
-	memset(de.name, 0, sizeof(PATH_MAX));
+	memset(de.name, 0, PATH_MAX);
 	
 	if (argc == 0)
 		getcwd(de.name, PATH_MAX);
 	else
 		str_cpy(de.name, PATH_MAX, argv[optind]);
-	
-	if (stat(de.name, &de.s)) {
-		cli_error(CL_ENOENT, de.name);
-		free(de.name);
-		return CMD_FAILURE;
-	}
 
-	if (de.s.is_file) {
+	scope = ls_scope(de.name, &de);
+	switch (scope) {
+	case LS_FILE:
 		ls_print(&de);
-	} else {
+		break;
+	case LS_DIR:
 		dirp = opendir(de.name);
 		if (!dirp) {
 			/* May have been deleted between scoping it and opening it */
@@ -273,12 +385,22 @@
 			free(de.name);
 			return CMD_FAILURE;
 		}
-		ls_scan_dir(de.name, dirp, sort);
+		if (ls.recursive)
+			ret = ls_recursive(de.name, dirp);
+		else  
+			ret = ls_scan_dir(de.name, dirp, NULL);
+
 		closedir(dirp);
+		break;
+	case LS_BOGUS:
+		return CMD_FAILURE;
 	}
 
 	free(de.name);
 
-	return CMD_SUCCESS;
+	if (ret == -1 || ret == CMD_FAILURE)
+		return CMD_FAILURE;
+	else
+		return CMD_SUCCESS;
 }
 

=== added file 'uspace/app/bdsh/cmds/modules/ls/ls.h'
--- uspace/app/bdsh/cmds/modules/ls/ls.h	1970-01-01 00:00:00 +0000
+++ uspace/app/bdsh/cmds/modules/ls/ls.h	2012-03-24 20:41:16 +0000
@@ -0,0 +1,26 @@
+#ifndef LS_H
+#define LS_H
+
+/* Various values that can be returned by ls_scope() */
+#define LS_BOGUS 0
+#define LS_FILE  1
+#define LS_DIR   2
+
+typedef struct {
+	/* Options set at runtime. */
+	unsigned int recursive;
+	unsigned int sort;
+
+} ls_job_t;
+
+/** Structure to represent a directory entry.
+ *
+ * Useful to keep together important information
+ * for sorting directory entries.
+ */
+struct dir_elem_t {
+	char *name;
+	struct stat s;
+};
+
+#endif

_______________________________________________
HelenOS-devel mailing list
[email protected]
http://lists.modry.cz/cgi-bin/listinfo/helenos-devel

Reply via email to