Beispiel #1
0
void
aiosrv::pathop (aiomsg_t msg)
{
  static int fd = -1;
  aiod_pathop *rq = buf->Xtmpl getptr<aiod_pathop> (msg);
  errno = 0;
  switch (rq->op) {
  case AIOD_UNLINK:
    unlink (rq->path1 ());
    break;
  case AIOD_LINK:
    rc_ignore (link (rq->path1 (), rq->path2 ()));
    break;
  case AIOD_SYMLINK:
    rc_ignore (symlink (rq->path1 (), rq->path2 ()));
    break;
  case AIOD_RENAME:
    rename (rq->path1 (), rq->path2 ());
    break;
  case AIOD_READLINK:
    rq->bufsize = readlink (rq->path1 (), rq->pathbuf, rq->bufsize);
    break;
  case AIOD_GETCWD:
    // XXX - shouldn't need to chdir... just write our own getcwd-like func.
    if ((fd >= 0 || (fd = open (".", O_RDONLY)) >= 0)
	&& chdir (rq->path1 ()) >= 0) {
      if (getcwd (rq->pathbuf, rq->bufsize))
	errno = 0;
      else if (!errno)
	errno = EINVAL;
      if (fchdir (fd))
	warn ("fchdir: %m\n");
    }
    break;
  case AIOD_STAT:
    stat (rq->path1 (), rq->statbuf ());
    break;
  case AIOD_LSTAT:
    lstat (rq->path1 (), rq->statbuf ());
    break;
  case AIOD_STATVFS: 
    {
      str s = rq->path1 ();
      int rc = statvfs (s, rq->statvfsbuf ());
      if (rc != 0) {
	warn ("statvfs('%s') failed: %m\n", s.cstr ());
      } else {
	errno = 0; /* statvfs sets errno even if no error .. */
      }
    }
    break;
  default:
    panic ("aiosrv::pathop: bad op %d\n", rq->op);
    break;
  }
  if (errno)
    rq->err = errno;
}
Beispiel #2
0
int
noise_from_prog::execprog (const char *const *av)
{
  int fds[2];
  if (pipe (fds) < 0)
    fatal ("pipe: %m\n");
  pid = afork ();

  if (!pid) {
    close (fds[0]);
    if (fds[1] != 1)
      dup2 (fds[1], 1);
    if (fds[1] != 2)
      dup2 (fds[1], 2);
    if (fds[1] != 1 && fds[1] != 2)
      close (fds[1]);
    close (0);
    rc_ignore (chdir ("/"));
    open ("/dev/null", O_RDONLY);

    char *env[] = { NULL };
    execve (av[0], const_cast<char *const *> (av), env);
    //warn ("%s: %m\n", av[0]);
    _exit (1);
  }

  close (fds[1]);
  close_on_exec (fds[0]);
  return fds[0];
}
Beispiel #3
0
static void
timeout (int)
{
  char msg[] = "lost a timecb\n";
  rc_ignore (write (2, msg, sizeof (msg) - 1));
  abort ();
}
Beispiel #4
0
str
agent_userdir (u_int32_t uid, bool create)
{
  int fd = open (".", O_RDONLY);
  if (fd < 0) {
    warn ("current working directory (.): %m\n");
    return NULL;
  }

  const char *tmpdir = safegetenv ("TMPDIR");
  if (!tmpdir || tmpdir[0] != '/')
    tmpdir = "/tmp";
  
  str ret;
  struct stat sb;
  uid_t myuid = getuid ();

  if (chdir (tmpdir) < 0)
    warn ("%s: %m\n", tmpdir);
  else if (stat (".", &sb) < 0)
    warn ("%s: %m\n", tmpdir);
  else if ((sb.st_mode & 022) && !(sb.st_mode & 01000))
    warn ("bad permissions on %s; chmod +t or set TMPDIR elsewhere", tmpdir);
  else if (myuid == uid)
    ret = agent_userdir_search (tmpdir, uid, create);
  else if (!myuid) {
    int fds[2];
    if (pipe (fds) < 0)
      warn ("pipe: %m\n");
    else if (pid_t pid = afork ()) {
      close (fds[1]);
      strbuf sb;
      while (sb.tosuio ()->input (fds[0]) > 0)
	;
      close (fds[0]);
      int status = 1;
      if (!waitpid (pid, &status, 0) && !status)
	ret = sb;
    }
    else {
      close (fds[0]);
      _exit (setuid (uid)
	     || !(ret = agent_userdir_search (tmpdir, uid, create))
	     || (write (fds[1], ret, ret.len ())
	         != implicit_cast<ssize_t> (ret.len ())));
    }
  }

  rc_ignore (fchdir (fd));
  close (fd);
  return ret ? str (strbuf ("%s/", tmpdir) << ret) : str (NULL);
}
Beispiel #5
0
void
aiosrv::mkdir (aiomsg_t msg)
{
  errno = 0;
  aiod_mkdirop *rq = buf->Xtmpl getptr<aiod_mkdirop> (msg);
  switch (rq->op) {
  case AIOD_MKDIR:
    rc_ignore (::mkdir (rq->path (), rq->mode));
    break;
  default:
    panic ("aiosrv::mkdir: bad op %d\n", rq->op);
    break;
  }
  if (errno) {
    str s = rq->path ();
    // warn ("mkdir(%s,%d) failed: %m\n", s.cstr (), rq->mode);
    rq->err = errno;
  }
}
Beispiel #6
0
void
sfsconst_init (bool lite_mode)
{
  if (const_set)
    return;
  const_set = true;

  {
    char *p = safegetenv ("SFS_RELEASE");
    if (!p || !convertint (p, &sfs_release)) {
      str rel (strbuf () << "SFS_RELEASE=" << sfs_release);
      xputenv (const_cast<char*>(rel.cstr()));
    }
  }

#ifdef MAINTAINER
  if (char *p = safegetenv ("SFS_RUNINPLACE")) {
    runinplace = true;
    builddir = p;
    buildtmpdir = builddir << "/runinplace";
  }
  if (char *p = safegetenv ("SFS_ROOT"))
    if (*p == '/')
      sfsroot = p;
#endif /* MAINTAINER */
  sfsdevdb = strbuf ("%s/.devdb", sfsroot);

#ifdef MAINTAINER
  if (runinplace) {
    sfsdir = buildtmpdir;
    sfssockdir = sfsdir;
    etc3dir = etc1dir;
    etc1dir = sfsdir.cstr();
    etc2dir = xstrdup (str (builddir << "/etc"));
  }
#endif /* MAINTAINER */
  if (char *ps = safegetenv ("SFS_PORT"))
    if (int pv = atoi (ps))
      sfs_defport = pv;

  str sfs_config = safegetenv ("SFS_CONFIG");
  if (sfs_config && sfs_config[0] == '/') {
    if (!parseconfig (NULL, sfs_config))
      fatal << sfs_config << ": " << strerror (errno) << "\n";
  }
  else {
    if (!parseconfig (etc3dir, sfs_config)) {
      parseconfig (etc3dir, "sfs_config");
      if (!parseconfig (etc2dir, sfs_config)) {
	parseconfig (etc2dir, "sfs_config");
	if (!parseconfig (etc1dir, sfs_config)) 
	  parseconfig (etc1dir, "sfs_config");
      }
    }
  }

  if (!lite_mode) {
    if (!sfs_uid)
      idlookup (NULL, NULL);
  }

  if (char *p = getenv ("SFS_HASHCOST")) {
    sfs_hashcost = strtoi64 (p);
    if (sfs_hashcost > sfs_maxhashcost)
      sfs_hashcost = sfs_maxhashcost;
  }

  if (!getuid () && !runinplace) {
    mksfsdir (sfsdir, 0755);
    mksfsdir (sfssockdir, 0750);
  }
  else if (runinplace && access (sfsdir, 0) < 0) {
    struct stat sb;
    if (!stat (builddir, &sb)) {
      mode_t m = umask (0);
      if (!getuid ()) {
	if (pid_t pid = fork ())
	  waitpid (pid, NULL, 0);
	else {
	  umask (0);
	  setgid (sfs_gid);
	  setuid (sb.st_uid);
	  if (mkdir (sfsdir, 02770) >= 0)
	    rc_ignore (chown (sfsdir, (uid_t) -1, sfs_gid));
	  _exit (0);
	}
      }
      else
	mkdir (sfsdir, 0777);
      umask (m);
    }
  }
}
Beispiel #7
0
void
aiosrv::fhop (aiomsg_t msg)
{
  aiod_fhop *rq = buf->Xtmpl getptr<aiod_fhop> (msg);
  aiod_file *af = buf->Xtmpl getptr<aiod_file> (rq->fh);

  if (rq->op == AIOD_OPEN) {
    fht.create (af, rq->mode, &rq->err);
    return;
  }
  if (rq->op == AIOD_CLOSE) {
    fht.close (af, &rq->err);
    return;
  }

  int fd = fht.lookup (af, &rq->err);
  if (fd < 0)
    return;

  errno = 0;
  switch (rq->op) {
  case AIOD_FSYNC:
    fsync (fd);
    break;
  case AIOD_FTRUNC:
    rc_ignore (ftruncate (fd, rq->length));
    break;
  case AIOD_READ:
#ifdef HAVE_PREAD
    if (rq->iobuf.pos == -1)
      rq->iobuf.len = read (fd, buf->getbuf (&rq->iobuf), rq->iobuf.len);
    else
      rq->iobuf.len = pread (fd, buf->getbuf (&rq->iobuf), rq->iobuf.len,
			     rq->iobuf.pos);
#else /* !HAVE_PREAD */
    if (rq->iobuf.pos == -1 || lseek (fd, rq->iobuf.pos, SEEK_SET) != -1)
      rq->iobuf.len = read (fd, buf->getbuf (&rq->iobuf), rq->iobuf.len);
    else
      rq->iobuf.len = -1;
#endif /* !HAVE_PREAD */
    break;
  case AIOD_WRITE:
#ifdef HAVE_PWRITE
    if (rq->iobuf.pos == -1)
      rq->iobuf.len = write (fd, buf->getbuf (&rq->iobuf), rq->iobuf.len);
    else
      rq->iobuf.len = pwrite (fd, buf->getbuf (&rq->iobuf), rq->iobuf.len,
			      rq->iobuf.pos);
#else /* !HAVE_PWRITE */
    if (rq->iobuf.pos == -1 || lseek (fd, rq->iobuf.pos, SEEK_SET) != -1)
      rq->iobuf.len = write (fd, buf->getbuf (&rq->iobuf), rq->iobuf.len);
    else
      rq->iobuf.len = -1;
#endif /* !HAVE_PWRITE */
    break;
  default:
    panic ("aiosrv::fhop: bad op %d\n", rq->op);
    break;
  }
  if (errno)
    rq->err = errno;
}
Beispiel #8
0
void
hclient_t::do_read ()
{
  int rc = uio.input (fd);
  if (rc == 0 && !output_stuff) {
    stats.empties ++;
    warn ("no content before EOF\n");
    cexit (-1);
    return;;
  } else if (rc == 0) {
    // legitimate EOF
    cexit (0);
    return;
  } else if (rc == -1) {
    if (errno != EAGAIN) {
      stats.read_errors ++ ;
      warn ("read error: %m\n");
      cexit (-1);
    }
    return;
  }

  assert (rc > 0);

  // for sane Web servers, this is easy...
  if (mode != SEDA) {
    while (uio.resid ()) {
      output_stuff = true;
      uio.output (1);
    }
    return;
  }

  //
  // for SEDA, we've had to parse the header and cut off the
  // connection, since it doesn't support closed connections
  // as we've asked.
  //
  rc = uio.copyout (bp);
  uio.rembytes (rc);
  bp += rc;
  
  //
  // reqsz < 0 if we haven't found a field yet in the header
  //
  if (reqsz < 0) {
    if (sz_rxx.search (buf)) {
      if (!convertint (sz_rxx[1], &reqsz)) {
	warn ("invalid length: %s\n", sz_rxx[1].cstr ());
	cexit (-1);
      }
    }
  }
  if (!body) 
    body = strstr (buf, "\r\n\r\n");
  
  //
  // if we've seen the required number of bytes (as given by
  // the header) then we're ready to close (or rock!)
  //
  if (body && (bp - body >= reqsz)) {
    rc_ignore (write (1, buf, bp - buf));
    if (noisy) warn ("ok, closing up!\n");
    cexit (0);
  }
}