summaryrefslogtreecommitdiffstats
path: root/lib/vfs/vfs.h
blob: 260e8f337b6a5f55b202f0036304bdb247f1889e (plain)
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
/**
 * \file
 * \brief Header: Virtual File System switch code
 */

#ifndef MC__VFS_VFS_H
#define MC__VFS_VFS_H

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>             /* DIR */
#ifdef HAVE_UTIMENSAT
#include <sys/time.h>
#elif defined (HAVE_UTIME_H)
#include <utime.h>
#endif
#include <stdio.h>
#include <unistd.h>
#include <stddef.h>

#include "lib/global.h"

#include "path.h"

/*** typedefs(not structures) and defined constants **********************************************/

#define VFS_CLASS(a) ((struct vfs_class *) (a))

#define VFS_ENCODING_PREFIX "#enc:"

#define O_ALL (O_CREAT | O_EXCL | O_NOCTTY | O_NDELAY | O_SYNC | O_WRONLY | O_RDWR | O_RDONLY)
/* Midnight commander code should _not_ use other flags than those
   listed above and O_APPEND */

#if (O_ALL & O_APPEND)
#warning "Unexpected problem with flags, O_LINEAR disabled, contact pavel@ucw.cz"
#define O_LINEAR 0
#define IS_LINEAR(a) 0
#define NO_LINEAR(a) a
#else
#define O_LINEAR O_APPEND
#define IS_LINEAR(a) ((a) == (O_RDONLY | O_LINEAR))     /* Return only 0 and 1 ! */
#define NO_LINEAR(a) (((a) == (O_RDONLY | O_LINEAR)) ? O_RDONLY : (a))
#endif

/* O_LINEAR is strange beast, be careful. If you open file asserting
 * O_RDONLY | O_LINEAR, you promise:
 *
 *      a) to read file linearly from beginning to the end
 *      b) not to open another file before you close this one
 *              (this will likely go away in future)
 *      as a special gift, you may
 *      c) lseek() immediately after open(), giving ftpfs chance to
 *         reget. Be warned that this lseek() can fail, and you _have_
 *         to handle that gratefully.
 *
 * O_LINEAR allows filesystems not to create temporary file in some
 * cases (ftp transfer).                                -- pavel@ucw.cz
 */

/* And now some defines for our errors. */

#ifdef ENOMSG
#define E_UNKNOWN ENOMSG        /* if we do not know what error happened */
#else
#define E_UNKNOWN EIO           /* if we do not know what error happened */
#endif

#ifdef EREMOTEIO
#define E_REMOTE EREMOTEIO      /* if other side of ftp/shell reports error */
#else
#define E_REMOTE ENETUNREACH    /* :-( there's no EREMOTEIO on some systems */
#endif

#ifdef EPROTO
#define E_PROTO EPROTO          /* if other side fails to follow protocol */
#else
#define E_PROTO EIO
#endif

/**
 * This is the type of callback function passed to vfs_fill_names.
 * It gets the name of the virtual file system as its first argument.
 * See also:
 *    vfs_fill_names().
 */
typedef void (*fill_names_f) (const char *);

typedef void *vfsid;

#ifdef HAVE_UTIMENSAT
typedef struct timespec mc_timesbuf_t[2];
#else
typedef struct utimbuf mc_timesbuf_t;
#endif

/*** enums ***************************************************************************************/

typedef enum
{
    VFSF_UNKNOWN = 0,
    VFSF_LOCAL = 1 << 0,        /* Class is local (not virtual) filesystem */
    VFSF_NOLINKS = 1 << 1,      /* Hard links not supported */

    VFSF_REMOTE = 1 << 2,
    VFSF_READONLY = 1 << 3,
    VFSF_USETMP = 1 << 4
} vfs_flags_t;

/* Operations for mc_ctl - on open file */
enum
{
    VFS_CTL_IS_NOTREADY
};

/* Operations for mc_setctl - on path */
enum
{
    VFS_SETCTL_FORGET,
    VFS_SETCTL_RUN,
    VFS_SETCTL_LOGFILE,
    VFS_SETCTL_FLUSH,           /* invalidate directory cache */

    /* Setting this makes vfs layer give out potentially incorrect data,
       but it also makes some operations much faster. Use with caution. */
    VFS_SETCTL_STALE_DATA
};

/*** structures declarations (and typedefs of structures)*****************************************/

