This source file includes following definitions.
- vfs_s_automake
- vfs_s_resolve_symlink
- vfs_s_find_entry_tree
- vfs_s_find_entry_linear
- vfs_s_new_super
- vfs_s_insert_super
- vfs_s_free_super
- vfs_s_new_fh
- vfs_s_free_fh
- vfs_s_inode_from_path
- vfs_s_opendir
- vfs_s_readdir
- vfs_s_closedir
- vfs_s_chdir
- vfs_s_internal_stat
- vfs_s_readlink
- vfs_s_read
- vfs_s_write
- vfs_s_lseek
- vfs_s_close
- vfs_s_print_stats
- vfs_s_fill_names
- vfs_s_ferrno
- vfs_s_getlocalcopy
- vfs_s_ungetlocalcopy
- vfs_s_setctl
- vfs_s_getid
- vfs_s_nothingisopen
- vfs_s_free
- vfs_s_dir_uptodate
- vfs_s_new_inode
- vfs_s_free_inode
- vfs_s_new_entry
- vfs_s_free_entry
- vfs_s_insert_entry
- vfs_s_entry_compare
- vfs_s_default_stat
- vfs_adjust_stat
- vfs_s_generate_entry
- vfs_s_find_inode
- vfs_get_super_by_vpath
- vfs_s_get_path
- vfs_s_invalidate
- vfs_s_fullpath
- vfs_s_init_fh
- vfs_s_open
- vfs_s_stat
- vfs_s_lstat
- vfs_s_fstat
- vfs_s_retrieve_file
- vfs_init_class
- vfs_init_subclass
- vfs_getid
- vfs_s_select_on_two
- vfs_s_get_line
- vfs_s_get_line_interruptible
- vfs_s_normalize_filename_leading_spaces
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 #include <config.h>
60
61 #include <errno.h>
62 #include <inttypes.h>
63 #include <stdarg.h>
64 #ifdef HAVE_SYS_SELECT_H
65 #include <sys/select.h>
66 #endif
67 #include <sys/types.h>
68 #include <unistd.h>
69
70 #include "lib/global.h"
71
72 #include "lib/tty/tty.h"
73 #include "lib/util.h"
74 #if 0
75 #include "lib/widget.h"
76 #endif
77
78 #include "vfs.h"
79 #include "utilvfs.h"
80 #include "xdirentry.h"
81 #include "gc.h"
82
83
84
85
86
87 #define CALL(x) \
88 if (VFS_SUBCLASS (me)->x != NULL) \
89 VFS_SUBCLASS (me)->x
90
91
92
93 struct dirhandle
94 {
95 GList *cur;
96 struct vfs_s_inode *dir;
97 };
98
99
100
101
102
103
104
105
106
107 static struct vfs_s_entry *
108 vfs_s_automake (struct vfs_class *me, struct vfs_s_inode *dir, char *path, int flags)
109 {
110 struct vfs_s_entry *res;
111 char *sep;
112
113 sep = strchr (path, PATH_SEP);
114 if (sep != NULL)
115 *sep = '\0';
116
117 res = vfs_s_generate_entry (me, path, dir, (flags & FL_MKDIR) != 0 ? (0777 | S_IFDIR) : 0777);
118 vfs_s_insert_entry (me, dir, res);
119
120 if (sep != NULL)
121 *sep = PATH_SEP;
122
123 return res;
124 }
125
126
127
128
129 static struct vfs_s_entry *
130 vfs_s_resolve_symlink (struct vfs_class *me, struct vfs_s_entry *entry, int follow)
131 {
132 char *linkname;
133 char *fullname = NULL;
134 struct vfs_s_entry *target;
135
136 if (follow == LINK_NO_FOLLOW)
137 return entry;
138 if (follow == 0)
139 ERRNOR (ELOOP, NULL);
140 if (entry == NULL)
141 ERRNOR (ENOENT, NULL);
142 if (!S_ISLNK (entry->ino->st.st_mode))
143 return entry;
144
145 linkname = entry->ino->linkname;
146 if (linkname == NULL)
147 ERRNOR (EFAULT, NULL);
148
149
150 if (!IS_PATH_SEP (*linkname))
151 {
152 char *fullpath;
153
154 fullpath = vfs_s_fullpath (me, entry->dir);
155 if (fullpath != NULL)
156 {
157 fullname = g_strconcat (fullpath, PATH_SEP_STR, linkname, (char *) NULL);
158 linkname = fullname;
159 g_free (fullpath);
160 }
161 }
162
163 target =
164 VFS_SUBCLASS (me)->find_entry (me, entry->dir->super->root, linkname, follow - 1, FL_NONE);
165 g_free (fullname);
166 return target;
167 }
168
169
170
171
172
173
174
175 static struct vfs_s_entry *
176 vfs_s_find_entry_tree (struct vfs_class *me, struct vfs_s_inode *root,
177 const char *a_path, int follow, int flags)
178 {
179 size_t pseg;
180 struct vfs_s_entry *ent = NULL;
181 char *const pathref = g_strdup (a_path);
182 char *path = pathref;
183
184
185 canonicalize_pathname_custom (path, CANON_PATH_ALL & (~CANON_PATH_REMDOUBLEDOTS));
186
187 while (root != NULL)
188 {
189 GList *iter;
190
191 while (IS_PATH_SEP (*path))
192 path++;
193
194 if (path[0] == '\0')
195 {
196 g_free (pathref);
197 return ent;
198 }
199
200 for (pseg = 0; path[pseg] != '\0' && !IS_PATH_SEP (path[pseg]); pseg++)
201 ;
202
203 for (iter = g_queue_peek_head_link (root->subdir); iter != NULL; iter = g_list_next (iter))
204 {
205 ent = VFS_ENTRY (iter->data);
206 if (strlen (ent->name) == pseg && strncmp (ent->name, path, pseg) == 0)
207
208 break;
209 }
210
211 ent = iter != NULL ? VFS_ENTRY (iter->data) : NULL;
212
213 if (ent == NULL && (flags & (FL_MKFILE | FL_MKDIR)) != 0)
214 ent = vfs_s_automake (me, root, path, flags);
215 if (ent == NULL)
216 {
217 me->verrno = ENOENT;
218 goto cleanup;
219 }
220
221 path += pseg;
222
223
224 ent = vfs_s_resolve_symlink (me, ent,
225 strchr (path, PATH_SEP) != NULL ? LINK_FOLLOW : follow);
226 if (ent == NULL)
227 goto cleanup;
228 root = ent->ino;
229 }
230 cleanup:
231 g_free (pathref);
232 return NULL;
233 }
234
235
236
237 static struct vfs_s_entry *
238 vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root,
239 const char *a_path, int follow, int flags)
240 {
241 struct vfs_s_entry *ent = NULL;
242 char *const path = g_strdup (a_path);
243 GList *iter;
244
245 if (root->super->root != root)
246 vfs_die ("We have to use _real_ root. Always. Sorry.");
247
248
249 canonicalize_pathname_custom (path, CANON_PATH_ALL & (~CANON_PATH_REMDOUBLEDOTS));
250
251 if ((flags & FL_DIR) == 0)
252 {
253 char *dirname, *name;
254 struct vfs_s_inode *ino;
255
256 dirname = g_path_get_dirname (path);
257 name = g_path_get_basename (path);
258 ino = vfs_s_find_inode (me, root->super, dirname, follow, flags | FL_DIR);
259 ent = vfs_s_find_entry_tree (me, ino, name, follow, flags);
260 g_free (dirname);
261 g_free (name);
262 g_free (path);
263 return ent;
264 }
265
266 iter = g_queue_find_custom (root->subdir, path, (GCompareFunc) vfs_s_entry_compare);
267 ent = iter != NULL ? VFS_ENTRY (iter->data) : NULL;
268
269 if (ent != NULL && !VFS_SUBCLASS (me)->dir_uptodate (me, ent->ino))
270 {
271 #if 1
272 vfs_print_message (_("Directory cache expired for %s"), path);
273 #endif
274 vfs_s_free_entry (me, ent);
275 ent = NULL;
276 }
277
278 if (ent == NULL)
279 {
280 struct vfs_s_inode *ino;
281
282 ino = vfs_s_new_inode (me, root->super, vfs_s_default_stat (me, S_IFDIR | 0755));
283 ent = vfs_s_new_entry (me, path, ino);
284 if (VFS_SUBCLASS (me)->dir_load (me, ino, path) == -1)
285 {
286 vfs_s_free_entry (me, ent);
287 g_free (path);
288 return NULL;
289 }
290
291 vfs_s_insert_entry (me, root, ent);
292
293 iter = g_queue_find_custom (root->subdir, path, (GCompareFunc) vfs_s_entry_compare);
294 ent = iter != NULL ? VFS_ENTRY (iter->data) : NULL;
295 }
296 if (ent == NULL)
297 vfs_die ("find_linear: success but directory is not there\n");
298
299 #if 0
300 if (vfs_s_resolve_symlink (me, ent, follow) == NULL)
301 {
302 g_free (path);
303 return NULL;
304 }
305 #endif
306 g_free (path);
307 return ent;
308 }
309
310
311
312
313
314 static struct vfs_s_super *
315 vfs_s_new_super (struct vfs_class *me)
316 {
317 struct vfs_s_super *super;
318
319 super = g_new0 (struct vfs_s_super, 1);
320 super->me = me;
321 return super;
322 }
323
324
325
326 static inline void
327 vfs_s_insert_super (struct vfs_class *me, struct vfs_s_super *super)
328 {
329 VFS_SUBCLASS (me)->supers = g_list_prepend (VFS_SUBCLASS (me)->supers, super);
330 }
331
332
333
334 static void
335 vfs_s_free_super (struct vfs_class *me, struct vfs_s_super *super)
336 {
337 if (super->root != NULL)
338 {
339 vfs_s_free_inode (me, super->root);
340 super->root = NULL;
341 }
342
343 #if 0
344
345 if (super->ino_usage != 0)
346 message (D_ERROR, "Direntry warning",
347 "Super ino_usage is %d, memory leak", super->ino_usage);
348
349 if (super->want_stale)
350 message (D_ERROR, "Direntry warning", "%s", "Super has want_stale set");
351 #endif
352
353 VFS_SUBCLASS (me)->supers = g_list_remove (VFS_SUBCLASS (me)->supers, super);
354
355 CALL (free_archive) (me, super);
356 #ifdef ENABLE_VFS_NET
357 vfs_path_element_free (super->path_element);
358 #endif
359 g_free (super->name);
360 g_free (super);
361 }
362
363
364
365 static vfs_file_handler_t *
366 vfs_s_new_fh (struct vfs_s_inode *ino, gboolean changed)
367 {
368 vfs_file_handler_t *fh;
369
370 fh = g_new0 (vfs_file_handler_t, 1);
371 vfs_s_init_fh (fh, ino, changed);
372
373 return fh;
374 }
375
376
377
378 static void
379 vfs_s_free_fh (struct vfs_s_subclass *s, vfs_file_handler_t * fh)
380 {
381 if (s->fh_free != NULL)
382 s->fh_free (fh);
383
384 g_free (fh);
385 }
386
387
388
389
390
391 static struct vfs_s_inode *
392 vfs_s_inode_from_path (const vfs_path_t * vpath, int flags)
393 {
394 struct vfs_s_super *super;
395 struct vfs_s_inode *ino;
396 const char *q;
397 const vfs_path_element_t *path_element;
398
399 q = vfs_s_get_path (vpath, &super, 0);
400 if (q == NULL)
401 return NULL;
402
403 path_element = vfs_path_get_by_index (vpath, -1);
404
405 ino =
406 vfs_s_find_inode (path_element->class, super, q,
407 (flags & FL_FOLLOW) != 0 ? LINK_FOLLOW : LINK_NO_FOLLOW,
408 flags & ~FL_FOLLOW);
409 if (ino == NULL && *q == '\0')
410
411 ino =
412 vfs_s_find_inode (path_element->class, super, q,
413 (flags & FL_FOLLOW) != 0 ? LINK_FOLLOW : LINK_NO_FOLLOW,
414 FL_DIR | (flags & ~FL_FOLLOW));
415 return ino;
416 }
417
418
419
420 static void *
421 vfs_s_opendir (const vfs_path_t * vpath)
422 {
423 struct vfs_s_inode *dir;
424 struct dirhandle *info;
425 const vfs_path_element_t *path_element;
426
427 dir = vfs_s_inode_from_path (vpath, FL_DIR | FL_FOLLOW);
428 if (dir == NULL)
429 return NULL;
430
431 path_element = vfs_path_get_by_index (vpath, -1);
432
433 if (!S_ISDIR (dir->st.st_mode))
434 {
435 path_element->class->verrno = ENOTDIR;
436 return NULL;
437 }
438
439 dir->st.st_nlink++;
440 #if 0
441 if (dir->subdir == NULL)
442 {
443 path_element->class->verrno = EAGAIN;
444 return NULL;
445 }
446 #endif
447 info = g_new (struct dirhandle, 1);
448 info->cur = g_queue_peek_head_link (dir->subdir);
449 info->dir = dir;
450
451 return info;
452 }
453
454
455
456 static struct vfs_dirent *
457 vfs_s_readdir (void *data)
458 {
459 struct vfs_dirent *dir = NULL;
460 struct dirhandle *info = (struct dirhandle *) data;
461 const char *name;
462
463 if (info->cur == NULL || info->cur->data == NULL)
464 return NULL;
465
466 name = VFS_ENTRY (info->cur->data)->name;
467 if (name != NULL)
468 dir = vfs_dirent_init (NULL, name, 0);
469 else
470 vfs_die ("Null in structure-cannot happen");
471
472 info->cur = g_list_next (info->cur);
473
474 return dir;
475 }
476
477
478
479 static int
480 vfs_s_closedir (void *data)
481 {
482 struct dirhandle *info = (struct dirhandle *) data;
483 struct vfs_s_inode *dir = info->dir;
484
485 vfs_s_free_inode (dir->super->me, dir);
486 g_free (data);
487 return 0;
488 }
489
490
491
492 static int
493 vfs_s_chdir (const vfs_path_t * vpath)
494 {
495 void *data;
496
497 data = vfs_s_opendir (vpath);
498 if (data == NULL)
499 return (-1);
500 vfs_s_closedir (data);
501 return 0;
502 }
503
504
505
506
507 static int
508 vfs_s_internal_stat (const vfs_path_t * vpath, struct stat *buf, int flag)
509 {
510 struct vfs_s_inode *ino;
511
512 ino = vfs_s_inode_from_path (vpath, flag);
513 if (ino == NULL)
514 return (-1);
515 *buf = ino->st;
516 return 0;
517 }
518
519
520
521 static int
522 vfs_s_readlink (const vfs_path_t * vpath, char *buf, size_t size)
523 {
524 struct vfs_s_inode *ino;
525 size_t len;
526 const vfs_path_element_t *path_element;
527
528 ino = vfs_s_inode_from_path (vpath, 0);
529 if (ino == NULL)
530 return (-1);
531
532 path_element = vfs_path_get_by_index (vpath, -1);
533
534 if (!S_ISLNK (ino->st.st_mode))
535 {
536 path_element->class->verrno = EINVAL;
537 return (-1);
538 }
539
540 if (ino->linkname == NULL)
541 {
542 path_element->class->verrno = EFAULT;
543 return (-1);
544 }
545
546 len = strlen (ino->linkname);
547 if (size < len)
548 len = size;
549
550 memcpy (buf, ino->linkname, len);
551 return len;
552 }
553
554
555
556 static ssize_t
557 vfs_s_read (void *fh, char *buffer, size_t count)
558 {
559 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
560 struct vfs_class *me = VFS_FILE_HANDLER_SUPER (fh)->me;
561
562 if (file->linear == LS_LINEAR_PREOPEN)
563 {
564 if (VFS_SUBCLASS (me)->linear_start (me, file, file->pos) == 0)
565 return (-1);
566 }
567
568 if (file->linear == LS_LINEAR_CLOSED)
569 vfs_die ("linear_start() did not set linear_state!");
570
571 if (file->linear == LS_LINEAR_OPEN)
572 return VFS_SUBCLASS (me)->linear_read (me, file, buffer, count);
573
574 if (file->handle != -1)
575 {
576 ssize_t n;
577
578 n = read (file->handle, buffer, count);
579 if (n < 0)
580 me->verrno = errno;
581 return n;
582 }
583 vfs_die ("vfs_s_read: This should not happen\n");
584 return (-1);
585 }
586
587
588
589 static ssize_t
590 vfs_s_write (void *fh, const char *buffer, size_t count)
591 {
592 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
593 struct vfs_class *me = VFS_FILE_HANDLER_SUPER (fh)->me;
594
595 if (file->linear != LS_NOT_LINEAR)
596 vfs_die ("no writing to linear files, please");
597
598 file->changed = TRUE;
599 if (file->handle != -1)
600 {
601 ssize_t n;
602
603 n = write (file->handle, buffer, count);
604 if (n < 0)
605 me->verrno = errno;
606 return n;
607 }
608 vfs_die ("vfs_s_write: This should not happen\n");
609 return 0;
610 }
611
612
613
614 static off_t
615 vfs_s_lseek (void *fh, off_t offset, int whence)
616 {
617 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
618 off_t size = file->ino->st.st_size;
619
620 if (file->linear == LS_LINEAR_OPEN)
621 vfs_die ("cannot lseek() after linear_read!");
622
623 if (file->handle != -1)
624 {
625 off_t retval;
626
627 retval = lseek (file->handle, offset, whence);
628 if (retval == -1)
629 VFS_FILE_HANDLER_SUPER (fh)->me->verrno = errno;
630 return retval;
631 }
632
633 switch (whence)
634 {
635 case SEEK_CUR:
636 offset += file->pos;
637 break;
638 case SEEK_END:
639 offset += size;
640 break;
641 default:
642 break;
643 }
644 if (offset < 0)
645 file->pos = 0;
646 else if (offset < size)
647 file->pos = offset;
648 else
649 file->pos = size;
650 return file->pos;
651 }
652
653
654
655 static int
656 vfs_s_close (void *fh)
657 {
658 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
659 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
660 struct vfs_class *me = super->me;
661 struct vfs_s_subclass *sub = VFS_SUBCLASS (me);
662 int res = 0;
663
664 if (me == NULL)
665 return (-1);
666
667 super->fd_usage--;
668 if (super->fd_usage == 0)
669 vfs_stamp_create (me, VFS_FILE_HANDLER_SUPER (fh));
670
671 if (file->linear == LS_LINEAR_OPEN)
672 sub->linear_close (me, fh);
673 if (sub->fh_close != NULL)
674 res = sub->fh_close (me, fh);
675 if ((me->flags & VFSF_USETMP) != 0 && file->changed && sub->file_store != NULL)
676 {
677 char *s;
678
679 s = vfs_s_fullpath (me, file->ino);
680
681 if (s == NULL)
682 res = -1;
683 else
684 {
685 res = sub->file_store (me, fh, s, file->ino->localname);
686 g_free (s);
687 }
688 vfs_s_invalidate (me, super);
689 }
690
691 if (file->handle != -1)
692 {
693 close (file->handle);
694 file->handle = -1;
695 }
696
697 vfs_s_free_inode (me, file->ino);
698 vfs_s_free_fh (sub, fh);
699
700 return res;
701 }
702
703
704
705 static void
706 vfs_s_print_stats (const char *fs_name, const char *action,
707 const char *file_name, off_t have, off_t need)
708 {
709 if (need != 0)
710 vfs_print_message (_("%s: %s: %s %3d%% (%lld) bytes transferred"), fs_name, action,
711 file_name, (int) ((double) have * 100 / need), (long long) have);
712 else
713 vfs_print_message (_("%s: %s: %s %lld bytes transferred"), fs_name, action, file_name,
714 (long long) have);
715 }
716
717
718
719
720 static void
721 vfs_s_fill_names (struct vfs_class *me, fill_names_f func)
722 {
723 GList *iter;
724
725 for (iter = VFS_SUBCLASS (me)->supers; iter != NULL; iter = g_list_next (iter))
726 {
727 const struct vfs_s_super *super = (const struct vfs_s_super *) iter->data;
728 char *name;
729
730 name = g_strconcat (super->name, PATH_SEP_STR, me->prefix, VFS_PATH_URL_DELIMITER,
731 (char *) NULL);
732 func (name);
733 g_free (name);
734 }
735 }
736
737
738
739 static int
740 vfs_s_ferrno (struct vfs_class *me)
741 {
742 return me->verrno;
743 }
744
745
746
747
748
749
750
751 static vfs_path_t *
752 vfs_s_getlocalcopy (const vfs_path_t * vpath)
753 {
754 vfs_file_handler_t *fh;
755 vfs_path_t *local = NULL;
756
757 if (vpath == NULL)
758 return NULL;
759
760 fh = vfs_s_open (vpath, O_RDONLY, 0);
761
762 if (fh != NULL)
763 {
764 const struct vfs_class *me;
765
766 me = vfs_path_get_by_index (vpath, -1)->class;
767 if ((me->flags & VFSF_USETMP) != 0 && fh->ino != NULL)
768 local = vfs_path_from_str_flags (fh->ino->localname, VPF_NO_CANON);
769
770 vfs_s_close (fh);
771 }
772
773 return local;
774 }
775
776
777
778
779
780
781
782 static int
783 vfs_s_ungetlocalcopy (const vfs_path_t * vpath, const vfs_path_t * local, gboolean has_changed)
784 {
785 (void) vpath;
786 (void) local;
787 (void) has_changed;
788 return 0;
789 }
790
791
792
793 static int
794 vfs_s_setctl (const vfs_path_t * vpath, int ctlop, void *arg)
795 {
796 const vfs_path_element_t *path_element;
797
798 path_element = vfs_path_get_by_index (vpath, -1);
799
800 switch (ctlop)
801 {
802 case VFS_SETCTL_STALE_DATA:
803 {
804 struct vfs_s_inode *ino;
805
806 ino = vfs_s_inode_from_path (vpath, 0);
807 if (ino == NULL)
808 return 0;
809 if (arg != NULL)
810 ino->super->want_stale = TRUE;
811 else
812 {
813 ino->super->want_stale = FALSE;
814 vfs_s_invalidate (path_element->class, ino->super);
815 }
816 return 1;
817 }
818 case VFS_SETCTL_LOGFILE:
819 path_element->class->logfile = fopen ((char *) arg, "w");
820 return 1;
821 case VFS_SETCTL_FLUSH:
822 path_element->class->flush = TRUE;
823 return 1;
824 default:
825 return 0;
826 }
827 }
828
829
830
831
832 static vfsid
833 vfs_s_getid (const vfs_path_t * vpath)
834 {
835 struct vfs_s_super *archive = NULL;
836 const char *p;
837
838 p = vfs_s_get_path (vpath, &archive, FL_NO_OPEN);
839 if (p == NULL)
840 return NULL;
841
842 return (vfsid) archive;
843 }
844
845
846
847 static gboolean
848 vfs_s_nothingisopen (vfsid id)
849 {
850 return (VFS_SUPER (id)->fd_usage <= 0);
851 }
852
853
854
855 static void
856 vfs_s_free (vfsid id)
857 {
858 vfs_s_free_super (VFS_SUPER (id)->me, VFS_SUPER (id));
859 }
860
861
862
863 static gboolean
864 vfs_s_dir_uptodate (struct vfs_class *me, struct vfs_s_inode *ino)
865 {
866 gint64 tim;
867
868 if (me->flush)
869 {
870 me->flush = FALSE;
871 return 0;
872 }
873
874 tim = g_get_monotonic_time ();
875
876 return (tim < ino->timestamp);
877 }
878
879
880
881
882
883 struct vfs_s_inode *
884 vfs_s_new_inode (struct vfs_class *me, struct vfs_s_super *super, struct stat *initstat)
885 {
886 struct vfs_s_inode *ino;
887
888 ino = g_try_new0 (struct vfs_s_inode, 1);
889 if (ino == NULL)
890 return NULL;
891
892 if (initstat != NULL)
893 ino->st = *initstat;
894 ino->super = super;
895 ino->subdir = g_queue_new ();
896 ino->st.st_nlink = 0;
897 ino->st.st_ino = VFS_SUBCLASS (me)->inode_counter++;
898 ino->st.st_dev = VFS_SUBCLASS (me)->rdev;
899
900 super->ino_usage++;
901
902 CALL (init_inode) (me, ino);
903
904 return ino;
905 }
906
907
908
909 void
910 vfs_s_free_inode (struct vfs_class *me, struct vfs_s_inode *ino)
911 {
912 if (ino == NULL)
913 vfs_die ("Don't pass NULL to me");
914
915
916 if (ino->st.st_nlink > 1)
917 {
918 ino->st.st_nlink--;
919 return;
920 }
921
922 while (g_queue_get_length (ino->subdir) != 0)
923 {
924 struct vfs_s_entry *entry;
925
926 entry = VFS_ENTRY (g_queue_peek_head (ino->subdir));
927 vfs_s_free_entry (me, entry);
928 }
929
930 g_queue_free (ino->subdir);
931 ino->subdir = NULL;
932
933 CALL (free_inode) (me, ino);
934 g_free (ino->linkname);
935 if ((me->flags & VFSF_USETMP) != 0 && ino->localname != NULL)
936 {
937 unlink (ino->localname);
938 g_free (ino->localname);
939 }
940 ino->super->ino_usage--;
941 g_free (ino);
942 }
943
944
945
946 struct vfs_s_entry *
947 vfs_s_new_entry (struct vfs_class *me, const char *name, struct vfs_s_inode *inode)
948 {
949 struct vfs_s_entry *entry;
950
951 entry = g_new0 (struct vfs_s_entry, 1);
952
953 entry->name = g_strdup (name);
954 entry->ino = inode;
955 entry->ino->ent = entry;
956 CALL (init_entry) (me, entry);
957
958 return entry;
959 }
960
961
962
963 void
964 vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent)
965 {
966 if (ent->dir != NULL)
967 g_queue_remove (ent->dir->subdir, ent);
968
969 MC_PTR_FREE (ent->name);
970
971 if (ent->ino != NULL)
972 {
973 ent->ino->ent = NULL;
974 vfs_s_free_inode (me, ent->ino);
975 }
976
977 g_free (ent);
978 }
979
980
981
982 void
983 vfs_s_insert_entry (struct vfs_class *me, struct vfs_s_inode *dir, struct vfs_s_entry *ent)
984 {
985 (void) me;
986
987 ent->dir = dir;
988
989 ent->ino->st.st_nlink++;
990 g_queue_push_tail (dir->subdir, ent);
991 }
992
993
994
995 int
996 vfs_s_entry_compare (const void *a, const void *b)
997 {
998 const struct vfs_s_entry *e = (const struct vfs_s_entry *) a;
999 const char *name = (const char *) b;
1000
1001 return strcmp (e->name, name);
1002 }
1003
1004
1005
1006 struct stat *
1007 vfs_s_default_stat (struct vfs_class *me, mode_t mode)
1008 {
1009 static struct stat st;
1010 mode_t myumask;
1011
1012 (void) me;
1013
1014 myumask = umask (022);
1015 umask (myumask);
1016 mode &= ~myumask;
1017
1018 st.st_mode = mode;
1019 st.st_ino = 0;
1020 st.st_dev = 0;
1021 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1022 st.st_rdev = 0;
1023 #endif
1024 st.st_uid = getuid ();
1025 st.st_gid = getgid ();
1026 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1027 st.st_blksize = 512;
1028 #endif
1029 st.st_size = 0;
1030
1031 st.st_mtime = st.st_atime = st.st_ctime = time (NULL);
1032 #ifdef HAVE_STRUCT_STAT_ST_MTIM
1033 st.st_atim.tv_nsec = st.st_mtim.tv_nsec = st.st_ctim.tv_nsec = 0;
1034 #endif
1035
1036 vfs_adjust_stat (&st);
1037
1038 return &st;
1039 }
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049 void
1050 vfs_adjust_stat (struct stat *s)
1051 {
1052 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1053 if (s->st_size == 0)
1054 s->st_blocks = 0;
1055 else
1056 {
1057 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1058 blkcnt_t ioblocks;
1059 blksize_t ioblock_size;
1060
1061
1062 ioblocks = 1 + (s->st_size - 1) / s->st_blksize;
1063
1064 ioblock_size = 1 + (s->st_blksize - 1) / 512;
1065
1066 s->st_blocks = ioblocks * ioblock_size;
1067 #else
1068
1069 s->st_blocks = 1 + (s->st_size - 1) / 512;
1070 #endif
1071 }
1072 #endif
1073 }
1074
1075
1076
1077 struct vfs_s_entry *
1078 vfs_s_generate_entry (struct vfs_class *me, const char *name, struct vfs_s_inode *parent,
1079 mode_t mode)
1080 {
1081 struct vfs_s_inode *inode;
1082 struct stat *st;
1083
1084 st = vfs_s_default_stat (me, mode);
1085 inode = vfs_s_new_inode (me, parent->super, st);
1086
1087 return vfs_s_new_entry (me, name, inode);
1088 }
1089
1090
1091
1092 struct vfs_s_inode *
1093 vfs_s_find_inode (struct vfs_class *me, const struct vfs_s_super *super,
1094 const char *path, int follow, int flags)
1095 {
1096 struct vfs_s_entry *ent;
1097
1098 if (((me->flags & VFSF_REMOTE) == 0) && (*path == '\0'))
1099 return super->root;
1100
1101 ent = VFS_SUBCLASS (me)->find_entry (me, super->root, path, follow, flags);
1102 return (ent != NULL ? ent->ino : NULL);
1103 }
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115 struct vfs_s_super *
1116 vfs_get_super_by_vpath (const vfs_path_t * vpath)
1117 {
1118 GList *iter;
1119 void *cookie = NULL;
1120 const vfs_path_element_t *path_element;
1121 struct vfs_s_subclass *subclass;
1122 struct vfs_s_super *super = NULL;
1123 vfs_path_t *vpath_archive;
1124
1125 path_element = vfs_path_get_by_index (vpath, -1);
1126 subclass = VFS_SUBCLASS (path_element->class);
1127
1128 vpath_archive = vfs_path_clone (vpath);
1129 vfs_path_remove_element_by_index (vpath_archive, -1);
1130
1131 if (subclass->archive_check != NULL)
1132 {
1133 cookie = subclass->archive_check (vpath_archive);
1134 if (cookie == NULL)
1135 goto ret;
1136 }
1137
1138 if (subclass->archive_same == NULL)
1139 goto ret;
1140
1141 for (iter = subclass->supers; iter != NULL; iter = g_list_next (iter))
1142 {
1143 int i;
1144
1145 super = VFS_SUPER (iter->data);
1146
1147
1148 i = subclass->archive_same (path_element, super, vpath_archive, cookie);
1149 if (i == 1)
1150 goto ret;
1151 if (i != 0)
1152 break;
1153
1154 super = NULL;
1155 }
1156
1157 ret:
1158 vfs_path_free (vpath_archive, TRUE);
1159 return super;
1160 }
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172 const char *
1173 vfs_s_get_path (const vfs_path_t * vpath, struct vfs_s_super **archive, int flags)
1174 {
1175 const char *retval = "";
1176 int result = -1;
1177 struct vfs_s_super *super;
1178 const vfs_path_element_t *path_element;
1179 struct vfs_s_subclass *subclass;
1180
1181 path_element = vfs_path_get_by_index (vpath, -1);
1182
1183 if (path_element->path != NULL)
1184 retval = path_element->path;
1185
1186 super = vfs_get_super_by_vpath (vpath);
1187 if (super != NULL)
1188 goto return_success;
1189
1190 if ((flags & FL_NO_OPEN) != 0)
1191 {
1192 path_element->class->verrno = EIO;
1193 return NULL;
1194 }
1195
1196 subclass = VFS_SUBCLASS (path_element->class);
1197
1198 super = subclass->new_archive != NULL ?
1199 subclass->new_archive (path_element->class) : vfs_s_new_super (path_element->class);
1200
1201 if (subclass->open_archive != NULL)
1202 {
1203 vfs_path_t *vpath_archive;
1204
1205 vpath_archive = vfs_path_clone (vpath);
1206 vfs_path_remove_element_by_index (vpath_archive, -1);
1207
1208 result = subclass->open_archive (super, vpath_archive, path_element);
1209 vfs_path_free (vpath_archive, TRUE);
1210 }
1211 if (result == -1)
1212 {
1213 vfs_s_free_super (path_element->class, super);
1214 path_element->class->verrno = EIO;
1215 return NULL;
1216 }
1217 if (super->name == NULL)
1218 vfs_die ("You have to fill name\n");
1219 if (super->root == NULL)
1220 vfs_die ("You have to fill root inode\n");
1221
1222 vfs_s_insert_super (path_element->class, super);
1223 vfs_stamp_create (path_element->class, super);
1224
1225 return_success:
1226 *archive = super;
1227 return retval;
1228 }
1229
1230
1231
1232 void
1233 vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super)
1234 {
1235 if (!super->want_stale)
1236 {
1237 vfs_s_free_inode (me, super->root);
1238 super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755));
1239 }
1240 }
1241
1242
1243
1244 char *
1245 vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino)
1246 {
1247 if (ino->ent == NULL)
1248 ERRNOR (EAGAIN, NULL);
1249
1250 if ((me->flags & VFSF_USETMP) == 0)
1251 {
1252
1253 char *path;
1254
1255 path = g_strdup (ino->ent->name);
1256
1257 while (TRUE)
1258 {
1259 char *newpath;
1260
1261 ino = ino->ent->dir;
1262 if (ino == ino->super->root)
1263 break;
1264
1265 newpath = g_strconcat (ino->ent->name, PATH_SEP_STR, path, (char *) NULL);
1266 g_free (path);
1267 path = newpath;
1268 }
1269 return path;
1270 }
1271
1272
1273 if (ino->ent->dir == NULL || ino->ent->dir->ent == NULL)
1274 return g_strdup (ino->ent->name);
1275
1276 return g_strconcat (ino->ent->dir->ent->name, PATH_SEP_STR, ino->ent->name, (char *) NULL);
1277 }
1278
1279
1280
1281 void
1282 vfs_s_init_fh (vfs_file_handler_t * fh, struct vfs_s_inode *ino, gboolean changed)
1283 {
1284 fh->ino = ino;
1285 fh->handle = -1;
1286 fh->changed = changed;
1287 fh->linear = LS_NOT_LINEAR;
1288 }
1289
1290
1291
1292
1293 void *
1294 vfs_s_open (const vfs_path_t * vpath, int flags, mode_t mode)
1295 {
1296 gboolean was_changed = FALSE;
1297 vfs_file_handler_t *fh;
1298 struct vfs_s_super *super;
1299 const char *q;
1300 struct vfs_s_inode *ino;
1301 const vfs_path_element_t *path_element;
1302 struct vfs_s_subclass *s;
1303
1304 q = vfs_s_get_path (vpath, &super, 0);
1305 if (q == NULL)
1306 return NULL;
1307
1308 path_element = vfs_path_get_by_index (vpath, -1);
1309
1310 ino = vfs_s_find_inode (path_element->class, super, q, LINK_FOLLOW, FL_NONE);
1311 if (ino != NULL && (flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
1312 {
1313 path_element->class->verrno = EEXIST;
1314 return NULL;
1315 }
1316
1317 s = VFS_SUBCLASS (path_element->class);
1318
1319 if (ino == NULL)
1320 {
1321 char *dirname, *name;
1322 struct vfs_s_entry *ent;
1323 struct vfs_s_inode *dir;
1324
1325
1326 if ((flags & O_CREAT) == 0 || path_element->class->write == NULL)
1327 return NULL;
1328
1329 dirname = g_path_get_dirname (q);
1330 name = g_path_get_basename (q);
1331 dir = vfs_s_find_inode (path_element->class, super, dirname, LINK_FOLLOW, FL_DIR);
1332 if (dir == NULL)
1333 {
1334 g_free (dirname);
1335 g_free (name);
1336 return NULL;
1337 }
1338
1339 ent = vfs_s_generate_entry (path_element->class, name, dir, 0755);
1340 ino = ent->ino;
1341 vfs_s_insert_entry (path_element->class, dir, ent);
1342 if ((VFS_CLASS (s)->flags & VFSF_USETMP) != 0)
1343 {
1344 int tmp_handle;
1345 vfs_path_t *tmp_vpath;
1346
1347 tmp_handle = vfs_mkstemps (&tmp_vpath, path_element->class->name, name);
1348 ino->localname = vfs_path_free (tmp_vpath, FALSE);
1349 if (tmp_handle == -1)
1350 {
1351 g_free (dirname);
1352 g_free (name);
1353 return NULL;
1354 }
1355
1356 close (tmp_handle);
1357 }
1358 g_free (dirname);
1359 g_free (name);
1360 was_changed = TRUE;
1361 }
1362
1363 if (S_ISDIR (ino->st.st_mode))
1364 {
1365 path_element->class->verrno = EISDIR;
1366 return NULL;
1367 }
1368
1369 fh = s->fh_new != NULL ? s->fh_new (ino, was_changed) : vfs_s_new_fh (ino, was_changed);
1370
1371 if (IS_LINEAR (flags))
1372 {
1373 if (s->linear_start != NULL)
1374 {
1375 vfs_print_message ("%s", _("Starting linear transfer..."));
1376 fh->linear = LS_LINEAR_PREOPEN;
1377 }
1378 }
1379 else
1380 {
1381 if (s->fh_open != NULL && s->fh_open (path_element->class, fh, flags, mode) != 0)
1382 {
1383 vfs_s_free_fh (s, fh);
1384 return NULL;
1385 }
1386 }
1387
1388 if ((VFS_CLASS (s)->flags & VFSF_USETMP) != 0 && fh->ino->localname != NULL)
1389 {
1390 fh->handle = open (fh->ino->localname, NO_LINEAR (flags), mode);
1391 if (fh->handle == -1)
1392 {
1393 vfs_s_free_fh (s, fh);
1394 path_element->class->verrno = errno;
1395 return NULL;
1396 }
1397 }
1398
1399
1400 vfs_rmstamp (path_element->class, (vfsid) super);
1401 super->fd_usage++;
1402 fh->ino->st.st_nlink++;
1403 return fh;
1404 }
1405
1406
1407
1408 int
1409 vfs_s_stat (const vfs_path_t * vpath, struct stat *buf)
1410 {
1411 return vfs_s_internal_stat (vpath, buf, FL_FOLLOW);
1412 }
1413
1414
1415
1416 int
1417 vfs_s_lstat (const vfs_path_t * vpath, struct stat *buf)
1418 {
1419 return vfs_s_internal_stat (vpath, buf, FL_NONE);
1420 }
1421
1422
1423
1424 int
1425 vfs_s_fstat (void *fh, struct stat *buf)
1426 {
1427 *buf = VFS_FILE_HANDLER (fh)->ino->st;
1428 return 0;
1429 }
1430
1431
1432
1433 int
1434 vfs_s_retrieve_file (struct vfs_class *me, struct vfs_s_inode *ino)
1435 {
1436
1437 off_t total = 0;
1438 char buffer[8192];
1439 int handle;
1440 ssize_t n;
1441 off_t stat_size = ino->st.st_size;
1442 vfs_file_handler_t *fh = NULL;
1443 vfs_path_t *tmp_vpath;
1444 struct vfs_s_subclass *s = VFS_SUBCLASS (me);
1445
1446 if ((me->flags & VFSF_USETMP) == 0)
1447 return (-1);
1448
1449 handle = vfs_mkstemps (&tmp_vpath, me->name, ino->ent->name);
1450 ino->localname = vfs_path_free (tmp_vpath, FALSE);
1451 if (handle == -1)
1452 {
1453 me->verrno = errno;
1454 goto error_4;
1455 }
1456
1457 fh = s->fh_new != NULL ? s->fh_new (ino, FALSE) : vfs_s_new_fh (ino, FALSE);
1458
1459 if (s->linear_start (me, fh, 0) == 0)
1460 goto error_3;
1461
1462
1463 tty_got_interrupt ();
1464 tty_enable_interrupt_key ();
1465
1466 while ((n = s->linear_read (me, fh, buffer, sizeof (buffer))) != 0)
1467 {
1468 int t;
1469
1470 if (n < 0)
1471 goto error_1;
1472
1473 total += n;
1474 vfs_s_print_stats (me->name, _("Getting file"), ino->ent->name, total, stat_size);
1475
1476 if (tty_got_interrupt ())
1477 goto error_1;
1478
1479 t = write (handle, buffer, n);
1480 if (t != n)
1481 {
1482 if (t == -1)
1483 me->verrno = errno;
1484 goto error_1;
1485 }
1486 }
1487 s->linear_close (me, fh);
1488 close (handle);
1489
1490 tty_disable_interrupt_key ();
1491 vfs_s_free_fh (s, fh);
1492 return 0;
1493
1494 error_1:
1495 s->linear_close (me, fh);
1496 error_3:
1497 tty_disable_interrupt_key ();
1498 close (handle);
1499 unlink (ino->localname);
1500 error_4:
1501 MC_PTR_FREE (ino->localname);
1502 if (fh != NULL)
1503 vfs_s_free_fh (s, fh);
1504 return (-1);
1505 }
1506
1507
1508
1509
1510
1511 void
1512 vfs_init_class (struct vfs_class *vclass, const char *name, vfs_flags_t flags, const char *prefix)
1513 {
1514 memset (vclass, 0, sizeof (struct vfs_class));
1515
1516 vclass->name = name;
1517 vclass->flags = flags;
1518 vclass->prefix = prefix;
1519
1520 vclass->fill_names = vfs_s_fill_names;
1521 vclass->open = vfs_s_open;
1522 vclass->close = vfs_s_close;
1523 vclass->read = vfs_s_read;
1524 if ((vclass->flags & VFSF_READONLY) == 0)
1525 vclass->write = vfs_s_write;
1526 vclass->opendir = vfs_s_opendir;
1527 vclass->readdir = vfs_s_readdir;
1528 vclass->closedir = vfs_s_closedir;
1529 vclass->stat = vfs_s_stat;
1530 vclass->lstat = vfs_s_lstat;
1531 vclass->fstat = vfs_s_fstat;
1532 vclass->readlink = vfs_s_readlink;
1533 vclass->chdir = vfs_s_chdir;
1534 vclass->ferrno = vfs_s_ferrno;
1535 vclass->lseek = vfs_s_lseek;
1536 vclass->getid = vfs_s_getid;
1537 vclass->nothingisopen = vfs_s_nothingisopen;
1538 vclass->free = vfs_s_free;
1539 vclass->setctl = vfs_s_setctl;
1540 if ((vclass->flags & VFSF_USETMP) != 0)
1541 {
1542 vclass->getlocalcopy = vfs_s_getlocalcopy;
1543 vclass->ungetlocalcopy = vfs_s_ungetlocalcopy;
1544 }
1545 }
1546
1547
1548
1549 void
1550 vfs_init_subclass (struct vfs_s_subclass *sub, const char *name, vfs_flags_t flags,
1551 const char *prefix)
1552 {
1553 struct vfs_class *vclass = VFS_CLASS (sub);
1554 size_t len;
1555 char *start;
1556
1557 vfs_init_class (vclass, name, flags, prefix);
1558
1559 len = sizeof (struct vfs_s_subclass) - sizeof (struct vfs_class);
1560 start = (char *) sub + sizeof (struct vfs_class);
1561 memset (start, 0, len);
1562
1563 if ((vclass->flags & VFSF_USETMP) != 0)
1564 sub->find_entry = vfs_s_find_entry_linear;
1565 else if ((vclass->flags & VFSF_REMOTE) != 0)
1566 sub->find_entry = vfs_s_find_entry_linear;
1567 else
1568 sub->find_entry = vfs_s_find_entry_tree;
1569 sub->dir_uptodate = vfs_s_dir_uptodate;
1570 }
1571
1572
1573
1574
1575 vfsid
1576 vfs_getid (const vfs_path_t * vpath)
1577 {
1578 const vfs_path_element_t *path_element;
1579
1580 path_element = vfs_path_get_by_index (vpath, -1);
1581 if (!vfs_path_element_valid (path_element) || path_element->class->getid == NULL)
1582 return NULL;
1583
1584 return (*path_element->class->getid) (vpath);
1585 }
1586
1587
1588
1589
1590 #ifdef ENABLE_VFS_NET
1591 int
1592 vfs_s_select_on_two (int fd1, int fd2)
1593 {
1594 fd_set set;
1595 struct timeval time_out;
1596 int v;
1597 int maxfd = MAX (fd1, fd2) + 1;
1598
1599 time_out.tv_sec = 1;
1600 time_out.tv_usec = 0;
1601 FD_ZERO (&set);
1602 FD_SET (fd1, &set);
1603 FD_SET (fd2, &set);
1604
1605 v = select (maxfd, &set, 0, 0, &time_out);
1606 if (v <= 0)
1607 return v;
1608 if (FD_ISSET (fd1, &set))
1609 return 1;
1610 if (FD_ISSET (fd2, &set))
1611 return 2;
1612 return (-1);
1613 }
1614
1615
1616
1617 int
1618 vfs_s_get_line (struct vfs_class *me, int sock, char *buf, int buf_len, char term)
1619 {
1620 FILE *logfile = me->logfile;
1621 int i;
1622 char c;
1623
1624 for (i = 0; i < buf_len - 1; i++, buf++)
1625 {
1626 if (read (sock, buf, sizeof (char)) <= 0)
1627 return 0;
1628
1629 if (logfile != NULL)
1630 {
1631 size_t ret1;
1632 int ret2;
1633
1634 ret1 = fwrite (buf, 1, 1, logfile);
1635 ret2 = fflush (logfile);
1636 (void) ret1;
1637 (void) ret2;
1638 }
1639
1640 if (*buf == term)
1641 {
1642 *buf = '\0';
1643 return 1;
1644 }
1645 }
1646
1647
1648 *buf = '\0';
1649 while (read (sock, &c, sizeof (c)) > 0)
1650 {
1651 if (logfile != NULL)
1652 {
1653 size_t ret1;
1654 int ret2;
1655
1656 ret1 = fwrite (&c, 1, 1, logfile);
1657 ret2 = fflush (logfile);
1658 (void) ret1;
1659 (void) ret2;
1660 }
1661 if (c == '\n')
1662 return 1;
1663 }
1664 return 0;
1665 }
1666
1667
1668
1669 int
1670 vfs_s_get_line_interruptible (struct vfs_class *me, char *buffer, int size, int fd)
1671 {
1672 int i;
1673 int res = 0;
1674
1675 (void) me;
1676
1677 tty_enable_interrupt_key ();
1678
1679 for (i = 0; i < size - 1; i++)
1680 {
1681 ssize_t n;
1682
1683 n = read (fd, &buffer[i], 1);
1684 if (n == -1 && errno == EINTR)
1685 {
1686 buffer[i] = '\0';
1687 res = EINTR;
1688 goto ret;
1689 }
1690 if (n == 0)
1691 {
1692 buffer[i] = '\0';
1693 goto ret;
1694 }
1695 if (buffer[i] == '\n')
1696 {
1697 buffer[i] = '\0';
1698 res = 1;
1699 goto ret;
1700 }
1701 }
1702
1703 buffer[size - 1] = '\0';
1704
1705 ret:
1706 tty_disable_interrupt_key ();
1707
1708 return res;
1709 }
1710 #endif
1711
1712
1713
1714
1715
1716
1717 void
1718 vfs_s_normalize_filename_leading_spaces (struct vfs_s_inode *root_inode, size_t final_num_spaces)
1719 {
1720 GList *iter;
1721
1722 for (iter = g_queue_peek_head_link (root_inode->subdir); iter != NULL;
1723 iter = g_list_next (iter))
1724 {
1725 struct vfs_s_entry *entry = VFS_ENTRY (iter->data);
1726
1727 if ((size_t) entry->ino->data_offset > final_num_spaces)
1728 {
1729 char *source_name, *spacer;
1730
1731 source_name = entry->name;
1732 spacer = g_strnfill (entry->ino->data_offset - final_num_spaces, ' ');
1733 entry->name = g_strconcat (spacer, source_name, (char *) NULL);
1734 g_free (spacer);
1735 g_free (source_name);
1736 }
1737
1738 entry->ino->data_offset = -1;
1739 }
1740 }
1741
1742