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
->rdev
.maj
= os_major(buf
->st_rdev
);
38 p
->rdev
.min
= os_minor(buf
->st_rdev
);
39 p
->dev
.maj
= os_major(buf
->st_dev
);
40 p
->dev
.min
= os_minor(buf
->st_dev
);
43 int stat_file(const char *path
, struct hostfs_stat
*p
, int fd
)
48 if (fstat64(fd
, &buf
) < 0)
50 } else if (lstat64(path
, &buf
) < 0) {
53 stat64_to_hostfs(&buf
, p
);
57 int access_file(char *path
, int r
, int w
, int x
)
67 if (access(path
, mode
) != 0)
72 int open_file(char *path
, int r
, int w
, int append
)
82 else panic("Impossible mode in open_file");
86 fd
= open64(path
, mode
);
92 void *open_dir(char *path
, int *err_out
)
102 void seek_dir(void *stream
, unsigned long long pos
)
109 char *read_dir(void *stream
, unsigned long long *pos_out
,
110 unsigned long long *ino_out
, int *len_out
,
111 unsigned int *type_out
)
119 *len_out
= strlen(ent
->d_name
);
120 *ino_out
= ent
->d_ino
;
121 *type_out
= ent
->d_type
;
122 *pos_out
= ent
->d_off
;
126 int read_file(int fd
, unsigned long long *offset
, char *buf
, int len
)
130 n
= pread64(fd
, buf
, len
, *offset
);
137 int write_file(int fd
, unsigned long long *offset
, const char *buf
, int len
)
141 n
= pwrite64(fd
, buf
, len
, *offset
);
148 int lseek_file(int fd
, long long offset
, int whence
)
152 ret
= lseek64(fd
, offset
, whence
);
158 int fsync_file(int fd
, int datasync
)
171 int replace_file(int oldfd
, int fd
)
173 return dup2(oldfd
, fd
);
176 void close_file(void *stream
)
178 close(*((int *) stream
));
181 void close_dir(void *stream
)
186 int file_create(char *name
, int mode
)
190 fd
= open64(name
, O_CREAT
| O_RDWR
, mode
);
196 int set_attr(const char *file
, struct hostfs_iattr
*attrs
, int fd
)
198 struct hostfs_stat st
;
199 struct timeval times
[2];
202 if (attrs
->ia_valid
& HOSTFS_ATTR_MODE
) {
204 if (fchmod(fd
, attrs
->ia_mode
) != 0)
206 } else if (chmod(file
, attrs
->ia_mode
) != 0) {
210 if (attrs
->ia_valid
& HOSTFS_ATTR_UID
) {
212 if (fchown(fd
, attrs
->ia_uid
, -1))
214 } else if (chown(file
, attrs
->ia_uid
, -1)) {
218 if (attrs
->ia_valid
& HOSTFS_ATTR_GID
) {
220 if (fchown(fd
, -1, attrs
->ia_gid
))
222 } else if (chown(file
, -1, attrs
->ia_gid
)) {
226 if (attrs
->ia_valid
& HOSTFS_ATTR_SIZE
) {
228 if (ftruncate(fd
, attrs
->ia_size
))
230 } else if (truncate(file
, attrs
->ia_size
)) {
236 * Update accessed and/or modified time, in two parts: first set
237 * times according to the changes to perform, and then call futimes()
238 * or utimes() to apply them.
240 ma
= (HOSTFS_ATTR_ATIME_SET
| HOSTFS_ATTR_MTIME_SET
);
241 if (attrs
->ia_valid
& ma
) {
242 err
= stat_file(file
, &st
, fd
);
246 times
[0].tv_sec
= st
.atime
.tv_sec
;
247 times
[0].tv_usec
= st
.atime
.tv_nsec
/ 1000;
248 times
[1].tv_sec
= st
.mtime
.tv_sec
;
249 times
[1].tv_usec
= st
.mtime
.tv_nsec
/ 1000;
251 if (attrs
->ia_valid
& HOSTFS_ATTR_ATIME_SET
) {
252 times
[0].tv_sec
= attrs
->ia_atime
.tv_sec
;
253 times
[0].tv_usec
= attrs
->ia_atime
.tv_nsec
/ 1000;
255 if (attrs
->ia_valid
& HOSTFS_ATTR_MTIME_SET
) {
256 times
[1].tv_sec
= attrs
->ia_mtime
.tv_sec
;
257 times
[1].tv_usec
= attrs
->ia_mtime
.tv_nsec
/ 1000;
261 if (futimes(fd
, times
) != 0)
263 } else if (utimes(file
, times
) != 0) {
268 /* Note: ctime is not handled */
269 if (attrs
->ia_valid
& (HOSTFS_ATTR_ATIME
| HOSTFS_ATTR_MTIME
)) {
270 err
= stat_file(file
, &st
, fd
);
271 attrs
->ia_atime
= st
.atime
;
272 attrs
->ia_mtime
= st
.mtime
;
279 int make_symlink(const char *from
, const char *to
)
283 err
= symlink(to
, from
);
289 int unlink_file(const char *file
)
299 int do_mkdir(const char *file
, int mode
)
303 err
= mkdir(file
, mode
);
309 int hostfs_do_rmdir(const char *file
)
319 int do_mknod(const char *file
, int mode
, unsigned int major
, unsigned int minor
)
323 err
= mknod(file
, mode
, os_makedev(major
, minor
));
329 int link_file(const char *to
, const char *from
)
333 err
= link(to
, from
);
339 int hostfs_do_readlink(char *file
, char *buf
, int size
)
343 n
= readlink(file
, buf
, size
);
351 int rename_file(char *from
, char *to
)
355 err
= rename(from
, to
);
361 int rename2_file(char *from
, char *to
, unsigned int flags
)
365 #ifndef SYS_renameat2
367 # define SYS_renameat2 316
370 # define SYS_renameat2 353
375 err
= syscall(SYS_renameat2
, AT_FDCWD
, from
, AT_FDCWD
, to
, flags
);
388 int do_statfs(char *root
, long *bsize_out
, long long *blocks_out
,
389 long long *bfree_out
, long long *bavail_out
,
390 long long *files_out
, long long *ffree_out
,
391 void *fsid_out
, int fsid_size
, long *namelen_out
)
396 err
= statfs64(root
, &buf
);
400 *bsize_out
= buf
.f_bsize
;
401 *blocks_out
= buf
.f_blocks
;
402 *bfree_out
= buf
.f_bfree
;
403 *bavail_out
= buf
.f_bavail
;
404 *files_out
= buf
.f_files
;
405 *ffree_out
= buf
.f_ffree
;
406 memcpy(fsid_out
, &buf
.f_fsid
,
407 sizeof(buf
.f_fsid
) > fsid_size
? fsid_size
:
409 *namelen_out
= buf
.f_namelen
;