Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
0003  * Licensed under the GPL
0004  */
0005 
0006 #include <stdio.h>
0007 #include <stddef.h>
0008 #include <unistd.h>
0009 #include <dirent.h>
0010 #include <errno.h>
0011 #include <fcntl.h>
0012 #include <string.h>
0013 #include <sys/stat.h>
0014 #include <sys/time.h>
0015 #include <sys/types.h>
0016 #include <sys/vfs.h>
0017 #include <sys/syscall.h>
0018 #include "hostfs.h"
0019 #include <utime.h>
0020 
0021 static void stat64_to_hostfs(const struct stat64 *buf, struct hostfs_stat *p)
0022 {
0023     p->ino = buf->st_ino;
0024     p->mode = buf->st_mode;
0025     p->nlink = buf->st_nlink;
0026     p->uid = buf->st_uid;
0027     p->gid = buf->st_gid;
0028     p->size = buf->st_size;
0029     p->atime.tv_sec = buf->st_atime;
0030     p->atime.tv_nsec = 0;
0031     p->ctime.tv_sec = buf->st_ctime;
0032     p->ctime.tv_nsec = 0;
0033     p->mtime.tv_sec = buf->st_mtime;
0034     p->mtime.tv_nsec = 0;
0035     p->blksize = buf->st_blksize;
0036     p->blocks = buf->st_blocks;
0037     p->maj = os_major(buf->st_rdev);
0038     p->min = os_minor(buf->st_rdev);
0039 }
0040 
0041 int stat_file(const char *path, struct hostfs_stat *p, int fd)
0042 {
0043     struct stat64 buf;
0044 
0045     if (fd >= 0) {
0046         if (fstat64(fd, &buf) < 0)
0047             return -errno;
0048     } else if (lstat64(path, &buf) < 0) {
0049         return -errno;
0050     }
0051     stat64_to_hostfs(&buf, p);
0052     return 0;
0053 }
0054 
0055 int access_file(char *path, int r, int w, int x)
0056 {
0057     int mode = 0;
0058 
0059     if (r)
0060         mode = R_OK;
0061     if (w)
0062         mode |= W_OK;
0063     if (x)
0064         mode |= X_OK;
0065     if (access(path, mode) != 0)
0066         return -errno;
0067     else return 0;
0068 }
0069 
0070 int open_file(char *path, int r, int w, int append)
0071 {
0072     int mode = 0, fd;
0073 
0074     if (r && !w)
0075         mode = O_RDONLY;
0076     else if (!r && w)
0077         mode = O_WRONLY;
0078     else if (r && w)
0079         mode = O_RDWR;
0080     else panic("Impossible mode in open_file");
0081 
0082     if (append)
0083         mode |= O_APPEND;
0084     fd = open64(path, mode);
0085     if (fd < 0)
0086         return -errno;
0087     else return fd;
0088 }
0089 
0090 void *open_dir(char *path, int *err_out)
0091 {
0092     DIR *dir;
0093 
0094     dir = opendir(path);
0095     *err_out = errno;
0096 
0097     return dir;
0098 }
0099 
0100 void seek_dir(void *stream, unsigned long long pos)
0101 {
0102     DIR *dir = stream;
0103 
0104     seekdir(dir, pos);
0105 }
0106 
0107 char *read_dir(void *stream, unsigned long long *pos_out,
0108            unsigned long long *ino_out, int *len_out,
0109            unsigned int *type_out)
0110 {
0111     DIR *dir = stream;
0112     struct dirent *ent;
0113 
0114     ent = readdir(dir);
0115     if (ent == NULL)
0116         return NULL;
0117     *len_out = strlen(ent->d_name);
0118     *ino_out = ent->d_ino;
0119     *type_out = ent->d_type;
0120     *pos_out = ent->d_off;
0121     return ent->d_name;
0122 }
0123 
0124 int read_file(int fd, unsigned long long *offset, char *buf, int len)
0125 {
0126     int n;
0127 
0128     n = pread64(fd, buf, len, *offset);
0129     if (n < 0)
0130         return -errno;
0131     *offset += n;
0132     return n;
0133 }
0134 
0135 int write_file(int fd, unsigned long long *offset, const char *buf, int len)
0136 {
0137     int n;
0138 
0139     n = pwrite64(fd, buf, len, *offset);
0140     if (n < 0)
0141         return -errno;
0142     *offset += n;
0143     return n;
0144 }
0145 
0146 int lseek_file(int fd, long long offset, int whence)
0147 {
0148     int ret;
0149 
0150     ret = lseek64(fd, offset, whence);
0151     if (ret < 0)
0152         return -errno;
0153     return 0;
0154 }
0155 
0156 int fsync_file(int fd, int datasync)
0157 {
0158     int ret;
0159     if (datasync)
0160         ret = fdatasync(fd);
0161     else
0162         ret = fsync(fd);
0163 
0164     if (ret < 0)
0165         return -errno;
0166     return 0;
0167 }
0168 
0169 int replace_file(int oldfd, int fd)
0170 {
0171     return dup2(oldfd, fd);
0172 }
0173 
0174 void close_file(void *stream)
0175 {
0176     close(*((int *) stream));
0177 }
0178 
0179 void close_dir(void *stream)
0180 {
0181     closedir(stream);
0182 }
0183 
0184 int file_create(char *name, int mode)
0185 {
0186     int fd;
0187 
0188     fd = open64(name, O_CREAT | O_RDWR, mode);
0189     if (fd < 0)
0190         return -errno;
0191     return fd;
0192 }
0193 
0194 int set_attr(const char *file, struct hostfs_iattr *attrs, int fd)
0195 {
0196     struct hostfs_stat st;
0197     struct timeval times[2];
0198     int err, ma;
0199 
0200     if (attrs->ia_valid & HOSTFS_ATTR_MODE) {
0201         if (fd >= 0) {
0202             if (fchmod(fd, attrs->ia_mode) != 0)
0203                 return -errno;
0204         } else if (chmod(file, attrs->ia_mode) != 0) {
0205             return -errno;
0206         }
0207     }
0208     if (attrs->ia_valid & HOSTFS_ATTR_UID) {
0209         if (fd >= 0) {
0210             if (fchown(fd, attrs->ia_uid, -1))
0211                 return -errno;
0212         } else if (chown(file, attrs->ia_uid, -1)) {
0213             return -errno;
0214         }
0215     }
0216     if (attrs->ia_valid & HOSTFS_ATTR_GID) {
0217         if (fd >= 0) {
0218             if (fchown(fd, -1, attrs->ia_gid))
0219                 return -errno;
0220         } else if (chown(file, -1, attrs->ia_gid)) {
0221             return -errno;
0222         }
0223     }
0224     if (attrs->ia_valid & HOSTFS_ATTR_SIZE) {
0225         if (fd >= 0) {
0226             if (ftruncate(fd, attrs->ia_size))
0227                 return -errno;
0228         } else if (truncate(file, attrs->ia_size)) {
0229             return -errno;
0230         }
0231     }
0232 
0233     /*
0234      * Update accessed and/or modified time, in two parts: first set
0235      * times according to the changes to perform, and then call futimes()
0236      * or utimes() to apply them.
0237      */
0238     ma = (HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET);
0239     if (attrs->ia_valid & ma) {
0240         err = stat_file(file, &st, fd);
0241         if (err != 0)
0242             return err;
0243 
0244         times[0].tv_sec = st.atime.tv_sec;
0245         times[0].tv_usec = st.atime.tv_nsec / 1000;
0246         times[1].tv_sec = st.mtime.tv_sec;
0247         times[1].tv_usec = st.mtime.tv_nsec / 1000;
0248 
0249         if (attrs->ia_valid & HOSTFS_ATTR_ATIME_SET) {
0250             times[0].tv_sec = attrs->ia_atime.tv_sec;
0251             times[0].tv_usec = attrs->ia_atime.tv_nsec / 1000;
0252         }
0253         if (attrs->ia_valid & HOSTFS_ATTR_MTIME_SET) {
0254             times[1].tv_sec = attrs->ia_mtime.tv_sec;
0255             times[1].tv_usec = attrs->ia_mtime.tv_nsec / 1000;
0256         }
0257 
0258         if (fd >= 0) {
0259             if (futimes(fd, times) != 0)
0260                 return -errno;
0261         } else if (utimes(file, times) != 0) {
0262             return -errno;
0263         }
0264     }
0265 
0266     /* Note: ctime is not handled */
0267     if (attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)) {
0268         err = stat_file(file, &st, fd);
0269         attrs->ia_atime = st.atime;
0270         attrs->ia_mtime = st.mtime;
0271         if (err != 0)
0272             return err;
0273     }
0274     return 0;
0275 }
0276 
0277 int make_symlink(const char *from, const char *to)
0278 {
0279     int err;
0280 
0281     err = symlink(to, from);
0282     if (err)
0283         return -errno;
0284     return 0;
0285 }
0286 
0287 int unlink_file(const char *file)
0288 {
0289     int err;
0290 
0291     err = unlink(file);
0292     if (err)
0293         return -errno;
0294     return 0;
0295 }
0296 
0297 int do_mkdir(const char *file, int mode)
0298 {
0299     int err;
0300 
0301     err = mkdir(file, mode);
0302     if (err)
0303         return -errno;
0304     return 0;
0305 }
0306 
0307 int hostfs_do_rmdir(const char *file)
0308 {
0309     int err;
0310 
0311     err = rmdir(file);
0312     if (err)
0313         return -errno;
0314     return 0;
0315 }
0316 
0317 int do_mknod(const char *file, int mode, unsigned int major, unsigned int minor)
0318 {
0319     int err;
0320 
0321     err = mknod(file, mode, os_makedev(major, minor));
0322     if (err)
0323         return -errno;
0324     return 0;
0325 }
0326 
0327 int link_file(const char *to, const char *from)
0328 {
0329     int err;
0330 
0331     err = link(to, from);
0332     if (err)
0333         return -errno;
0334     return 0;
0335 }
0336 
0337 int hostfs_do_readlink(char *file, char *buf, int size)
0338 {
0339     int n;
0340 
0341     n = readlink(file, buf, size);
0342     if (n < 0)
0343         return -errno;
0344     if (n < size)
0345         buf[n] = '\0';
0346     return n;
0347 }
0348 
0349 int rename_file(char *from, char *to)
0350 {
0351     int err;
0352 
0353     err = rename(from, to);
0354     if (err < 0)
0355         return -errno;
0356     return 0;
0357 }
0358 
0359 int rename2_file(char *from, char *to, unsigned int flags)
0360 {
0361     int err;
0362 
0363 #ifndef SYS_renameat2
0364 #  ifdef __x86_64__
0365 #    define SYS_renameat2 316
0366 #  endif
0367 #  ifdef __i386__
0368 #    define SYS_renameat2 353
0369 #  endif
0370 #endif
0371 
0372 #ifdef SYS_renameat2
0373     err = syscall(SYS_renameat2, AT_FDCWD, from, AT_FDCWD, to, flags);
0374     if (err < 0) {
0375         if (errno != ENOSYS)
0376             return -errno;
0377         else
0378             return -EINVAL;
0379     }
0380     return 0;
0381 #else
0382     return -EINVAL;
0383 #endif
0384 }
0385 
0386 int do_statfs(char *root, long *bsize_out, long long *blocks_out,
0387           long long *bfree_out, long long *bavail_out,
0388           long long *files_out, long long *ffree_out,
0389           void *fsid_out, int fsid_size, long *namelen_out)
0390 {
0391     struct statfs64 buf;
0392     int err;
0393 
0394     err = statfs64(root, &buf);
0395     if (err < 0)
0396         return -errno;
0397 
0398     *bsize_out = buf.f_bsize;
0399     *blocks_out = buf.f_blocks;
0400     *bfree_out = buf.f_bfree;
0401     *bavail_out = buf.f_bavail;
0402     *files_out = buf.f_files;
0403     *ffree_out = buf.f_ffree;
0404     memcpy(fsid_out, &buf.f_fsid,
0405            sizeof(buf.f_fsid) > fsid_size ? fsid_size :
0406            sizeof(buf.f_fsid));
0407     *namelen_out = buf.f_namelen;
0408 
0409     return 0;
0410 }