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