2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
15 #include <sys/types.h>
22 static void stat64_to_hostfs(const struct stat64
*buf
, struct hostfs_stat
*p
)
25 p
->mode
= buf
->st_mode
;
26 p
->nlink
= buf
->st_nlink
;
29 p
->size
= buf
->st_size
;
30 p
->atime
.tv_sec
= buf
->st_atime
;
32 p
->ctime
.tv_sec
= buf
->st_ctime
;
34 p
->mtime
.tv_sec
= buf
->st_mtime
;
36 p
->blksize
= buf
->st_blksize
;
37 p
->blocks
= buf
->st_blocks
;
38 p
->maj
= os_major(buf
->st_rdev
);
39 p
->min
= os_minor(buf
->st_rdev
);
42 int stat_file(const char *path
, struct hostfs_stat
*p
, int fd
)
47 if (fstat64(fd
, &buf
) < 0)
49 } else if (lstat64(path
, &buf
) < 0) {
52 stat64_to_hostfs(&buf
, p
);
56 int file_type(const char *path
, int *maj
, int *min
)
60 if (lstat64(path
, &buf
) < 0)
63 * We cannot pass rdev as is because glibc and the kernel disagree
64 * about its definition.
67 *maj
= os_major(buf
.st_rdev
);
69 *min
= os_minor(buf
.st_rdev
);
71 if (S_ISDIR(buf
.st_mode
))
73 else if (S_ISLNK(buf
.st_mode
))
74 return OS_TYPE_SYMLINK
;
75 else if (S_ISCHR(buf
.st_mode
))
76 return OS_TYPE_CHARDEV
;
77 else if (S_ISBLK(buf
.st_mode
))
78 return OS_TYPE_BLOCKDEV
;
79 else if (S_ISFIFO(buf
.st_mode
))
81 else if (S_ISSOCK(buf
.st_mode
))
83 else return OS_TYPE_FILE
;
86 int access_file(char *path
, int r
, int w
, int x
)
96 if (access(path
, mode
) != 0)
101 int open_file(char *path
, int r
, int w
, int append
)
111 else panic("Impossible mode in open_file");
115 fd
= open64(path
, mode
);
121 void *open_dir(char *path
, int *err_out
)
132 char *read_dir(void *stream
, unsigned long long *pos
,
133 unsigned long long *ino_out
, int *len_out
)
142 *len_out
= strlen(ent
->d_name
);
143 *ino_out
= ent
->d_ino
;
148 int read_file(int fd
, unsigned long long *offset
, char *buf
, int len
)
152 n
= pread64(fd
, buf
, len
, *offset
);
159 int write_file(int fd
, unsigned long long *offset
, const char *buf
, int len
)
163 n
= pwrite64(fd
, buf
, len
, *offset
);
170 int lseek_file(int fd
, long long offset
, int whence
)
174 ret
= lseek64(fd
, offset
, whence
);
180 int fsync_file(int fd
, int datasync
)
193 void close_file(void *stream
)
195 close(*((int *) stream
));
198 void close_dir(void *stream
)
203 int file_create(char *name
, int ur
, int uw
, int ux
, int gr
,
204 int gw
, int gx
, int or, int ow
, int ox
)
209 mode
|= ur
? S_IRUSR
: 0;
210 mode
|= uw
? S_IWUSR
: 0;
211 mode
|= ux
? S_IXUSR
: 0;
212 mode
|= gr
? S_IRGRP
: 0;
213 mode
|= gw
? S_IWGRP
: 0;
214 mode
|= gx
? S_IXGRP
: 0;
215 mode
|= or ? S_IROTH
: 0;
216 mode
|= ow
? S_IWOTH
: 0;
217 mode
|= ox
? S_IXOTH
: 0;
218 fd
= open64(name
, O_CREAT
| O_RDWR
, mode
);
224 int set_attr(const char *file
, struct hostfs_iattr
*attrs
, int fd
)
226 struct hostfs_stat st
;
227 struct timeval times
[2];
230 if (attrs
->ia_valid
& HOSTFS_ATTR_MODE
) {
232 if (fchmod(fd
, attrs
->ia_mode
) != 0)
234 } else if (chmod(file
, attrs
->ia_mode
) != 0) {
238 if (attrs
->ia_valid
& HOSTFS_ATTR_UID
) {
240 if (fchown(fd
, attrs
->ia_uid
, -1))
242 } else if (chown(file
, attrs
->ia_uid
, -1)) {
246 if (attrs
->ia_valid
& HOSTFS_ATTR_GID
) {
248 if (fchown(fd
, -1, attrs
->ia_gid
))
250 } else if (chown(file
, -1, attrs
->ia_gid
)) {
254 if (attrs
->ia_valid
& HOSTFS_ATTR_SIZE
) {
256 if (ftruncate(fd
, attrs
->ia_size
))
258 } else if (truncate(file
, attrs
->ia_size
)) {
264 * Update accessed and/or modified time, in two parts: first set
265 * times according to the changes to perform, and then call futimes()
266 * or utimes() to apply them.
268 ma
= (HOSTFS_ATTR_ATIME_SET
| HOSTFS_ATTR_MTIME_SET
);
269 if (attrs
->ia_valid
& ma
) {
270 err
= stat_file(file
, &st
, fd
);
274 times
[0].tv_sec
= st
.atime
.tv_sec
;
275 times
[0].tv_usec
= st
.atime
.tv_nsec
/ 1000;
276 times
[1].tv_sec
= st
.mtime
.tv_sec
;
277 times
[1].tv_usec
= st
.mtime
.tv_nsec
/ 1000;
279 if (attrs
->ia_valid
& HOSTFS_ATTR_ATIME_SET
) {
280 times
[0].tv_sec
= attrs
->ia_atime
.tv_sec
;
281 times
[0].tv_usec
= attrs
->ia_atime
.tv_nsec
/ 1000;
283 if (attrs
->ia_valid
& HOSTFS_ATTR_MTIME_SET
) {
284 times
[1].tv_sec
= attrs
->ia_mtime
.tv_sec
;
285 times
[1].tv_usec
= attrs
->ia_mtime
.tv_nsec
/ 1000;
289 if (futimes(fd
, times
) != 0)
291 } else if (utimes(file
, times
) != 0) {
296 /* Note: ctime is not handled */
297 if (attrs
->ia_valid
& (HOSTFS_ATTR_ATIME
| HOSTFS_ATTR_MTIME
)) {
298 err
= stat_file(file
, &st
, fd
);
299 attrs
->ia_atime
= st
.atime
;
300 attrs
->ia_mtime
= st
.mtime
;
307 int make_symlink(const char *from
, const char *to
)
311 err
= symlink(to
, from
);
317 int unlink_file(const char *file
)
327 int do_mkdir(const char *file
, int mode
)
331 err
= mkdir(file
, mode
);
337 int do_rmdir(const char *file
)
347 int do_mknod(const char *file
, int mode
, unsigned int major
, unsigned int minor
)
351 err
= mknod(file
, mode
, os_makedev(major
, minor
));
357 int link_file(const char *to
, const char *from
)
361 err
= link(to
, from
);
367 int hostfs_do_readlink(char *file
, char *buf
, int size
)
371 n
= readlink(file
, buf
, size
);
379 int rename_file(char *from
, char *to
)
383 err
= rename(from
, to
);
389 int do_statfs(char *root
, long *bsize_out
, long long *blocks_out
,
390 long long *bfree_out
, long long *bavail_out
,
391 long long *files_out
, long long *ffree_out
,
392 void *fsid_out
, int fsid_size
, long *namelen_out
,
398 err
= statfs64(root
, &buf
);
402 *bsize_out
= buf
.f_bsize
;
403 *blocks_out
= buf
.f_blocks
;
404 *bfree_out
= buf
.f_bfree
;
405 *bavail_out
= buf
.f_bavail
;
406 *files_out
= buf
.f_files
;
407 *ffree_out
= buf
.f_ffree
;
408 memcpy(fsid_out
, &buf
.f_fsid
,
409 sizeof(buf
.f_fsid
) > fsid_size
? fsid_size
:
411 *namelen_out
= buf
.f_namelen
;
412 spare_out
[0] = buf
.f_spare
[0];
413 spare_out
[1] = buf
.f_spare
[1];
414 spare_out
[2] = buf
.f_spare
[2];
415 spare_out
[3] = buf
.f_spare
[3];
416 spare_out
[4] = buf
.f_spare
[4];