2 * Single File fileSystem
4 * Copyright 1998 Pavel Machek, distribute under GPL
8 * This defines whole class of filesystems which contain single file
9 * inside. It is somehow similar to extfs, except that extfs makes
10 * whole virtual trees and we do only single virtual files.
12 * If you want to gunzip something, you should open it with #ugz
13 * suffix, DON'T try to gunzip it yourself.
15 * Namespace: exports vfs_sfs_ops */
19 #include <sys/types.h>
33 struct cachedfile
*next
;
36 static struct cachedfile
*head
;
39 static int sfs_no
= 0;
40 static char *sfs_prefix
[ MAXFS
];
41 static char *sfs_command
[ MAXFS
];
42 static int sfs_flags
[ MAXFS
];
45 #define F_NOLOCALCOPY 4
48 static int uptodate (char *name
, char *cache
)
53 static int vfmake (vfs
*me
, char *name
, char *cache
)
61 vfs_split (name
, &inpath
, &op
);
62 if ((w
= (*me
->which
) (me
, op
)) == -1)
63 vfs_die ("This cannot happen... Hopefully.\n");
65 if ((sfs_flags
[w
] & F_1
) || (!strcmp (name
, "/"))) ; else return -1;
66 /* if ((sfs_flags[w] & F_2) || (!inpath) || (!*inpath)); else return -1; */
67 if (!(sfs_flags
[w
] & F_NOLOCALCOPY
)) {
68 s
= mc_getlocalcopy (name
);
71 name
= name_quote (s
, 0);
74 name
= name_quote (name
, 0);
75 #define COPY_CHAR if (t-pad>sizeof(pad)) { g_free (name); return -1; } else *t++ = *s;
76 #define COPY_STRING(a) if ((t-pad)+strlen(a)>sizeof(pad)) { g_free (name); return -1; } else { strcpy (t, a); t+= strlen(a); }
77 for (s
= sfs_command
[w
]; *s
; s
++) {
84 case '1': ptr
= name
; break;
85 case '2': ptr
= op
+ strlen (sfs_prefix
[w
]); break;
86 case '3': ptr
= cache
; break;
87 case '%': COPY_CHAR
; continue;
99 if (my_system (EXECUTE_AS_SHELL
| EXECUTE_SETUID
| EXECUTE_WAIT
, "/bin/sh", pad
)) {
107 redirect (vfs
*me
, char *name
)
109 struct cachedfile
*cur
= head
;
115 if ((!strcmp (name
, cur
->name
)) &&
117 (uptodate (cur
->name
, cur
->cache
)))
118 /* FIXME: when not uptodate, we might want to kill cache
119 * file immediately, not to wait until timeout. */ {
120 vfs_stamp (&vfs_sfs_ops
, cur
);
126 handle
= mc_mkstemps (&cache
, "sfs", NULL
);
129 return "/SOMEONE_PLAYING_DIRTY_TMP_TRICKS_ON_US";
134 if (!vfmake (me
, name
, cache
)){
135 cur
= g_new (struct cachedfile
, 1);
136 cur
->name
= g_strdup (name
);
142 vfs_add_noncurrent_stamps (&vfs_sfs_ops
, (vfsid
) head
, NULL
);
143 vfs_rm_parents (NULL
);
150 return "/I_MUST_NOT_EXIST";
154 sfs_open (vfs
*me
, char *path
, int flags
, int mode
)
159 path
= redirect (me
, path
);
160 fd
= open (path
, flags
, mode
);
164 sfs_info
= g_new (int, 1);
170 static int sfs_stat (vfs
*me
, char *path
, struct stat
*buf
)
172 path
= redirect (me
, path
);
173 return stat (path
, buf
);
176 static int sfs_lstat (vfs
*me
, char *path
, struct stat
*buf
)
178 path
= redirect (me
, path
);
179 #ifndef HAVE_STATLSTAT
180 return lstat (path
, buf
);
182 return statlstat (path
, buf
);
186 static int sfs_chmod (vfs
*me
, char *path
, int mode
)
188 path
= redirect (me
, path
);
189 return chmod (path
, mode
);
192 static int sfs_chown (vfs
*me
, char *path
, int owner
, int group
)
194 path
= redirect (me
, path
);
195 return chown (path
, owner
, group
);
198 static int sfs_utime (vfs
*me
, char *path
, struct utimbuf
*times
)
200 path
= redirect (me
, path
);
201 return utime (path
, times
);
204 static int sfs_readlink (vfs
*me
, char *path
, char *buf
, int size
)
206 path
= redirect (me
, path
);
207 return readlink (path
, buf
, size
);
210 static vfsid
sfs_getid (vfs
*me
, char *path
, struct vfs_stamping
**parent
)
211 { /* FIXME: what should I do? */
214 struct vfs_stamping
*par
;
215 struct cachedfile
*cur
= head
;
218 if ((!strcmp( path
, cur
->name
)) &&
219 (vfs_uid
== cur
->uid
))
230 char *path2
= g_strdup (path
);
231 v
= vfs_split (path2
, NULL
, NULL
); /* Strip suffix which led to this being sfs */
232 v
= vfs_split (path2
, NULL
, NULL
); /* ... and learn whoever was the parent system */
233 id
= (*v
->getid
) (v
, path2
, &par
);
237 if (id
!= (vfsid
)-1) {
238 *parent
= g_new (struct vfs_stamping
, 1);
241 (*parent
)->parent
= par
;
242 (*parent
)->next
= NULL
;
247 static void sfs_free (vfsid id
)
249 struct cachedfile
*which
= (struct cachedfile
*) id
;
250 struct cachedfile
*cur
, *prev
;
252 for (cur
= head
, prev
= 0; cur
&& cur
!= which
; prev
= cur
, cur
= cur
->next
)
255 vfs_die( "Free of thing which is unknown to me\n" );
259 prev
->next
= cur
->next
;
264 static void sfs_fill_names (vfs
*me
, void (*func
)(char *))
266 struct cachedfile
*cur
= head
;
274 static int sfs_nothingisopen (vfsid id
)
276 /* FIXME: Investigate whether have to guard this like in
277 the other VFSs (see fd_usage in extfs) -- Norbert */
281 static char *sfs_getlocalcopy (vfs
*me
, char *path
)
283 path
= redirect (me
, path
);
284 return g_strdup (path
);
287 static int sfs_ungetlocalcopy (vfs
*me
, char *path
, char *local
, int has_changed
)
293 static int sfs_init (vfs
*me
)
298 mc_sfsini
= concat_dir_and_file (mc_home
, "extfs/sfs.ini");
299 cfg
= fopen (mc_sfsini
, "r");
302 fprintf (stderr
, _("Warning: file %s not found\n"), mc_sfsini
);
309 while (sfs_no
< MAXFS
){
311 char *c
, *semi
= NULL
, flags
= 0;
313 if (!fgets (key
, sizeof (key
), cfg
))
319 for (c
= key
; *c
; c
++)
320 if ((*c
== ':') || (*c
== '/')){
324 flags
|= F_FULLMATCH
;
330 fprintf (stderr
, _("Warning: Invalid line in sfs.ini:\n%s\n"), key
);
335 while ((*c
!= ' ') && (*c
!= '\t')) {
337 case '1': flags
|= F_1
; break;
338 case '2': flags
|= F_2
; break;
339 case 'R': flags
|= F_NOLOCALCOPY
; break;
341 fprintf (stderr
, _("Warning: Invalid flag %c in sfs.ini:\n%s\n"), *c
, key
);
347 if ((semi
= strchr (c
, '\n')))
350 sfs_prefix
[sfs_no
] = g_strdup (key
);
351 sfs_command
[sfs_no
] = g_strdup (c
);
352 sfs_flags
[sfs_no
] = flags
;
364 for (i
= 0; i
< sfs_no
; i
++){
365 g_free (sfs_prefix
[i
]);
366 g_free (sfs_command
[i
]);
367 sfs_prefix
[i
] = sfs_command
[i
] = NULL
;
373 sfs_which (vfs
*me
, char *path
)
377 for (i
= 0; i
< sfs_no
; i
++)
378 if (sfs_flags
[i
] & F_FULLMATCH
) {
379 if (!strcmp (path
, sfs_prefix
[i
]))
382 if (!strncmp (path
, sfs_prefix
[i
], strlen (sfs_prefix
[i
])))
389 NULL
, /* This is place of next pointer */