linux/arch/um/os-Linux/file.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   3 * Licensed under the GPL
   4 */
   5
   6#include <stdio.h>
   7#include <unistd.h>
   8#include <errno.h>
   9#include <fcntl.h>
  10#include <signal.h>
  11#include <sys/ioctl.h>
  12#include <sys/mount.h>
  13#include <sys/socket.h>
  14#include <sys/stat.h>
  15#include <sys/un.h>
  16#include "os.h"
  17
  18static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
  19{
  20        *dst = ((struct uml_stat) {
  21                .ust_dev     = src->st_dev,     /* device */
  22                .ust_ino     = src->st_ino,     /* inode */
  23                .ust_mode    = src->st_mode,    /* protection */
  24                .ust_nlink   = src->st_nlink,   /* number of hard links */
  25                .ust_uid     = src->st_uid,     /* user ID of owner */
  26                .ust_gid     = src->st_gid,     /* group ID of owner */
  27                .ust_size    = src->st_size,    /* total size, in bytes */
  28                .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
  29                .ust_blocks  = src->st_blocks,  /* number of blocks allocated */
  30                .ust_atime   = src->st_atime,   /* time of last access */
  31                .ust_mtime   = src->st_mtime,   /* time of last modification */
  32                .ust_ctime   = src->st_ctime,   /* time of last change */
  33        });
  34}
  35
  36int os_stat_fd(const int fd, struct uml_stat *ubuf)
  37{
  38        struct stat64 sbuf;
  39        int err;
  40
  41        CATCH_EINTR(err = fstat64(fd, &sbuf));
  42        if (err < 0)
  43                return -errno;
  44
  45        if (ubuf != NULL)
  46                copy_stat(ubuf, &sbuf);
  47        return err;
  48}
  49
  50int os_stat_file(const char *file_name, struct uml_stat *ubuf)
  51{
  52        struct stat64 sbuf;
  53        int err;
  54
  55        CATCH_EINTR(err = stat64(file_name, &sbuf));
  56        if (err < 0)
  57                return -errno;
  58
  59        if (ubuf != NULL)
  60                copy_stat(ubuf, &sbuf);
  61        return err;
  62}
  63
  64int os_access(const char *file, int mode)
  65{
  66        int amode, err;
  67
  68        amode = (mode & OS_ACC_R_OK ? R_OK : 0) |
  69                (mode & OS_ACC_W_OK ? W_OK : 0) |
  70                (mode & OS_ACC_X_OK ? X_OK : 0) |
  71                (mode & OS_ACC_F_OK ? F_OK : 0);
  72
  73        err = access(file, amode);
  74        if (err < 0)
  75                return -errno;
  76
  77        return 0;
  78}
  79
  80/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
  81int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
  82{
  83        int err;
  84
  85        err = ioctl(fd, cmd, arg);
  86        if (err < 0)
  87                return -errno;
  88
  89        return err;
  90}
  91
  92/* FIXME: ensure namebuf in os_get_if_name is big enough */
  93int os_get_ifname(int fd, char* namebuf)
  94{
  95        if (ioctl(fd, SIOCGIFNAME, namebuf) < 0)
  96                return -errno;
  97
  98        return 0;
  99}
 100
 101int os_set_slip(int fd)
 102{
 103        int disc, sencap;
 104
 105        disc = N_SLIP;
 106        if (ioctl(fd, TIOCSETD, &disc) < 0)
 107                return -errno;
 108
 109        sencap = 0;
 110        if (ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
 111                return -errno;
 112
 113        return 0;
 114}
 115
 116int os_mode_fd(int fd, int mode)
 117{
 118        int err;
 119
 120        CATCH_EINTR(err = fchmod(fd, mode));
 121        if (err < 0)
 122                return -errno;
 123
 124        return 0;
 125}
 126
 127int os_file_type(char *file)
 128{
 129        struct uml_stat buf;
 130        int err;
 131
 132        err = os_stat_file(file, &buf);
 133        if (err < 0)
 134                return err;
 135
 136        if (S_ISDIR(buf.ust_mode))
 137                return OS_TYPE_DIR;
 138        else if (S_ISLNK(buf.ust_mode))
 139                return OS_TYPE_SYMLINK;
 140        else if (S_ISCHR(buf.ust_mode))
 141                return OS_TYPE_CHARDEV;
 142        else if (S_ISBLK(buf.ust_mode))
 143                return OS_TYPE_BLOCKDEV;
 144        else if (S_ISFIFO(buf.ust_mode))
 145                return OS_TYPE_FIFO;
 146        else if (S_ISSOCK(buf.ust_mode))
 147                return OS_TYPE_SOCK;
 148        else return OS_TYPE_FILE;
 149}
 150
 151int os_file_mode(const char *file, struct openflags *mode_out)
 152{
 153        int err;
 154
 155        *mode_out = OPENFLAGS();
 156
 157        err = access(file, W_OK);
 158        if (err && (errno != EACCES))
 159                return -errno;
 160        else if (!err)
 161                *mode_out = of_write(*mode_out);
 162
 163        err = access(file, R_OK);
 164        if (err && (errno != EACCES))
 165                return -errno;
 166        else if (!err)
 167                *mode_out = of_read(*mode_out);
 168
 169        return err;
 170}
 171
 172int os_open_file(const char *file, struct openflags flags, int mode)
 173{
 174        int fd, err, f = 0;
 175
 176        if (flags.r && flags.w)
 177                f = O_RDWR;
 178        else if (flags.r)
 179                f = O_RDONLY;
 180        else if (flags.w)
 181                f = O_WRONLY;
 182        else f = 0;
 183
 184        if (flags.s)
 185                f |= O_SYNC;
 186        if (flags.c)
 187                f |= O_CREAT;
 188        if (flags.t)
 189                f |= O_TRUNC;
 190        if (flags.e)
 191                f |= O_EXCL;
 192        if (flags.a)
 193                f |= O_APPEND;
 194
 195        fd = open64(file, f, mode);
 196        if (fd < 0)
 197                return -errno;
 198
 199        if (flags.cl && fcntl(fd, F_SETFD, 1)) {
 200                err = -errno;
 201                close(fd);
 202                return err;
 203        }
 204
 205        return fd;
 206}
 207
 208int os_connect_socket(const char *name)
 209{
 210        struct sockaddr_un sock;
 211        int fd, err;
 212
 213        sock.sun_family = AF_UNIX;
 214        snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
 215
 216        fd = socket(AF_UNIX, SOCK_STREAM, 0);
 217        if (fd < 0) {
 218                err = -errno;
 219                goto out;
 220        }
 221
 222        err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
 223        if (err) {
 224                err = -errno;
 225                goto out_close;
 226        }
 227
 228        return fd;
 229
 230out_close:
 231        close(fd);
 232out:
 233        return err;
 234}
 235
 236void os_close_file(int fd)
 237{
 238        close(fd);
 239}
 240
 241int os_seek_file(int fd, unsigned long long offset)
 242{
 243        unsigned long long actual;
 244
 245        actual = lseek64(fd, offset, SEEK_SET);
 246        if (actual != offset)
 247                return -errno;
 248        return 0;
 249}
 250
 251int os_read_file(int fd, void *buf, int len)
 252{
 253        int n = read(fd, buf, len);
 254
 255        if (n < 0)
 256                return -errno;
 257        return n;
 258}
 259
 260int os_write_file(int fd, const void *buf, int len)
 261{
 262        int n = write(fd, (void *) buf, len);
 263
 264        if (n < 0)
 265                return -errno;
 266        return n;
 267}
 268
 269int os_file_size(const char *file, unsigned long long *size_out)
 270{
 271        struct uml_stat buf;
 272        int err;
 273
 274        err = os_stat_file(file, &buf);
 275        if (err < 0) {
 276                printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
 277                       -err);
 278                return err;
 279        }
 280
 281        if (S_ISBLK(buf.ust_mode)) {
 282                int fd;
 283                long blocks;
 284
 285                fd = open(file, O_RDONLY, 0);
 286                if (fd < 0) {
 287                        err = -errno;
 288                        printk(UM_KERN_ERR "Couldn't open \"%s\", "
 289                               "errno = %d\n", file, errno);
 290                        return err;
 291                }
 292                if (ioctl(fd, BLKGETSIZE, &blocks) < 0) {
 293                        err = -errno;
 294                        printk(UM_KERN_ERR "Couldn't get the block size of "
 295                               "\"%s\", errno = %d\n", file, errno);
 296                        close(fd);
 297                        return err;
 298                }
 299                *size_out = ((long long) blocks) * 512;
 300                close(fd);
 301        }
 302        else *size_out = buf.ust_size;
 303
 304        return 0;
 305}
 306
 307int os_file_modtime(const char *file, unsigned long *modtime)
 308{
 309        struct uml_stat buf;
 310        int err;
 311
 312        err = os_stat_file(file, &buf);
 313        if (err < 0) {
 314                printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
 315                       -err);
 316                return err;
 317        }
 318
 319        *modtime = buf.ust_mtime;
 320        return 0;
 321}
 322
 323int os_set_exec_close(int fd)
 324{
 325        int err;
 326
 327        CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
 328
 329        if (err < 0)
 330                return -errno;
 331        return err;
 332}
 333
 334int os_pipe(int *fds, int stream, int close_on_exec)
 335{
 336        int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
 337
 338        err = socketpair(AF_UNIX, type, 0, fds);
 339        if (err < 0)
 340                return -errno;
 341
 342        if (!close_on_exec)
 343                return 0;
 344
 345        err = os_set_exec_close(fds[0]);
 346        if (err < 0)
 347                goto error;
 348
 349        err = os_set_exec_close(fds[1]);
 350        if (err < 0)
 351                goto error;
 352
 353        return 0;
 354
 355 error:
 356        printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n",
 357               -err);
 358        close(fds[1]);
 359        close(fds[0]);
 360        return err;
 361}
 362
 363int os_set_fd_async(int fd)
 364{
 365        int err, flags;
 366
 367        flags = fcntl(fd, F_GETFL);
 368        if (flags < 0)
 369                return -errno;
 370
 371        flags |= O_ASYNC | O_NONBLOCK;
 372        if (fcntl(fd, F_SETFL, flags) < 0) {
 373                err = -errno;
 374                printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC "
 375                       "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
 376                return err;
 377        }
 378
 379        if ((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
 380            (fcntl(fd, F_SETOWN, os_getpid()) < 0)) {
 381                err = -errno;
 382                printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN "
 383                       "(or F_SETSIG) fd %d, errno = %d\n", fd, errno);
 384                return err;
 385        }
 386
 387        return 0;
 388}
 389
 390int os_clear_fd_async(int fd)
 391{
 392        int flags;
 393
 394        flags = fcntl(fd, F_GETFL);
 395        if (flags < 0)
 396                return -errno;
 397
 398        flags &= ~(O_ASYNC | O_NONBLOCK);
 399        if (fcntl(fd, F_SETFL, flags) < 0)
 400                return -errno;
 401        return 0;
 402}
 403
 404int os_set_fd_block(int fd, int blocking)
 405{
 406        int flags;
 407
 408        flags = fcntl(fd, F_GETFL);
 409        if (flags < 0)
 410                return -errno;
 411
 412        if (blocking)
 413                flags &= ~O_NONBLOCK;
 414        else
 415                flags |= O_NONBLOCK;
 416
 417        if (fcntl(fd, F_SETFL, flags) < 0)
 418                return -errno;
 419
 420        return 0;
 421}
 422
 423int os_accept_connection(int fd)
 424{
 425        int new;
 426
 427        new = accept(fd, NULL, 0);
 428        if (new < 0)
 429                return -errno;
 430        return new;
 431}
 432
 433#ifndef SHUT_RD
 434#define SHUT_RD 0
 435#endif
 436
 437#ifndef SHUT_WR
 438#define SHUT_WR 1
 439#endif
 440
 441#ifndef SHUT_RDWR
 442#define SHUT_RDWR 2
 443#endif
 444
 445int os_shutdown_socket(int fd, int r, int w)
 446{
 447        int what, err;
 448
 449        if (r && w)
 450                what = SHUT_RDWR;
 451        else if (r)
 452                what = SHUT_RD;
 453        else if (w)
 454                what = SHUT_WR;
 455        else
 456                return -EINVAL;
 457
 458        err = shutdown(fd, what);
 459        if (err < 0)
 460                return -errno;
 461        return 0;
 462}
 463
 464int os_rcv_fd(int fd, int *helper_pid_out)
 465{
 466        int new, n;
 467        char buf[CMSG_SPACE(sizeof(new))];
 468        struct msghdr msg;
 469        struct cmsghdr *cmsg;
 470        struct iovec iov;
 471
 472        msg.msg_name = NULL;
 473        msg.msg_namelen = 0;
 474        iov = ((struct iovec) { .iov_base  = helper_pid_out,
 475                                .iov_len   = sizeof(*helper_pid_out) });
 476        msg.msg_iov = &iov;
 477        msg.msg_iovlen = 1;
 478        msg.msg_control = buf;
 479        msg.msg_controllen = sizeof(buf);
 480        msg.msg_flags = 0;
 481
 482        n = recvmsg(fd, &msg, 0);
 483        if (n < 0)
 484                return -errno;
 485        else if (n != iov.iov_len)
 486                *helper_pid_out = -1;
 487
 488        cmsg = CMSG_FIRSTHDR(&msg);
 489        if (cmsg == NULL) {
 490                printk(UM_KERN_ERR "rcv_fd didn't receive anything, "
 491                       "error = %d\n", errno);
 492                return -1;
 493        }
 494        if ((cmsg->cmsg_level != SOL_SOCKET) ||
 495            (cmsg->cmsg_type != SCM_RIGHTS)) {
 496                printk(UM_KERN_ERR "rcv_fd didn't receive a descriptor\n");
 497                return -1;
 498        }
 499
 500        new = ((int *) CMSG_DATA(cmsg))[0];
 501        return new;
 502}
 503
 504int os_create_unix_socket(const char *file, int len, int close_on_exec)
 505{
 506        struct sockaddr_un addr;
 507        int sock, err;
 508
 509        sock = socket(PF_UNIX, SOCK_DGRAM, 0);
 510        if (sock < 0)
 511                return -errno;
 512
 513        if (close_on_exec) {
 514                err = os_set_exec_close(sock);
 515                if (err < 0)
 516                        printk(UM_KERN_ERR "create_unix_socket : "
 517                               "close_on_exec failed, err = %d", -err);
 518        }
 519
 520        addr.sun_family = AF_UNIX;
 521
 522        snprintf(addr.sun_path, len, "%s", file);
 523
 524        err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
 525        if (err < 0)
 526                return -errno;
 527
 528        return sock;
 529}
 530
 531void os_flush_stdout(void)
 532{
 533        fflush(stdout);
 534}
 535
 536int os_lock_file(int fd, int excl)
 537{
 538        int type = excl ? F_WRLCK : F_RDLCK;
 539        struct flock lock = ((struct flock) { .l_type   = type,
 540                                              .l_whence = SEEK_SET,
 541                                              .l_start  = 0,
 542                                              .l_len    = 0 } );
 543        int err, save;
 544
 545        err = fcntl(fd, F_SETLK, &lock);
 546        if (!err)
 547                goto out;
 548
 549        save = -errno;
 550        err = fcntl(fd, F_GETLK, &lock);
 551        if (err) {
 552                err = -errno;
 553                goto out;
 554        }
 555
 556        printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n",
 557               lock.l_pid);
 558        err = save;
 559 out:
 560        return err;
 561}
 562
 563unsigned os_major(unsigned long long dev)
 564{
 565        return major(dev);
 566}
 567
 568unsigned os_minor(unsigned long long dev)
 569{
 570        return minor(dev);
 571}
 572
 573unsigned long long os_makedev(unsigned major, unsigned minor)
 574{
 575        return makedev(major, minor);
 576}
 577