shithub: vcardfs

Download patch

ref: 53f2de182c03080309f9661fd483877bcb8f21e8
parent: 5cc3bea8aa3d93571b40c4ce687e8fe5c610ecf9
author: sirjofri <sirjofri@sirjofri.de>
date: Mon Oct 21 14:08:33 EDT 2024

adds deletion functionality

--- a/README.md
+++ b/README.md
@@ -13,14 +13,15 @@
 
 Default database is at: /usr/$user/lib/vcarddb.vcf
 
-	/mnt/vcf/
+	/mnt/vard/
 	   ctl
 	   import
 	   export
 	   John_Doe/
 	      export
-	      fn/
+	      groupname.fn/
 	         data
+	         group
 	         params/
 	            ...
 	      n/
@@ -32,11 +33,22 @@
 	   Jane_Doe/
 	      ...
 
+Interaction:
+
+- `rm /mnt/vcard/John_Doe` deletes the whole card
+- `rm /mnt/vcard/John_Doe/fn` deletes the selected line
+- `rm /mnt/vcard/John_Doe/fn/params/type` deletes the param
+- `rm /mnt/vcard/John_Doe/fn/group` will delete the group association (not implemented yet)
+
 Future plans:
 
 - export: line breaks
 - import: update existing entries (how?)
 - files: output with newline at the end?
+
+Known bugs:
+
+- deleting files potentially leads to memory leaks, as the destroy function isn't called properly (see comment there)
 
 ### libvcard
 
--- a/vcardfs.c
+++ b/vcardfs.c
@@ -656,6 +656,115 @@
 }
 
 static void
+rmclearlchildren(File *f, Vline *l)
+{
+	File *file, *subfile;
+	Vparam *p;
+	
+	file = walkfile(f, "data");
+	if (file)
+		removefile(file);
+	file = walkfile(f, "group");
+	if (file)
+		removefile(file);
+	file = walkfile(f, "params");
+	if (file) {
+		for (p = l->params; p; p = p->next) {
+			subfile = walkfile(file, p->name);
+			if (subfile)
+				removefile(subfile);
+		}
+		removefile(file);
+	}
+}
+
+static void
+rmclearcchildren(File *f, Vcard *c)
+{
+	File *file;
+	Vline *l;
+	
+	for (l = c->content; l; l = l->next) {
+		if (!l->name)
+			continue;
+		file = walkfile(f, l->name);
+		incref(f);
+		if (file) {
+			rmclearlchildren(file, l);
+			removefile(file);
+		}
+	}
+	
+	file = walkfile(f, "export");
+	if (file)
+		removefile(file);
+}
+
+static void
+rmcard(Req *r, File *f)
+{
+	Vfile *vf = f->aux;
+	Vcard *c = vf->card;
+	Vcard *cp;
+	
+	if (cards == c) {
+		cards = c->next;
+		goto Out;
+	}
+	for (cp = cards; cp; cp = cp->next)
+		if (cp->next == c)
+			break;
+	
+	if (!cp) {
+		respond(r, "card not found!");
+		return;
+	}
+	cp->next = c->next;
+
+Out:
+	c->next = nil;
+	rmclearcchildren(f, c);
+	vcfreecards(c);
+	vf->card = nil;
+	respond(r, nil);
+}
+
+static void
+rmline(Req *r, File *f)
+{
+	Vfile *vf = f->aux;
+	Vcard *c = vf->card;
+	Vline *l = vf->line;
+	Vline *pl;
+	
+	if (!l) {
+		respond(r, nil);
+		return;
+	}
+	
+	if (c->content == l) {
+		c->content = l->next;
+		goto Out;
+	}
+	
+	for (pl = c->content; pl; pl = pl->next)
+		if (pl->next == l)
+			break;
+	
+	if (!pl) {
+		respond(r, "property not found");
+		return;
+	}
+	pl->next = l->next;
+Out:
+	l->next = nil;
+	rmclearlchildren(f, l);
+	vcfreelines(l);
+	vf->line = nil;
+	respond(r, nil);
+}
+
+static void
 rmparam(Req *r, Vfile *f)
 {
 	Vline *l = f->line;
@@ -694,7 +803,11 @@
 	vf = r->fid->file->aux;
 	switch (vf->level) {
 	case Qcard:
+		rmcard(r, r->fid->file);
+		return;
 	case Qline:
+		rmline(r, r->fid->file);
+		return;
 	case Qgroup:
 		break;
 	case Qparamdata:
@@ -839,6 +952,20 @@
 	}
 }
 
+/* TODO: for some reason, deleting leaf nodes like export doesn't call fdestroy */
+static void
+fdestroy(File *f)
+{
+	Vfile *vf;
+	
+	vf = f->aux;
+	
+//	fprint(2, "destroy: %s\n", f->name);
+	
+	if (vf)
+		free(vf);
+}
+
 void
 main(int argc, char **argv)
 {
@@ -876,7 +1003,7 @@
 	if (!cards)
 		sysfatal("%r");
 	
-	fs.tree = alloctree("vcard", "vcard", DMDIR|0555, nil);
+	fs.tree = alloctree("vcard", "vcard", DMDIR|0777, fdestroy);
 	createfile(fs.tree->root, "ctl", user, 0222,
 		emkvfile(Qctl, nil, nil, nil, nil));
 	createfile(fs.tree->root, "import", user, 0222,