rostring: renamed funcs to mixpsrv_*(), added close and str is copied now
[libmixpsrv.git] / libmixpsrv / union_ops.c
blobf524010f2f7f8008ad0e5f7f61ed6c62dd10729d
2 // UNUSABLE FOR NOW !
3 // will not be built
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <malloc.h>
10 #include <9p-mixpsrv/types.h>
11 #include <9p-mixpsrv/p9srv.h>
12 #include <9p-mixpsrv/propertylist_ops.h>
14 #define PROPLISTPRIV(f) ((Ixp_Union_Def*)(f->priv.name))
15 #define PROPENTPRIV(f) ((Ixp_Union_Ent*)(f->priv.text))
17 #define UNIONENTPRIV(f) ((Ixp_Union_Ent*)(f->priv.text))
19 typedef struct _union_node UNODE;
21 struct _union_node
23 int refcount;
24 char* name;
25 UNODE* next;
26 UNODE* childs;
27 MIXPSRV_FILESERVER* server;
28 MIXPSRV_FILE_HANDLE* parent_handle;
29 MIXPSRV_FILE_HANDLE* file_handle;
32 static UNODE* unode_alloc(const char* name)
34 UNODE* n = calloc(1,sizeof(name));
35 n->name = strdup(name);
36 n->recount = 1;
37 return n;
40 static UNODE* unode_find(UNODE* parent, const char* name)
42 if (n==NULL)
43 return NULL;
45 UNODE* walk;
46 for (walk=n->childs; walk; walk=walk->next)
47 if (strcmp(name,walk->name)==0)
48 return walk;
50 return NULL;
53 static int unode_insert(UNODE* parent, UNODE* node)
55 if (parent==NULL)
56 return -EFAULT;
57 if (node==NULL)
58 return -EINVAL;
60 node->next = parent->childs;
61 parent->childs = node;
63 return 0;
66 // open an file handle for the given unode
67 MIXPSRV_FILE_HANDLE* unode_get_handle_for_subnode(UNODE* parent, UNODE* child)
69 MIXPSRV_FILE_HANDLE* fh = p9srv_get_file();
72 // lookup an specific file entry within an given node
73 MIXPSRV_FILE_HANDLE* unode_ops_lookup_sub(UNODE* node, const char* name)
75 // look for an matching child node
76 UNODE* walk;
77 for (walk=node->childs; walk; walk=walk->next)
79 if (strcmp(name,walk->name)==0)
80 return unode_get_handle_for_subnode(node, walk);
83 // found none, so let's look if the parent node has an file handle
84 // and try to lookup the desired file there
85 if (node->file_handle != NULL)
87 MIXPSRV_FILE_HANDLE* sub = mixp_file_lookup(node->file_handle, name);
88 if (sub!=NULL)
89 return sub;
92 // nothing, again. last try: check for an fileserver an query
93 // its root
94 if (node->fileserver)
96 MIXPSRV_FILE_HANDLE* root = mixp
100 // okay, got one. returning handle with this node
112 MIXPSRV_FILE_HANDLE* f = p9srv_get_file();
113 f->name = strdup(ent->name);
114 f->qtype = P9_QTFILE;
115 f->type = 0;
116 f->perm = 0555;
117 f->priv.name = (char*)pr;
118 f->priv.text = (char*)ent;
119 f->ops = propertylist_ops;
120 return f;
126 static MIXPSRV_FILE_HANDLE* ixp_union_ops_lookup (MIXPSRV_FILE_HANDLE* f, char* name);
127 static long ixp_union_ops_read (MIXPSRV_FILE_HANDLE* f, long offset, long size, void* buf);
128 static long ixp_union_ops_write (MIXPSRV_FILE_HANDLE* f, long offset, long size, void* buf);
129 static int ixp_union_ops_open (MIXPSRV_FILE_HANDLE* f, long mode);
130 static int ixp_union_ops_stat (MIXPSRV_FILE_HANDLE* f, MIXP_STAT* stat);
131 static long ixp_union_ops_size (MIXPSRV_FILE_HANDLE* f);
133 static MIXPSRV_FILE_OPS propertylist_ops =
135 .read = ixp_union_ops_read,
136 .write = ixp_union_ops_write,
137 .open = ixp_union_ops_open,
138 .stat = ixp_union_ops_stat,
139 .size = ixp_union_ops_size,
140 .lookup = ixp_union_ops_lookup
143 MIXPSRV_FILE_HANDLE* ixp_union_create(const char* name, Ixp_Union_Def* pr)
145 MIXPSRV_FILE_HANDLE* f = p9srv_get_file();
146 f->name = strdup(name);
147 f->qtype = P9_QTDIR;
148 f->type = 0;
149 f->perm = 0555|P9_DMDIR;
150 f->priv.name = (char*)pr;
151 f->ops = propertylist_ops;
152 return f;
155 static MIXPSRV_FILE_HANDLE* ixp_union_createent(Ixp_Union_Def* pr, Ixp_Union_Ent* ent)
157 if (ent->getFileHandle)
158 return ent->getFileHandle(pr,ent);
160 MIXPSRV_FILE_HANDLE* f = p9srv_get_file();
161 f->name = strdup(ent->name);
162 f->qtype = P9_QTFILE;
163 f->type = 0;
164 f->perm = 0555;
165 f->priv.name = (char*)pr;
166 f->priv.text = (char*)ent;
167 f->ops = propertylist_ops;
168 return f;
171 static inline MIXPSRV_FILE_HANDLE* ixp_union_ops_lookup_list(MIXPSRV_FILE_HANDLE*f)
173 Ixp_Union_Ent* ent = UNIONENTPRIV(f);
175 // look if we have an file handle (fs mounted in)
176 MIXPSRV_FILE_HANDLE* childs = ((f.ops.lookup == NULL) ? NULL : f.ops.lookup(f,NULL));
178 if (childs!=NULL)
183 // we've basicly to possible situations:
184 // MIXPSRV_FILE_HANDLE* sublist
186 int x;
187 MIXPSRV_FILE_HANDLE* fh = NULL;
188 MIXPSRV_FILE_HANDLE* f = NULL;
189 for (x=0; def->entries[x].name; x++)
191 fprintf(stderr,"ixp_union_ops_lookup_list() walking: \"%s\"\n", def->entries[x].name);
192 if (fh==NULL)
194 f = fh = ixp_union_createent(def,&(def->entries[x]));
196 else
198 fh->next = ixp_union_createent(def,&(def->entries[x]));
199 fh = fh->next;
203 return f;
206 static inline MIXPSRV_FILE_HANDLE* ixp_union_ops_lookup_ent(Ixp_Union_Def* def, const char* name)
208 int x;
209 for (x=0; def->entries[x].name; x++)
211 if (strcmp(def->entries[x].name,name)==0)
213 return ixp_union_createent(def, &(def->entries[x]));
216 return NULL;
219 static MIXPSRV_FILE_HANDLE* ixp_union_ops_lookup(MIXPSRV_FILE_HANDLE* f, char* name)
221 if (name==NULL)
222 return ixp_union_ops_lookup_list(f);
223 else
224 return ixp_union_ops_lookup_ent(PROPLISTPRIV(f),name);
227 static inline long ixp_union_write_long(Ixp_Union_Def* pr, Ixp_Union_Ent* ent, const char* text)
229 if (pr->ops.setInt == NULL)
231 fprintf(stderr,"ixp_union_write_long(): Propertylist has no setInt() method. Sending EPERM\n");
232 return -EPERM;
235 long l = -666;
236 errno = 0;
237 l = strtol(text,NULL,0);
239 if (errno!=0)
241 fprintf(stderr,"ixp_union_write_long(): hmm, could not parse long out of text \"%s\" - sending EPERM\n", text);
242 perror("conversion failed: ");
243 return -EPERM;
246 return pr->ops.setInt(pr,ent,l);
249 static inline long ixp_union_write_string(Ixp_Union_Def* pr, Ixp_Union_Ent* ent, const char* text)
251 if (pr->ops.setString == NULL)
253 fprintf(stderr,"ixp_union_write_string(): Propertylist has no setInt() method. Sending EPERM\n");
254 return -EPERM;
257 fprintf(stderr,"ixp_union_write_string() writing string \"%s\"\n", text);
258 return pr->ops.setString(pr,ent,text);
261 static long ixp_union_ops_write(MIXPSRV_FILE_HANDLE* f, long offset, long size, void* buf)
263 if (size==0)
265 // fprintf(stderr,"DEBUG ixp_union_ops_write() ignoring empty write (kind of EOF ?)\n");
266 return 0;
269 Ixp_Union_Def * def = (Ixp_Union_Def*) f->priv.name;
270 Ixp_Union_Ent * ent = (Ixp_Union_Ent*) f->priv.text;
272 // fprintf(stderr,"ixp_union_ops_write() offset=%ld size=%ld ptr=%ld\n", offset, size, buf);
273 // fprintf(stderr," -> name=\"%s\"\n", ent->name);
275 if (buf==NULL)
277 fprintf(stderr,"ERROR: ixp_union_ops_write() NULL buffer !\n");
278 return -EPERM;
281 fprintf(stderr,"ixp_union_ops_write() offset=%ld size=%ld\n", offset, size);
283 // convert counted-size memchunk to 0-terminated char
284 char* text = malloc(size+1);
285 memset(text,0,size+1);
286 memcpy(text,buf,size);
288 if (offset)
290 fprintf(stderr,"FIXME: ixp_union_ops_write() offset=%d > 0 - not supported. sending EPERM\n", offset);
291 return -EPERM;
294 switch (ent->type)
296 case P9_PL_INT:
297 return ((ixp_union_write_long(def,ent,text)) ? size : 0);
298 case P9_PL_STRING:
299 return ((ixp_union_write_string(def,ent,text)) ? size : 0);
300 default:
301 fprintf(stderr,"ixp_union_ops_write() unsupported ent type %d - sending EPERM\n", ent->type);
302 return -EPERM;
306 // FIMXE: add sanity checks
307 static long ixp_union_ops_read(MIXPSRV_FILE_HANDLE* f, long offset, long size, void* buf)
309 Ixp_Union_Def * def = (Ixp_Union_Def*) f->priv.name;
310 Ixp_Union_Ent * ent = (Ixp_Union_Ent*) f->priv.text;
312 fprintf(stderr,"ixp_union_ops_read() reading from \"%s\" offset %ld size %ld\n", ent->name, offset, size);
314 // the buffer is *always* zero'ed first. our clients can rely on that
315 memset(buf,0,size);
317 switch (ent->type)
319 case P9_PL_STRING:
320 // we've got an constant value
321 if (ent->value)
323 // FIXME: should handle offsets !
324 if (offset)
326 fprintf(stderr,"read_string() does not yet support offsets in consts (%d)\n", offset);
327 return 0;
329 strncpy(buf,ent->value,size-1);
330 return strlen(buf);
333 // no constant value -- check for getString() handler
334 if (def->ops.getString == NULL)
336 fprintf(stderr,"read_string() no getString handler in this propertylist\n");
337 strcpy(buf,"");
338 return 0;
341 // offsets are not yet support :(
342 if (offset)
344 fprintf(stderr,"read_string() does not support offsets (%d)\n", offset);
345 return 0;
348 // evrything seems okay - call the getString() handler
349 fprintf(stderr,"reading string\n");
350 def->ops.getString(def,ent,buf,size);
351 return strlen(buf);
352 break;
354 case P9_PL_INT:
355 // check if we have an constant value
356 if (ent->value)
358 strncpy(buf,ent->value,size-1);
359 return strlen(buf);
362 if (offset)
364 fprintf(stderr,"read_int() does not support offsets (%d)\n", offset);
365 return 0;
368 // do we have an getInt() handler in the propertylist ?
369 if (def->ops.getInt==NULL)
371 fprintf(stderr,"read_int() propertylist has no getInt() handler\n");
372 return 0;
375 // evrything seems okay - get
376 long ret;
377 def->ops.getInt(def,ent,&ret);
378 return snprintf(buf,size-1,"%ld",ret);
379 break;
381 case P9_PL_DIR:
382 fprintf(stderr,"Reading text from directories not supported yet\n");
383 return 0;
384 break;
386 default:
387 fprintf(stderr,"ixp_union_ops_read() unsupported entry type %d\n", ent->type);
388 return 0;
391 return 0;
394 static long ixp_union_ops_size(MIXPSRV_FILE_HANDLE* f)
396 char buffer[1024];
397 buffer[0] = 0;
398 ixp_union_ops_read(f, 0, sizeof(buffer)-1, buffer);
399 return strlen(buffer);
402 static int ixp_union_ops_open(MIXPSRV_FILE_HANDLE* f, long mode)
404 Ixp_Union_Def * def = (Ixp_Union_Def*) f->priv.name;
405 Ixp_Union_Ent * ent = (Ixp_Union_Ent*) f->priv.text;
407 // fprintf(stderr,"ixp_union_ops_open() mode %ld\n", mode);
408 // fprintf(stderr,"ixp_union_ops_open() \"%s\" mode %ld\n", ent->name, mode);
409 return 0;
412 static int ixp_union_ops_stat (MIXPSRV_FILE_HANDLE* f, MIXP_STAT* stat)
414 Ixp_Union_Def * def = (Ixp_Union_Def*) f->priv.name;
416 mixpsrv_default_ops_stat(f,stat);
417 if (def->uid)
418 stat->uid = strdup(def->uid);
420 if (def->gid)
421 stat->gid = strdup(def->gid);
423 return 1;
427 static int ixp_union_ops_stat (MIXPSRV_FILE_HANDLE* f, MIXP_STAT* stat)
429 Ixp_Union_Def * def = (Ixp_Union_Def*) f->priv.name;
430 Ixp_Union_Ent * ent = (Ixp_Union_Ent*) f->priv.text;
432 mixpsrv_default_ops_stat(f,stat);
433 if (ent->uid)
434 stat->uid = strdup(ent->uid);
435 else if (def->uid)
436 stat->uid = strdup(def->uid);
438 if (ent->gid)
439 stat->gid = strdup(ent->gid);
440 else if (def->gid)
441 stat->gid = strdup(def->gid);
443 return 1;