mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 1/2] rm: implement -r
@ 2012-11-29 19:27 Sascha Hauer
  2012-11-29 19:27 ` [PATCH 2/2] loadenv: allow more fine grained environment loading Sascha Hauer
  0 siblings, 1 reply; 2+ messages in thread
From: Sascha Hauer @ 2012-11-29 19:27 UTC (permalink / raw)
  To: barebox

To recursively remove files and directories.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 commands/rm.c          |   28 ++++++++++++++++++++----
 include/fs.h           |    2 ++
 lib/Makefile           |    1 +
 lib/recursive_action.c |    1 -
 lib/unlink-recursive.c |   56 ++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 83 insertions(+), 5 deletions(-)
 create mode 100644 lib/unlink-recursive.c

diff --git a/commands/rm.c b/commands/rm.c
index 4e765ac..5486005 100644
--- a/commands/rm.c
+++ b/commands/rm.c
@@ -19,17 +19,36 @@
 #include <common.h>
 #include <command.h>
 #include <fs.h>
+#include <getopt.h>
 #include <errno.h>
 
 static int do_rm(int argc, char *argv[])
 {
-	int i = 1;
+	int i, opt, recursive = 0;
+
+	while ((opt = getopt(argc, argv, "r")) > 0) {
+		switch (opt) {
+		case 'r':
+			recursive = 1;
+			break;
+		default:
+			return COMMAND_ERROR_USAGE;
+		}
+	}
 
 	if (argc < 2)
 		return COMMAND_ERROR_USAGE;
 
+	i = optind;
+
 	while (i < argc) {
-		if (unlink(argv[i])) {
+		int ret;
+
+		if (recursive)
+			ret = unlink_recursive(argv[i], NULL);
+		else
+			ret = unlink(argv[i]);
+		if (ret) {
 			printf("could not remove %s: %s\n", argv[i], errno_str());
 			return 1;
 		}
@@ -40,8 +59,9 @@ static int do_rm(int argc, char *argv[])
 }
 
 static const __maybe_unused char cmd_rm_help[] =
-"Usage: rm [FILES]\n"
-"Remove files\n";
+"Usage: rm [OPTIONS] [FILES]\n"
+"Remove files\n"
+"-r  remove directories and their contents recursively\n";
 
 BAREBOX_CMD_START(rm)
 	.cmd		= do_rm,
diff --git a/include/fs.h b/include/fs.h
index 3d5714c..8ff7300 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -182,4 +182,6 @@ void automount_remove(const char *_path);
 int automount_add(const char *path, const char *cmd);
 void automount_print(void);
 
+int unlink_recursive(const char *path, char **failedpath);
+
 #endif /* __FS_H */
diff --git a/lib/Makefile b/lib/Makefile
index eb0af92..635d52e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -36,3 +36,4 @@ obj-$(CONFIG_BITREV)	+= bitrev.o
 obj-$(CONFIG_QSORT)	+= qsort.o
 obj-y			+= gui/
 obj-$(CONFIG_XYMODEM)	+= xymodem.o
+obj-y			+= unlink-recursive.o
diff --git a/lib/recursive_action.c b/lib/recursive_action.c
index 5bc2595..345d3db 100644
--- a/lib/recursive_action.c
+++ b/lib/recursive_action.c
@@ -130,7 +130,6 @@ int recursive_action(const char *fileName,
 		return 0;
 	return 1;
 done_nak_warn:
-	printf("%s", fileName);
 	return 0;
 }
 
diff --git a/lib/unlink-recursive.c b/lib/unlink-recursive.c
new file mode 100644
index 0000000..a488553
--- /dev/null
+++ b/lib/unlink-recursive.c
@@ -0,0 +1,56 @@
+#include <common.h>
+#include <libbb.h>
+#include <fs.h>
+
+static char unlink_recursive_failedpath[PATH_MAX];
+
+struct data {
+	int error;
+};
+
+static int file_action(const char *filename, struct stat *statbuf,
+			    void *userdata, int depth)
+{
+	struct data *data = userdata;
+	int ret;
+
+	ret = unlink(filename);
+	if (ret) {
+		strcpy(unlink_recursive_failedpath, filename);
+		data->error = ret;
+	}
+
+	return ret ? 0 : 1;
+}
+
+static int dir_action(const char *dirname, struct stat *statbuf,
+			    void *userdata, int depth)
+{
+	struct data *data = userdata;
+	int ret;
+
+	ret = rmdir(dirname);
+	if (ret) {
+		strcpy(unlink_recursive_failedpath, dirname);
+		data->error = ret;
+	}
+
+	return ret ? 0 : 1;
+}
+
+int unlink_recursive(const char *path, char **failedpath)
+{
+	struct data data = {};
+	int ret;
+
+	if (failedpath)
+		*failedpath = NULL;
+
+	ret = recursive_action(path, ACTION_RECURSE | ACTION_DEPTHFIRST,
+			file_action, dir_action, &data, 0);
+
+	if (!ret && failedpath)
+		*failedpath = unlink_recursive_failedpath;
+
+	return ret ? 0 : errno;
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [PATCH 2/2] loadenv: allow more fine grained environment loading
  2012-11-29 19:27 [PATCH 1/2] rm: implement -r Sascha Hauer
@ 2012-11-29 19:27 ` Sascha Hauer
  0 siblings, 0 replies; 2+ messages in thread
