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; }
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]; }
static void timeout (int) { char msg[] = "lost a timecb\n"; rc_ignore (write (2, msg, sizeof (msg) - 1)); abort (); }
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); }
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; } }
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); } } }
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; }
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); } }