Example #1
0
/*
 * Emulate futimes() via futime()
 */
int
futimes(int fd, const struct timeval *times)
{
    if (times != NULL) {
	struct utimbuf utb;

	utb.actime = (time_t)(times[0].tv_sec + times[0].tv_usec / 1000000);
	utb.modtime = (time_t)(times[1].tv_sec + times[1].tv_usec / 1000000);
	return futime(fd, &utb);
    } else
	return futime(fd, NULL);
}
Example #2
0
File: utime.c Project: mmcx/cegcc
int
utime(const char *fname, struct utimbuf *times)
{
  int fd;
  int retval;
  if ((fd = open(fname, O_RDWR)) < 0)
    return (-1);
  retval = futime(fd, times);
  close(fd);
  return(retval);
}
Example #3
0
File: cp.c Project: HarryR/sanos
static int copy_file(char *src, char *dest, struct options *opts) {
  int fin;
  int fout;
  struct stat st;
  char *buffer;
  int n;

  // Refuse to copy file unto itself
  if (!opts->force && strcmp(src, dest) == 0) {
    fprintf(stderr, "%s: cannot copy file unto itself\n");
    return 1;
  }

  // Open source file
  fin = open(src, O_RDONLY | O_BINARY);
  if (fin < 0  || fstat(fin, &st) < 0) {
    perror(src);
    return 1;
  }
  
  // If source is a directory copy recursively if requested
  if (S_ISDIR(st.st_mode)) {
    close(fin);
    if (opts->recurse) {
      return copy_directory(src, dest, opts);
    } else {
      errno = EISDIR;
      perror(src);
      return 1;
    }
  }

  // Copy source file to destination
  if (opts->verbose) printf("%s -> %s\n", src, dest);
  if (opts->force) unlink(dest);
  fout = open(dest, O_WRONLY | O_CREAT | (opts->noclobber ? O_EXCL : O_TRUNC) | O_BINARY, 0666);
  buffer = malloc(BLKSIZE);
  if (fout < 0 || !buffer) {
    perror(dest);
    close(fin);
    return 1;
  }
  while ((n = read(fin, buffer, BLKSIZE)) != 0) {
    if (n < 0) {
      perror(src);
      break;
    }
    if (write(fout, buffer, n) != n) {
      perror(dest);
      break;
    }
  }
  fchmod(fout, st.st_mode);

  if (opts->preserve) {
    struct utimbuf times;
    times.modtime = st.st_mtime;
    times.actime = st.st_atime;
    times.ctime = -1;
    futime(fout, &times);
    fchown(fout, st.st_uid, st.st_gid);
  }

  free(buffer);
  close(fin);
  close(fout);

  return n;
}
Example #4
0
File: pkg.c Project: HarryR/sanos
static int extract_files(char *url, FILE *f, char *manifest, int verbose, int *time) {
  unsigned char buffer[TAR_BLKSIZ];
  unsigned char fn[FILENAME_MAX];
  struct tarhdr *hdr;
  unsigned int checksum;
  int n, size, left, mode, first, zeroblks;
  struct utimbuf times;
  char *slash;
  int fd;

  zeroblks = 0;
  first = 1;
  while (!feof(f)) {
    // Read next tar header
    if (fread(buffer, 1, TAR_BLKSIZ, f) != TAR_BLKSIZ) {
      fprintf(stderr, "%s: tar archive truncated\n", url);
      return 1;
    }
    hdr = (struct tarhdr *) buffer;

    // Two all-zero blocks marks the end of the archive
    if (hdr->name[0] == 0) {
      if (++zeroblks == 2) break;
      continue;
    }
    zeroblks = 0;

    // Check tar header integrity
    if (memcmp(hdr->magic, "ustar ", 6) != 0) {
      fprintf(stderr, "%s: invalid tar header (%s)\n", url, hdr->magic);
      return 1;
    }
    checksum = parse_octal(hdr->chksum, 6);
    memcpy(hdr->chksum, "        ", 8);
    if (buffersum(buffer, TAR_BLKSIZ) != checksum) {
      fprintf(stderr, "%s: corrupted tar file\n", url);
      return 1;
    }

    // Get file information
    strcpy(fn, "/");
    strcat(fn, hdr->name);
    mode = parse_octal(hdr->mode, 7);
    size = parse_octal(hdr->size, 11);
    times.modtime = parse_octal(hdr->mtime, 11);
    times.actime = -1;
    times.ctime = -1;
    if (verbose) printf("extracting '%s' size: %d mode: %o\n", fn, size, mode);
    if (times.modtime > *time) *time = times.modtime;

    if (hdr->typeflag == DIRTYPE) {
      // Create directory
      if (make_directory(fn, mode) < 0) {
        perror(fn);
        return 1;
      }
    } else if (hdr->typeflag == REGTYPE || hdr->typeflag == AREGTYPE)  {
      // Make sure target directory exists
      slash = strrchr(fn, '/');
      if (slash && slash != fn) {
        *slash = 0;
        if (make_directory(fn, mode) < 0) {
          perror(fn);
          return 1;
        }
        *slash = '/';
      }

      // Extract file
      fd = open(fn, O_CREAT | O_TRUNC, mode);
      if (fd < 0) {
        perror(fn);
        return 1;
      }
      left = size;
      while (left > 0) {
        n = fread(buffer, 1, TAR_BLKSIZ, f);
        if (n != TAR_BLKSIZ) {
          fprintf(stderr, "%s: tar archive truncated (%s)\n", url, fn);
          close(fd);
          unlink(fn);
          return 1;
        }
        if (write(fd, buffer, n > left ? left : n) < 0) {
          perror(fn);
          close(fd);
          unlink(fn);
          return 1;
        }
        left -= n;
      }

      futime(fd, &times);
      fchmod(fd, mode);
      close(fd);

      if (first) {
        strcpy(manifest, fn);
        first = 0;
      }
    } else {
      fprintf(stderr, "ignoring %s (type %c)\n", fn, hdr->typeflag);
    }
  }

  return 0;
}
Example #5
0
static void * worker_thread_handler(void * x) {
    WorkerThread * wt = (WorkerThread *)x;

    for (;;) {
        AsyncReqInfo * req = wt->req;

        assert(req != NULL);
        req->error = 0;
        switch(req->type) {
        case AsyncReqTimer:
#if defined(_WIN32) && !defined(__CYGWIN__)
            Sleep(EVENTS_TIMER_RESOLUTION);
            events_timer_ms = GetTickCount();
#else
            {
                struct timespec timenow;
                usleep(EVENTS_TIMER_RESOLUTION * 1000);
                if (clock_gettime(CLOCK_REALTIME, &timenow) == 0) {
                    events_timer_ms = (uint32_t)(timenow.tv_nsec / 1000000 + timenow.tv_sec * 1000);
                }
            }
#endif
            break;

        case AsyncReqRead:              /* File read */
            req->u.fio.rval = read(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz);
            if (req->u.fio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
            break;

        case AsyncReqWrite:             /* File write */
            req->u.fio.rval = write(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz);
            if (req->u.fio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
            break;

        case AsyncReqSeekRead:          /* File read at offset */
            req->u.fio.rval = pread(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz, (off_t)req->u.fio.offset);
            if (req->u.fio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
            break;

        case AsyncReqSeekWrite:         /* File write at offset */
            req->u.fio.rval = pwrite(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz, (off_t)req->u.fio.offset);
            if (req->u.fio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
            break;

        case AsyncReqRecv:              /* Socket recv */
            req->u.sio.rval = recv(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags);
            if (req->u.sio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
            break;

        case AsyncReqSend:              /* Socket send */
            req->u.sio.rval = send(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags);
            if (req->u.sio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
            break;

        case AsyncReqRecvFrom:          /* Socket recvfrom */
            req->u.sio.rval = recvfrom(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags, req->u.sio.addr, &req->u.sio.addrlen);
            if (req->u.sio.rval == -1) {
                req->error = errno;
                trace(LOG_ASYNCREQ, "AsyncReqRecvFrom: req %p, type %d, error %d", req, req->type, req->error);
                assert(req->error);
            }
            break;

        case AsyncReqSendTo:            /* Socket sendto */
            req->u.sio.rval = sendto(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags, req->u.sio.addr, req->u.sio.addrlen);
            if (req->u.sio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
            break;

        case AsyncReqAccept:            /* Accept socket connections */
            req->u.acc.rval = accept(req->u.acc.sock, req->u.acc.addr, req->u.acc.addr ? &req->u.acc.addrlen : NULL);
            if (req->u.acc.rval == -1) {
                req->error = errno;
                trace(LOG_ASYNCREQ, "AsyncReqAccept: req %p, type %d, error %d", req, req->type, req->error);
                assert(req->error);
            }
            break;

        case AsyncReqConnect:           /* Connect to socket */
            req->u.con.rval = connect(req->u.con.sock, req->u.con.addr, req->u.con.addrlen);
            if (req->u.con.rval == -1) {
                req->error = errno;
                trace(LOG_ASYNCREQ, "AsyncReqConnect: req %p, type %d, error %d", req, req->type, req->error);
                assert(req->error);
            }
            break;

/* Platform dependant IO methods */
#if defined(_WIN32) || defined(__CYGWIN__)
        case AsyncReqConnectPipe:
            req->u.cnp.rval = ConnectNamedPipe(req->u.cnp.pipe, NULL);
            if (!req->u.cnp.rval) {
                req->error = set_win32_errno(GetLastError());
                assert(req->error);
            }
            break;
#elif defined(_WRS_KERNEL)
#else
        case AsyncReqWaitpid:           /* Wait for process change */
            req->u.wpid.rval = waitpid(req->u.wpid.pid, &req->u.wpid.status, req->u.wpid.options);
            if (req->u.wpid.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
            break;
#endif

        case AsyncReqSelect:
            {
                struct timeval tv;
                tv.tv_sec = (long)req->u.select.timeout.tv_sec;
                tv.tv_usec = req->u.select.timeout.tv_nsec / 1000;
                req->u.select.rval = select(req->u.select.nfds, &req->u.select.readfds,
                            &req->u.select.writefds, &req->u.select.errorfds, &tv);
                if (req->u.select.rval == -1) {
                    req->error = errno;
                    assert(req->error);
                }
            }
            break;

        case AsyncReqClose:
            req->u.fio.rval = close(req->u.fio.fd);
            if (req->u.fio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
            break;

        case AsyncReqCloseDir:
            req->u.dio.rval = closedir((DIR *)req->u.dio.dir);
            if (req->u.dio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
            break;

        case AsyncReqOpen:
            req->u.fio.rval = open(req->u.fio.file_name, req->u.fio.flags, req->u.fio.permission);
            if (req->u.fio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
            break;

        case AsyncReqOpenDir:
            req->u.dio.dir = opendir(req->u.dio.path);
            if (req->u.dio.dir == NULL) {
                req->error = errno;
                assert(req->error);
            }
            break;

        case AsyncReqFstat:
            memset(&req->u.fio.statbuf, 0, sizeof(req->u.fio.statbuf));
            req->u.fio.rval = fstat(req->u.fio.fd, &req->u.fio.statbuf);
            if (req->u.fio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
#if defined(_WIN32) || defined(__CYGWIN__)
            req->u.fio.win32_attrs = req->error || !req->u.fio.file_name ?
                INVALID_FILE_ATTRIBUTES : GetFileAttributes(req->u.fio.file_name);
#endif
            break;

        case AsyncReqStat:
            memset(&req->u.fio.statbuf, 0, sizeof(req->u.fio.statbuf));
            req->u.fio.rval = stat(req->u.fio.file_name, &req->u.fio.statbuf);
            if (req->u.fio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
#if defined(_WIN32) || defined(__CYGWIN__)
            req->u.fio.win32_attrs = req->error ?
                INVALID_FILE_ATTRIBUTES : GetFileAttributes(req->u.fio.file_name);
#endif
            break;

        case AsyncReqLstat:
            memset(&req->u.fio.statbuf, 0, sizeof(req->u.fio.statbuf));
            req->u.fio.rval = lstat(req->u.fio.file_name, &req->u.fio.statbuf);
            if (req->u.fio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
#if defined(_WIN32) || defined(__CYGWIN__)
            req->u.fio.win32_attrs = req->error ?
                INVALID_FILE_ATTRIBUTES : GetFileAttributes(req->u.fio.file_name);
#endif
            break;

        case AsyncReqSetStat:
            {
                int err = 0;
                if (req->u.fio.set_stat_flags & AsyncReqSetSize) {
                    if (truncate(req->u.fio.file_name, (off_t)req->u.fio.statbuf.st_size) < 0) err = errno;
                }
                if (req->u.fio.set_stat_flags & AsyncReqSetPermissions) {
                    if (chmod(req->u.fio.file_name, req->u.fio.statbuf.st_mode) < 0) err = errno;
                }
#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WRS_KERNEL)
#  if defined(_WIN32) || defined(__CYGWIN__)
                if (req->u.fio.win32_attrs != INVALID_FILE_ATTRIBUTES) {
                    if (SetFileAttributes(req->u.fio.file_name, req->u.fio.win32_attrs) == 0)
                        err = set_win32_errno(GetLastError());
                }
#  endif
#else
                if (req->u.fio.set_stat_flags & AsyncReqSetUidGid) {
                    if (chown(req->u.fio.file_name, req->u.fio.statbuf.st_uid, req->u.fio.statbuf.st_gid) < 0) err = errno;
                }
#endif
                if (req->u.fio.set_stat_flags & AsyncReqSetAcModTime) {
                    struct utimbuf buf;
                    buf.actime = req->u.fio.statbuf.st_atime;
                    buf.modtime = req->u.fio.statbuf.st_mtime;
                    if (utime(req->u.fio.file_name, &buf) < 0) err = errno;
                }
                req->error = err;
            }
            break;

        case AsyncReqFSetStat:
            {
                int err = 0;
                if (req->u.fio.set_stat_flags & AsyncReqSetSize) {
                    if (ftruncate(req->u.fio.fd, (off_t)req->u.fio.statbuf.st_size) < 0) err = errno;
                }
#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WRS_KERNEL)
                if (req->u.fio.set_stat_flags & AsyncReqSetPermissions) {
                    if (chmod(req->u.fio.file_name, req->u.fio.statbuf.st_mode) < 0) err = errno;
                }
#  if defined(_WIN32) || defined(__CYGWIN__)
                if (req->u.fio.win32_attrs != INVALID_FILE_ATTRIBUTES) {
                    if (SetFileAttributes(req->u.fio.file_name, req->u.fio.win32_attrs) == 0)
                        err = set_win32_errno(GetLastError());
                }
#  endif
#else
                if (req->u.fio.set_stat_flags & AsyncReqSetUidGid) {
                    if (fchown(req->u.fio.fd, req->u.fio.statbuf.st_uid, req->u.fio.statbuf.st_gid) < 0) err = errno;
                }
                if (req->u.fio.set_stat_flags & AsyncReqSetPermissions) {
                    if (fchmod(req->u.fio.fd, req->u.fio.statbuf.st_mode) < 0) err = errno;
                }
#endif
                if (req->u.fio.set_stat_flags & AsyncReqSetAcModTime) {
                    struct utimbuf buf;
                    buf.actime = req->u.fio.statbuf.st_atime;
                    buf.modtime = req->u.fio.statbuf.st_mtime;
#if defined(_WIN32) && !defined(__MINGW32__)
                    if (futime(req->u.fio.fd, &buf) < 0) err = errno;
#else
                    if (utime(req->u.fio.file_name, &buf) < 0) err = errno;
#endif
                }
                req->error = err;
            }
            break;

        case AsyncReqRemove:
            req->u.fio.rval = remove(req->u.fio.file_name);
            if (req->u.fio.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
            break;

        case AsyncReqReadDir:
            {
                int cnt = 0;
                while (cnt < req->u.dio.max_files) {
                    char path[FILE_PATH_SIZE];
                    struct DirFileNode * file = req->u.dio.files + cnt;
                    struct dirent * e;
                    struct stat st;
                    errno = 0;
                    e = readdir((DIR *)req->u.dio.dir);
                    if (e == NULL) {
                        req->error = errno;
                        if (req->error == 0) req->u.dio.eof = 1;
                        break;
                    }
                    if (strcmp(e->d_name, ".") == 0) continue;
                    if (strcmp(e->d_name, "..") == 0) continue;
                    file->path = loc_strdup(e->d_name);
                    memset(&st, 0, sizeof(st));
                    snprintf(path, sizeof(path), "%s/%s", req->u.dio.path, e->d_name);
                    if (stat(path, &st) == 0) {
#if defined(_WIN32) || defined(__CYGWIN__)
                        file->win32_attrs =  GetFileAttributes(path);
#endif
                        file->statbuf = (struct stat *)loc_alloc(sizeof(struct stat));
                        memcpy(file->statbuf, &st, sizeof(struct stat));
                    }
                    cnt++;
                }
            }
            break;

        case AsyncReqRoots:
            {
                struct stat st;
                struct RootDevNode * newDevNode = NULL;

#if defined(_WIN32) || defined(__CYGWIN__)
                {
                    struct RootDevNode * curDevNode = NULL;
                    int disk = 0;
                    DWORD disks = GetLogicalDrives();
                    for (disk = 0; disk <= 30; disk++) {
                        if (disks & (1 << disk)) {
                            char path[32];
                            newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode));
                            if (curDevNode == NULL) req->u.root.lst = newDevNode;
                            else curDevNode->next = newDevNode;
                            curDevNode = newDevNode;
                            snprintf(path, sizeof(path), "%c:\\", 'A' + disk);
                            newDevNode->devname = loc_strdup(path);
                            if (disk >= 2) {
                                ULARGE_INTEGER total_number_of_bytes;
                                BOOL has_size = GetDiskFreeSpaceExA(path, NULL, &total_number_of_bytes, NULL);
                                memset(&st, 0, sizeof(st));
#if defined(__CYGWIN__)
                                snprintf(path, sizeof(path), "/cygdrive/%c", 'a' + disk);
#endif
                                if (has_size && stat(path, &st) == 0) {
                                    newDevNode->win32_attrs =  GetFileAttributes(path);
                                    newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat));
                                    memcpy(newDevNode->statbuf, &st, sizeof(struct stat));
                                }
                            }
                        }
                    }
                }
#elif defined(_WRS_KERNEL)
                {
                    struct RootDevNode * curDevNode = NULL;
                    extern DL_LIST iosDvList;
                    DEV_HDR * dev;
                    for (dev = (DEV_HDR *)DLL_FIRST(&iosDvList); dev != NULL; dev = (DEV_HDR *)DLL_NEXT(&dev->node)) {
                        char path[FILE_PATH_SIZE];
                        if (strcmp(dev->name, "host:") == 0) {
                            /* Windows host is special case */
                            int d;
                            for (d = 'a'; d < 'z'; d++) {
                                snprintf(path, sizeof(path), "%s%c:/", dev->name, d);
                                if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) {
                                    newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode));
                                    if (curDevNode == NULL) req->u.root.lst = newDevNode;
                                    else curDevNode->next = newDevNode;
                                    curDevNode = newDevNode;

                                    newDevNode->devname = loc_strdup(path);
                                    newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat));
                                    memcpy(newDevNode->statbuf, &st, sizeof(struct stat));
                                }
                            }
                        }
                        snprintf(path, sizeof(path), "%s/", dev->name);
                        if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) {
                            newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode));
                            if (curDevNode == NULL) req->u.root.lst = newDevNode;
                            else curDevNode->next = newDevNode;
                            curDevNode = newDevNode;

                            newDevNode->devname = loc_strdup(path);
                            newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat));
                            memcpy(newDevNode->statbuf, &st, sizeof(struct stat));
                        }
                    }
                }
#else
                req->u.root.lst = newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode));
                newDevNode->devname = loc_strdup("/");
                if (stat("/", &st) == 0) {
                    newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat));
                    memcpy(newDevNode->statbuf, &st, sizeof(struct stat));
                }
#endif
            }
            break;

        case AsyncReqUser:              /* User defined request */
            req->u.user.rval = req->u.user.func(req->u.user.data);
            if (req->u.user.rval == -1) {
                req->error = errno;
                assert(req->error);
            }
            break;

        default:
            req->error = ENOSYS;
            break;
        }
        if (req->type == AsyncReqTimer) {
            if (async_shutdown.state == SHUTDOWN_STATE_PENDING) break;
            continue;
        }
        trace(LOG_ASYNCREQ, "async_req_complete: req %p, type %d, error %d", req, req->type, req->error);
        check_error(pthread_mutex_lock(&wtlock));
        /* Post event inside lock to make sure a new worker thread is not created unnecessarily */
        post_event(req->done, req);
        wt->req = NULL;
        if (wtlist_size >= MAX_WORKER_THREADS || async_shutdown.state == SHUTDOWN_STATE_PENDING) {
            check_error(pthread_mutex_unlock(&wtlock));
            break;
        }
        list_add_last(&wt->wtlink, &wtlist);
        wtlist_size++;
        for (;;) {
            check_error(pthread_cond_wait(&wt->cond, &wtlock));
            if (wt->req != NULL) break;
        }
        check_error(pthread_mutex_unlock(&wtlock));
        if (wt->req == &shutdown_req) break;
    }
    post_event(worker_thread_exit, wt);
    return NULL;
}