From: Sascha Hauer @ 2012-11-29 19:27 UTC (permalink / raw)
  To: barebox

This implements two new options for the loadenv command:

-s: removes (scrubs) old directory contents to be able to
    create a fresh environment from for example /dev/defaultenv
-n: no overwrite. Do not overwrite existing files. This allows
    to keep parts of the old environment.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 commands/loadenv.c    |   53 +++++++++++++++++++++++++++++++++++++++++++------
 common/environment.c  |   12 +++++++++--
 common/startup.c      |    4 ++--
 include/environment.h |    7 ++++---
 scripts/bareboxenv.c  |    2 +-
 5 files changed, 64 insertions(+), 14 deletions(-)

diff --git a/commands/loadenv.c b/commands/loadenv.c
index 5bf1740..48284d7 100644
--- a/commands/loadenv.c
+++ b/commands/loadenv.c
@@ -21,27 +21,68 @@
  */
 
 #include <common.h>
+#include <getopt.h>
 #include <command.h>
 #include <environment.h>
+#include <fs.h>
 
 static int do_loadenv(int argc, char *argv[])
 {
 	char *filename, *dirname;
+	unsigned flags = 0;
+	int opt;
+	int scrub = 0;
 
-	if (argc < 3)
+	while ((opt = getopt(argc, argv, "ns")) > 0) {
+		switch (opt) {
+		case 'n':
+			flags |= ENV_FLAG_NO_OVERWRITE;
+			break;
+		case 's':
+			scrub = 1;
+			break;
+		default:
+			return COMMAND_ERROR_USAGE;
+		}
+	}
+
+	if (argc - optind < 2)
 		dirname = "/env";
 	else
-		dirname = argv[2];
-	if (argc < 2)
+		dirname = argv[optind + 1];
+
+	if (argc - optind < 1)
 		filename = default_environment_path;
 	else
-		filename = argv[1];
+		filename = argv[optind];
+
+	if (scrub) {
+		int ret;
+
+		ret = unlink_recursive(dirname, NULL);
+		if (ret) {
+			eprintf("cannot remove %s: %s\n", dirname,
+					strerror(-ret));
+			return 1;
+		}
+
+		ret = mkdir(dirname, 0);
+		if (ret) {
+			eprintf("cannot create %s: %s\n", dirname,
+					strerror(-ret));
+			return ret;
+		}
+	}
+
 	printf("loading environment from %s\n", filename);
-	return envfs_load(filename, dirname);
+
+	return envfs_load(filename, dirname, flags);
 }
 
 BAREBOX_CMD_HELP_START(loadenv)
