2 libmvfs - metux Virtual Filesystem Library
4 Filesystem driver: local filesystem
6 Copyright (C) 2008 Enrico Weigelt, metux IT service <weigelt@metux.de>
7 This code is published under the terms of the GNU Public License 2.0
11 FD private data layout:
18 #include "mvfs-internal.h"
22 #define PRIV_FD(file) (file->priv.id)
23 #define PRIV_NAME(file) (file->priv.name)
24 #define PRIV_DIRP(file) ((DIR*)(file->priv.ptr))
26 #define PRIV_SET_FD(file,fd) file->priv.id = fd;
27 #define PRIV_SET_NAME(file,name) file->priv.name = strdup(name)
28 #define PRIV_SET_DIRP(file,dirp) file->priv.ptr = dirp;
30 #include <mvfs/mvfs.h>
31 #include <mvfs/default_ops.h>
32 #include <mvfs/hostfs.h>
33 #include <mvfs/_utils.h>
35 #include <sys/types.h>
47 #define FS_MAGIC "hostfs"
49 static int mvfs_hostfs_fileops_open (MVFS_FILE
* file
, mode_t mode
);
50 static off64_t
mvfs_hostfs_fileops_seek (MVFS_FILE
* file
, off64_t offset
, int whence
);
51 static ssize_t
mvfs_hostfs_fileops_read (MVFS_FILE
* file
, void* buf
, size_t count
);
52 static ssize_t
mvfs_hostfs_fileops_write (MVFS_FILE
* file
, const void* buf
, size_t count
);
53 static ssize_t
mvfs_hostfs_fileops_pread (MVFS_FILE
* file
, void* buf
, size_t count
, off64_t offset
);
54 static ssize_t
mvfs_hostfs_fileops_pwrite (MVFS_FILE
* file
, const void* buf
, size_t count
, off64_t offset
);
55 static int mvfs_hostfs_fileops_setflag (MVFS_FILE
* file
, MVFS_FILE_FLAG flag
, long value
);
56 static int mvfs_hostfs_fileops_getflag (MVFS_FILE
* file
, MVFS_FILE_FLAG flag
, long* value
);
57 static MVFS_STAT
* mvfs_hostfs_fileops_stat (MVFS_FILE
* file
);
58 static int mvfs_hostfs_fileops_close (MVFS_FILE
* file
);
59 static int mvfs_hostfs_fileops_eof (MVFS_FILE
* file
);
60 static MVFS_FILE
* mvfs_hostfs_fileops_lookup (MVFS_FILE
* file
, const char* name
);
61 static MVFS_STAT
* mvfs_hostfs_fileops_scan (MVFS_FILE
* file
);
62 static int mvfs_hostfs_fileops_reset (MVFS_FILE
* file
);
64 static MVFS_FILE_OPS hostfs_fileops
=
66 .seek
= mvfs_hostfs_fileops_seek
,
67 .read
= mvfs_hostfs_fileops_read
,
68 .write
= mvfs_hostfs_fileops_write
,
69 .pread
= mvfs_hostfs_fileops_pread
,
70 .pwrite
= mvfs_hostfs_fileops_pwrite
,
71 .close
= mvfs_hostfs_fileops_close
,
72 .eof
= mvfs_hostfs_fileops_eof
,
73 .lookup
= mvfs_hostfs_fileops_lookup
,
74 .reset
= mvfs_hostfs_fileops_reset
,
75 .scan
= mvfs_hostfs_fileops_scan
,
76 .stat
= mvfs_hostfs_fileops_stat
79 static MVFS_FILE
* mvfs_hostfs_fsops_open (MVFS_FILESYSTEM
* fs
, const char* name
, mode_t mode
);
80 static MVFS_STAT
* mvfs_hostfs_fsops_stat (MVFS_FILESYSTEM
* fs
, const char* name
);
81 static int mvfs_hostfs_fsops_unlink (MVFS_FILESYSTEM
* fs
, const char* name
);
82 static int mvfs_hostfs_fsops_free (MVFS_FILESYSTEM
* fs
);
83 static int mvfs_hostfs_fsops_mkdir (MVFS_FILESYSTEM
* file
, const char* name
, mode_t mode
);
84 static int mvfs_hostfs_fsops_chmod (MVFS_FILESYSTEM
* fs
, const char* name
, mode_t mode
);
85 static MVFS_SYMLINK
mvfs_hostfs_fsops_readlink (MVFS_FILESYSTEM
* fs
, const char* path
);
87 static MVFS_FILESYSTEM_OPS hostfs_fsops
=
89 .openfile
= mvfs_hostfs_fsops_open
,
90 .unlink
= mvfs_hostfs_fsops_unlink
,
91 .stat
= mvfs_hostfs_fsops_stat
,
92 .mkdir
= mvfs_hostfs_fsops_mkdir
,
93 .chmod
= mvfs_hostfs_fsops_chmod
,
94 .readlink
= mvfs_hostfs_fsops_readlink
97 static off64_t
mvfs_hostfs_fileops_seek (MVFS_FILE
* file
, off64_t offset
, int whence
)
99 off_t ret
= lseek(PRIV_FD(file
), offset
, whence
);
100 file
->errcode
= errno
;
104 static ssize_t
mvfs_hostfs_fileops_read (MVFS_FILE
* file
, void* buf
, size_t count
)
106 memset(buf
, 0, count
);
107 ssize_t s
= read(PRIV_FD(file
), buf
, count
);
108 file
->errcode
= errno
;
110 file
->priv
.status
= 1;
114 static ssize_t
mvfs_hostfs_fileops_pread (MVFS_FILE
* file
, void* buf
, size_t count
, off64_t offset
)
116 mvfs_hostfs_fileops_seek(file
, offset
, SEEK_SET
);
117 return mvfs_hostfs_fileops_read(file
, buf
, count
);
120 static ssize_t
mvfs_hostfs_fileops_write (MVFS_FILE
* file
, const void* buf
, size_t count
)
122 ssize_t s
= write(PRIV_FD(file
), buf
, count
);
123 file
->errcode
= errno
;
127 static ssize_t
mvfs_hostfs_fileops_pwrite (MVFS_FILE
* file
, const void* buf
, size_t count
, off64_t offset
)
129 mvfs_hostfs_fileops_seek(file
,offset
,SEEK_SET
);
130 return mvfs_hostfs_fileops_write(file
,buf
,count
);
133 static inline const char* __mvfs_flag2str(MVFS_FILE_FLAG f
)
137 case NONBLOCK
: return "NONBLOCK";
138 case READ_TIMEOUT
: return "READ_TIMEOUT";
139 case WRITE_TIMEOUT
: return "WRITE_TIMEOUT";
140 case READ_AHEAD
: return "READ_AHEAD";
141 case WRITE_ASYNC
: return "WRITE_ASYNNC";
142 default: return "UNKNOWN";
146 static int mvfs_hostfs_fileops_setflag (MVFS_FILE
* fp
, MVFS_FILE_FLAG flag
, long value
)
148 ERRMSG("%s not supported", __mvfs_flag2str(flag
));
149 fp
->errcode
= EINVAL
;
153 static int mvfs_hostfs_fileops_getflag (MVFS_FILE
* fp
, MVFS_FILE_FLAG flag
, long* value
)
155 ERRMSG("%s not supported", __mvfs_flag2str(flag
));
156 fp
->errcode
= EINVAL
;
160 static MVFS_STAT
* mvfs_stat_from_unix(const char* name
, struct stat s
)
162 struct passwd
* pw
= getpwuid(s
.st_uid
);
163 struct group
* gr
= getgrgid(s
.st_gid
);
165 const char* uid
="???";
166 const char* gid
="???";
173 MVFS_STAT
* mstat
= mvfs_stat_alloc(name
, uid
, gid
);
174 mstat
->mode
= s
.st_mode
;
175 mstat
->size
= s
.st_size
;
176 mstat
->atime
= s
.st_atime
;
177 mstat
->mtime
= s
.st_mtime
;
178 mstat
->ctime
= s
.st_ctime
;
183 static MVFS_STAT
* mvfs_hostfs_fileops_stat(MVFS_FILE
* fp
)
186 int ret
= fstat(PRIV_FD(fp
), &ust
);
190 fp
->fs
->errcode
= errno
;
194 return mvfs_stat_from_unix(PRIV_NAME(fp
), ust
);
197 static MVFS_FILE
* mvfs_hostfs_fsops_open(MVFS_FILESYSTEM
* fs
, const char* name
, mode_t mode
)
199 int fd
= open(name
, mode
);
203 ERRMSG("error opening file: %s", strerror(errno
));
207 MVFS_FILE
* file
= mvfs_file_alloc(fs
,hostfs_fileops
);
208 file
->priv
.name
= strdup(name
);
214 static MVFS_STAT
* mvfs_hostfs_fsops_stat(MVFS_FILESYSTEM
* fs
, const char* name
)
224 ERRMSG("name==NULL");
225 fs
->errcode
= EFAULT
;
230 int ret
= lstat(name
, &ust
);
238 return mvfs_stat_from_unix(name
, ust
);
241 static int mvfs_hostfs_fsops_unlink(MVFS_FILESYSTEM
* fs
, const char* name
)
243 int ret
= unlink(name
);
245 if ((ret
!= 0) && (errno
== EISDIR
))
255 static int mvfs_hostfs_fsops_mkdir(MVFS_FILESYSTEM
* fs
, const char* fn
, mode_t mode
)
257 DEBUGMSG("fn=\"%s\"", fn
);
258 return mkdir(fn
,mode
);
261 MVFS_FILESYSTEM
* mvfs_hostfs_create(MVFS_HOSTFS_PARAM par
)
263 DEBUGMSG("params currently ignored !");
264 MVFS_FILESYSTEM
* fs
= mvfs_fs_alloc(hostfs_fsops
,FS_MAGIC
);
268 MVFS_FILESYSTEM
* mvfs_hostfs_create_args(MVFS_ARGS
* args
)
270 const char* chroot
= mvfs_args_get(args
,"chroot");
271 if ((chroot
) && (strlen(chroot
)) && (!strcmp(chroot
,"/")))
273 ERRMSG("chroot not supported yet!");
277 MVFS_FILESYSTEM
* fs
= mvfs_fs_alloc(hostfs_fsops
, FS_MAGIC
);
281 static int mvfs_hostfs_fileops_close(MVFS_FILE
* file
)
283 int ret
= close(PRIV_FD(file
));
288 static int mvfs_hostfs_fileops_eof(MVFS_FILE
* file
)
290 return ((file
->priv
.status
) ? 1 : 0);
293 static MVFS_FILE
* mvfs_hostfs_fileops_lookup (MVFS_FILE
* file
, const char* name
)
295 int fd
= openat(PRIV_FD(file
), name
, O_RDONLY
);
299 MVFS_FILE
* f2
= mvfs_file_alloc(file
->fs
,hostfs_fileops
);
300 f2
->priv
.name
= strdup(name
);
306 static DIR* mvfs_hostfs_fileops_init_dir(MVFS_FILE
* file
)
308 DIR* dir
= PRIV_DIRP(file
);
316 dir
= fdopendir(dup(PRIV_FD(file
)));
317 PRIV_SET_DIRP(file
,dir
);
321 static MVFS_STAT
* mvfs_hostfs_fileops_scan(MVFS_FILE
* file
)
323 DIR* dir
= mvfs_hostfs_fileops_init_dir(file
);
326 ERRMSG("cannot get DIR* ptr");
330 struct dirent
* ent
= readdir(dir
);
334 if ((strcmp(ent
->d_name
,".")==0) || (strcmp(ent
->d_name
,"..")==0))
335 return mvfs_hostfs_fileops_scan(file
);
339 memset(buffer
,0,sizeof(buffer
));
340 snprintf(buffer
,sizeof(buffer
)-1,"%s/%s", PRIV_NAME(file
),ent
->d_name
);
343 return mvfs_stat_from_unix(ent
->d_name
, st
);
346 static int mvfs_hostfs_fileops_reset(MVFS_FILE
* file
)
348 DIR* dir
= mvfs_hostfs_fileops_init_dir(file
);
351 ERRMSG("cannot get DIR* ptr");
359 static int mvfs_hostfs_fsops_chmod(MVFS_FILESYSTEM
* fs
, const char* name
, mode_t mode
)
361 return chmod(name
, mode
);
364 static MVFS_SYMLINK
mvfs_hostfs_fsops_readlink(MVFS_FILESYSTEM
* fs
, const char* path
)
367 if (readlink(path
, (char*)&link
.target
, sizeof(link
.target
)) == -1)
368 link
.errcode
= errno
;