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,