typedef struct vfs_class
{
    const char *name;           /* "FIles over SHell" */
    vfs_flags_t flags;
    const char *prefix;         /* "shell:" */
    int verrno;                 /* can't use errno because glibc2 might define errno as function */
    gboolean flush;             /* if set to TRUE, invalidate directory cache */
    FILE *logfile;

    /* *INDENT-OFF* */
    int (*init) (struct vfs_class * me);
    void (*done) (struct vfs_class * me);

    /**
     * The fill_names method shall call the callback function for every
     * filesystem name that this vfs module supports.
     */
    void (*fill_names) (struct vfs_class * me, fill_names_f);

    /**
     * The which() method shall return the index of the vfs subsystem
     * or -1 if this vfs cannot handle the given pathname.
     */
    int (*which) (struct vfs_class * me, const char *path);

    void *(*open) (const vfs_path_t * vpath, int flags, mode_t mode);
    int (*close) (void *vfs_info);
    ssize_t (*read) (void *vfs_info, char *buffer, size_t count);
    ssize_t (*write) (void *vfs_info, const char *buf, size_t count);

    void *(*opendir) (const vfs_path_t * vpath);
    struct vfs_dirent *(*readdir) (void *vfs_info);
    int (*closedir) (void *vfs_info);

    int (*stat) (const vfs_path_t * vpath, struct stat * buf);
    int (*lstat) (const vfs_path_t * vpath, struct stat * buf);
    int (*fstat) (void *vfs_info, struct stat * buf);

    int (*chmod) (const vfs_path_t * vpath, mode_t mode);
    int (*chown) (const vfs_path_t * vpath, uid_t owner, gid_t group);

    int (*fgetflags) (const vfs_path_t * vpath, unsigned long *flags);
    int (*fsetflags) (const vfs_path_t * vpath, unsigned long flags);

    int (*utime) (const vfs_path_t * vpath, mc_timesbuf_t * times);

    int (*readlink) (const vfs_path_t * vpath, char *buf, size_t size);
    int (*symlink) (const vfs_path_t * vpath1, const vfs_path_t * vpath2);
    int (*link) (const vfs_path_t * vpath1, const vfs_path_t * vpath2);
    int (*unlink) (const vfs_path_t * vpath);
    int (*rename) (const vfs_path_t * vpath1, const vfs_path_t * vpath2);
    int (*chdir) (const vfs_path_t * vpath);
    int (*ferrno) (struct vfs_class * me);
    off_t (*lseek) (void *vfs_info, off_t offset, int whence);
    int (*mknod) (const vfs_path_t * vpath, mode_t mode, dev_t dev);

    vfsid (*getid) (const vfs_path_t * vpath);

    gboolean (*nothingisopen) (vfsid id);
    void (*free) (vfsid id);

    vfs_path_t *(*getlocalcopy) (const vfs_path_t * vpath);
    int (*ungetlocalcopy) (const vfs_path_t * vpath, const vfs_path_t * local_vpath,
                           gboolean has_changed);

    int (*mkdir) (const vfs_path_t * vpath, mode_t mode);
    int (*rmdir) (const vfs_path_t * vpath);

    int (*ctl) (void *vfs_info, int ctlop, void *arg);
    int (*setctl) (const vfs_path_t * vpath, int ctlop, void *arg);
    /* *INDENT-ON* */
} vfs_class;

/*
 * This struct is used instead of standard dirent to hold file name of any length
 * (not limited to NAME_MAX).
 */
struct vfs_dirent
{
    /* private */
    GString *d_name_str;

    /* public */
    ino_t d_ino;
    char *d_name;               /* Alias of d_name_str->str */
};

/*** global variables defined in .c file *********************************************************/

extern int vfs_timeout;

#ifdef ENABLE_VFS_NET
extern int use_netrc;
#endif

/*** declarations of public functions ************************************************************/

/* lib/vfs/direntry.c: */
void vfs_init_class (struct vfs_class *vclass, const char *name, vfs_flags_t flags,
                     const char *prefix);

void *vfs_s_open (const vfs_path_t * vpath, int flags, mode_t mode);
int vfs_s_stat (const vfs_path_t * vpath, struct stat *buf);
int vfs_s_lstat (const vfs_path_t * vpath, struct stat *buf);
int vfs_s_fstat (void *fh, struct stat *buf);

void vfs_adjust_stat (struct stat *s);

vfsid vfs_getid (const vfs_path_t * vpath);

