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,
179 const char *a_path, 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 = vfs_s_resolve_symlink (me, ent,
227 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,
241 const char *a_path, 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 =
408 vfs_s_find_inode (me, super, q,
409 (flags & FL_FOLLOW) != 0 ? LINK_FOLLOW : LINK_NO_FOLLOW,
410 flags & ~FL_FOLLOW);
411 if (ino == NULL && *q == '\0')
412
413 ino =
414 vfs_s_find_inode (me, super, q,
415 (flags & FL_FOLLOW) != 0 ? LINK_FOLLOW : LINK_NO_FOLLOW,
416 FL_DIR | (flags & ~FL_FOLLOW));
417 return ino;
418 }
419
420
421
422 static void *
423 vfs_s_opendir (const vfs_path_t *vpath)
424 {
425 struct vfs_s_inode *dir;
426 struct dirhandle *info;
427 struct vfs_class *me;
428
429 dir = vfs_s_inode_from_path (vpath, FL_DIR | FL_FOLLOW);
430 if (dir == NULL)
431 return NULL;
432
433 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
434
435 if (!S_ISDIR (dir->st.st_mode))
436 {
437 me->verrno = ENOTDIR;
438 return NULL;
439 }
440
441 dir->st.st_nlink++;
442 #if 0
443 if (dir->subdir == NULL)
444 {
445 me->verrno = EAGAIN;
446 return NULL;
447 }
448 #endif
449 info = g_new (struct dirhandle, 1);
450 info->cur = g_queue_peek_head_link (dir->subdir);
451 info->dir = dir;
452
453 return info;
454 }
455
456
457
458 static struct vfs_dirent *
459 vfs_s_readdir (void *data)
460 {
461 struct vfs_dirent *dir = NULL;
462 struct dirhandle *info = (struct dirhandle *) data;
463 const char *name;
464
465 if (info->cur == NULL || info->cur->data == NULL)
466 return NULL;
467
468 name = VFS_ENTRY (info->cur->data)->name;
469 if (name != NULL)
470 dir = vfs_dirent_init (NULL, name, 0);
471 else
472 vfs_die ("Null in structure-cannot happen");
473
474 info->cur = g_list_next (info->cur);
475
476 return dir;
477 }
478
479
480
481 static int
482 vfs_s_closedir (void *data)
483 {
484 struct dirhandle *info = (struct dirhandle *) data;
485 struct vfs_s_inode *dir = info->dir;
486
487 vfs_s_free_inode (dir->super->me, dir);
488 g_free (data);
489 return 0;
490 }
491
492
493
494 static int
495 vfs_s_chdir (const vfs_path_t *vpath)
496 {
497 void *data;
498
499 data = vfs_s_opendir (vpath);
500 if (data == NULL)
501 return (-1);
502 vfs_s_closedir (data);
503 return 0;
504 }
505
506
507
508
509 static int
510 vfs_s_internal_stat (const vfs_path_t *vpath, struct stat *buf, int flag)
511 {
512 struct vfs_s_inode *ino;
513
514 ino = vfs_s_inode_from_path (vpath, flag);
515 if (ino == NULL)
516 return (-1);
517 *buf = ino->st;
518 return 0;
519 }
520
521
522
523 static int
524 vfs_s_readlink (const vfs_path_t *vpath, char *buf, size_t size)
525 {
526 struct vfs_s_inode *ino;
527 size_t len;
528 struct vfs_class *me;
529
530 ino = vfs_s_inode_from_path (vpath, 0);
531 if (ino == NULL)
532 return (-1);
533
534 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
535
536 if (!S_ISLNK (ino->st.st_mode))
537 {
538 me->verrno = EINVAL;
539 return (-1);
540 }
541
542 if (ino->linkname == NULL)
543 {
544 me->verrno = EFAULT;
545 return (-1);
546 }
547
548 len = strlen (ino->linkname);
549 if (size < len)
550 len = size;
551
552 memcpy (buf, ino->linkname, len);
553 return len;
554 }
555
556
557
558 static ssize_t
559 vfs_s_read (void *fh, char *buffer, size_t count)
560 {
561 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
562 struct vfs_class *me = VFS_FILE_HANDLER_SUPER (fh)->me;
563
564 if (file->linear == LS_LINEAR_PREOPEN)
565 if (VFS_SUBCLASS (me)->linear_start (me, file, file->pos) == 0)
566 return (-1);
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_last_path_vfs (vpath);
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 struct vfs_class *me;
797
798 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
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 (me, ino->super);
815 }
816 return 1;
817 }
818 case VFS_SETCTL_LOGFILE:
819 me->logfile = fopen ((char *) arg, "w");
820 return 1;
821 case VFS_SETCTL_FLUSH:
822 me->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 return (p == NULL ? NULL : (vfsid) archive);
840 }
841
842
843
844 static gboolean
845 vfs_s_nothingisopen (vfsid id)
846 {
847 return (VFS_SUPER (id)->fd_usage <= 0);
848 }
849
850
851
852 static void
853 vfs_s_free (vfsid id)
854 {
855 vfs_s_free_super (VFS_SUPER (id)->me, VFS_SUPER (id));
856 }
857
858
859
860 static gboolean
861 vfs_s_dir_uptodate (struct vfs_class *me, struct vfs_s_inode *ino)
862 {
863 gint64 tim;
864
865 if (me->flush)
866 {
867 me->flush = FALSE;
868 return 0;
869 }
870
871 tim = g_get_monotonic_time ();
872
873 return (tim < ino->timestamp);
874 }
875
876
877
878
879
880 struct vfs_s_inode *
881 vfs_s_new_inode (struct vfs_class *me, struct vfs_s_super *super, struct stat *initstat)
882 {
883 struct vfs_s_inode *ino;
884
885 ino = g_try_new0 (struct vfs_s_inode, 1);
886 if (ino == NULL)
887 return NULL;
888
889 if (initstat != NULL)
890 ino->st = *initstat;
891 ino->super = super;
892 ino->subdir = g_queue_new ();
893 ino->st.st_nlink = 0;
894 ino->st.st_ino = VFS_SUBCLASS (me)->inode_counter++;
895 ino->st.st_dev = VFS_SUBCLASS (me)->rdev;
896
897 super->ino_usage++;
898
899 CALL (init_inode) (me, ino);
900
901 return ino;
902 }
903
904
905
906 void
907 vfs_s_free_inode (struct vfs_class *me, struct vfs_s_inode *ino)
908 {
909 if (ino == NULL)
910 vfs_die ("Don't pass NULL to me");
911
912
913 if (ino->st.st_nlink > 1)
914 {
915 ino->st.st_nlink--;
916 return;
917 }
918
919 while (g_queue_get_length (ino->subdir) != 0)
920 {
921 struct vfs_s_entry *entry;
922
923 entry = VFS_ENTRY (g_queue_peek_head (ino->subdir));
924 vfs_s_free_entry (me, entry);
925 }
926
927 g_queue_free (ino->subdir);
928 ino->subdir = NULL;
929
930 CALL (free_inode) (me, ino);
931 g_free (ino->linkname);
932 if ((me->flags & VFSF_USETMP) != 0 && ino->localname != NULL)
933 {
934 unlink (ino->localname);
935 g_free (ino->localname);
936 }
937 ino->super->ino_usage--;
938 g_free (ino);
939 }
940
941
942
943 struct vfs_s_entry *
944 vfs_s_new_entry (struct vfs_class *me, const char *name, struct vfs_s_inode *inode)
945 {
946 struct vfs_s_entry *entry;
947
948 entry = g_new0 (struct vfs_s_entry, 1);
949
950 entry->name = g_strdup (name);
951 entry->ino = inode;
952 entry->ino->ent = entry;
953 CALL (init_entry) (me, entry);
954
955 return entry;
956 }
957
958
959
960 void
961 vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent)
962 {
963 if (ent->dir != NULL)
964 g_queue_remove (ent->dir->subdir, ent);
965
966 MC_PTR_FREE (ent->name);
967
968 if (ent->ino != NULL)
969 {
970 ent->ino->ent = NULL;
971 vfs_s_free_inode (me, ent->ino);
972 }
973
974 g_free (ent);
975 }
976
977
978
979 void
980 vfs_s_insert_entry (struct vfs_class *me, struct vfs_s_inode *dir, struct vfs_s_entry *ent)
981 {
982 (void) me;
983
984 ent->dir = dir;
985
986 ent->ino->st.st_nlink++;
987 g_queue_push_tail (dir->subdir, ent);
988 }
989
990
991
992 int
993 vfs_s_entry_compare (const void *a, const void *b)
994 {
995 const struct vfs_s_entry *e = (const struct vfs_s_entry *) a;
996 const char *name = (const char *) b;
997
998 return strcmp (e->name, name);
999 }
1000
1001
1002
1003 struct stat *
1004 vfs_s_default_stat (struct vfs_class *me, mode_t mode)
1005 {
1006 static struct stat st;
1007 mode_t myumask;
1008
1009 (void) me;
1010
1011 myumask = umask (022);
1012 umask (myumask);
1013 mode &= ~myumask;
1014
1015 st.st_mode = mode;
1016 st.st_ino = 0;
1017 st.st_dev = 0;
1018 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1019 st.st_rdev = 0;
1020 #endif
1021 st.st_uid = getuid ();
1022 st.st_gid = getgid ();
1023 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1024 st.st_blksize = 512;
1025 #endif
1026 st.st_size = 0;
1027
1028 vfs_zero_stat_times (&st);
1029
1030 vfs_adjust_stat (&st);
1031
1032 return &st;
1033 }
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043 void
1044 vfs_adjust_stat (struct stat *s)
1045 {
1046 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1047 if (s->st_size == 0)
1048 s->st_blocks = 0;
1049 else
1050 {
1051 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1052 blkcnt_t ioblocks;
1053 blksize_t ioblock_size;
1054
1055
1056 ioblocks = 1 + (s->st_size - 1) / s->st_blksize;
1057
1058 ioblock_size = 1 + (s->st_blksize - 1) / 512;
1059
1060 s->st_blocks = ioblocks * ioblock_size;
1061 #else
1062
1063 s->st_blocks = 1 + (s->st_size - 1) / 512;
1064 #endif
1065 }
1066 #endif
1067 }
1068
1069
1070
1071 struct vfs_s_entry *
1072 vfs_s_generate_entry (struct vfs_class *me, const char *name, struct vfs_s_inode *parent,
1073 mode_t mode)
1074 {
1075 struct vfs_s_inode *inode;
1076 struct stat *st;
1077
1078 st = vfs_s_default_stat (me, mode);
1079 inode = vfs_s_new_inode (me, parent->super, st);
1080
1081 return vfs_s_new_entry (me, name, inode);
1082 }
1083
1084
1085
1086 struct vfs_s_inode *
1087 vfs_s_find_inode (struct vfs_class *me, const struct vfs_s_super *super,
1088 const char *path, int follow, int flags)
1089 {
1090 struct vfs_s_entry *ent;
1091
1092 if (((me->flags & VFSF_REMOTE) == 0) && (*path == '\0'))
1093 return super->root;
1094
1095 ent = VFS_SUBCLASS (me)->find_entry (me, super->root, path, follow, flags);
1096 return (ent != NULL ? ent->ino : NULL);
1097 }
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109 struct vfs_s_super *
1110 vfs_get_super_by_vpath (const vfs_path_t *vpath)
1111 {
1112 GList *iter;
1113 void *cookie = NULL;
1114 const vfs_path_element_t *path_element;
1115 struct vfs_s_subclass *subclass;
1116 struct vfs_s_super *super = NULL;
1117 vfs_path_t *vpath_archive;
1118
1119 path_element = vfs_path_get_by_index (vpath, -1);
1120 subclass = VFS_SUBCLASS (path_element->class);
1121
1122 vpath_archive = vfs_path_clone (vpath);
1123 vfs_path_remove_element_by_index (vpath_archive, -1);
1124
1125 if (subclass->archive_check != NULL)
1126 {
1127 cookie = subclass->archive_check (vpath_archive);
1128 if (cookie == NULL)
1129 goto ret;
1130 }
1131
1132 if (subclass->archive_same == NULL)
1133 goto ret;
1134
1135 for (iter = subclass->supers; iter != NULL; iter = g_list_next (iter))
1136 {
1137 int i;
1138
1139 super = VFS_SUPER (iter->data);
1140
1141
1142 i = subclass->archive_same (path_element, super, vpath_archive, cookie);
1143 if (i == 1)
1144 goto ret;
1145 if (i != 0)
1146 break;
1147
1148 super = NULL;
1149 }
1150
1151 ret:
1152 vfs_path_free (vpath_archive, TRUE);
1153 return super;
1154 }
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166 const char *
1167 vfs_s_get_path (const vfs_path_t *vpath, struct vfs_s_super **archive, int flags)
1168 {
1169 const char *retval = "";
1170 int result = -1;
1171 struct vfs_s_super *super;
1172 const vfs_path_element_t *path_element;
1173 struct vfs_s_subclass *subclass;
1174
1175 path_element = vfs_path_get_by_index (vpath, -1);
1176
1177 if (path_element->path != NULL)
1178 retval = path_element->path;
1179
1180 super = vfs_get_super_by_vpath (vpath);
1181 if (super != NULL)
1182 goto return_success;
1183
1184 if ((flags & FL_NO_OPEN) != 0)
1185 {
1186 path_element->class->verrno = EIO;
1187 return NULL;
1188 }
1189
1190 subclass = VFS_SUBCLASS (path_element->class);
1191
1192 super = subclass->new_archive != NULL ?
1193 subclass->new_archive (path_element->class) : vfs_s_new_super (path_element->class);
1194
1195 if (subclass->open_archive != NULL)
1196 {
1197 vfs_path_t *vpath_archive;
1198
1199 vpath_archive = vfs_path_clone (vpath);
1200 vfs_path_remove_element_by_index (vpath_archive, -1);
1201
1202 result = subclass->open_archive (super, vpath_archive, path_element);
1203 vfs_path_free (vpath_archive, TRUE);
1204 }
1205 if (result == -1)
1206 {
1207 vfs_s_free_super (path_element->class, super);
1208 path_element->class->verrno = EIO;
1209 return NULL;
1210 }
1211 if (super->name == NULL)
1212 vfs_die ("You have to fill name\n");
1213 if (super->root == NULL)
1214 vfs_die ("You have to fill root inode\n");
1215
1216 vfs_s_insert_super (path_element->class, super);
1217 vfs_stamp_create (path_element->class, super);
1218
1219 return_success:
1220 *archive = super;
1221 return retval;
1222 }
1223
1224
1225
1226 void
1227 vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super)
1228 {
1229 if (!super->want_stale)
1230 {
1231 vfs_s_free_inode (me, super->root);
1232 super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755));
1233 }
1234 }
1235
1236
1237
1238 char *
1239 vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino)
1240 {
1241 if (ino->ent == NULL)
1242 ERRNOR (EAGAIN, NULL);
1243
1244 if ((me->flags & VFSF_USETMP) == 0)
1245 {
1246
1247 char *path;
1248
1249 path = g_strdup (ino->ent->name);
1250
1251 while (TRUE)
1252 {
1253 char *newpath;
1254
1255 ino = ino->ent->dir;
1256 if (ino == ino->super->root)
1257 break;
1258
1259 newpath = g_strconcat (ino->ent->name, PATH_SEP_STR, path, (char *) NULL);
1260 g_free (path);
1261 path = newpath;
1262 }
1263 return path;
1264 }
1265
1266
1267 if (ino->ent->dir == NULL || ino->ent->dir->ent == NULL)
1268 return g_strdup (ino->ent->name);
1269
1270 return g_strconcat (ino->ent->dir->ent->name, PATH_SEP_STR, ino->ent->name, (char *) NULL);
1271 }
1272
1273
1274
1275 void
1276 vfs_s_init_fh (vfs_file_handler_t *fh, struct vfs_s_inode *ino, gboolean changed)
1277 {
1278 fh->ino = ino;
1279 fh->handle = -1;
1280 fh->changed = changed;
1281 fh->linear = LS_NOT_LINEAR;
1282 }
1283
1284
1285
1286
1287 void *
1288 vfs_s_open (const vfs_path_t *vpath, int flags, mode_t mode)
1289 {
1290 gboolean was_changed = FALSE;
1291 vfs_file_handler_t *fh;
1292 struct vfs_s_super *super;
1293 const char *q;
1294 struct vfs_s_inode *ino;
1295 struct vfs_class *me;
1296 struct vfs_s_subclass *s;
1297
1298 q = vfs_s_get_path (vpath, &super, 0);
1299 if (q == NULL)
1300 return NULL;
1301
1302 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1303
1304 ino = vfs_s_find_inode (me, super, q, LINK_FOLLOW, FL_NONE);
1305 if (ino != NULL && (flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
1306 {
1307 me->verrno = EEXIST;
1308 return NULL;
1309 }
1310
1311 s = VFS_SUBCLASS (me);
1312
1313 if (ino == NULL)
1314 {
1315 char *name;
1316 struct vfs_s_entry *ent;
1317 struct vfs_s_inode *dir;
1318
1319
1320 if ((flags & O_CREAT) == 0 || me->write == NULL)
1321 return NULL;
1322
1323 name = g_path_get_dirname (q);
1324 dir = vfs_s_find_inode (me, super, name, LINK_FOLLOW, FL_DIR);
1325 g_free (name);
1326 if (dir == NULL)
1327 return NULL;
1328
1329 name = g_path_get_basename (q);
1330 ent = vfs_s_generate_entry (me, name, dir, 0755);
1331 ino = ent->ino;
1332 vfs_s_insert_entry (me, dir, ent);
1333 if ((VFS_CLASS (s)->flags & VFSF_USETMP) != 0)
1334 {
1335 int tmp_handle;
1336 vfs_path_t *tmp_vpath;
1337
1338 tmp_handle = vfs_mkstemps (&tmp_vpath, me->name, name);
1339 ino->localname = vfs_path_free (tmp_vpath, FALSE);
1340 if (tmp_handle == -1)
1341 {
1342 g_free (name);
1343 return NULL;
1344 }
1345
1346 close (tmp_handle);
1347 }
1348
1349 g_free (name);
1350 was_changed = TRUE;
1351 }
1352
1353 if (S_ISDIR (ino->st.st_mode))
1354 {
1355 me->verrno = EISDIR;
1356 return NULL;
1357 }
1358
1359 fh = s->fh_new != NULL ? s->fh_new (ino, was_changed) : vfs_s_new_fh (ino, was_changed);
1360
1361 if (IS_LINEAR (flags))
1362 {
1363 if (s->linear_start != NULL)
1364 {
1365 vfs_print_message ("%s", _("Starting linear transfer..."));
1366 fh->linear = LS_LINEAR_PREOPEN;
1367 }
1368 }
1369 else
1370 {
1371 if (s->fh_open != NULL && s->fh_open (me, fh, flags, mode) != 0)
1372 {
1373 vfs_s_free_fh (s, fh);
1374 return NULL;
1375 }
1376 }
1377
1378 if ((VFS_CLASS (s)->flags & VFSF_USETMP) != 0 && fh->ino->localname != NULL)
1379 {
1380 fh->handle = open (fh->ino->localname, NO_LINEAR (flags), mode);
1381 if (fh->handle == -1)
1382 {
1383 vfs_s_free_fh (s, fh);
1384 me->verrno = errno;
1385 return NULL;
1386 }
1387 }
1388
1389
1390 vfs_rmstamp (me, (vfsid) super);
1391 super->fd_usage++;
1392 fh->ino->st.st_nlink++;
1393 return fh;
1394 }
1395
1396
1397
1398 int
1399 vfs_s_stat (const vfs_path_t *vpath, struct stat *buf)
1400 {
1401 return vfs_s_internal_stat (vpath, buf, FL_FOLLOW);
1402 }
1403
1404
1405
1406 int
1407 vfs_s_lstat (const vfs_path_t *vpath, struct stat *buf)
1408 {
1409 return vfs_s_internal_stat (vpath, buf, FL_NONE);
1410 }
1411
1412
1413
1414 int
1415 vfs_s_fstat (void *fh, struct stat *buf)
1416 {
1417 *buf = VFS_FILE_HANDLER (fh)->ino->st;
1418 return 0;
1419 }
1420
1421
1422
1423 int
1424 vfs_s_retrieve_file (struct vfs_class *me, struct vfs_s_inode *ino)
1425 {
1426
1427 off_t total = 0;
1428 char buffer[BUF_8K];
1429 int handle;
1430 ssize_t n;
1431 off_t stat_size = ino->st.st_size;
1432 vfs_file_handler_t *fh = NULL;
1433 vfs_path_t *tmp_vpath;
1434 struct vfs_s_subclass *s = VFS_SUBCLASS (me);
1435
1436 if ((me->flags & VFSF_USETMP) == 0)
1437 return (-1);
1438
1439 handle = vfs_mkstemps (&tmp_vpath, me->name, ino->ent->name);
1440 ino->localname = vfs_path_free (tmp_vpath, FALSE);
1441 if (handle == -1)
1442 {
1443 me->verrno = errno;
1444 goto error_4;
1445 }
1446
1447 fh = s->fh_new != NULL ? s->fh_new (ino, FALSE) : vfs_s_new_fh (ino, FALSE);
1448
1449 if (s->linear_start (me, fh, 0) == 0)
1450 goto error_3;
1451
1452
1453 tty_got_interrupt ();
1454 tty_enable_interrupt_key ();
1455
1456 while ((n = s->linear_read (me, fh, buffer, sizeof (buffer))) != 0)
1457 {
1458 int t;
1459
1460 if (n < 0)
1461 goto error_1;
1462
1463 total += n;
1464 vfs_s_print_stats (me->name, _("Getting file"), ino->ent->name, total, stat_size);
1465
1466 if (tty_got_interrupt ())
1467 goto error_1;
1468
1469 t = write (handle, buffer, n);
1470 if (t != n)
1471 {
1472 if (t == -1)
1473 me->verrno = errno;
1474 goto error_1;
1475 }
1476 }
1477 s->linear_close (me, fh);
1478 close (handle);
1479
1480 tty_disable_interrupt_key ();
1481 vfs_s_free_fh (s, fh);
1482 return 0;
1483
1484 error_1:
1485 s->linear_close (me, fh);
1486 error_3:
1487 tty_disable_interrupt_key ();
1488 close (handle);
1489 unlink (ino->localname);
1490 error_4:
1491 MC_PTR_FREE (ino->localname);
1492 if (fh != NULL)
1493 vfs_s_free_fh (s, fh);
1494 return (-1);
1495 }
1496
1497
1498
1499
1500
1501 void
1502 vfs_init_class (struct vfs_class *vclass, const char *name, vfs_flags_t flags, const char *prefix)
1503 {
1504 memset (vclass, 0, sizeof (struct vfs_class));
1505
1506 vclass->name = name;
1507 vclass->flags = flags;
1508 vclass->prefix = prefix;
1509
1510 vclass->fill_names = vfs_s_fill_names;
1511 vclass->open = vfs_s_open;
1512 vclass->close = vfs_s_close;
1513 vclass->read = vfs_s_read;
1514 if ((vclass->flags & VFSF_READONLY) == 0)
1515 vclass->write = vfs_s_write;
1516 vclass->opendir = vfs_s_opendir;
1517 vclass->readdir = vfs_s_readdir;
1518 vclass->closedir = vfs_s_closedir;
1519 vclass->stat = vfs_s_stat;
1520 vclass->lstat = vfs_s_lstat;
1521 vclass->fstat = vfs_s_fstat;
1522 vclass->readlink = vfs_s_readlink;
1523 vclass->chdir = vfs_s_chdir;
1524 vclass->ferrno = vfs_s_ferrno;
1525 vclass->lseek = vfs_s_lseek;
1526 vclass->getid = vfs_s_getid;
1527 vclass->nothingisopen = vfs_s_nothingisopen;
1528 vclass->free = vfs_s_free;
1529 vclass->setctl = vfs_s_setctl;
1530 if ((vclass->flags & VFSF_USETMP) != 0)
1531 {
1532 vclass->getlocalcopy = vfs_s_getlocalcopy;
1533 vclass->ungetlocalcopy = vfs_s_ungetlocalcopy;
1534 }
1535 }
1536
1537
1538
1539 void
1540 vfs_init_subclass (struct vfs_s_subclass *sub, const char *name, vfs_flags_t flags,
1541 const char *prefix)
1542 {
1543 struct vfs_class *vclass = VFS_CLASS (sub);
1544 size_t len;
1545 char *start;
1546
1547 vfs_init_class (vclass, name, flags, prefix);
1548
1549 len = sizeof (struct vfs_s_subclass) - sizeof (struct vfs_class);
1550 start = (char *) sub + sizeof (struct vfs_class);
1551 memset (start, 0, len);
1552
1553 if ((vclass->flags & VFSF_USETMP) != 0)
1554 sub->find_entry = vfs_s_find_entry_linear;
1555 else if ((vclass->flags & VFSF_REMOTE) != 0)
1556 sub->find_entry = vfs_s_find_entry_linear;
1557 else
1558 sub->find_entry = vfs_s_find_entry_tree;
1559 sub->dir_uptodate = vfs_s_dir_uptodate;
1560 }
1561
1562
1563
1564
1565 vfsid
1566 vfs_getid (const vfs_path_t *vpath)
1567 {
1568 const struct vfs_class *me;
1569
1570 me = vfs_path_get_last_path_vfs (vpath);
1571 if (me == NULL || me->getid == NULL)
1572 return NULL;
1573
1574 return me->getid (vpath);
1575 }
1576
1577
1578
1579
1580 #ifdef ENABLE_VFS_NET
1581 int
1582 vfs_s_select_on_two (int fd1, int fd2)
1583 {
1584 struct timeval time_out = {
1585 .tv_sec = 1,
1586 .tv_usec = 0
1587 };
1588 fd_set set;
1589 int maxfd;
1590 int v;
1591
1592 maxfd = MAX (fd1, fd2) + 1;
1593
1594 FD_ZERO (&set);
1595 FD_SET (fd1, &set);
1596 FD_SET (fd2, &set);
1597
1598 v = select (maxfd, &set, 0, 0, &time_out);
1599 if (v <= 0)
1600 return v;
1601 if (FD_ISSET (fd1, &set))
1602 return 1;
1603 if (FD_ISSET (fd2, &set))
1604 return 2;
1605 return (-1);
1606 }
1607
1608
1609
1610 int
1611 vfs_s_get_line (struct vfs_class *me, int sock, char *buf, int buf_len, char term)
1612 {
1613 FILE *logfile = me->logfile;
1614 int i;
1615 char c;
1616
1617 for (i = 0; i < buf_len - 1; i++, buf++)
1618 {
1619 if (read (sock, buf, sizeof (char)) <= 0)
1620 return 0;
1621
1622 if (logfile != NULL)
1623 {
1624 size_t ret1;
1625 int ret2;
1626
1627 ret1 = fwrite (buf, 1, 1, logfile);
1628 ret2 = fflush (logfile);
1629 (void) ret1;
1630 (void) ret2;
1631 }
1632
1633 if (*buf == term)
1634 {
1635 *buf = '\0';
1636 return 1;
1637 }
1638 }
1639
1640
1641 *buf = '\0';
1642 while (read (sock, &c, sizeof (c)) > 0)
1643 {
1644 if (logfile != NULL)
1645 {
1646 size_t ret1;
1647 int ret2;
1648
1649 ret1 = fwrite (&c, 1, 1, logfile);
1650 ret2 = fflush (logfile);
1651 (void) ret1;
1652 (void) ret2;
1653 }
1654 if (c == '\n')
1655 return 1;
1656 }
1657 return 0;
1658 }
1659
1660
1661
1662 int
1663 vfs_s_get_line_interruptible (struct vfs_class *me, char *buffer, int size, int fd)
1664 {
1665 int i;
1666 int res = 0;
1667
1668 (void) me;
1669
1670 tty_enable_interrupt_key ();
1671
1672 for (i = 0; i < size - 1; i++)
1673 {
1674 ssize_t n;
1675
1676 n = read (fd, &buffer[i], 1);
1677 if (n == -1 && errno == EINTR)
1678 {
1679 buffer[i] = '\0';
1680 res = EINTR;
1681 goto ret;
1682 }
1683 if (n == 0)
1684 {
1685 buffer[i] = '\0';
1686 goto ret;
1687 }
1688 if (buffer[i] == '\n')
1689 {
1690 buffer[i] = '\0';
1691 res = 1;
1692 goto ret;
1693 }
1694 }
1695
1696 buffer[size - 1] = '\0';
1697
1698 ret:
1699 tty_disable_interrupt_key ();
1700
1701 return res;
1702 }
1703 #endif
1704
1705
1706
1707
1708
1709
1710 void
1711 vfs_s_normalize_filename_leading_spaces (struct vfs_s_inode *root_inode, size_t final_num_spaces)
1712 {
1713 GList *iter;
1714
1715 for (iter = g_queue_peek_head_link (root_inode->subdir); iter != NULL;
1716 iter = g_list_next (iter))
1717 {
1718 struct vfs_s_entry *entry = VFS_ENTRY (iter->data);
1719
1720 if ((size_t) entry->leading_spaces > final_num_spaces)
1721 {
1722 char *source_name, *spacer;
1723
1724 source_name = entry->name;
1725 spacer = g_strnfill ((size_t) entry->leading_spaces - final_num_spaces, ' ');
1726 entry->name = g_strconcat (spacer, source_name, (char *) NULL);
1727 g_free (spacer);
1728 g_free (source_name);
1729 }
1730
1731 entry->leading_spaces = -1;
1732 }
1733 }
1734
1735