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
;
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
);
40 static UNODE
* unode_find(UNODE
* parent
, const char* name
)
46 for (walk
=n
->childs
; walk
; walk
=walk
->next
)
47 if (strcmp(name
,walk
->name
)==0)
53 static int unode_insert(UNODE
* parent
, UNODE
* node
)
60 node
->next
= parent
->childs
;
61 parent
->childs
= node
;
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
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
);
92 // nothing, again. last try: check for an fileserver an query
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
;
117 f
->priv
.name
= (char*)pr
;
118 f
->priv
.text
= (char*)ent
;
119 f
->ops
= propertylist_ops
;
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
);
149 f
->perm
= 0555|P9_DMDIR
;
150 f
->priv
.name
= (char*)pr
;
151 f
->ops
= propertylist_ops
;
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
;
165 f
->priv
.name
= (char*)pr
;
166 f
->priv
.text
= (char*)ent
;
167 f
->ops
= propertylist_ops
;
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
));
183 // we've basicly to possible situations:
184 // MIXPSRV_FILE_HANDLE* sublist
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
);
194 f
= fh
= ixp_union_createent(def
,&(def
->entries
[x
]));
198 fh
->next
= ixp_union_createent(def
,&(def
->entries
[x
]));
206 static inline MIXPSRV_FILE_HANDLE
* ixp_union_ops_lookup_ent(Ixp_Union_Def
* def
, const char* name
)
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
]));
219 static MIXPSRV_FILE_HANDLE
* ixp_union_ops_lookup(MIXPSRV_FILE_HANDLE
* f
, char* name
)
222 return ixp_union_ops_lookup_list(f
);
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");
237 l
= strtol(text
,NULL
,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: ");
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");
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
)
265 // fprintf(stderr,"DEBUG ixp_union_ops_write() ignoring empty write (kind of EOF ?)\n");
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);
277 fprintf(stderr
,"ERROR: ixp_union_ops_write() NULL buffer !\n");
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
);
290 fprintf(stderr
,"FIXME: ixp_union_ops_write() offset=%d > 0 - not supported. sending EPERM\n", offset
);
297 return ((ixp_union_write_long(def
,ent
,text
)) ? size
: 0);
299 return ((ixp_union_write_string(def
,ent
,text
)) ? size
: 0);
301 fprintf(stderr
,"ixp_union_ops_write() unsupported ent type %d - sending EPERM\n", ent
->type
);
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
320 // we've got an constant value
323 // FIXME: should handle offsets !
326 fprintf(stderr
,"read_string() does not yet support offsets in consts (%d)\n", offset
);
329 strncpy(buf
,ent
->value
,size
-1);
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");
341 // offsets are not yet support :(
344 fprintf(stderr
,"read_string() does not support offsets (%d)\n", offset
);
348 // evrything seems okay - call the getString() handler
349 fprintf(stderr
,"reading string\n");
350 def
->ops
.getString(def
,ent
,buf
,size
);
355 // check if we have an constant value
358 strncpy(buf
,ent
->value
,size
-1);
364 fprintf(stderr
,"read_int() does not support offsets (%d)\n", offset
);
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");
375 // evrything seems okay - get
377 def
->ops
.getInt(def
,ent
,&ret
);
378 return snprintf(buf
,size
-1,"%ld",ret
);
382 fprintf(stderr
,"Reading text from directories not supported yet\n");
387 fprintf(stderr
,"ixp_union_ops_read() unsupported entry type %d\n", ent
->type
);
394 static long ixp_union_ops_size(MIXPSRV_FILE_HANDLE
* f
)
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);
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
);
418 stat
->uid
= strdup(def
->uid
);
421 stat
->gid
= strdup(def
->gid
);
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
);
434 stat
->uid
= strdup(ent
->uid
);
436 stat
->uid
= strdup(def
->uid
);
439 stat
->gid
= strdup(ent
->gid
);
441 stat
->gid
= strdup(def
->gid
);