void vfs_init (void);
void vfs_shut (void);
/* Register a file system class */
gboolean vfs_register_class (struct vfs_class *vfs);
void vfs_unregister_class (struct vfs_class *vfs);

void vfs_setup_work_dir (void);

void vfs_timeout_handler (void);
int vfs_timeouts (void);
void vfs_expire (gboolean now);

const char *vfs_get_current_dir (void);
char *vfs_get_current_dir_n (void);
const vfs_path_t *vfs_get_raw_current_dir (void);
void vfs_set_raw_current_dir (const vfs_path_t * vpath);

gboolean vfs_current_is_local (void);
gboolean vfs_file_is_local (const vfs_path_t * vpath);

char *vfs_strip_suffix_from_filename (const char *filename);

vfs_flags_t vfs_file_class_flags (const vfs_path_t * vpath);

/* translate path back to terminal encoding, remove all #enc:
 * every invalid character is replaced with question mark
 * return static buffer */
const char *vfs_translate_path (const char *path);
/* return new string */
char *vfs_translate_path_n (const char *path);

void vfs_stamp_path (const vfs_path_t * path);

void vfs_release_path (const vfs_path_t * vpath);

struct vfs_dirent *vfs_dirent_init (struct vfs_dirent *d, const char *fname, ino_t ino);
void vfs_dirent_assign (struct vfs_dirent *d, const char *fname, ino_t ino);
void vfs_dirent_free (struct vfs_dirent *d);

void vfs_fill_names (fill_names_f);

/* *INDENT-OFF* */
void vfs_print_message (const char *msg, ...) G_GNUC_PRINTF (1, 2);
/* *INDENT-ON* */

int vfs_ferrno (struct vfs_class *vfs);

int vfs_new_handle (struct vfs_class *vclass, void *fsinfo);

struct vfs_class *vfs_class_find_by_handle (int handle, void **fsinfo);

void vfs_free_handle (int handle);

void vfs_setup_cwd (void);
char *vfs_get_cwd (void);

int vfs_preallocate (int dest_desc, off_t src_fsize, off_t dest_fsize);

int vfs_clone_file (int dest_vfs_fd, int src_vfs_fd);

/**
 * Interface functions described in interface.c
 */
ssize_t mc_read (int handle, void *buffer, size_t count);
ssize_t mc_write (int handle, const void *buffer, size_t count);
int mc_utime (const vfs_path_t * vpath, mc_timesbuf_t * times);
int mc_readlink (const vfs_path_t * vpath, char *buf, size_t bufsiz);
int mc_close (int handle);
off_t mc_lseek (int fd, off_t offset, int whence);
DIR *mc_opendir (const vfs_path_t * vpath);
struct vfs_dirent *mc_readdir (DIR * dirp);
int mc_closedir (DIR * dir);
int mc_stat (const vfs_path_t * vpath, struct stat *buf);
int mc_mknod (const vfs_path_t * vpath, mode_t mode, dev_t dev);
int mc_link (const vfs_path_t * vpath1, const vfs_path_t * vpath2);
int mc_mkdir (const vfs_path_t * vpath, mode_t mode);
int mc_rmdir (const vfs_path_t * vpath);
int mc_fstat (int fd, struct stat *buf);
int mc_lstat (const vfs_path_t * vpath, struct stat *buf);
int mc_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2);
int mc_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2);
int mc_chmod (const vfs_path_t * vpath, mode_t mode);
int mc_chown (const vfs_path_t * vpath, uid_t owner, gid_t group);
int mc_fgetflags (const vfs_path_t * vpath, unsigned long *flags);
int mc_fsetflags (const vfs_path_t * vpath, unsigned long flags);
int mc_chdir (const vfs_path_t * vpath);
int mc_unlink (const vfs_path_t * vpath);
int mc_ctl (int fd, int ctlop, void *arg);
int mc_setctl (const vfs_path_t * vpath, int ctlop, void *arg);
int mc_open (const vfs_path_t * vpath, int flags, ...);
vfs_path_t *mc_getlocalcopy (const vfs_path_t * pathname_vpath);
int mc_ungetlocalcopy (const vfs_path_t * pathname_vpath, const vfs_path_t * local_vpath,
                       gboolean has_changed);
int mc_mkstemps (vfs_path_t ** pname_vpath, const char *prefix, const char *suffix);

/* Creating temporary files safely */
const char *mc_tmpdir (void);


/*** inline functions ****************************************************************************/

#endif /* MC_VFS_VFS_H */