2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
15 #include <sys/types.h>
22 int stat_file(const char *path
, unsigned long long *inode_out
, int *mode_out
,
23 int *nlink_out
, int *uid_out
, int *gid_out
,
24 unsigned long long *size_out
, struct timespec
*atime_out
,
25 struct timespec
*mtime_out
, struct timespec
*ctime_out
,
26 int *blksize_out
, unsigned long long *blocks_out
, int fd
)
31 if (fstat64(fd
, &buf
) < 0)
33 } else if (lstat64(path
, &buf
) < 0) {
37 if (inode_out
!= NULL
)
38 *inode_out
= buf
.st_ino
;
40 *mode_out
= buf
.st_mode
;
41 if (nlink_out
!= NULL
)
42 *nlink_out
= buf
.st_nlink
;
44 *uid_out
= buf
.st_uid
;
46 *gid_out
= buf
.st_gid
;
48 *size_out
= buf
.st_size
;
49 if (atime_out
!= NULL
) {
50 atime_out
->tv_sec
= buf
.st_atime
;
51 atime_out
->tv_nsec
= 0;
53 if (mtime_out
!= NULL
) {
54 mtime_out
->tv_sec
= buf
.st_mtime
;
55 mtime_out
->tv_nsec
= 0;
57 if (ctime_out
!= NULL
) {
58 ctime_out
->tv_sec
= buf
.st_ctime
;
59 ctime_out
->tv_nsec
= 0;
61 if (blksize_out
!= NULL
)
62 *blksize_out
= buf
.st_blksize
;
63 if (blocks_out
!= NULL
)
64 *blocks_out
= buf
.st_blocks
;
68 int file_type(const char *path
, int *maj
, int *min
)
72 if (lstat64(path
, &buf
) < 0)
75 * We cannot pass rdev as is because glibc and the kernel disagree
76 * about its definition.
79 *maj
= major(buf
.st_rdev
);
81 *min
= minor(buf
.st_rdev
);
83 if (S_ISDIR(buf
.st_mode
))
85 else if (S_ISLNK(buf
.st_mode
))
86 return OS_TYPE_SYMLINK
;
87 else if (S_ISCHR(buf
.st_mode
))
88 return OS_TYPE_CHARDEV
;
89 else if (S_ISBLK(buf
.st_mode
))
90 return OS_TYPE_BLOCKDEV
;
91 else if (S_ISFIFO(buf
.st_mode
))
93 else if (S_ISSOCK(buf
.st_mode
))
95 else return OS_TYPE_FILE
;
98 int access_file(char *path
, int r
, int w
, int x
)
108 if (access(path
, mode
) != 0)
113 int open_file(char *path
, int r
, int w
, int append
)
123 else panic("Impossible mode in open_file");
127 fd
= open64(path
, mode
);
133 void *open_dir(char *path
, int *err_out
)
144 char *read_dir(void *stream
, unsigned long long *pos
,
145 unsigned long long *ino_out
, int *len_out
)
154 *len_out
= strlen(ent
->d_name
);
155 *ino_out
= ent
->d_ino
;
160 int read_file(int fd
, unsigned long long *offset
, char *buf
, int len
)
164 n
= pread64(fd
, buf
, len
, *offset
);
171 int write_file(int fd
, unsigned long long *offset
, const char *buf
, int len
)
175 n
= pwrite64(fd
, buf
, len
, *offset
);
182 int lseek_file(int fd
, long long offset
, int whence
)
186 ret
= lseek64(fd
, offset
, whence
);
192 int fsync_file(int fd
, int datasync
)
205 void close_file(void *stream
)
207 close(*((int *) stream
));
210 void close_dir(void *stream
)
215 int file_create(char *name
, int ur
, int uw
, int ux
, int gr
,
216 int gw
, int gx
, int or, int ow
, int ox
)
221 mode
|= ur
? S_IRUSR
: 0;
222 mode
|= uw
? S_IWUSR
: 0;
223 mode
|= ux
? S_IXUSR
: 0;
224 mode
|= gr
? S_IRGRP
: 0;
225 mode
|= gw
? S_IWGRP
: 0;
226 mode
|= gx
? S_IXGRP
: 0;
227 mode
|= or ? S_IROTH
: 0;
228 mode
|= ow
? S_IWOTH
: 0;
229 mode
|= ox
? S_IXOTH
: 0;
230 fd
= open64(name
, O_CREAT
| O_RDWR
, mode
);
236 int set_attr(const char *file
, struct hostfs_iattr
*attrs
, int fd
)
238 struct timeval times
[2];
239 struct timespec atime_ts
, mtime_ts
;
242 if (attrs
->ia_valid
& HOSTFS_ATTR_MODE
) {
244 if (fchmod(fd
, attrs
->ia_mode
) != 0)
246 } else if (chmod(file
, attrs
->ia_mode
) != 0) {
250 if (attrs
->ia_valid
& HOSTFS_ATTR_UID
) {
252 if (fchown(fd
, attrs
->ia_uid
, -1))
254 } else if (chown(file
, attrs
->ia_uid
, -1)) {
258 if (attrs
->ia_valid
& HOSTFS_ATTR_GID
) {
260 if (fchown(fd
, -1, attrs
->ia_gid
))
262 } else if (chown(file
, -1, attrs
->ia_gid
)) {
266 if (attrs
->ia_valid
& HOSTFS_ATTR_SIZE
) {
268 if (ftruncate(fd
, attrs
->ia_size
))
270 } else if (truncate(file
, attrs
->ia_size
)) {
276 * Update accessed and/or modified time, in two parts: first set
277 * times according to the changes to perform, and then call futimes()
278 * or utimes() to apply them.
280 ma
= (HOSTFS_ATTR_ATIME_SET
| HOSTFS_ATTR_MTIME_SET
);
281 if (attrs
->ia_valid
& ma
) {
282 err
= stat_file(file
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
283 &atime_ts
, &mtime_ts
, NULL
, NULL
, NULL
, fd
);
287 times
[0].tv_sec
= atime_ts
.tv_sec
;
288 times
[0].tv_usec
= atime_ts
.tv_nsec
/ 1000;
289 times
[1].tv_sec
= mtime_ts
.tv_sec
;
290 times
[1].tv_usec
= mtime_ts
.tv_nsec
/ 1000;
292 if (attrs
->ia_valid
& HOSTFS_ATTR_ATIME_SET
) {
293 times
[0].tv_sec
= attrs
->ia_atime
.tv_sec
;
294 times
[0].tv_usec
= attrs
->ia_atime
.tv_nsec
/ 1000;
296 if (attrs
->ia_valid
& HOSTFS_ATTR_MTIME_SET
) {
297 times
[1].tv_sec
= attrs
->ia_mtime
.tv_sec
;
298 times
[1].tv_usec
= attrs
->ia_mtime
.tv_nsec
/ 1000;
302 if (futimes(fd
, times
) != 0)
304 } else if (utimes(file
, times
) != 0) {
309 /* Note: ctime is not handled */
310 if (attrs
->ia_valid
& (HOSTFS_ATTR_ATIME
| HOSTFS_ATTR_MTIME
)) {
311 err
= stat_file(file
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
312 &attrs
->ia_atime
, &attrs
->ia_mtime
, NULL
,
320 int make_symlink(const char *from
, const char *to
)
324 err
= symlink(to
, from
);
330 int unlink_file(const char *file
)
340 int do_mkdir(const char *file
, int mode
)
344 err
= mkdir(file
, mode
);
350 int do_rmdir(const char *file
)
360 int do_mknod(const char *file
, int mode
, unsigned int major
, unsigned int minor
)
364 err
= mknod(file
, mode
, makedev(major
, minor
));
370 int link_file(const char *to
, const char *from
)
374 err
= link(to
, from
);
380 int hostfs_do_readlink(char *file
, char *buf
, int size
)
384 n
= readlink(file
, buf
, size
);
392 int rename_file(char *from
, char *to
)
396 err
= rename(from
, to
);
402 int do_statfs(char *root
, long *bsize_out
, long long *blocks_out
,
403 long long *bfree_out
, long long *bavail_out
,
404 long long *files_out
, long long *ffree_out
,
405 void *fsid_out
, int fsid_size
, long *namelen_out
,
411 err
= statfs64(root
, &buf
);
415 *bsize_out
= buf
.f_bsize
;
416 *blocks_out
= buf
.f_blocks
;
417 *bfree_out
= buf
.f_bfree
;
418 *bavail_out
= buf
.f_bavail
;
419 *files_out
= buf
.f_files
;
420 *ffree_out
= buf
.f_ffree
;
421 memcpy(fsid_out
, &buf
.f_fsid
,
422 sizeof(buf
.f_fsid
) > fsid_size
? fsid_size
:
424 *namelen_out
= buf
.f_namelen
;
425 spare_out
[0] = buf
.f_spare
[0];
426 spare_out
[1] = buf
.f_spare
[1];
427 spare_out
[2] = buf
.f_spare
[2];
428 spare_out
[3] = buf
.f_spare
[3];
429 spare_out
[4] = buf
.f_spare
[4];