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}
 240int os_fsync_file(int fd)
 241{
 242        if (fsync(fd) < 0)
 243            return -errno;
 244        return 0;
 245}
 246
 247int os_seek_file(int fd, unsigned long long offset)
 248{
 249        unsigned long long actual;
 250
 251        actual = lseek64(fd, offset, SEEK_SET);
 252        if (actual != offset)
 253                return -errno;
 254        return 0;
 255}
 256
 257int os_read_file(int fd, void *buf, int len)
 258{
 259        int n = read(fd, buf, len);
 260
 261        if (n < 0)
 262                return -errno;
 263        return n;
 264}
 265
 266int os_write_file(int fd, const void *buf, int len)
 267{
 268        int n = write(fd, (void *) buf, len);
 269
 270        if (n < 0)
 271                return -errno;
 272        return n;
 273}
 274
 275int os_sync_file(int fd)
 276{
 277        int n = fsync(fd);
 278
 279        if (n < 0)
 280                return -errno;
 281        return n;
 282}
 283
 284int os_file_size(const char *file, unsigned long long *size_out)
 285{
 286        struct uml_stat buf;
 287        int err;
 288
 289        err = os_stat_file(file, &buf);
 290        if (err < 0) {
 291                printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
 292                       -err);
 293                return err;
 294        }
 295
 296        if (S_ISBLK(buf.ust_mode)) {
 297                int fd;
 298                long blocks;
 299
 300                fd = open(file, O_RDONLY, 0);
 301                if (fd < 0) {
 302                        err = -errno;
 303                        printk(UM_KERN_ERR "Couldn't open \"%s\", "
 304                               "errno = %d\n", file, errno);
 305                        return err;
 306                }
 307                if (ioctl(fd, BLKGETSIZE, &blocks) < 0) {
 308                        err = -errno;
 309                        printk(UM_KERN_ERR "Couldn't get the block size of "
 310                               "\"%s\", errno = %d\n", file, errno);
 311                        close(fd);
 312                        return err;
 313                }
 314                *size_out = ((long long) blocks) * 512;
 315                close(fd);
 316        }
 317        else *size_out = buf.ust_size;
 318
 319        return 0;
 320}
 321
 322int os_file_modtime(const char *file, unsigned long *modtime)
 323{
 324        struct uml_stat buf;
 325        int err;
 326
 327        err = os_stat_file(file, &buf);
 328        if (err < 0) {
 329                printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
 330                       -err);
 331                return err;
 332        }
 333
 334        *modtime = buf.ust_mtime;
 335        return 0;
 336}
 337
 338int os_set_exec_close(int fd)
 339{
 340        int err;
 341
 342        CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
 343
 344        if (err < 0)
 345                return -errno;
 346        return err;
 347}
 348
 349int os_pipe(int *fds, int stream, int close_on_exec)
 350{
 351        int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
 352
 353        err = socketpair(AF_UNIX, type, 0, fds);
 354        if (err < 0)
 355                return -errno;
 356
 357        if (!close_on_exec)
 358                return 0;
 359
 360        err = os_set_exec_close(fds[0]);
 361        if (err < 0)
 362                goto error;
 363
 364        err = os_set_exec_close(fds[1]);
 365        if (err < 0)
 366                goto error;
 367
 368        return 0;
 369
 370 error:
 371        printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n",
 372               -err);
 373        close(fds[1]);
 374        close(fds[0]);
 375        return err;
 376}
 377
 378int os_set_fd_async(int fd)
 379{
 380        int err, flags;
 381
 382        flags = fcntl(fd, F_GETFL);
 383        if (flags < 0)
 384                return -errno;
 385
 386        flags |= O_ASYNC | O_NONBLOCK;
 387        if (fcntl(fd, F_SETFL, flags) < 0) {
 388                err = -errno;
 389                printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC "
 390                       "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
 391                return err;
 392        }
 393
 394        if ((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
 395            (fcntl(fd, F_SETOWN, os_getpid()) < 0)) {
 396                err = -errno;
 397                printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN "
 398                       "(or F_SETSIG) fd %d, errno = %d\n", fd, errno);
 399                return err;
 400        }
 401
 402        return 0;
 403}
 404
 405int os_clear_fd_async(int fd)
 406{
 407        int flags;
 408
 409        flags = fcntl(fd, F_GETFL);
 410        if (flags < 0)
 411                return -errno;
 412
 413        flags &= ~(O_ASYNC | O_NONBLOCK);
 414        if (fcntl(fd, F_SETFL, flags) < 0)
 415                return -errno;
 416        return 0;
 417}
 418
 419int os_set_fd_block(int fd, int blocking)
 420{
 421        int flags;
 422
 423        flags = fcntl(fd, F_GETFL);
 424        if (flags < 0)
 425                return -errno;
 426
 427        if (blocking)
 428                flags &= ~O_NONBLOCK;
 429        else
 430                flags |= O_NONBLOCK;
 431
 432        if (fcntl(fd, F_SETFL, flags) < 0)
 433                return -errno;
 434
 435        return 0;
 436}
 437
 438int os_accept_connection(int fd)
 439{
 440        int new;
 441
 442        new = accept(fd, NULL, 0);
 443        if (new < 0)
 444                return -errno;
 445        return new;
 446}
 447
 448#ifndef SHUT_RD
 449#define SHUT_RD 0
 450#endif
 451
 452#ifndef SHUT_WR
 453#define SHUT_WR 1
 454#endif
 455
 456#ifndef SHUT_RDWR
 457#define SHUT_RDWR 2
 458#endif
 459
 460int os_shutdown_socket(int fd, int r, int w)
 461{
 462        int what, err;
 463
 464        if (r && w)
 465                what = SHUT_RDWR;
 466        else if (r)
 467                what = SHUT_RD;
 468        else if (w)
 469                what = SHUT_WR;
 470        else
 471                return -EINVAL;
 472
 473        err = shutdown(fd, what);
 474        if (err < 0)
 475                return -errno;
 476        return 0;
 477}
 478
 479int os_rcv_fd(int fd, int *helper_pid_out)
 480{
 481        int new, n;
 482        char buf[CMSG_SPACE(sizeof(new))];
 483        struct msghdr msg;
 484        struct cmsghdr *cmsg;
 485        struct iovec iov;
 486
 487        msg.msg_name = NULL;
 488        msg.msg_namelen = 0;
 489        iov = ((struct iovec) { .iov_base  = helper_pid_out,
 490                                .iov_len   = sizeof(*helper_pid_out) });
 491        msg.msg_iov = &iov;
 492        msg.msg_iovlen = 1;
 493        msg.msg_control = buf;
 494        msg.msg_controllen = sizeof(buf);
 495        msg.msg_flags = 0;
 496
 497        n = recvmsg(fd, &msg, 0);
 498        if (n < 0)
 499                return -errno;
 500        else if (n != iov.iov_len)
 501                *helper_pid_out = -1;
 502
 503        cmsg = CMSG_FIRSTHDR(&msg);
 504        if (cmsg == NULL) {
 505                printk(UM_KERN_ERR "rcv_fd didn't receive anything, "
 506                       "error = %d\n", errno);
 507                return -1;
 508        }
 509        if ((cmsg->cmsg_level != SOL_SOCKET) ||
 510            (cmsg->cmsg_type != SCM_RIGHTS)) {
 511                printk(UM_KERN_ERR "rcv_fd didn't receive a descriptor\n");
 512                return -1;
 513        }
 514
 515        new = ((int *) CMSG_DATA(cmsg))[0];
 516        return new;
 517}
 518
 519int os_create_unix_socket(const char *file, int len, int close_on_exec)
 520{
 521        struct sockaddr_un addr;
 522        int sock, err;
 523
 524        sock = socket(PF_UNIX, SOCK_DGRAM, 0);
 525        if (sock < 0)
 526                return -errno;
 527
 528        if (close_on_exec) {
 529                err = os_set_exec_close(sock);
 530                if (err < 0)
 531                        printk(UM_KERN_ERR "create_unix_socket : "
 532                               "close_on_exec failed, err = %d", -err);
 533        }
 534
 535        addr.sun_family = AF_UNIX;
 536
 537        snprintf(addr.sun_path, len, "%s", file);
 538
 539        err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
 540        if (err < 0)
 541                return -errno;
 542
 543        return sock;
 544}
 545
 546void os_flush_stdout(void)
 547{
 548        fflush(stdout);
 549}
 550
 551int os_lock_file(int fd, int excl)
 552{
 553        int type = excl ? F_WRLCK : F_RDLCK;
 554        struct flock lock = ((struct flock) { .l_type   = type,
 555                                              .l_whence = SEEK_SET,
 556                                              .l_start  = 0,
 557                                              .l_len    = 0 } );
 558        int err, save;
 559
 560        err = fcntl(fd, F_SETLK, &lock);
 561        if (!err)
 562                goto out;
 563
 564        save = -errno;
 565        err = fcntl(fd, F_GETLK, &lock);
 566        if (err) {
 567                err = -errno;
 568                goto out;
 569        }
 570
 571        printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n",
 572               lock.l_pid);
 573        err = save;
 574 out:
 575        return err;
 576}
 577
 578unsigned os_major(unsigned long long dev)
 579{
 580        return major(dev);
 581}
 582
 583unsigned os_minor(unsigned long long dev)
 584{
 585        return minor(dev);
 586}
 587
 588unsigned long long os_makedev(unsigned major, unsigned minor)
 589{
 590        return makedev(major, minor);
 591}
 592