-BAREBOX_CMD_HELP_USAGE("loadenv [ENVFS] [DIRECTORY]\n")
+BAREBOX_CMD_HELP_USAGE("loadenv OPTIONS [ENVFS] [DIRECTORY]\n")
+BAREBOX_CMD_HELP_OPT("-n", "do not overwrite existing files\n")
+BAREBOX_CMD_HELP_OPT("-s", "scrub old environment\n")
 BAREBOX_CMD_HELP_SHORT("Load environment from ENVFS into DIRECTORY (default: /dev/env0 -> /env).\n")
 BAREBOX_CMD_HELP_END
 
diff --git a/common/environment.c b/common/environment.c
index 69c4c0a..e11cd9d 100644
--- a/common/environment.c
+++ b/common/environment.c
@@ -206,7 +206,7 @@ EXPORT_SYMBOL(envfs_save);
  * Note: This function will also be used on the host! See note in the header
  * of this file.
  */
-int envfs_load(char *filename, char *dir)
+int envfs_load(char *filename, char *dir, unsigned flags)
 {
 	struct envfs_super super;
 	void *buf = NULL, *buf_free = NULL;
@@ -316,6 +316,14 @@ int envfs_load(char *filename, char *dir)
 			}
 			free(str);
 		} else {
+			struct stat s;
+
+			if (flags & ENV_FLAG_NO_OVERWRITE &&
+					!stat(str, &s)) {
+				printf("skip %s\n", str);
+				goto skip;
+			}
+
 			fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644);
 			free(str);
 			if (fd < 0) {
@@ -333,7 +341,7 @@ int envfs_load(char *filename, char *dir)
 			}
 			close(fd);
 		}
-
+skip:
 		buf += PAD4(inode_size);
 		size -= headerlen_full + PAD4(inode_size) +
 				sizeof(struct envfs_inode);
diff --git a/common/startup.c b/common/startup.c
index 7bb3c73..14409a2 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -108,12 +108,12 @@ void start_barebox (void)
 	debug("initcalls done\n");
 
 #ifdef CONFIG_ENV_HANDLING
-	if (envfs_load(default_environment_path, "/env")) {
+	if (envfs_load(default_environment_path, "/env", 0)) {
 #ifdef CONFIG_DEFAULT_ENVIRONMENT
 		printf("no valid environment found on %s. "
 			"Using default environment\n",
 			default_environment_path);
-		envfs_load("/dev/defaultenv", "/env");
+		envfs_load("/dev/defaultenv", "/env", 0);
 #endif
 	}
 #endif
diff --git a/include/environment.h b/include/environment.h
index 4184977..096c169 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -75,9 +75,6 @@ int env_push_context(void);
 /* defaults to /dev/env0 */
 extern char *default_environment_path;
 
-int envfs_load(char *filename, char *dirname);
-int envfs_save(char *filename, char *dirname);
-
 int export(const char *);
 
 struct stat;
@@ -86,6 +83,10 @@ int file_save_action(const char *, struct stat *, void *, int);
 
 #endif /* __BAREBOX__ */
 
+#define ENV_FLAG_NO_OVERWRITE	(1 << 0)
+int envfs_load(char *filename, char *dirname, unsigned flags);
+int envfs_save(char *filename, char *dirname);
+
 /* This part is used for the host and the target */
 struct action_data {
 	int fd;
diff --git a/scripts/bareboxenv.c b/scripts/bareboxenv.c
index 5fdc62e..707d63d 100644
--- a/scripts/bareboxenv.c
+++ b/scripts/bareboxenv.c
@@ -191,7 +191,7 @@ int main(int argc, char *argv[])
 	if (load) {
 		if (verbose)
 			printf("loading env from file %s to %s\n", filename, dirname);
-		envfs_load(filename, dirname);
+		envfs_load(filename, dirname, 0);
 	}
 	if (save) {
 		if (verbose)
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2012-11-29 19:27 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-29 19:27 [PATCH 1/2] rm: implement -r Sascha Hauer
2012-11-29 19:27 ` [PATCH 2/2] loadenv: allow more fine grained environment loading Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox