Quellcode durchsuchen

implement uci rename

Felix Fietkau vor 16 Jahren
Ursprung
Commit
b69b459ecc
4 geänderte Dateien mit 94 neuen und 20 gelöschten Zeilen
  1. 30 8
      cli.c
  2. 10 2
      file.c
  3. 38 5
      list.c
  4. 16 5
      uci.h

+ 30 - 8
cli.c

@@ -20,13 +20,14 @@ static const char *appname = "uci";
 static struct uci_context *ctx;
 enum {
 	/* section cmds */
-	CMD_GET = 1,
-	CMD_SET = 2,
-	CMD_DEL = 3,
+	CMD_GET,
+	CMD_SET,
+	CMD_DEL,
+	CMD_RENAME,
 	/* package cmds */
-	CMD_SHOW = 4,
-	CMD_EXPORT = 5,
-	CMD_COMMIT = 6,
+	CMD_SHOW,
+	CMD_EXPORT,
+	CMD_COMMIT,
 };
 
 static void uci_usage(int argc, char **argv)
@@ -126,13 +127,22 @@ static int uci_do_section_cmd(int cmd, int argc, char **argv)
 	char *section = NULL;
 	char *option = NULL;
 	char *value = NULL;
+	char **ptr = NULL;
 	struct uci_package *p = NULL;
 	struct uci_element *e = NULL;
 
 	if (argc != 2)
 		return 255;
 
-	if (uci_parse_tuple(ctx, argv[1], &package, &section, &option, (cmd == CMD_SET ? &value : NULL)) != UCI_OK)
+	switch(cmd) {
+	case CMD_SET:
+	case CMD_RENAME:
+		ptr = &value;
+		break;
+	default:
+		break;
+	}
+	if (uci_parse_tuple(ctx, argv[1], &package, &section, &option, ptr) != UCI_OK)
 		return 1;
 
 	if (uci_load(ctx, package, &p) != UCI_OK) {
@@ -159,6 +169,12 @@ static int uci_do_section_cmd(int cmd, int argc, char **argv)
 		/* throw the value to stdout */
 		printf("%s\n", value);
 		break;
+	case CMD_RENAME:
+		if (uci_rename(ctx, p, section, option, value) != UCI_OK) {
+			uci_perror(ctx, appname);
+			return 1;
+		}
+		break;
 	case CMD_SET:
 		if (uci_set(ctx, p, section, option, value) != UCI_OK) {
 			uci_perror(ctx, appname);
@@ -166,7 +182,7 @@ static int uci_do_section_cmd(int cmd, int argc, char **argv)
 		}
 		break;
 	case CMD_DEL:
-		if (uci_del(ctx, p, section, option) != UCI_OK) {
+		if (uci_delete(ctx, p, section, option) != UCI_OK) {
 			uci_perror(ctx, appname);
 			return 1;
 		}
@@ -200,13 +216,19 @@ static int uci_cmd(int argc, char **argv)
 		cmd = CMD_GET;
 	else if (!strcasecmp(argv[0], "set"))
 		cmd = CMD_SET;
+	else if (!strcasecmp(argv[0], "ren") ||
+	         !strcasecmp(argv[0], "rename"))
+		cmd = CMD_RENAME;
 	else if (!strcasecmp(argv[0], "del"))
 		cmd = CMD_DEL;
+	else
+		cmd = -1;
 
 	switch(cmd) {
 		case CMD_GET:
 		case CMD_SET:
 		case CMD_DEL:
+		case CMD_RENAME:
 			return uci_do_section_cmd(cmd, argc, argv);
 		case CMD_SHOW:
 		case CMD_EXPORT:

+ 10 - 2
file.c

@@ -639,6 +639,7 @@ static void uci_close_stream(FILE *stream)
 static void uci_parse_history_line(struct uci_context *ctx, struct uci_package *p, char *buf)
 {
 	bool delete = false;
+	bool rename = false;
 	char *package = NULL;
 	char *section = NULL;
 	char *option = NULL;
@@ -647,6 +648,9 @@ static void uci_parse_history_line(struct uci_context *ctx, struct uci_package *
 	if (buf[0] == '-') {
 		delete = true;
 		buf++;
+	} else if (buf[0] == '@') {
+		rename = true;
+		buf++;
 	}
 
 	UCI_INTERNAL(uci_parse_tuple, ctx, buf, &package, &section, &option, &value);
@@ -659,8 +663,10 @@ static void uci_parse_history_line(struct uci_context *ctx, struct uci_package *
 	if (option && !uci_validate_name(option))
 		goto error;
 
-	if (delete)
-		UCI_INTERNAL(uci_del, ctx, p, section, option);
+	if (rename)
+		UCI_INTERNAL(uci_rename, ctx, p, section, option, value);
+	else if (delete)
+		UCI_INTERNAL(uci_delete, ctx, p, section, option);
 	else
 		UCI_INTERNAL(uci_set, ctx, p, section, option, value);
 
@@ -809,6 +815,8 @@ int uci_save(struct uci_context *ctx, struct uci_package *p)
 
 		if (h->cmd == UCI_CMD_REMOVE)
 			fprintf(f, "-");
+		else if (h->cmd == UCI_CMD_RENAME)
+			fprintf(f, "@");
 
 		fprintf(f, "%s.%s", p->e.name, h->section);
 		if (e->name)

+ 38 - 5
list.c

@@ -61,23 +61,30 @@ uci_alloc_generic(struct uci_context *ctx, int type, const char *name, int size)
 	int datalen = size;
 	void *ptr;
 
-	if (name)
-		datalen += strlen(name) + 1;
 	ptr = uci_malloc(ctx, datalen);
 	e = (struct uci_element *) ptr;
 	e->type = type;
 	if (name) {
-		e->name = (char *) ptr + size;
-		strcpy(e->name, name);
+		UCI_TRAP_SAVE(ctx, error);
+		e->name = uci_strdup(ctx, name);
+		UCI_TRAP_RESTORE(ctx);
 	}
 	uci_list_init(&e->list);
+	goto done;
 
+error:
+	free(ptr);
+	UCI_THROW(ctx, ctx->errno);
+
+done:
 	return e;
 }
 
 static void
 uci_free_element(struct uci_element *e)
 {
+	if (e->name)
+		free(e->name);
 	if (!uci_list_empty(&e->list))
 		uci_list_del(&e->list);
 	free(e);
@@ -372,7 +379,33 @@ int uci_set_element_value(struct uci_context *ctx, struct uci_element **element,
 	return 0;
 }
 
-int uci_del(struct uci_context *ctx, struct uci_package *p, char *section, char *option)
+int uci_rename(struct uci_context *ctx, struct uci_package *p, char *section, char *option, char *name)
+{
+	/* NB: UCI_INTERNAL use means without history tracking */
+	bool internal = ctx->internal;
+	struct uci_element *e;
+	struct uci_section *s = NULL;
+	struct uci_option *o = NULL;
+
+	UCI_HANDLE_ERR(ctx);
+	UCI_ASSERT(ctx, p != NULL);
+	UCI_ASSERT(ctx, section != NULL);
+
+	UCI_INTERNAL(uci_lookup, ctx, &e, p, section, option);
+
+	if (!internal)
+		uci_add_history(ctx, p, UCI_CMD_RENAME, section, option, name);
+
+	name = uci_strdup(ctx, name);
+	if (e->name)
+		free(e->name);
+	e->name = name;
+
+	return 0;
+}
+
+
+int uci_delete(struct uci_context *ctx, struct uci_package *p, char *section, char *option)
 {
 	/* NB: pass on internal flag to uci_del_element */
 	bool internal = ctx->internal;

+ 16 - 5
uci.h

@@ -177,20 +177,30 @@ extern int uci_set_element_value(struct uci_context *ctx, struct uci_element **e
 extern int uci_set(struct uci_context *ctx, struct uci_package *p, char *section, char *option, char *value);
 
 /**
- * uci_del_element: Delete a section or option
+ * uci_rename: Rename an element
+ * @ctx: uci context
+ * @package: package name
+ * @section: section name
+ * @option: option name
+ * @name: new name
+ */
+extern int uci_rename(struct uci_context *ctx, struct uci_package *p, char *section, char *option, char *name);
+
+/**
+ * uci_delete_element: Delete a section or option
  * @ctx: uci context
  * @e: element (section or option)
  */
-extern int uci_del_element(struct uci_context *ctx, struct uci_element *e);
+extern int uci_delete_element(struct uci_context *ctx, struct uci_element *e);
 
 /**
- * uci_del: Delete a section or option
+ * uci_delete: Delete a section or option
  * @ctx: uci context
  * @p: uci package
  * @section: section name
  * @option: option name (optional)
  */
-extern int uci_del(struct uci_context *ctx, struct uci_package *p, char *section, char *option);
+extern int uci_delete(struct uci_context *ctx, struct uci_package *p, char *section, char *option);
 
 /**
  * uci_save: save change history for a package
@@ -304,7 +314,8 @@ struct uci_option
 enum uci_command {
 	UCI_CMD_ADD,
 	UCI_CMD_REMOVE,
-	UCI_CMD_CHANGE
+	UCI_CMD_CHANGE,
+	UCI_CMD_RENAME
 };
 
 struct uci_history