2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
15 #include <sys/types.h>
17 #include <sys/syscall.h>
21 static void stat64_to_hostfs(const struct stat64
*buf
, struct hostfs_stat
*p
)
24 p
->mode
= buf
->st_mode
;
25 p
->nlink
= buf
->st_nlink
;
28 p
->size
= buf
->st_size
;
29 p
->atime
.tv_sec
= buf
->st_atime
;
31 p
->ctime
.tv_sec
= buf
->st_ctime
;
33 p
->mtime
.tv_sec
= buf
->st_mtime
;
35 p
->blksize
= buf
->st_blksize
;
36 p
->blocks
= buf
->st_blocks
;
37 p
->maj
= os_major(buf
->st_rdev
);
38 p
->min
= os_minor(buf
->st_rdev
);
41 int stat_file(const char *path
, struct hostfs_stat
*p
, int fd
)
46 if (fstat64(fd
, &buf
) < 0)
48 } else if (lstat64(path
, &buf
) < 0) {
51 stat64_to_hostfs(&buf
, p
);
55 int access_file(char *path
, int r
, int w
, int x
)
65 if (access(path
, mode
) != 0)
70 int open_file(char *path
, int r
, int w
, int append
)
80 else panic("Impossible mode in open_file");
84 fd
= open64(path
, mode
);
90 void *open_dir(char *path
, int *err_out
)
100 void seek_dir(void *stream
, unsigned long long pos
)
107 char *read_dir(void *stream
, unsigned long long *pos_out
,
108 unsigned long long *ino_out
, int *len_out
,
109 unsigned int *type_out
)
117 *len_out
= strlen(ent
->d_name
);
118 *ino_out
= ent
->d_ino
;
119 *type_out
= ent
->d_type
;
120 *pos_out
= ent
->d_off
;
124 int read_file(int fd
, unsigned long long *offset
, char *buf
, int len
)
128 n
= pread64(fd
, buf
, len
, *offset
);
135 int write_file(int fd
, unsigned long long *offset
, const char *buf
, int len
)
139 n
= pwrite64(fd
, buf
, len
, *offset
);
146 int lseek_file(int fd
, long long offset
, int whence
)
150 ret
= lseek64(fd
, offset
, whence
);
156 int fsync_file(int fd
, int datasync
)
169 int replace_file(int oldfd
, int fd
)
171 return dup2(oldfd
, fd
);
174 void close_file(void *stream
)
176 close(*((int *) stream
));
179 void close_dir(void *stream
)
184 int file_create(char *name
, int mode
)
188 fd
= open64(name
, O_CREAT
| O_RDWR
, mode
);
194 int set_attr(const char *file
, struct hostfs_iattr
*attrs
, int fd
)
196 struct hostfs_stat st
;
197 struct timeval times
[2];
200 if (attrs
->ia_valid
& HOSTFS_ATTR_MODE
) {
202 if (fchmod(fd
, attrs
->ia_mode
) != 0)
204 } else if (chmod(file
, attrs
->ia_mode
) != 0) {
208 if (attrs
->ia_valid
& HOSTFS_ATTR_UID
) {
210 if (fchown(fd
, attrs
->ia_uid
, -1))
212 } else if (chown(file
, attrs
->ia_uid
, -1)) {
216 if (attrs
->ia_valid
& HOSTFS_ATTR_GID
) {
218 if (fchown(fd
, -1, attrs
->ia_gid
))
220 } else if (chown(file
, -1, attrs
->ia_gid
)) {
224 if (attrs
->ia_valid
& HOSTFS_ATTR_SIZE
) {
226 if (ftruncate(fd
, attrs
->ia_size
))
228 } else if (truncate(file
, attrs
->ia_size
)) {
234 * Update accessed and/or modified time, in two parts: first set
235 * times according to the changes to perform, and then call futimes()
236 * or utimes() to apply them.
238 ma
= (HOSTFS_ATTR_ATIME_SET
| HOSTFS_ATTR_MTIME_SET
);
239 if (attrs
->ia_valid
& ma
) {
240 err
= stat_file(file
, &st
, fd
);
244 times
[0].tv_sec
= st
.atime
.tv_sec
;
245 times
[0].tv_usec
= st
.atime
.tv_nsec
/ 1000;
246 times
[1].tv_sec
= st
.mtime
.tv_sec
;
247 times
[1].tv_usec
= st
.mtime
.tv_nsec
/ 1000;
249 if (attrs
->ia_valid
& HOSTFS_ATTR_ATIME_SET
) {
250 times
[0].tv_sec
= attrs
->ia_atime
.tv_sec
;
251 times
[0].tv_usec
= attrs
->ia_atime
.tv_nsec
/ 1000;
253 if (attrs
->ia_valid
& HOSTFS_ATTR_MTIME_SET
) {
254 times
[1].tv_sec
= attrs
->ia_mtime
.tv_sec
;
255 times
[1].tv_usec
= attrs
->ia_mtime
.tv_nsec
/ 1000;
259 if (futimes(fd
, times
) != 0)
261 } else if (utimes(file
, times
) != 0) {
266 /* Note: ctime is not handled */
267 if (attrs
->ia_valid
& (HOSTFS_ATTR_ATIME
| HOSTFS_ATTR_MTIME
)) {
268 err
= stat_file(file
, &st
, fd
);
269 attrs
->ia_atime
= st
.atime
;
270 attrs
->ia_mtime
= st
.mtime
;
277 int make_symlink(const char *from
, const char *to
)
281 err
= symlink(to
, from
);
287 int unlink_file(const char *file
)
297 int do_mkdir(const char *file
, int mode
)
301 err
= mkdir(file
, mode
);
307 int do_rmdir(const char *file
)
317 int do_mknod(const char *file
, int mode
, unsigned int major
, unsigned int minor
)
321 err
= mknod(file
, mode
, os_makedev(major
, minor
));
327 int link_file(const char *to
, const char *from
)
331 err
= link(to
, from
);
337 int hostfs_do_readlink(char *file
, char *buf
, int size
)
341 n
= readlink(file
, buf
, size
);
349 int rename_file(char *from
, char *to
)
353 err
= rename(from
, to
);
359 int rename2_file(char *from
, char *to
, unsigned int flags
)
363 #ifndef SYS_renameat2
365 # define SYS_renameat2 316
368 # define SYS_renameat2 353
373 err
= syscall(SYS_renameat2
, AT_FDCWD
, from
, AT_FDCWD
, to
, flags
);
386 int do_statfs(char *root
, long *bsize_out
, long long *blocks_out
,
387 long long *bfree_out
, long long *bavail_out
,
388 long long *files_out
, long long *ffree_out
,
389 void *fsid_out
, int fsid_size
, long *namelen_out
)
394 err
= statfs64(root
, &buf
);
398 *bsize_out
= buf
.f_bsize
;
399 *blocks_out
= buf
.f_blocks
;
400 *bfree_out
= buf
.f_bfree
;
401 *bavail_out
= buf
.f_bavail
;
402 *files_out
= buf
.f_files
;
403 *ffree_out
= buf
.f_ffree
;
404 memcpy(fsid_out
, &buf
.f_fsid
,
405 sizeof(buf
.f_fsid
) > fsid_size
? fsid_size
:
407 *namelen_out
= buf
.f_namelen
;