Esempio n. 1
0
TError TMount::Find(TPath path, const TPath mounts) {

    path = path.NormalPath();
    auto device = path.GetDev();
    if (!device)
        return TError(EError::Unknown, "device not found: " + path.ToString() + ")");

    FILE* f = setmntent(mounts.c_str(), "r");
    if (!f)
        return TError(EError::Unknown, errno, "setmntent(" + mounts.ToString() + ")");

    struct mntent* m, mntbuf;
    TScopedMem buf(4096);
    TError error(EError::Unknown, "mountpoint not found: " + path.ToString() + ")");

    while ((m = getmntent_r(f, &mntbuf, (char *)buf.GetData(), buf.GetSize()))) {

        TPath source(m->mnt_fsname);
        TPath target(m->mnt_dir);

        if (target.InnerPath(path).IsEmpty() ||
                source.GetBlockDev() != device)
            continue;

        Source = source;
        Target = target;
        Type = m->mnt_type;
        Data.clear();
        error = SplitString(m->mnt_opts, ',', Data);
        break;
    }
    endmntent(f);

    return error;
}
Esempio n. 2
0
TError TMount::Move(TPath destination) {
    int ret = mount(Target.ToString().c_str(), destination.ToString().c_str(), NULL, MS_MOVE, NULL);
    if (ret)
        return TError(EError::Unknown, errno, "mount(" + Target.ToString() + ", " + destination.ToString() + ", MS_MOVE)");
    Target = destination;
    return TError::Success();
}
Esempio n. 3
0
TError TNamespaceFd::Open(TPath path) {
    Close();
    Fd = open(path.c_str(), O_RDONLY | O_NOCTTY | O_NONBLOCK | O_CLOEXEC);
    if (Fd < 0)
        return TError(EError::Unknown, errno, "Cannot open " + path.ToString());
    return TError::Success();
}
Esempio n. 4
0
TError TTask::ChildMountDev() {
    struct {
        const std::string path;
        unsigned int mode;
        unsigned int dev;
    } node[] = {
        { "/dev/null",    0666 | S_IFCHR, MKDEV(1, 3) },
        { "/dev/zero",    0666 | S_IFCHR, MKDEV(1, 5) },
        { "/dev/full",    0666 | S_IFCHR, MKDEV(1, 7) },
        { "/dev/random",  0666 | S_IFCHR, MKDEV(1, 8) },
        { "/dev/urandom", 0666 | S_IFCHR, MKDEV(1, 9) },
    };

    TMount dev("tmpfs", Env->Root + "/dev", "tmpfs", { "mode=755", "size=32m" });
    TError error = dev.MountDir(MS_NOSUID | MS_STRICTATIME);
    if (error)
        return error;

    TMount devpts("devpts", Env->Root + "/dev/pts", "devpts",
                  { "newinstance", "ptmxmode=0666", "mode=620" ,"gid=5" });
    error = devpts.MountDir(MS_NOSUID | MS_NOEXEC);
    if (error)
        return error;

    for (size_t i = 0; i < sizeof(node) / sizeof(node[0]); i++) {
        error = ChildCreateNode(Env->Root + node[i].path,
                           node[i].mode, node[i].dev);
        if (error)
            return error;
    }

    TPath ptmx = Env->Root + "/dev/ptmx";
    if (symlink("pts/ptmx", ptmx.ToString().c_str()) < 0)
        return TError(EError::Unknown, errno, "symlink(/dev/pts/ptmx)");

    TPath fd = Env->Root + "/dev/fd";
    if (symlink("/proc/self/fd", fd.ToString().c_str()) < 0)
        return TError(EError::Unknown, errno, "symlink(/dev/fd)");

    TFile f(Env->Root + "/dev/console", 0755);
    (void)f.Touch();

    return TError::Success();
}
Esempio n. 5
0
std::string ReadLink(const std::string &path) {
    TPath lnk;

    TPath f(path);
    TError error = f.ReadLink(lnk);
    if (error)
        throw error.GetMsg();

    return lnk.ToString();
}
Esempio n. 6
0
TError TTask::ChildOpenStdFile(const TPath &path, int expected) {
    int ret = open(path.ToString().c_str(), O_CREAT | O_WRONLY | O_APPEND, 0660);
    if (ret < 0)
        return TError(EError::InvalidValue, errno,
                      "open(" + path.ToString() + ") -> " +
                      std::to_string(expected));

    if (ret != expected)
        return TError(EError::Unknown, EINVAL,
                      "open(" + path.ToString() + ") -> " +
                      std::to_string(expected) + ": unexpected fd " +
                      std::to_string(ret));

    ret = fchown(ret, Env->Cred.Uid, Env->Cred.Gid);
    if (ret < 0)
        return TError(EError::Unknown, errno,
                      "fchown(" + path.ToString() + ") -> " +
                      std::to_string(expected));

    return TError::Success();
}
Esempio n. 7
0
void BootstrapCommand(const std::string &cmd, const TPath &path, bool remove) {
    if (remove)
        (void)path.RemoveAll();

    vector<string> lines;
    ExpectSuccess(Popen("ldd " + cmd, lines));

    for (auto &line : lines) {
        vector<string> tokens;
        TError error = SplitString(line, ' ', tokens);
        if (error)
            throw error.GetMsg();

        TPath from;
        string name;
        if (tokens.size() == 2) {
            from = StringTrim(tokens[0]);
            TPath p(tokens[0]);
            name = p.BaseName();
        } else if (tokens.size() == 4) {
            if (tokens[2] == "")
                continue;

            from = StringTrim(tokens[2]);
            name = StringTrim(tokens[0]);
        } else {
            continue;
        }

        TPath dest = path / from.DirName();
        if (!dest.Exists()) {
            error = dest.MkdirAll(0755);
            if (error)
                throw error.GetMsg();
        }

        Expect(system(("cp " + from.ToString() + " " + dest.ToString() + "/" + name).c_str()) == 0);
    }
    Expect(system(("cp " + cmd + " " + path.ToString()).c_str()) == 0);
}
Esempio n. 8
0
TError TTask::CreateTmpDir(const TPath &path, std::shared_ptr<TFolder> &dir) const {
    bool cleanup = path.ToString().find(config().container().tmp_dir()) == 0;

    dir = std::make_shared<TFolder>(path, cleanup);
    if (!dir->Exists()) {
        TError error = dir->Create(0755, true);
        if (error)
            return error;
        error = path.Chown(Env->Cred.Uid, Env->Cred.Gid);
        if (error)
            return error;
    }

    return TError::Success();
}
Esempio n. 9
0
TError TMount::Snapshot(std::vector<std::shared_ptr<TMount>> &result, const TPath mounts) {
    FILE* f = setmntent(mounts.c_str(), "r");
    if (!f)
        return TError(EError::Unknown, errno, "setmntent(" + mounts.ToString() + ")");

    struct mntent* m, mntbuf;
    TScopedMem buf(4096);
    while ((m = getmntent_r(f, &mntbuf, (char *)buf.GetData(), buf.GetSize()))) {
        vector<string> flags;
        TError error = SplitString(m->mnt_opts, ',', flags);
        if (error) {
            endmntent(f);
            return error;
        }
        result.push_back(std::make_shared<TMount>(m->mnt_fsname, m->mnt_dir, m->mnt_type, flags));
    }
    endmntent(f);
    return TError::Success();
}
Esempio n. 10
0
TError TTask::ChildCreateNode(const TPath &path, unsigned int mode, unsigned int dev) {
    if (mknod(path.ToString().c_str(), mode, dev) < 0)
        return TError(EError::Unknown, errno, "mknod(" + path.ToString() + ")");

    return TError::Success();
}
Esempio n. 11
0
TError SetupLoopDevice(TPath image, int &dev)
{
    static std::mutex BigLoopLock;
    int control_fd, image_fd, loop_nr, loop_fd;
    struct loop_info64 info;
    std::string loop;
    int retry = 10;
    TError error;

    image_fd = open(image.c_str(), O_RDWR | O_CLOEXEC);
    if (image_fd < 0) {
        error = TError(EError::Unknown, errno, "open(" + image.ToString() + ")");
        goto err_image;
    }

    control_fd = open("/dev/loop-control", O_RDWR | O_CLOEXEC);
    if (control_fd < 0) {
        error = TError(EError::Unknown, errno, "open(/dev/loop-control)");
        goto err_control;
    }

    BigLoopLock.lock();

again:
    loop_nr = ioctl(control_fd, LOOP_CTL_GET_FREE);
    if (loop_nr < 0) {
        error = TError(EError::Unknown, errno, "ioctl(LOOP_CTL_GET_FREE)");
        goto err_get_free;
    }

    loop = "/dev/loop" + std::to_string(loop_nr);
    loop_fd = open(loop.c_str(), O_RDWR | O_CLOEXEC);
    if (loop_fd < 0) {
        error = TError(EError::Unknown, errno, "open(" + loop + ")");
        goto err_loop_open;
    }

    if (ioctl(loop_fd, LOOP_SET_FD, image_fd) < 0) {
        error = TError(EError::Unknown, errno, "ioctl(LOOP_SET_FD)");
        if (errno == EBUSY) {
            if (!ioctl(loop_fd, LOOP_GET_STATUS64, &info) || errno == ENXIO) {
                if (--retry > 0) {
                    close(loop_fd);
                    goto again;
                }
            }
        }
        goto err_set_fd;
    }

    memset(&info, 0, sizeof(info));
    strncpy((char *)info.lo_file_name, image.c_str(), LO_NAME_SIZE);

    if (ioctl(loop_fd, LOOP_SET_STATUS64, &info) < 0) {
        error = TError(EError::Unknown, errno, "ioctl(LOOP_SET_STATUS64)");
        ioctl(loop_fd, LOOP_CLR_FD, 0);
        goto err_set_status;
    }

    dev = loop_nr;
    error = TError::Success();
err_set_status:
err_set_fd:
    close(loop_fd);
err_loop_open:
err_get_free:
    BigLoopLock.unlock();
    close(control_fd);
err_control:
    close(image_fd);
err_image:
    return error;
}
Esempio n. 12
0
TError TMount::Remount(TPath path, unsigned long flags) {
    if (mount(NULL, path.c_str(), NULL, flags, NULL))
        return TError(EError::Unknown, errno, "mount(NULL, " + path.ToString() + ", NULL, " + std::to_string(flags) + ", NULL)");
    return TError::Success();
}
Esempio n. 13
0
 friend bool operator>(const TPath& a, const TPath& b) {
     return a.ToString() > b.ToString();
 }
Esempio n. 14
0
 friend bool operator!=(const TPath& a, const TPath& b) {
     return a.ToString() != b.ToString();
 }
Esempio n. 15
0
 TPath operator+(const TPath &p) const {
     return TPath(Path + p.ToString());
 }