linux/fs/hostfs/hostfs_user.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   3 * Licensed under the GPL
   4 */
   5
   6#include <stdio.h>
   7#include <stddef.h>
   8#include <unistd.h>
   9#include <dirent.h>
  10#include <errno.h>
  11#include <fcntl.h>
  12#include <string.h>
  13#include <sys/stat.h>
  14#include <sys/time.h>
  15#include <sys/types.h>
  16#include <sys/vfs.h>
  17#include "hostfs.h"
  18#include "os.h"
  19#include "user.h"
  20#include <utime.h>
  21
  22int 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)
  27{
  28        struct stat64 buf;
  29
  30        if (fd >= 0) {
  31                if (fstat64(fd, &buf) < 0)
  32                        return -errno;
  33        } else if (lstat64(path, &buf) < 0) {
  34                return -errno;
  35        }
  36
  37        if (inode_out != NULL)
  38                *inode_out = buf.st_ino;
  39        if (mode_out != NULL)
  40                *mode_out = buf.st_mode;
  41        if (nlink_out != NULL)
  42                *nlink_out = buf.st_nlink;
  43        if (uid_out != NULL)
  44                *uid_out = buf.st_uid;
  45        if (gid_out != NULL)
  46                *gid_out = buf.st_gid;
  47        if (size_out != NULL)
  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;
  52        }
  53        if (mtime_out != NULL) {
  54                mtime_out->tv_sec = buf.st_mtime;
  55                mtime_out->tv_nsec = 0;
  56        }
  57        if (ctime_out != NULL) {
  58                ctime_out->tv_sec = buf.st_ctime;
  59                ctime_out->tv_nsec = 0;
  60        }
  61        if (blksize_out != NULL)
  62                *blksize_out = buf.st_blksize;
  63        if (blocks_out != NULL)
  64                *blocks_out = buf.st_blocks;
  65        return 0;
  66}
  67
  68int file_type(const char *path, int *maj, int *min)
  69{
  70        struct stat64 buf;
  71
  72        if (lstat64(path, &buf) < 0)
  73                return -errno;
  74        /*
  75         * We cannot pass rdev as is because glibc and the kernel disagree
  76         * about its definition.
  77         */
  78        if (maj != NULL)
  79                *maj = major(buf.st_rdev);
  80        if (min != NULL)
  81                *min = minor(buf.st_rdev);
  82
  83        if (S_ISDIR(buf.st_mode))
  84                return OS_TYPE_DIR;
  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))
  92                return OS_TYPE_FIFO;
  93        else if (S_ISSOCK(buf.st_mode))
  94                return OS_TYPE_SOCK;
  95        else return OS_TYPE_FILE;
  96}
  97
  98int access_file(char *path, int r, int w, int x)
  99{
 100        int mode = 0;
 101
 102        if (r)
 103                mode = R_OK;
 104        if (w)
 105                mode |= W_OK;
 106        if (x)
 107                mode |= X_OK;
 108        if (access(path, mode) != 0)
 109                return -errno;
 110        else return 0;
 111}
 112
 113int open_file(char *path, int r, int w, int append)
 114{
 115        int mode = 0, fd;
 116
 117        if (r && !w)
 118                mode = O_RDONLY;
 119        else if (!r && w)
 120                mode = O_WRONLY;
 121        else if (r && w)
 122                mode = O_RDWR;
 123        else panic("Impossible mode in open_file");
 124
 125        if (append)
 126                mode |= O_APPEND;
 127        fd = open64(path, mode);
 128        if (fd < 0)
 129                return -errno;
 130        else return fd;
 131}
 132
 133void *open_dir(char *path, int *err_out)
 134{
 135        DIR *dir;
 136
 137        dir = opendir(path);
 138        *err_out = errno;
 139        if (dir == NULL)
 140                return NULL;
 141        return dir;
 142}
 143
 144char *read_dir(void *stream, unsigned long long *pos,
 145               unsigned long long *ino_out, int *len_out)
 146{
 147        DIR *dir = stream;
 148        struct dirent *ent;
 149
 150        seekdir(dir, *pos);
 151        ent = readdir(dir);
 152        if (ent == NULL)
 153                return NULL;
 154        *len_out = strlen(ent->d_name);
 155        *ino_out = ent->d_ino;
 156        *pos = telldir(dir);
 157        return ent->d_name;
 158}
 159
 160int read_file(int fd, unsigned long long *offset, char *buf, int len)
 161{
 162        int n;
 163
 164        n = pread64(fd, buf, len, *offset);
 165        if (n < 0)
 166                return -errno;
 167        *offset += n;
 168        return n;
 169}
 170
 171int write_file(int fd, unsigned long long *offset, const char *buf, int len)
 172{
 173        int n;
 174
 175        n = pwrite64(fd, buf, len, *offset);
 176        if (n < 0)
 177                return -errno;
 178        *offset += n;
 179        return n;
 180}
 181
 182int lseek_file(int fd, long long offset, int whence)
 183{
 184        int ret;
 185
 186        ret = lseek64(fd, offset, whence);
 187        if (ret < 0)
 188                return -errno;
 189        return 0;
 190}
 191
 192int fsync_file(int fd, int datasync)
 193{
 194        int ret;
 195        if (datasync)
 196                ret = fdatasync(fd);
 197        else
 198                ret = fsync(fd);
 199
 200        if (ret < 0)
 201                return -errno;
 202        return 0;
 203}
 204
 205void close_file(void *stream)
 206{
 207        close(*((int *) stream));
 208}
 209
 210void close_dir(void *stream)
 211{
 212        closedir(stream);
 213}
 214
 215int file_create(char *name, int ur, int uw, int ux, int gr,
 216                int gw, int gx, int or, int ow, int ox)
 217{
 218        int mode, fd;
 219
 220        mode = 0;
 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);
 231        if (fd < 0)
 232                return -errno;
 233        return fd;
 234}
 235
 236int set_attr(const char *file, struct hostfs_iattr *attrs, int fd)
 237{
 238        struct timeval times[2];
 239        struct timespec atime_ts, mtime_ts;
 240        int err, ma;
 241
 242        if (attrs->ia_valid & HOSTFS_ATTR_MODE) {
 243                if (fd >= 0) {
 244                        if (fchmod(fd, attrs->ia_mode) != 0)
 245                                return (-errno);
 246                } else if (chmod(file, attrs->ia_mode) != 0) {
 247                        return -errno;
 248                }
 249        }
 250        if (attrs->ia_valid & HOSTFS_ATTR_UID) {
 251                if (fd >= 0) {
 252                        if (fchown(fd, attrs->ia_uid, -1))
 253                                return -errno;
 254                } else if (chown(file, attrs->ia_uid, -1)) {
 255                        return -errno;
 256                }
 257        }
 258        if (attrs->ia_valid & HOSTFS_ATTR_GID) {
 259                if (fd >= 0) {
 260                        if (fchown(fd, -1, attrs->ia_gid))
 261                                return -errno;
 262                } else if (chown(file, -1, attrs->ia_gid)) {
 263                        return -errno;
 264                }
 265        }
 266        if (attrs->ia_valid & HOSTFS_ATTR_SIZE) {
 267                if (fd >= 0) {
 268                        if (ftruncate(fd, attrs->ia_size))
 269                                return -errno;
 270                } else if (truncate(file, attrs->ia_size)) {
 271                        return -errno;
 272                }
 273        }
 274
 275        /*
 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.
 279         */
 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);
 284                if (err != 0)
 285                        return err;
 286
 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;
 291
 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;
 295                }
 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;
 299                }
 300
 301                if (fd >= 0) {
 302                        if (futimes(fd, times) != 0)
 303                                return -errno;
 304                } else if (utimes(file, times) != 0) {
 305                        return -errno;
 306                }
 307        }
 308
 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,
 313                                NULL, NULL, fd);
 314                if (err != 0)
 315                        return err;
 316        }
 317        return 0;
 318}
 319
 320int make_symlink(const char *from, const char *to)
 321{
 322        int err;
 323
 324        err = symlink(to, from);
 325        if (err)
 326                return -errno;
 327        return 0;
 328}
 329
 330int unlink_file(const char *file)
 331{
 332        int err;
 333
 334        err = unlink(file);
 335        if (err)
 336                return -errno;
 337        return 0;
 338}
 339
 340int do_mkdir(const char *file, int mode)
 341{
 342        int err;
 343
 344        err = mkdir(file, mode);
 345        if (err)
 346                return -errno;
 347        return 0;
 348}
 349
 350int do_rmdir(const char *file)
 351{
 352        int err;
 353
 354        err = rmdir(file);
 355        if (err)
 356                return -errno;
 357        return 0;
 358}
 359
 360int do_mknod(const char *file, int mode, unsigned int major, unsigned int minor)
 361{
 362        int err;
 363
 364        err = mknod(file, mode, makedev(major, minor));
 365        if (err)
 366                return -errno;
 367        return 0;
 368}
 369
 370int link_file(const char *to, const char *from)
 371{
 372        int err;
 373
 374        err = link(to, from);
 375        if (err)
 376                return -errno;
 377        return 0;
 378}
 379
 380int hostfs_do_readlink(char *file, char *buf, int size)
 381{
 382        int n;
 383
 384        n = readlink(file, buf, size);
 385        if (n < 0)
 386                return -errno;
 387        if (n < size)
 388                buf[n] = '\0';
 389        return n;
 390}
 391
 392int rename_file(char *from, char *to)
 393{
 394        int err;
 395
 396        err = rename(from, to);
 397        if (err < 0)
 398                return -errno;
 399        return 0;
 400}
 401
 402int 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,
 406              long *spare_out)
 407{
 408        struct statfs64 buf;
 409        int err;
 410
 411        err = statfs64(root, &buf);
 412        if (err < 0)
 413                return -errno;
 414
 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 :
 423               sizeof(buf.f_fsid));
 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];
 430        return 0;
 431}
 432