25 |
* archive/site is simply "". Beware. */ |
* archive/site is simply "". Beware. */ |
26 |
|
|
27 |
#include <config.h> |
#include <config.h> |
28 |
|
#include <errno.h> |
29 |
|
|
30 |
#include "utilvfs.h" |
#include "utilvfs.h" |
31 |
#include "xdirentry.h" |
#include "xdirentry.h" |
35 |
|
|
36 |
static volatile int total_inodes = 0, total_entries = 0; |
static volatile int total_inodes = 0, total_entries = 0; |
37 |
|
|
38 |
vfs_s_inode * |
struct vfs_s_inode * |
39 |
vfs_s_new_inode (vfs *me, vfs_s_super *super, struct stat *initstat) |
vfs_s_new_inode (struct vfs_class *me, struct vfs_s_super *super, struct stat *initstat) |
40 |
{ |
{ |
41 |
vfs_s_inode *ino; |
struct vfs_s_inode *ino; |
42 |
|
|
43 |
ino = g_new0 (vfs_s_inode, 1); |
ino = g_new0 (struct vfs_s_inode, 1); |
44 |
if (!ino) |
if (!ino) |
45 |
return NULL; |
return NULL; |
46 |
|
|
59 |
return ino; |
return ino; |
60 |
} |
} |
61 |
|
|
62 |
vfs_s_entry * |
struct vfs_s_entry * |
63 |
vfs_s_new_entry (vfs *me, char *name, vfs_s_inode *inode) |
vfs_s_new_entry (struct vfs_class *me, char *name, struct vfs_s_inode *inode) |
64 |
{ |
{ |
65 |
vfs_s_entry *entry; |
struct vfs_s_entry *entry; |
66 |
|
|
67 |
entry = g_new0 (struct vfs_s_entry, 1); |
entry = g_new0 (struct vfs_s_entry, 1); |
68 |
total_entries++; |
total_entries++; |
78 |
} |
} |
79 |
|
|
80 |
static void |
static void |
81 |
vfs_s_free_inode (vfs *me, vfs_s_inode *ino) |
vfs_s_free_inode (struct vfs_class *me, struct vfs_s_inode *ino) |
82 |
{ |
{ |
83 |
if (!ino) |
if (!ino) |
84 |
vfs_die ("Don't pass NULL to me"); |
vfs_die ("Don't pass NULL to me"); |
102 |
} |
} |
103 |
|
|
104 |
void |
void |
105 |
vfs_s_free_entry (vfs *me, vfs_s_entry *ent) |
vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent) |
106 |
{ |
{ |
107 |
int is_dot = 0; |
int is_dot = 0; |
108 |
if (ent->prevp){ /* It is possible that we are deleting freshly created entry */ |
if (ent->prevp){ /* It is possible that we are deleting freshly created entry */ |
128 |
} |
} |
129 |
|
|
130 |
void |
void |
131 |
vfs_s_insert_entry (vfs *me, vfs_s_inode *dir, vfs_s_entry *ent) |
vfs_s_insert_entry (struct vfs_class *me, struct vfs_s_inode *dir, struct vfs_s_entry *ent) |
132 |
{ |
{ |
133 |
vfs_s_entry **ep; |
struct vfs_s_entry **ep; |
134 |
|
|
135 |
for (ep = &dir->subdir; *ep != NULL; ep = &((*ep)->next)) |
for (ep = &dir->subdir; *ep != NULL; ep = &((*ep)->next)) |
136 |
; |
; |
143 |
} |
} |
144 |
|
|
145 |
struct stat * |
struct stat * |
146 |
vfs_s_default_stat (vfs *me, mode_t mode) |
vfs_s_default_stat (struct vfs_class *me, mode_t mode) |
147 |
{ |
{ |
148 |
static struct stat st; |
static struct stat st; |
149 |
int myumask; |
int myumask; |
165 |
} |
} |
166 |
|
|
167 |
void |
void |
168 |
vfs_s_add_dots (vfs *me, vfs_s_inode *dir, vfs_s_inode *parent) |
vfs_s_add_dots (struct vfs_class *me, struct vfs_s_inode *dir, struct vfs_s_inode *parent) |
169 |
{ |
{ |
170 |
struct vfs_s_entry *dot, *dotdot; |
struct vfs_s_entry *dot, *dotdot; |
171 |
|
|
180 |
} |
} |
181 |
|
|
182 |
struct vfs_s_entry * |
struct vfs_s_entry * |
183 |
vfs_s_generate_entry (vfs *me, char *name, struct vfs_s_inode *parent, mode_t mode) |
vfs_s_generate_entry (struct vfs_class *me, char *name, struct vfs_s_inode *parent, mode_t mode) |
184 |
{ |
{ |
185 |
struct vfs_s_inode *inode; |
struct vfs_s_inode *inode; |
186 |
struct stat *st; |
struct stat *st; |
194 |
} |
} |
195 |
|
|
196 |
/* We were asked to create entries automagically */ |
/* We were asked to create entries automagically */ |
197 |
vfs_s_entry * |
static struct vfs_s_entry * |
198 |
vfs_s_automake (vfs *me, vfs_s_inode *dir, char *path, int flags) |
vfs_s_automake (struct vfs_class *me, struct vfs_s_inode *dir, char *path, int flags) |
199 |
{ |
{ |
200 |
struct vfs_s_entry *res; |
struct vfs_s_entry *res; |
201 |
char *sep = strchr (path, PATH_SEP); |
char *sep = strchr (path, PATH_SEP); |
211 |
return res; |
return res; |
212 |
} |
} |
213 |
|
|
214 |
|
/* If the entry is a symlink, find the entry for its target */ |
215 |
|
static struct vfs_s_entry * |
216 |
|
vfs_s_resolve_symlink (struct vfs_class *me, struct vfs_s_entry *entry, |
217 |
|
char *path, int follow) |
218 |
|
{ |
219 |
|
char *linkname; |
220 |
|
char *fullname = NULL; |
221 |
|
struct vfs_s_entry *target; |
222 |
|
|
223 |
|
if (follow == LINK_NO_FOLLOW) |
224 |
|
return entry; |
225 |
|
if (follow == 0) |
226 |
|
ERRNOR (ELOOP, NULL); |
227 |
|
if (!entry) |
228 |
|
ERRNOR (ENOENT, NULL); |
229 |
|
if (!S_ISLNK (entry->ino->st.st_mode)) |
230 |
|
return entry; |
231 |
|
|
232 |
|
linkname = entry->ino->linkname; |
233 |
|
if (linkname == NULL) |
234 |
|
ERRNOR (EFAULT, NULL); |
235 |
|
|
236 |
|
/* make full path from relative */ |
237 |
|
if (*linkname != PATH_SEP) { |
238 |
|
char *fullpath = vfs_s_fullpath (me, entry->dir); |
239 |
|
fullname = g_strdup_printf ("%s/%s", fullpath, linkname); |
240 |
|
linkname = fullname; |
241 |
|
g_free (fullpath); |
242 |
|
} |
243 |
|
|
244 |
|
target = |
245 |
|
(MEDATA->find_entry) (me, entry->dir->super->root, linkname, |
246 |
|
follow - 1, 0); |
247 |
|
g_free (fullname); |
248 |
|
return target; |
249 |
|
} |
250 |
|
|
251 |
/* |
/* |
252 |
* Follow > 0: follow links, serves as loop protect, |
* Follow > 0: follow links, serves as loop protect, |
253 |
* == -1: do not follow links |
* == -1: do not follow links |
254 |
*/ |
*/ |
255 |
vfs_s_entry * |
struct vfs_s_entry * |
256 |
vfs_s_find_entry_tree (vfs *me, vfs_s_inode *root, char *path, int follow, int flags) |
vfs_s_find_entry_tree (struct vfs_class *me, struct vfs_s_inode *root, |
257 |
|
char *path, int follow, int flags) |
258 |
{ |
{ |
259 |
unsigned int pseg; |
unsigned int pseg; |
260 |
vfs_s_entry *ent = NULL; |
struct vfs_s_entry *ent = NULL; |
261 |
char p[MC_MAXPATHLEN] = ""; |
char p[MC_MAXPATHLEN] = ""; |
262 |
|
|
263 |
while (root){ |
if (strlen(path) >= MC_MAXPATHLEN) |
264 |
|
return NULL; |
265 |
|
|
266 |
|
while (root) { |
267 |
int t; |
int t; |
268 |
|
|
269 |
while (*path == PATH_SEP) /* Strip leading '/' */ |
while (*path == PATH_SEP) /* Strip leading '/' */ |
270 |
path++; |
path++; |
271 |
|
|
272 |
if (!path [0]) |
if (!path[0]) |
273 |
return ent; |
return ent; |
274 |
|
|
275 |
for (pseg = 0; path[pseg] && path[pseg] != PATH_SEP; pseg++) |
for (pseg = 0; path[pseg] && path[pseg] != PATH_SEP; pseg++); |
|
; |
|
276 |
|
|
277 |
strcat (p, PATH_SEP_STR); |
strcat (p, PATH_SEP_STR); |
278 |
strncpy (p + (t = strlen (p)), path, pseg); |
strncpy (p + (t = strlen (p)), path, pseg); |
279 |
p[t + pseg] = '\0'; |
p[t + pseg] = '\0'; |
280 |
|
|
281 |
for (ent = root->subdir; ent != NULL; ent = ent->next) |
for (ent = root->subdir; ent != NULL; ent = ent->next) |
282 |
if (strlen (ent->name) == pseg && (!strncmp (ent->name, path, pseg))) |
if (strlen (ent->name) == pseg |
283 |
|
&& (!strncmp (ent->name, path, pseg))) |
284 |
/* FOUND! */ |
/* FOUND! */ |
285 |
break; |
break; |
286 |
|
|
287 |
if (!ent && (flags & (FL_MKFILE | FL_MKDIR))) |
if (!ent && (flags & (FL_MKFILE | FL_MKDIR))) |
288 |
ent = vfs_s_automake (me, root, path, flags); |
ent = vfs_s_automake (me, root, path, flags); |
289 |
if (!ent) ERRNOR (ENOENT, NULL); |
if (!ent) |
290 |
|
ERRNOR (ENOENT, NULL); |
291 |
path += pseg; |
path += pseg; |
292 |
/* here we must follow leading directories always; only the actual file is optional */ |
/* here we must follow leading directories always; |
293 |
if (!(ent = vfs_s_resolve_symlink (me, ent, p, strchr (path, PATH_SEP) ? LINK_FOLLOW : follow))) |
only the actual file is optional */ |
294 |
|
ent = |
295 |
|
vfs_s_resolve_symlink (me, ent, p, |
296 |
|
strchr (path, |
297 |
|
PATH_SEP) ? LINK_FOLLOW : |
298 |
|
follow); |
299 |
|
if (!ent) |
300 |
return NULL; |
return NULL; |
301 |
root = ent->ino; |
root = ent->ino; |
302 |
} |
} |
305 |
} |
} |
306 |
|
|
307 |
static void |
static void |
308 |
split_dir_name (vfs *me, char *path, char **dir, char **name, char **save) |
split_dir_name (struct vfs_class *me, char *path, char **dir, char **name, char **save) |
309 |
{ |
{ |
310 |
char *s; |
char *s; |
311 |
s = strrchr (path, PATH_SEP); |
s = strrchr (path, PATH_SEP); |
321 |
} |
} |
322 |
} |
} |
323 |
|
|
324 |
vfs_s_entry * |
struct vfs_s_entry * |
325 |
vfs_s_find_entry_linear (vfs *me, vfs_s_inode *root, char *path, int follow, int flags) |
vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root, char *path, int follow, int flags) |
326 |
{ |
{ |
327 |
vfs_s_entry* ent = NULL; |
struct vfs_s_entry* ent = NULL; |
328 |
|
|
329 |
if (root->super->root != root) |
if (root->super->root != root) |
330 |
vfs_die ("We have to use _real_ root. Always. Sorry." ); |
vfs_die ("We have to use _real_ root. Always. Sorry." ); |
333 |
|
|
334 |
if (!(flags & FL_DIR)){ |
if (!(flags & FL_DIR)){ |
335 |
char *dirname, *name, *save; |
char *dirname, *name, *save; |
336 |
vfs_s_inode *ino; |
struct vfs_s_inode *ino; |
337 |
split_dir_name (me, path, &dirname, &name, &save); |
split_dir_name (me, path, &dirname, &name, &save); |
338 |
ino = vfs_s_find_inode (me, root, dirname, follow, flags | FL_DIR); |
ino = vfs_s_find_inode (me, root, dirname, follow, flags | FL_DIR); |
339 |
if (save) |
if (save) |
354 |
} |
} |
355 |
|
|
356 |
if (!ent){ |
if (!ent){ |
357 |
vfs_s_inode *ino; |
struct vfs_s_inode *ino; |
358 |
|
|
359 |
ino = vfs_s_new_inode (me, root->super, vfs_s_default_stat (me, S_IFDIR | 0755)); |
ino = vfs_s_new_inode (me, root->super, vfs_s_default_stat (me, S_IFDIR | 0755)); |
360 |
ent = vfs_s_new_entry (me, path, ino); |
ent = vfs_s_new_entry (me, path, ino); |
377 |
return ent; |
return ent; |
378 |
} |
} |
379 |
|
|
380 |
vfs_s_inode * |
struct vfs_s_inode * |
381 |
vfs_s_find_inode (vfs *me, vfs_s_inode *root, char *path, int follow, int flags) |
vfs_s_find_inode (struct vfs_class *me, struct vfs_s_inode *root, char *path, int follow, int flags) |
382 |
{ |
{ |
383 |
vfs_s_entry *ent; |
struct vfs_s_entry *ent; |
384 |
if ((MEDATA->find_entry == vfs_s_find_entry_tree) && (!*path)) |
if ((MEDATA->find_entry == vfs_s_find_entry_tree) && (!*path)) |
385 |
return root; |
return root; |
386 |
ent = (MEDATA->find_entry)(me, root, path, follow, flags); |
ent = (MEDATA->find_entry)(me, root, path, follow, flags); |
389 |
return ent->ino; |
return ent->ino; |
390 |
} |
} |
391 |
|
|
|
vfs_s_entry * |
|
|
vfs_s_resolve_symlink (vfs *me, vfs_s_entry *entry, char *path, int follow) |
|
|
{ |
|
|
char buf[MC_MAXPATHLEN], *linkname; |
|
|
|
|
|
if (follow == LINK_NO_FOLLOW) |
|
|
return entry; |
|
|
if (follow == 0) |
|
|
ERRNOR (ELOOP, NULL); |
|
|
if (!entry) |
|
|
ERRNOR (ENOENT, NULL); |
|
|
if (!S_ISLNK (entry->ino->st.st_mode)) |
|
|
return entry; |
|
|
|
|
|
linkname = entry->ino->linkname; |
|
|
|
|
|
if (linkname == NULL) |
|
|
ERRNOR (EFAULT, NULL); |
|
|
|
|
|
if (MEDATA->find_entry == vfs_s_find_entry_linear) { |
|
|
if (*linkname == PATH_SEP) |
|
|
return (MEDATA->find_entry) (me, entry->dir->super->root, |
|
|
linkname, follow - 1, 0); |
|
|
else { |
|
|
char *fullpath = vfs_s_fullpath (me, entry->dir); |
|
|
|
|
|
g_snprintf (buf, sizeof (buf), "%s/%s", fullpath, linkname); |
|
|
g_free (fullpath); |
|
|
return (MEDATA->find_entry) (me, entry->dir->super->root, buf, |
|
|
follow - 1, 0); |
|
|
} |
|
|
} |
|
|
|
|
|
/* Convert absolute paths to relative ones */ |
|
|
if (*linkname == PATH_SEP) { |
|
|
char *p, *q; |
|
|
|
|
|
for (p = path, q = entry->ino->linkname; *p == *q; p++, q++); |
|
|
while (*(--q) != PATH_SEP); |
|
|
q++; |
|
|
for (;; p++) { |
|
|
p = strchr (p, PATH_SEP); |
|
|
if (!p) { |
|
|
strcat (buf, q); |
|
|
break; |
|
|
} |
|
|
strcat (buf, ".."); |
|
|
strcat (buf, PATH_SEP_STR); |
|
|
} |
|
|
linkname = buf; |
|
|
} |
|
|
|
|
|
return (MEDATA->find_entry) (me, entry->dir, linkname, follow - 1, 0); |
|
|
} |
|
|
|
|
392 |
/* Ook, these were functions around directory entries / inodes */ |
/* Ook, these were functions around directory entries / inodes */ |
393 |
/* -------------------------------- superblock games -------------------------- */ |
/* -------------------------------- superblock games -------------------------- */ |
394 |
|
|
395 |
vfs_s_super * |
static struct vfs_s_super * |
396 |
vfs_s_new_super (vfs *me) |
vfs_s_new_super (struct vfs_class *me) |
397 |
{ |
{ |
398 |
vfs_s_super *super; |
struct vfs_s_super *super; |
399 |
|
|
400 |
super = g_new0 (struct vfs_s_super, 1); |
super = g_new0 (struct vfs_s_super, 1); |
401 |
super->me = me; |
super->me = me; |
403 |
} |
} |
404 |
|
|
405 |
static void |
static void |
406 |
vfs_s_insert_super (vfs *me, vfs_s_super *super) |
vfs_s_insert_super (struct vfs_class *me, struct vfs_s_super *super) |
407 |
{ |
{ |
408 |
super->next = MEDATA->supers; |
super->next = MEDATA->supers; |
409 |
super->prevp = &MEDATA->supers; |
super->prevp = &MEDATA->supers; |
413 |
MEDATA->supers = super; |
MEDATA->supers = super; |
414 |
} |
} |
415 |
|
|
416 |
void |
static void |
417 |
vfs_s_free_super (vfs *me, vfs_s_super *super) |
vfs_s_free_super (struct vfs_class *me, struct vfs_s_super *super) |
418 |
{ |
{ |
419 |
if (super->root){ |
if (super->root){ |
420 |
vfs_s_free_inode (me, super->root); |
vfs_s_free_inode (me, super->root); |
447 |
/* ------------------------------------------------------------------------= */ |
/* ------------------------------------------------------------------------= */ |
448 |
|
|
449 |
static void |
static void |
450 |
vfs_s_stamp_me (vfs *me, struct vfs_s_super *psup, char *fs_name) |
vfs_s_stamp_me (struct vfs_class *me, struct vfs_s_super *psup, char *fs_name) |
451 |
{ |
{ |
452 |
struct vfs_stamping *parent; |
struct vfs_stamping *parent; |
453 |
vfs *v; |
struct vfs_class *v; |
454 |
|
|
455 |
v = vfs_type (fs_name); |
v = vfs_get_class (fs_name); |
456 |
if (v == &vfs_local_ops){ |
if (v->flags & VFSF_LOCAL){ |
457 |
parent = NULL; |
parent = NULL; |
458 |
} else { |
} else { |
459 |
parent = g_new (struct vfs_stamping, 1); |
parent = g_new (struct vfs_stamping, 1); |
462 |
parent->id = (*v->getid) (v, fs_name, &(parent->parent)); |
parent->id = (*v->getid) (v, fs_name, &(parent->parent)); |
463 |
} |
} |
464 |
vfs_add_noncurrent_stamps (me, (vfsid) psup, parent); |
vfs_add_noncurrent_stamps (me, (vfsid) psup, parent); |
|
vfs_rm_parents (parent); |
|
465 |
} |
} |
466 |
|
|
467 |
char * |
char * |
468 |
vfs_s_get_path_mangle (vfs *me, char *inname, struct vfs_s_super **archive, int flags) |
vfs_s_get_path_mangle (struct vfs_class *me, char *inname, struct vfs_s_super **archive, int flags) |
469 |
{ |
{ |
470 |
char *local, *op, *archive_name; |
char *local, *op, *archive_name; |
471 |
int result = -1; |
int result = -1; |
511 |
return local; |
return local; |
512 |
} |
} |
513 |
|
|
514 |
char * |
static char * |
515 |
vfs_s_get_path (vfs *me, char *inname, struct vfs_s_super **archive, int flags) |
vfs_s_get_path (struct vfs_class *me, const char *inname, struct vfs_s_super **archive, int flags) |
516 |
{ |
{ |
517 |
char *buf = g_strdup( inname ); |
char *buf = g_strdup( inname ); |
518 |
char *res = vfs_s_get_path_mangle (me, buf, archive, flags); |
char *res = vfs_s_get_path_mangle (me, buf, archive, flags); |
523 |
} |
} |
524 |
|
|
525 |
void |
void |
526 |
vfs_s_invalidate (vfs *me, vfs_s_super *super) |
vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super) |
527 |
{ |
{ |
528 |
if (!super->want_stale){ |
if (!super->want_stale){ |
529 |
vfs_s_free_inode (me, super->root); |
vfs_s_free_inode (me, super->root); |
532 |
} |
} |
533 |
|
|
534 |
char * |
char * |
535 |
vfs_s_fullpath (vfs *me, vfs_s_inode *ino) |
vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino) |
536 |
{ |
{ |
537 |
/* For now, usable only on filesystems with _linear structure */ |
if (!ino->ent) |
|
if (MEDATA->find_entry != vfs_s_find_entry_linear) |
|
|
vfs_die ("Implement me!"); |
|
|
if (!ino->ent) /* That must be directory... */ |
|
538 |
ERRNOR (EAGAIN, NULL); |
ERRNOR (EAGAIN, NULL); |
539 |
|
|
540 |
if ((!ino->ent->dir) || (!ino->ent->dir->ent)) /* It must be directory */ |
if (MEDATA->find_entry != vfs_s_find_entry_linear) { |
541 |
return g_strdup (ino->ent->name); |
char *newpath; |
542 |
|
char *path = g_strdup (ino->ent->name); |
543 |
|
while (1) { |
544 |
|
ino = ino->ent->dir; |
545 |
|
if (ino == ino->super->root) |
546 |
|
break; |
547 |
|
newpath = g_strdup_printf ("%s/%s", ino->ent->name, path); |
548 |
|
g_free (path); |
549 |
|
path = newpath; |
550 |
|
} |
551 |
|
return path; |
552 |
|
} |
553 |
|
|
554 |
|
/* It must be directory */ |
555 |
|
if ((!ino->ent->dir) || (!ino->ent->dir->ent)) |
556 |
|
return g_strdup (ino->ent->name); |
557 |
|
|
558 |
return g_strconcat (ino->ent->dir->ent->name, PATH_SEP_STR, |
return g_strconcat (ino->ent->dir->ent->name, PATH_SEP_STR, |
559 |
ino->ent->name, NULL); |
ino->ent->name, NULL); |
560 |
} |
} |
561 |
|
|
562 |
/* Support of archives */ |
/* Support of archives */ |
563 |
/* ------------------------ readdir & friends ----------------------------- */ |
/* ------------------------ readdir & friends ----------------------------- */ |
564 |
|
|
565 |
vfs_s_super *vfs_s_super_from_path (vfs *me, char *name) |
static struct vfs_s_inode * |
566 |
{ |
vfs_s_inode_from_path (struct vfs_class *me, char *name, int flags) |
|
struct vfs_s_super *super; |
|
|
|
|
|
if (!vfs_s_get_path_mangle (me, name, &super, 0)) |
|
|
return NULL; |
|
|
return super; |
|
|
} |
|
|
|
|
|
vfs_s_inode * |
|
|
vfs_s_inode_from_path (vfs *me, char *name, int flags) |
|
567 |
{ |
{ |
568 |
struct vfs_s_super *super; |
struct vfs_s_super *super; |
569 |
struct vfs_s_inode *ino; |
struct vfs_s_inode *ino; |
580 |
} |
} |
581 |
|
|
582 |
struct dirhandle { |
struct dirhandle { |
583 |
vfs_s_entry *cur; |
struct vfs_s_entry *cur; |
584 |
vfs_s_inode *dir; |
struct vfs_s_inode *dir; |
585 |
}; |
}; |
586 |
|
|
587 |
void * |
static void * |
588 |
vfs_s_opendir (vfs *me, char *dirname) |
vfs_s_opendir (struct vfs_class *me, char *dirname) |
589 |
{ |
{ |
590 |
struct vfs_s_inode *dir; |
struct vfs_s_inode *dir; |
591 |
struct dirhandle *info; |
struct dirhandle *info; |
608 |
return info; |
return info; |
609 |
} |
} |
610 |
|
|
611 |
void * |
static void * |
612 |
vfs_s_readdir(void *data) |
vfs_s_readdir(void *data) |
613 |
{ |
{ |
614 |
static union vfs_dirent dir; |
static union vfs_dirent dir; |
630 |
return (void *) &dir; |
return (void *) &dir; |
631 |
} |
} |
632 |
|
|
633 |
int |
static int |
|
vfs_s_telldir (void *data) |
|
|
{ |
|
|
struct dirhandle *info = (struct dirhandle *) data; |
|
|
struct vfs_s_entry *cur; |
|
|
int num = 0; |
|
|
|
|
|
cur = info->dir->subdir; |
|
|
while (cur!=NULL){ |
|
|
if (cur == info->cur) |
|
|
return num; |
|
|
num++; |
|
|
cur = cur->next; |
|
|
} |
|
|
return -1; |
|
|
} |
|
|
|
|
|
void |
|
|
vfs_s_seekdir (void *data, int offset) |
|
|
{ |
|
|
struct dirhandle *info = (struct dirhandle *) data; |
|
|
int i; |
|
|
info->cur = info->dir->subdir; |
|
|
for (i=0; i<offset; i++) |
|
|
vfs_s_readdir (data); |
|
|
} |
|
|
|
|
|
int |
|
634 |
vfs_s_closedir (void *data) |
vfs_s_closedir (void *data) |
635 |
{ |
{ |
636 |
struct dirhandle *info = (struct dirhandle *) data; |
struct dirhandle *info = (struct dirhandle *) data; |
641 |
return 0; |
return 0; |
642 |
} |
} |
643 |
|
|
644 |
int |
static int |
645 |
vfs_s_chdir (vfs *me, char *path) |
vfs_s_chdir (struct vfs_class *me, char *path) |
646 |
{ |
{ |
647 |
void *data; |
void *data; |
648 |
if (!(data = vfs_s_opendir (me, path))) |
if (!(data = vfs_s_opendir (me, path))) |
654 |
/* --------------------------- stat and friends ---------------------------- */ |
/* --------------------------- stat and friends ---------------------------- */ |
655 |
|
|
656 |
static int |
static int |
657 |
vfs_s_internal_stat (vfs *me, char *path, struct stat *buf, int flag) |
vfs_s_internal_stat (struct vfs_class *me, char *path, struct stat *buf, int flag) |
658 |
{ |
{ |
659 |
struct vfs_s_inode *ino; |
struct vfs_s_inode *ino; |
660 |
|
|
664 |
return 0; |
return 0; |
665 |
} |
} |
666 |
|
|
667 |
int |
static int |
668 |
vfs_s_stat (vfs *me, char *path, struct stat *buf) |
vfs_s_stat (struct vfs_class *me, char *path, struct stat *buf) |
669 |
{ |
{ |
670 |
return vfs_s_internal_stat (me, path, buf, FL_FOLLOW); |
return vfs_s_internal_stat (me, path, buf, FL_FOLLOW); |
671 |
} |
} |
672 |
|
|
673 |
int |
static int |
674 |
vfs_s_lstat (vfs *me, char *path, struct stat *buf) |
vfs_s_lstat (struct vfs_class *me, char *path, struct stat *buf) |
675 |
{ |
{ |
676 |
return vfs_s_internal_stat (me, path, buf, FL_NONE); |
return vfs_s_internal_stat (me, path, buf, FL_NONE); |
677 |
} |
} |
678 |
|
|
679 |
int |
static int |
680 |
vfs_s_fstat (void *fh, struct stat *buf) |
vfs_s_fstat (void *fh, struct stat *buf) |
681 |
{ |
{ |
682 |
*buf = FH->ino->st; |
*buf = FH->ino->st; |
683 |
return 0; |
return 0; |
684 |
} |
} |
685 |
|
|
686 |
int |
static int |
687 |
vfs_s_readlink (vfs *me, char *path, char *buf, int size) |
vfs_s_readlink (struct vfs_class *me, char *path, char *buf, int size) |
688 |
{ |
{ |
689 |
struct vfs_s_inode *ino; |
struct vfs_s_inode *ino; |
690 |
|
|
703 |
return strlen (buf); |
return strlen (buf); |
704 |
} |
} |
705 |
|
|
706 |
void * |
static void * |
707 |
vfs_s_open (vfs *me, char *file, int flags, int mode) |
vfs_s_open (struct vfs_class *me, char *file, int flags, int mode) |
708 |
{ |
{ |
709 |
int was_changed = 0; |
int was_changed = 0; |
710 |
struct vfs_s_fh *fh; |
struct vfs_s_fh *fh; |
711 |
vfs_s_super *super; |
struct vfs_s_super *super; |
712 |
char *q; |
char *q; |
713 |
struct vfs_s_inode *ino; |
struct vfs_s_inode *ino; |
714 |
|
|
719 |
ERRNOR (EEXIST, NULL); |
ERRNOR (EEXIST, NULL); |
720 |
if (!ino){ |
if (!ino){ |
721 |
char *dirname, *name, *save; |
char *dirname, *name, *save; |
722 |
vfs_s_entry *ent; |
struct vfs_s_entry *ent; |
723 |
vfs_s_inode *dir; |
struct vfs_s_inode *dir; |
724 |
int tmp_handle; |
int tmp_handle; |
725 |
|
|
726 |
/* If the filesystem is read-only, disable file creation */ |
/* If the filesystem is read-only, disable file creation */ |
781 |
return fh; |
return fh; |
782 |
} |
} |
783 |
|
|
784 |
int |
static int |
785 |
vfs_s_read (void *fh, char *buffer, int count) |
vfs_s_read (void *fh, char *buffer, int count) |
786 |
{ |
{ |
787 |
int n; |
int n; |
788 |
vfs *me = FH_SUPER->me; |
struct vfs_class *me = FH_SUPER->me; |
789 |
|
|
790 |
if (FH->linear == LS_LINEAR_CLOSED) |
if (FH->linear == LS_LINEAR_CLOSED) |
791 |
vfs_die ("linear_start() did not set linear_state!"); |
vfs_die ("linear_start() did not set linear_state!"); |
803 |
return -1; |
return -1; |
804 |
} |
} |
805 |
|
|
806 |
int |
static int |
807 |
vfs_s_write (void *fh, char *buffer, int count) |
vfs_s_write (void *fh, char *buffer, int count) |
808 |
{ |
{ |
809 |
int n; |
int n; |
810 |
vfs *me = FH_SUPER->me; |
struct vfs_class *me = FH_SUPER->me; |
811 |
|
|
812 |
if (FH->linear) |
if (FH->linear) |
813 |
vfs_die ("no writing to linear files, please"); |
vfs_die ("no writing to linear files, please"); |
823 |
return 0; |
return 0; |
824 |
} |
} |
825 |
|
|
826 |
int |
static int |
827 |
vfs_s_lseek (void *fh, off_t offset, int whence) |
vfs_s_lseek (void *fh, off_t offset, int whence) |
828 |
{ |
{ |
829 |
off_t size = FH->ino->st.st_size; |
off_t size = FH->ino->st.st_size; |
850 |
return FH->pos; |
return FH->pos; |
851 |
} |
} |
852 |
|
|
853 |
int |
static int |
854 |
vfs_s_close (void *fh) |
vfs_s_close (void *fh) |
855 |
{ |
{ |
856 |
int res = 0; |
int res = 0; |
857 |
vfs *me = FH_SUPER->me; |
struct vfs_class *me = FH_SUPER->me; |
858 |
|
|
859 |
FH_SUPER->fd_usage--; |
FH_SUPER->fd_usage--; |
860 |
if (!FH_SUPER->fd_usage){ |
if (!FH_SUPER->fd_usage){ |
861 |
struct vfs_stamping *parent; |
struct vfs_stamping *parent; |
862 |
vfs *v; |
struct vfs_class *v; |
863 |
|
|
864 |
v = vfs_type (FH_SUPER->name); |
v = vfs_get_class (FH_SUPER->name); |
865 |
if (v == &vfs_local_ops){ |
if (v->flags & VFSF_LOCAL) { |
866 |
parent = NULL; |
parent = NULL; |
867 |
} else { |
} else { |
868 |
parent = g_new (struct vfs_stamping, 1); |
parent = g_new (struct vfs_stamping, 1); |
871 |
parent->id = (*v->getid) (v, FH_SUPER->name, &(parent->parent)); |
parent->id = (*v->getid) (v, FH_SUPER->name, &(parent->parent)); |
872 |
} |
} |
873 |
vfs_add_noncurrent_stamps (me, (vfsid) (FH_SUPER), parent); |
vfs_add_noncurrent_stamps (me, (vfsid) (FH_SUPER), parent); |
|
vfs_rm_parents (parent); |
|
874 |
} |
} |
875 |
if (FH->linear == LS_LINEAR_OPEN) |
if (FH->linear == LS_LINEAR_OPEN) |
876 |
MEDATA->linear_close (me, fh); |
MEDATA->linear_close (me, fh); |
895 |
} |
} |
896 |
|
|
897 |
int |
int |
898 |
vfs_s_retrieve_file (vfs *me, struct vfs_s_inode *ino) |
vfs_s_retrieve_file (struct vfs_class *me, struct vfs_s_inode *ino) |
899 |
{ |
{ |
900 |
/* If you want reget, you'll have to open file with O_LINEAR */ |
/* If you want reget, you'll have to open file with O_LINEAR */ |
901 |
off_t total = 0; |
off_t total = 0; |
959 |
|
|
960 |
/* ------------------------------- mc support ---------------------------- */ |
/* ------------------------------- mc support ---------------------------- */ |
961 |
|
|
962 |
void |
static void |
963 |
vfs_s_fill_names (vfs *me, void (*func)(char *)) |
vfs_s_fill_names (struct vfs_class *me, void (*func)(char *)) |
964 |
{ |
{ |
965 |
struct vfs_s_super *a = MEDATA->supers; |
struct vfs_s_super *a = MEDATA->supers; |
966 |
char *name; |
char *name; |
973 |
} |
} |
974 |
} |
} |
975 |
|
|
976 |
int |
static int |
977 |
vfs_s_ferrno (vfs *me) |
vfs_s_ferrno (struct vfs_class *me) |
978 |
{ |
{ |
979 |
return me->verrno; |
return me->verrno; |
980 |
} |
} |
981 |
|
|
982 |
void |
static char * |
983 |
vfs_s_dump (vfs *me, char *prefix, vfs_s_inode *ino) |
vfs_s_getlocalcopy (struct vfs_class *me, char *path) |
|
{ |
|
|
printf ("%s %s %d ", prefix, S_ISDIR (ino->st.st_mode) ? "DIR" : "FILE", ino->st.st_mode); |
|
|
if (!ino->subdir) |
|
|
printf ("FILE\n"); |
|
|
else |
|
|
{ |
|
|
struct vfs_s_entry *ent; |
|
|
for (ent = ino->subdir; ent ; ent = ent->next){ |
|
|
char *s = g_strconcat (prefix, "/", ent->name, NULL); |
|
|
if (ent->name[0] == '.') |
|
|
printf ("%s IGNORED\n", s); |
|
|
else |
|
|
vfs_s_dump (me, s, ent->ino); |
|
|
g_free(s); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
char * |
|
|
vfs_s_getlocalcopy (vfs *me, char *path) |
|
984 |
{ |
{ |
985 |
struct vfs_s_inode *ino; |
struct vfs_s_inode *ino; |
986 |
char buf[MC_MAXPATHLEN]; |
char buf[MC_MAXPATHLEN]; |
994 |
return g_strdup (ino->localname); |
return g_strdup (ino->localname); |
995 |
} |
} |
996 |
|
|
997 |
int |
static int |
998 |
vfs_s_setctl (vfs *me, char *path, int ctlop, char *arg) |
vfs_s_setctl (struct vfs_class *me, char *path, int ctlop, void *arg) |
999 |
{ |
{ |
1000 |
vfs_s_inode *ino = vfs_s_inode_from_path (me, path, 0); |
switch (ctlop) { |
1001 |
if (!ino) |
case VFS_SETCTL_STALE_DATA: |
1002 |
return 0; |
{ |
1003 |
switch (ctlop){ |
struct vfs_s_inode *ino = vfs_s_inode_from_path (me, path, 0); |
1004 |
case MCCTL_WANT_STALE_DATA: |
|
1005 |
ino->super->want_stale = 1; |
if (!ino) |
1006 |
|
return 0; |
1007 |
|
if (arg) |
1008 |
|
ino->super->want_stale = 1; |
1009 |
|
else { |
1010 |
|
ino->super->want_stale = 0; |
1011 |
|
vfs_s_invalidate (me, ino->super); |
1012 |
|
} |
1013 |
|
return 1; |
1014 |
|
} |
1015 |
|
case VFS_SETCTL_LOGFILE: |
1016 |
|
MEDATA->logfile = fopen ((char *) arg, "w"); |
1017 |
return 1; |
return 1; |
1018 |
case MCCTL_NO_STALE_DATA: |
case VFS_SETCTL_FLUSH: |
1019 |
ino->super->want_stale = 0; |
MEDATA->flush = 1; |
|
vfs_s_invalidate(me, ino->super); |
|
1020 |
return 1; |
return 1; |
|
#if 0 /* FIXME: We should implement these */ |
|
|
case MCCTL_REMOVELOCALCOPY: |
|
|
return remove_temp_file (path); |
|
|
case MCCTL_FORGET_ABOUT: |
|
|
my_forget(path); |
|
|
return 0; |
|
|
#endif |
|
1021 |
} |
} |
1022 |
return 0; |
return 0; |
1023 |
} |
} |
1025 |
|
|
1026 |
/* ----------------------------- Stamping support -------------------------- */ |
/* ----------------------------- Stamping support -------------------------- */ |
1027 |
|
|
1028 |
vfsid |
static vfsid |
1029 |
vfs_s_getid (vfs *me, char *path, struct vfs_stamping **parent) |
vfs_s_getid (struct vfs_class *me, const char *path, struct vfs_stamping **parent) |
1030 |
{ |
{ |
1031 |
vfs_s_super *archive; |
struct vfs_s_super *archive; |
1032 |
vfs *v; |
struct vfs_class *v; |
1033 |
char *p; |
char *p; |
1034 |
vfsid id; |
vfsid id; |
1035 |
struct vfs_stamping *par; |
struct vfs_stamping *par; |
1038 |
if (!(p = vfs_s_get_path (me, path, &archive, FL_NO_OPEN))) |
if (!(p = vfs_s_get_path (me, path, &archive, FL_NO_OPEN))) |
1039 |
return (vfsid) -1; |
return (vfsid) -1; |
1040 |
g_free(p); |
g_free(p); |
1041 |
v = vfs_type (archive->name); |
v = vfs_get_class (archive->name); |
1042 |
id = (*v->getid) (v, archive->name, &par); |
id = (*v->getid) (v, archive->name, &par); |
1043 |
if (id != (vfsid)-1){ |
if (id != (vfsid)-1){ |
1044 |
*parent = g_new (struct vfs_stamping, 1); |
*parent = g_new (struct vfs_stamping, 1); |
1050 |
return (vfsid) archive; |
return (vfsid) archive; |
1051 |
} |
} |
1052 |
|
|
1053 |
int |
static int |
1054 |
vfs_s_nothingisopen (vfsid id) |
vfs_s_nothingisopen (vfsid id) |
1055 |
{ |
{ |
1056 |
/* Our data structures should survive free of superblock at any time */ |
/* Our data structures should survive free of superblock at any time */ |
1057 |
return 1; |
return 1; |
1058 |
} |
} |
1059 |
|
|
1060 |
void |
static void |
1061 |
vfs_s_free (vfsid id) |
vfs_s_free (vfsid id) |
1062 |
{ |
{ |
1063 |
vfs_s_free_super (((vfs_s_super *)id)->me, (vfs_s_super *)id); |
vfs_s_free_super (((struct vfs_s_super *)id)->me, (struct vfs_s_super *)id); |
1064 |
|
} |
1065 |
|
|
1066 |
|
void |
1067 |
|
vfs_s_init_class (struct vfs_class *vclass) |
1068 |
|
{ |
1069 |
|
vclass->fill_names = vfs_s_fill_names; |
1070 |
|
vclass->open = vfs_s_open; |
1071 |
|
vclass->close = vfs_s_close; |
1072 |
|
vclass->read = vfs_s_read; |
1073 |
|
vclass->write = vfs_s_write; |
1074 |
|
vclass->opendir = vfs_s_opendir; |
1075 |
|
vclass->readdir = vfs_s_readdir; |
1076 |
|
vclass->closedir = vfs_s_closedir; |
1077 |
|
vclass->stat = vfs_s_stat; |
1078 |
|
vclass->lstat = vfs_s_lstat; |
1079 |
|
vclass->fstat = vfs_s_fstat; |
1080 |
|
vclass->readlink = vfs_s_readlink; |
1081 |
|
vclass->chdir = vfs_s_chdir; |
1082 |
|
vclass->ferrno = vfs_s_ferrno; |
1083 |
|
vclass->lseek = vfs_s_lseek; |
1084 |
|
vclass->getid = vfs_s_getid; |
1085 |
|
vclass->nothingisopen = vfs_s_nothingisopen; |
1086 |
|
vclass->free = vfs_s_free; |
1087 |
|
vclass->getlocalcopy = vfs_s_getlocalcopy; |
1088 |
|
vclass->setctl = vfs_s_setctl; |
1089 |
} |
} |
1090 |
|
|
1091 |
/* ----------- Utility functions for networked filesystems -------------- */ |
/* ----------- Utility functions for networked filesystems -------------- */ |
1115 |
} |
} |
1116 |
|
|
1117 |
int |
int |
1118 |
vfs_s_get_line (vfs *me, int sock, char *buf, int buf_len, char term) |
vfs_s_get_line (struct vfs_class *me, int sock, char *buf, int buf_len, char term) |
1119 |
{ |
{ |
1120 |
FILE *logfile = MEDATA->logfile; |
FILE *logfile = MEDATA->logfile; |
1121 |
int i, status; |
int i, status; |
1148 |
} |
} |
1149 |
|
|
1150 |
int |
int |
1151 |
vfs_s_get_line_interruptible (vfs *me, char *buffer, int size, int fd) |
vfs_s_get_line_interruptible (struct vfs_class *me, char *buffer, int size, int fd) |
1152 |
{ |
{ |
1153 |
int n; |
int n; |
1154 |
int i; |
int i; |