Exemplo n.º 1
0
static unsigned routes_max(void) {
        static thread_local unsigned cached = 0;

        _cleanup_free_ char *s4 = NULL, *s6 = NULL;
        unsigned val4 = ROUTES_DEFAULT_MAX_PER_FAMILY, val6 = ROUTES_DEFAULT_MAX_PER_FAMILY;

        if (cached > 0)
                return cached;

        if (sysctl_read("net/ipv4/route/max_size", &s4) >= 0) {
                truncate_nl(s4);
                if (safe_atou(s4, &val4) >= 0 &&
                    val4 == 2147483647U)
                        /* This is the default "no limit" value in the kernel */
                        val4 = ROUTES_DEFAULT_MAX_PER_FAMILY;
        }

        if (sysctl_read("net/ipv6/route/max_size", &s6) >= 0) {
                truncate_nl(s6);
                (void) safe_atou(s6, &val6);
        }

        cached = MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val4) +
                 MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val6);
        return cached;
}
Exemplo n.º 2
0
int read_hostname_config(const char *path, char **hostname) {
        _cleanup_fclose_ FILE *f = NULL;
        char l[LINE_MAX];
        char *name = NULL;

        assert(path);
        assert(hostname);

        f = fopen(path, "re");
        if (!f)
                return -errno;

        /* may have comments, ignore them */
        FOREACH_LINE(l, f, return -errno) {
                truncate_nl(l);
                if (l[0] != '\0' && l[0] != '#') {
                        /* found line with value */
                        name = hostname_cleanup(l);
                        name = strdup(name);
                        if (!name)
                                return -ENOMEM;
                        break;
                }
        }

        if (!name)
                /* no non-empty line found */
                return -ENOENT;

        *hostname = name;
        return 0;
}
Exemplo n.º 3
0
int clock_is_localtime(const char* adjtime_path) {
        _cleanup_fclose_ FILE *f;

        if (adjtime_path == NULL)
                adjtime_path = "/etc/adjtime";

        /*
         * The third line of adjtime is "UTC" or "LOCAL" or nothing.
         *   # /etc/adjtime
         *   0.0 0 0
         *   0
         *   UTC
         */
        f = fopen(adjtime_path, "re");
        if (f) {
                char line[LINE_MAX];
                bool b;

                b = fgets(line, sizeof(line), f) &&
                        fgets(line, sizeof(line), f) &&
                        fgets(line, sizeof(line), f);
                if (!b)
                        /* less than three lines -> default to UTC */
                        return 0;

                truncate_nl(line);
                return streq(line, "LOCAL");

        } else if (errno != ENOENT)
                return -errno;

        /* adjtime not present -> default to UTC */
        return 0;
}
Exemplo n.º 4
0
static int condition_test_capability(Condition *c) {
        _cleanup_fclose_ FILE *f = NULL;
        int value;
        char line[LINE_MAX];
        unsigned long long capabilities = -1;

        assert(c);
        assert(c->parameter);
        assert(c->type == CONDITION_CAPABILITY);

        /* If it's an invalid capability, we don't have it */
        value = capability_from_name(c->parameter);
        if (value < 0)
                return -EINVAL;

        /* If it's a valid capability we default to assume
         * that we have it */

        f = fopen("/proc/self/status", "re");
        if (!f)
                return -errno;

        while (fgets(line, sizeof(line), f)) {
                truncate_nl(line);

                if (startswith(line, "CapBnd:")) {
                        (void) sscanf(line+7, "%llx", &capabilities);
                        break;
                }
        }

        return !!(capabilities & (1ULL << value));
}
Exemplo n.º 5
0
int hwclock_is_localtime(void) {
    _cleanup_fclose_ FILE *f;

    /*
     * The third line of adjtime is "UTC" or "LOCAL" or nothing.
     *   # /etc/adjtime
     *   0.0 0 0
     *   0
     *   UTC
     */
    f = fopen("/etc/adjtime", "re");
    if (f) {
        char line[LINE_MAX];
        bool b;

        b = fgets(line, sizeof(line), f) &&
            fgets(line, sizeof(line), f) &&
            fgets(line, sizeof(line), f);
        if (!b)
            return -EIO;

        truncate_nl(line);
        return streq(line, "LOCAL");

    } else if (errno != ENOENT)
        return -errno;

    return 0;
}
Exemplo n.º 6
0
int read_one_line_file(const char *fn, char **line) {
        _cleanup_fclose_ FILE *f = NULL;
        char t[LINE_MAX], *c;

        assert(fn);
        assert(line);

        f = fopen(fn, "re");
        if (!f)
                return -errno;

        if (!fgets(t, sizeof(t), f)) {

                if (ferror(f))
                        return errno ? -errno : -EIO;

                t[0] = 0;
        }

        c = strdup(t);
        if (!c)
                return -ENOMEM;
        truncate_nl(c);

        *line = c;
        return 0;
}
Exemplo n.º 7
0
int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
        struct termios old_termios, new_termios;
        char c, line[LINE_MAX];

        assert(f);
        assert(ret);

        if (tcgetattr(fileno(f), &old_termios) >= 0) {
                new_termios = old_termios;

                new_termios.c_lflag &= ~ICANON;
                new_termios.c_cc[VMIN] = 1;
                new_termios.c_cc[VTIME] = 0;

                if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
                        size_t k;

                        if (t != USEC_INFINITY) {
                                if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
                                        tcsetattr(fileno(f), TCSADRAIN, &old_termios);
                                        return -ETIMEDOUT;
                                }
                        }

                        k = fread(&c, 1, 1, f);

                        tcsetattr(fileno(f), TCSADRAIN, &old_termios);

                        if (k <= 0)
                                return -EIO;

                        if (need_nl)
                                *need_nl = c != '\n';

                        *ret = c;
                        return 0;
                }
        }

        if (t != USEC_INFINITY) {
                if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
                        return -ETIMEDOUT;
        }

        errno = 0;
        if (!fgets(line, sizeof(line), f))
                return errno ? -errno : -EIO;

        truncate_nl(line);

        if (strlen(line) != 1)
                return -EBADMSG;

        if (need_nl)
                *need_nl = false;

        *ret = line[0];
        return 0;
}
Exemplo n.º 8
0
static int clean_sysvipc_shm(uid_t delete_uid) {
        _cleanup_fclose_ FILE *f = NULL;
        char line[LINE_MAX];
        bool first = true;
        int ret = 0;

        f = fopen("/proc/sysvipc/shm", "re");
        if (!f) {
                if (errno == ENOENT)
                        return 0;

                log_warning_errno(errno, "Failed to open /proc/sysvipc/shm: %m");
                return -errno;
        }

        FOREACH_LINE(line, f, goto fail) {
                unsigned n_attached;
                pid_t cpid, lpid;
                uid_t uid, cuid;
                gid_t gid, cgid;
                int shmid;

                if (first) {
                        first = false;
                        continue;
                }

                truncate_nl(line);

                if (sscanf(line, "%*i %i %*o %*u " PID_FMT " " PID_FMT " %u " UID_FMT " " GID_FMT " " UID_FMT " " GID_FMT,
                           &shmid, &cpid, &lpid, &n_attached, &uid, &gid, &cuid, &cgid) != 8)
                        continue;

                if (n_attached > 0)
                        continue;

                if (uid != delete_uid)
                        continue;

                if (shmctl(shmid, IPC_RMID, NULL) < 0) {

                        /* Ignore entries that are already deleted */
                        if (errno == EIDRM || errno == EINVAL)
                                continue;

                        ret = log_warning_errno(errno,
                                                "Failed to remove SysV shared memory segment %i: %m",
                                                shmid);
                }
        }

        return ret;

fail:
        log_warning_errno(errno, "Failed to read /proc/sysvipc/shm: %m");
        return -errno;
}
Exemplo n.º 9
0
static int clean_sysvipc_msg(uid_t delete_uid) {
        _cleanup_fclose_ FILE *f = NULL;
        char line[LINE_MAX];
        bool first = true;
        int ret = 0;

        f = fopen("/proc/sysvipc/msg", "re");
        if (!f) {
                if (errno == ENOENT)
                        return 0;

                log_warning_errno(errno, "Failed to open /proc/sysvipc/msg: %m");
                return -errno;
        }

        FOREACH_LINE(line, f, goto fail) {
                uid_t uid, cuid;
                gid_t gid, cgid;
                pid_t cpid, lpid;
                int msgid;

                if (first) {
                        first = false;
                        continue;
                }

                truncate_nl(line);

                if (sscanf(line, "%*i %i %*o %*u %*u " PID_FMT " " PID_FMT " " UID_FMT " " GID_FMT " " UID_FMT " " GID_FMT,
                           &msgid, &cpid, &lpid, &uid, &gid, &cuid, &cgid) != 7)
                        continue;

                if (uid != delete_uid)
                        continue;

                if (msgctl(msgid, IPC_RMID, NULL) < 0) {

                        /* Ignore entries that are already deleted */
                        if (errno == EIDRM || errno == EINVAL)
                                continue;

                        ret = log_warning_errno(errno,
                                                "Failed to remove SysV message queue %i: %m",
                                                msgid);
                }
        }

        return ret;

fail:
        log_warning_errno(errno, "Failed to read /proc/sysvipc/msg: %m");
        return -errno;
}
Exemplo n.º 10
0
static int clean_sysvipc_sem(uid_t delete_uid) {
        _cleanup_fclose_ FILE *f = NULL;
        char line[LINE_MAX];
        bool first = true;
        int ret = 0;

        f = fopen("/proc/sysvipc/sem", "re");
        if (!f) {
                if (errno == ENOENT)
                        return 0;

                log_warning_errno(errno, "Failed to open /proc/sysvipc/sem: %m");
                return -errno;
        }

        FOREACH_LINE(line, f, goto fail) {
                uid_t uid, cuid;
                gid_t gid, cgid;
                int semid;

                if (first) {
                        first = false;
                        continue;
                }

                truncate_nl(line);

                if (sscanf(line, "%*i %i %*o %*u " UID_FMT " " GID_FMT " " UID_FMT " " GID_FMT,
                           &semid, &uid, &gid, &cuid, &cgid) != 5)
                        continue;

                if (uid != delete_uid)
                        continue;

                if (semctl(semid, 0, IPC_RMID) < 0) {

                        /* Ignore entries that are already deleted */
                        if (errno == EIDRM || errno == EINVAL)
                                continue;

                        ret = log_warning_errno(errno,
                                                "Failed to remove SysV semaphores object %i: %m",
                                                semid);
                }
        }

        return ret;

fail:
        log_warning_errno(errno, "Failed to read /proc/sysvipc/sem: %m");
        return -errno;
}
Exemplo n.º 11
0
static bool promote_secondaries_enabled(const char *ifname) {
        _cleanup_free_ char *promote_secondaries_sysctl = NULL;
        char *promote_secondaries_path;
        int r;

        promote_secondaries_path = strjoina("net/ipv4/conf/", ifname, "/promote_secondaries");
        r = sysctl_read(promote_secondaries_path, &promote_secondaries_sysctl);
        if (r < 0) {
                log_debug_errno(r, "Cannot read sysctl %s", promote_secondaries_path);
                return false;
        }

        truncate_nl(promote_secondaries_sysctl);
        r = parse_boolean(promote_secondaries_sysctl);
        if (r < 0)
                log_warning_errno(r, "Cannot parse sysctl %s with content %s as boolean", promote_secondaries_path, promote_secondaries_sysctl);
        return r > 0;
}
Exemplo n.º 12
0
int ask_string(char **ret, const char *text, ...) {
        assert(ret);
        assert(text);

        for (;;) {
                char line[LINE_MAX];
                va_list ap;

                if (on_tty())
                        fputs(ANSI_HIGHLIGHT, stdout);

                va_start(ap, text);
                vprintf(text, ap);
                va_end(ap);

                if (on_tty())
                        fputs(ANSI_NORMAL, stdout);

                fflush(stdout);

                errno = 0;
                if (!fgets(line, sizeof(line), stdin))
                        return errno ? -errno : -EIO;

                if (!endswith(line, "\n"))
                        putchar('\n');
                else {
                        char *s;

                        if (isempty(line))
                                continue;

                        truncate_nl(line);
                        s = strdup(line);
                        if (!s)
                                return -ENOMEM;

                        *ret = s;
                        return 0;
                }
        }
}
Exemplo n.º 13
0
int fs_on_ssd(const char *p) {
        struct stat st;
        _cleanup_udev_unref_ struct udev *udev = NULL;
        _cleanup_udev_device_unref_ struct udev_device *udev_device = NULL;
        struct udev_device *look_at = NULL;
        const char *devtype, *rotational, *model, *id;
        int r;

        assert(p);

        if (stat(p, &st) < 0)
                return -errno;

        if (major(st.st_dev) == 0) {
                _cleanup_fclose_ FILE *f = NULL;
                int mount_id;
                struct file_handle *h;

                /* Might be btrfs, which exposes "ssd" as mount flag if it is on ssd.
                 *
                 * We first determine the mount ID here, if we can,
                 * and then lookup the mount ID in mountinfo to find
                 * the mount options. */

                h = alloca(MAX_HANDLE_SZ);
                h->handle_bytes = MAX_HANDLE_SZ;
                r = name_to_handle_at(AT_FDCWD, p, h, &mount_id, AT_SYMLINK_FOLLOW);
                if (r < 0)
                        return false;

                f = fopen("/proc/self/mountinfo", "re");
                if (!f)
                        return false;

                for (;;) {
                        char line[LINE_MAX], *e;
                        _cleanup_free_ char *opts = NULL;
                        int mid;

                        if (!fgets(line, sizeof(line), f))
                                return false;

                        truncate_nl(line);

                        if (sscanf(line, "%i", &mid) != 1)
                                continue;

                        if (mid != mount_id)
                                continue;

                        e = strstr(line, " - ");
                        if (!e)
                                continue;

                        if (sscanf(e+3, "%*s %*s %ms", &opts) != 1)
                                continue;

                        if (streq(opts, "ssd") || startswith(opts, "ssd,") || endswith(opts, ",ssd") || strstr(opts, ",ssd,"))
                                return true;
                }

                return false;
        }

        udev = udev_new();
        if (!udev)
                return -ENOMEM;

        udev_device = udev_device_new_from_devnum(udev, 'b', st.st_dev);
        if (!udev_device)
                return false;

        devtype = udev_device_get_property_value(udev_device, "DEVTYPE");
        if (devtype && streq(devtype, "partition"))
                look_at = udev_device_get_parent(udev_device);
        else
                look_at = udev_device;

        if (!look_at)
                return false;

        /* First, try high-level property */
        id = udev_device_get_property_value(look_at, "ID_SSD");
        if (id)
                return streq(id, "1");

        /* Second, try kernel attribute */
        rotational = udev_device_get_sysattr_value(look_at, "queue/rotational");
        if (rotational)
                return streq(rotational, "0");

        /* Finally, fallback to heuristics */
        look_at = udev_device_get_parent(look_at);
        if (!look_at)
                return false;

        model = udev_device_get_sysattr_value(look_at, "model");
        if (model)
                return !!strstr(model, "SSD");

        return false;
}
Exemplo n.º 14
0
/* Go through the file and parse each line */
int config_parse(const char *unit,
                 const char *filename,
                 FILE *f,
                 const char *sections,
                 ConfigItemLookup lookup,
                 const void *table,
                 bool relaxed,
                 bool allow_include,
                 bool warn,
                 void *userdata) {

    _cleanup_free_ char *section = NULL, *continuation = NULL;
    _cleanup_fclose_ FILE *ours = NULL;
    unsigned line = 0, section_line = 0;
    bool section_ignored = false;
    int r;

    assert(filename);
    assert(lookup);

    if (!f) {
        f = ours = fopen(filename, "re");
        if (!f) {
            /* Only log on request, except for ENOENT,
             * since we return 0 to the caller. */
            if (warn || errno == ENOENT)
                log_full(errno == ENOENT ? LOG_DEBUG : LOG_ERR,
                         "Failed to open configuration file '%s': %m", filename);
            return errno == ENOENT ? 0 : -errno;
        }
    }

    fd_warn_permissions(filename, fileno(f));

    while (!feof(f)) {
        char l[LINE_MAX], *p, *c = NULL, *e;
        bool escaped = false;

        if (!fgets(l, sizeof(l), f)) {
            if (feof(f))
                break;

            log_error_errno(errno, "Failed to read configuration file '%s': %m", filename);
            return -errno;
        }

        truncate_nl(l);

        if (continuation) {
            c = strappend(continuation, l);
            if (!c) {
                if (warn)
                    log_oom();
                return -ENOMEM;
            }

            continuation = mfree(continuation);
            p = c;
        } else
            p = l;

        for (e = p; *e; e++) {
            if (escaped)
                escaped = false;
            else if (*e == '\\')
                escaped = true;
        }

        if (escaped) {
            *(e-1) = ' ';

            if (c)
                continuation = c;
            else {
                continuation = strdup(l);
                if (!continuation) {
                    if (warn)
                        log_oom();
                    return -ENOMEM;
                }
            }

            continue;
        }

        r = parse_line(unit,
                       filename,
                       ++line,
                       sections,
                       lookup,
                       table,
                       relaxed,
                       allow_include,
                       &section,
                       &section_line,
                       &section_ignored,
                       p,
                       userdata);
        free(c);

        if (r < 0) {
            if (warn)
                log_warning_errno(r, "Failed to parse file '%s': %m",
                                  filename);
            return r;
        }
    }

    return 0;
}
Exemplo n.º 15
0
int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
        uint64_t missing;
        int r;

        assert(c);
        assert(c->allocated);

        missing = mask & ~c->mask;
        if (missing == 0)
                return 0;

        /* Try to retrieve PID from creds if it wasn't passed to us */
        if (pid <= 0 && (c->mask & SD_BUS_CREDS_PID))
                pid = c->pid;

        if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
                tid = c->pid;

        /* Without pid we cannot do much... */
        if (pid <= 0)
                return 0;

        if (missing & (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID |
                       SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
                       SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {

                _cleanup_fclose_ FILE *f = NULL;
                char line[LINE_MAX];
                const char *p;

                p = procfs_file_alloca(pid, "status");

                f = fopen(p, "re");
                if (!f)
                        return errno == ENOENT ? -ESRCH : -errno;

                FOREACH_LINE(line, f, return -errno) {
                        truncate_nl(line);

                        if (missing & SD_BUS_CREDS_UID) {
                                p = startswith(line, "Uid:");
                                if (p) {
                                        unsigned long uid;

                                        p += strspn(p, WHITESPACE);
                                        if (sscanf(p, "%lu", &uid) != 1)
                                                return -EIO;

                                        c->uid = (uid_t) uid;
                                        c->mask |= SD_BUS_CREDS_UID;
                                        continue;
                                }
                        }

                        if (missing & SD_BUS_CREDS_GID) {
                                p = startswith(line, "Gid:");
                                if (p) {
                                        unsigned long gid;

                                        p += strspn(p, WHITESPACE);
                                        if (sscanf(p, "%lu", &gid) != 1)
                                                return -EIO;

                                        c->gid = (uid_t) gid;
                                        c->mask |= SD_BUS_CREDS_GID;
                                        continue;
                                }
                        }

                        if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
                                p = startswith(line, "CapEff:");
                                if (p) {
                                        r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
                                        if (r < 0)
                                                return r;

                                        c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
                                        continue;
                                }
                        }

                        if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
                                p = startswith(line, "CapPrm:");
                                if (p) {
                                        r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
                                        if (r < 0)
                                                return r;

                                        c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
                                        continue;
                                }
                        }

                        if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
                                p = startswith(line, "CapInh:");
                                if (p) {
                                        r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
                                        if (r < 0)
                                                return r;

                                        c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
                                        continue;
                                }
                        }

                        if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
                                p = startswith(line, "CapBnd:");
                                if (p) {
                                        r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
                                        if (r < 0)
                                                return r;

                                        c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
                                        continue;
                                }
                        }
                }
        }
Exemplo n.º 16
0
/* Go through the file and parse each line */
int config_parse(const char *unit,
                 const char *filename,
                 FILE *f,
                 const char *sections,
                 ConfigItemLookup lookup,
                 void *table,
                 bool relaxed,
                 bool allow_include,
                 void *userdata) {

        _cleanup_free_ char *section = NULL, *continuation = NULL;
        _cleanup_fclose_ FILE *ours = NULL;
        unsigned line = 0, section_line = 0;
        int r;

        assert(filename);
        assert(lookup);

        if (!f) {
                f = ours = fopen(filename, "re");
                if (!f) {
                        log_error("Failed to open configuration file '%s': %m", filename);
                        return -errno;
                }
        }

        fd_warn_permissions(filename, fileno(f));

        while (!feof(f)) {
                char l[LINE_MAX], *p, *c = NULL, *e;
                bool escaped = false;

                if (!fgets(l, sizeof(l), f)) {
                        if (feof(f))
                                break;

                        log_error("Failed to read configuration file '%s': %m", filename);
                        return -errno;
                }

                truncate_nl(l);

                if (continuation) {
                        c = strappend(continuation, l);
                        if (!c)
                                return -ENOMEM;

                        free(continuation);
                        continuation = NULL;
                        p = c;
                } else
                        p = l;

                for (e = p; *e; e++) {
                        if (escaped)
                                escaped = false;
                        else if (*e == '\\')
                                escaped = true;
                }

                if (escaped) {
                        *(e-1) = ' ';

                        if (c)
                                continuation = c;
                        else {
                                continuation = strdup(l);
                                if (!continuation)
                                        return -ENOMEM;
                        }

                        continue;
                }

                r = parse_line(unit,
                               filename,
                               ++line,
                               sections,
                               lookup,
                               table,
                               relaxed,
                               allow_include,
                               &section,
                               &section_line,
                               p,
                               userdata);
                free(c);

                if (r < 0)
                        return r;
        }

        return 0;
}
Exemplo n.º 17
0
static void load_unix_sockets(void) {
        FILE *f = NULL;
        char line[LINE_MAX];

        if (unix_sockets)
                return;

        /* We maintain a cache of the sockets we found in
         * /proc/net/unix to speed things up a little. */

        unix_sockets = set_new(string_hash_func, string_compare_func);
        if (!unix_sockets)
                return;

        f = fopen("/proc/net/unix", "re");
        if (!f)
                return;

        /* Skip header */
        if (!fgets(line, sizeof(line), f))
                goto fail;

        for (;;) {
                char *p, *s;
                int k;

                if (!fgets(line, sizeof(line), f))
                        break;

                truncate_nl(line);

                p = strchr(line, ':');
                if (!p)
                        continue;

                if (strlen(p) < 37)
                        continue;

                p += 37;
                p += strspn(p, WHITESPACE);
                p += strcspn(p, WHITESPACE); /* skip one more word */
                p += strspn(p, WHITESPACE);

                if (*p != '/')
                        continue;

                s = strdup(p);
                if (!s)
                        goto fail;

                path_kill_slashes(s);

                k = set_put(unix_sockets, s);
                if (k < 0) {
                        free(s);

                        if (k != -EEXIST)
                                goto fail;
                }
        }

        fclose(f);
        return;

fail:
        set_free_free(unix_sockets);
        unix_sockets = NULL;

        if (f)
                fclose(f);
}
Exemplo n.º 18
0
int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
        int r;
        char *p = NULL;
        FILE *f;
        char *fs;
        size_t cs;

        assert(controller);
        assert(path);
        assert(pid >= 0);

        if (pid == 0)
                pid = getpid();

        if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
                return -ENOMEM;

        f = fopen(fs, "re");
        free(fs);

        if (!f)
                return errno == ENOENT ? -ESRCH : -errno;

        cs = strlen(controller);

        while (!feof(f)) {
                char line[LINE_MAX];
                char *l;

                errno = 0;
                if (!(fgets(line, sizeof(line), f))) {
                        if (feof(f))
                                break;

                        r = errno ? -errno : -EIO;
                        goto finish;
                }

                truncate_nl(line);

                if (!(l = strchr(line, ':')))
                        continue;

                l++;
                if (strncmp(l, controller, cs) != 0)
                        continue;

                if (l[cs] != ':')
                        continue;

                if (!(p = strdup(l + cs + 1))) {
                        r = -ENOMEM;
                        goto finish;
                }

                *path = p;
                r = 0;
                goto finish;
        }

        r = -ENOENT;

finish:
        fclose(f);

        return r;
}
Exemplo n.º 19
0
static int test_string_util_truncate_nl_newline_first_char(void)
{
	char str[] = "\nhello, world!";
	truncate_nl(str);
	return strcmp(str, "");
}
Exemplo n.º 20
0
int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) {
        _cleanup_fclose_ FILE *f = NULL;
        _cleanup_free_ char *payload = NULL;
        unsigned n = 0;
        sd_id128_t id;
        char language[32];
        bool got_id = false, empty_line = true;
        int r;

        assert(h);
        assert(sb);
        assert(path);

        f = fopen(path, "re");
        if (!f) {
                log_error("Failed to open file %s: %m", path);
                return -errno;
        }

        for (;;) {
                char line[LINE_MAX];
                size_t a, b, c;
                char *t;

                if (!fgets(line, sizeof(line), f)) {
                        if (feof(f))
                                break;

                        log_error("Failed to read file %s: %m", path);
                        return -errno;
                }

                n++;

                truncate_nl(line);

                if (line[0] == 0) {
                        empty_line = true;
                        continue;
                }

                if (strchr(COMMENTS "\n", line[0]))
                        continue;

                if (empty_line &&
                    strlen(line) >= 2+1+32 &&
                    line[0] == '-' &&
                    line[1] == '-' &&
                    line[2] == ' ' &&
                    (line[2+1+32] == ' ' || line[2+1+32] == '\0')) {

                        bool with_language;
                        sd_id128_t jd;

                        /* New entry */

                        with_language = line[2+1+32] != '\0';
                        line[2+1+32] = '\0';

                        if (sd_id128_from_string(line + 2 + 1, &jd) >= 0) {

                                if (got_id) {
                                        r = finish_item(h, sb, id, language, payload);
                                        if (r < 0)
                                                return r;
                                }

                                if (with_language) {
                                        t = strstrip(line + 2 + 1 + 32 + 1);

                                        c = strlen(t);
                                        if (c <= 0) {
                                                log_error("[%s:%u] Language too short.", path, n);
                                                return -EINVAL;
                                        }
                                        if (c > sizeof(language) - 1) {
                                                log_error("[%s:%u] language too long.", path, n);
                                                return -EINVAL;
                                        }

                                        strscpy(language, sizeof(language), t);
                                } else
                                        language[0] = '\0';

                                got_id = true;
                                empty_line = false;
                                id = jd;

                                if (payload)
                                        payload[0] = '\0';

                                continue;
                        }
                }

                /* Payload */
                if (!got_id) {
                        log_error("[%s:%u] Got payload before ID.", path, n);
                        return -EINVAL;
                }

                a = payload ? strlen(payload) : 0;
                b = strlen(line);

                c = a + (empty_line ? 1 : 0) + b + 1 + 1;
                t = realloc(payload, c);
                if (!t)
                        return log_oom();

                if (empty_line) {
                        t[a] = '\n';
                        memcpy(t + a + 1, line, b);
                        t[a+b+1] = '\n';
                        t[a+b+2] = 0;
                } else {
                        memcpy(t + a, line, b);
                        t[a+b] = '\n';
                        t[a+b+1] = 0;
                }

                payload = t;
                empty_line = false;
        }

        if (got_id) {
                r = finish_item(h, sb, id, language, payload);
                if (r < 0)
                        return r;
        }

        return 0;
}
Exemplo n.º 21
0
static int test_string_util_truncate_nl_null(void)
{
	truncate_nl(NULL); /* make sure it doesn't segfault */
	return 0;
}
Exemplo n.º 22
0
static int unpack_file(FILE *pack) {
        _cleanup_close_ int fd = -1;
        char fn[PATH_MAX];
        bool any = false;
        struct stat st;
        uint64_t inode;

        assert(pack);

        if (!fgets(fn, sizeof(fn), pack))
                return 0;

        char_array_0(fn);
        truncate_nl(fn);

        fd = open(fn, O_RDONLY|O_CLOEXEC|O_NOATIME|O_NOCTTY|O_NOFOLLOW);
        if (fd < 0) {
                if (errno != ENOENT && errno != EPERM && errno != EACCES && errno != ELOOP)
                        log_warning("open(%s) failed: %m", fn);

        } else if (file_verify(fd, fn, arg_file_size_max, &st) <= 0)
                fd = safe_close(fd);

        if (fread(&inode, sizeof(inode), 1, pack) != 1) {
                log_error("Premature end of pack file.");
                return -EIO;
        }

        if (fd >= 0) {
                /* If the inode changed the file got deleted, so just
                 * ignore this entry */
                if (st.st_ino != (uint64_t) inode)
                        fd = safe_close(fd);
        }

        for (;;) {
                uint32_t b, c;

                if (fread(&b, sizeof(b), 1, pack) != 1 ||
                    fread(&c, sizeof(c), 1, pack) != 1) {
                        log_error("Premature end of pack file.");
                        return -EIO;
                }

                if (b == 0 && c == 0)
                        break;

                if (c <= b) {
                        log_error("Invalid pack file.");
                        return -EIO;
                }

                log_debug("%s: page %u to %u", fn, b, c);

                any = true;

                if (fd >= 0) {
                        if (posix_fadvise(fd, b * page_size(), (c - b) * page_size(), POSIX_FADV_WILLNEED) < 0) {
                                log_warning("posix_fadvise() failed: %m");
                                return -errno;
                        }
                }
        }

        if (!any && fd >= 0) {
                /* if no range is encoded in the pack file this is
                 * intended to mean that the whole file shall be
                 * read */

                if (posix_fadvise(fd, 0, st.st_size, POSIX_FADV_WILLNEED) < 0) {
                        log_warning("posix_fadvise() failed: %m");
                        return -errno;
                }
        }

        return 0;
}
Exemplo n.º 23
0
static int test_string_util_truncate_nl_empty_string(void)
{
	char str[] = "";
	truncate_nl(str);
	return strcmp(str, "");
}
Exemplo n.º 24
0
int change_uid_gid(const char *user, char **_home) {
        char line[LINE_MAX], *x, *u, *g, *h;
        const char *word, *state;
        _cleanup_free_ uid_t *uids = NULL;
        _cleanup_free_ char *home = NULL;
        _cleanup_fclose_ FILE *f = NULL;
        _cleanup_close_ int fd = -1;
        unsigned n_uids = 0;
        size_t sz = 0, l;
        uid_t uid;
        gid_t gid;
        pid_t pid;
        int r;

        assert(_home);

        if (!user || streq(user, "root") || streq(user, "0")) {
                /* Reset everything fully to 0, just in case */

                r = reset_uid_gid();
                if (r < 0)
                        return log_error_errno(r, "Failed to become root: %m");

                *_home = NULL;
                return 0;
        }

        /* First, get user credentials */
        fd = spawn_getent("passwd", user, &pid);
        if (fd < 0)
                return fd;

        f = fdopen(fd, "r");
        if (!f)
                return log_oom();
        fd = -1;

        if (!fgets(line, sizeof(line), f)) {

                if (!ferror(f)) {
                        log_error("Failed to resolve user %s.", user);
                        return -ESRCH;
                }

                log_error_errno(errno, "Failed to read from getent: %m");
                return -errno;
        }

        truncate_nl(line);

        wait_for_terminate_and_warn("getent passwd", pid, true);

        x = strchr(line, ':');
        if (!x) {
                log_error("/etc/passwd entry has invalid user field.");
                return -EIO;
        }

        u = strchr(x+1, ':');
        if (!u) {
                log_error("/etc/passwd entry has invalid password field.");
                return -EIO;
        }

        u++;
        g = strchr(u, ':');
        if (!g) {
                log_error("/etc/passwd entry has invalid UID field.");
                return -EIO;
        }

        *g = 0;
        g++;
        x = strchr(g, ':');
        if (!x) {
                log_error("/etc/passwd entry has invalid GID field.");
                return -EIO;
        }

        *x = 0;
        h = strchr(x+1, ':');
        if (!h) {
                log_error("/etc/passwd entry has invalid GECOS field.");
                return -EIO;
        }

        h++;
        x = strchr(h, ':');
        if (!x) {
                log_error("/etc/passwd entry has invalid home directory field.");
                return -EIO;
        }

        *x = 0;

        r = parse_uid(u, &uid);
        if (r < 0) {
                log_error("Failed to parse UID of user.");
                return -EIO;
        }

        r = parse_gid(g, &gid);
        if (r < 0) {
                log_error("Failed to parse GID of user.");
                return -EIO;
        }

        home = strdup(h);
        if (!home)
                return log_oom();

        /* Second, get group memberships */
        fd = spawn_getent("initgroups", user, &pid);
        if (fd < 0)
                return fd;

        fclose(f);
        f = fdopen(fd, "r");
        if (!f)
                return log_oom();
        fd = -1;

        if (!fgets(line, sizeof(line), f)) {
                if (!ferror(f)) {
                        log_error("Failed to resolve user %s.", user);
                        return -ESRCH;
                }

                log_error_errno(errno, "Failed to read from getent: %m");
                return -errno;
        }

        truncate_nl(line);

        wait_for_terminate_and_warn("getent initgroups", pid, true);

        /* Skip over the username and subsequent separator whitespace */
        x = line;
        x += strcspn(x, WHITESPACE);
        x += strspn(x, WHITESPACE);

        FOREACH_WORD(word, l, x, state) {
                char c[l+1];

                memcpy(c, word, l);
                c[l] = 0;

                if (!GREEDY_REALLOC(uids, sz, n_uids+1))
                        return log_oom();

                r = parse_uid(c, &uids[n_uids++]);
                if (r < 0) {
                        log_error("Failed to parse group data from getent.");
                        return -EIO;
                }
        }
Exemplo n.º 25
0
static int test_string_util_truncate_nl_newline_middle(void)
{
	char str[] = "hello, \nworld!";
	truncate_nl(str);
	return strcmp(str, "hello, ");
}
Exemplo n.º 26
0
int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
        uint64_t missing;
        int r;

        assert(c);
        assert(c->allocated);

        if (!(mask & SD_BUS_CREDS_AUGMENT))
                return 0;

        /* Try to retrieve PID from creds if it wasn't passed to us */
        if (pid > 0) {
                c->pid = pid;
                c->mask |= SD_BUS_CREDS_PID;
        } else if (c->mask & SD_BUS_CREDS_PID)
                pid = c->pid;
        else
                /* Without pid we cannot do much... */
                return 0;

        /* Try to retrieve TID from creds if it wasn't passed to us */
        if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
                tid = c->tid;

        /* Calculate what we shall and can add */
        missing = mask & ~(c->mask|SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_AUGMENT);
        if (missing == 0)
                return 0;

        if (tid > 0) {
                c->tid = tid;
                c->mask |= SD_BUS_CREDS_TID;
        }

        if (missing & (SD_BUS_CREDS_PPID |
                       SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
                       SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
                       SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
                       SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
                       SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {

                _cleanup_fclose_ FILE *f = NULL;
                const char *p;

                p = procfs_file_alloca(pid, "status");

                f = fopen(p, "re");
                if (!f) {
                        if (errno == ENOENT)
                                return -ESRCH;
                        else if (errno != EPERM && errno != EACCES)
                                return -errno;
                } else {
                        char line[LINE_MAX];

                        FOREACH_LINE(line, f, return -errno) {
                                truncate_nl(line);

                                if (missing & SD_BUS_CREDS_PPID) {
                                        p = startswith(line, "PPid:");
                                        if (p) {
                                                p += strspn(p, WHITESPACE);

                                                /* Explicitly check for PPID 0 (which is the case for PID 1) */
                                                if (!streq(p, "0")) {
                                                        r = parse_pid(p, &c->ppid);
                                                        if (r < 0)
                                                                return r;

                                                } else
                                                        c->ppid = 0;

                                                c->mask |= SD_BUS_CREDS_PPID;
                                                continue;
                                        }
                                }

                                if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
                                        p = startswith(line, "Uid:");
                                        if (p) {
                                                unsigned long uid, euid, suid, fsuid;

                                                p += strspn(p, WHITESPACE);
                                                if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
                                                        return -EIO;

                                                if (missing & SD_BUS_CREDS_UID)
                                                        c->uid = (uid_t) uid;
                                                if (missing & SD_BUS_CREDS_EUID)
                                                        c->euid = (uid_t) euid;
                                                if (missing & SD_BUS_CREDS_SUID)
                                                        c->suid = (uid_t) suid;
                                                if (missing & SD_BUS_CREDS_FSUID)
                                                        c->fsuid = (uid_t) fsuid;

                                                c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
                                                continue;
                                        }
                                }

                                if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
                                        p = startswith(line, "Gid:");
                                        if (p) {
                                                unsigned long gid, egid, sgid, fsgid;

                                                p += strspn(p, WHITESPACE);
                                                if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
                                                        return -EIO;

                                                if (missing & SD_BUS_CREDS_GID)
                                                        c->gid = (gid_t) gid;
                                                if (missing & SD_BUS_CREDS_EGID)
                                                        c->egid = (gid_t) egid;
                                                if (missing & SD_BUS_CREDS_SGID)
                                                        c->sgid = (gid_t) sgid;
                                                if (missing & SD_BUS_CREDS_FSGID)
                                                        c->fsgid = (gid_t) fsgid;

                                                c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
                                                continue;
                                        }
                                }

                                if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
                                        p = startswith(line, "Groups:");
                                        if (p) {
                                                size_t allocated = 0;

                                                for (;;) {
                                                        unsigned long g;
                                                        int n = 0;

                                                        p += strspn(p, WHITESPACE);
                                                        if (*p == 0)
                                                                break;

                                                        if (sscanf(p, "%lu%n", &g, &n) != 1)
                                                                return -EIO;

                                                        if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
                                                                return -ENOMEM;

                                                        c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
                                                        p += n;
                                                }

                                                c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
                                                continue;
                                        }
                                }

                                if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
                                        p = startswith(line, "CapEff:");
                                        if (p) {
                                                r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
                                                if (r < 0)
                                                        return r;

                                                c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
                                                continue;
                                        }
                                }

                                if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
                                        p = startswith(line, "CapPrm:");
                                        if (p) {
                                                r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
                                                if (r < 0)
                                                        return r;

                                                c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
                                                continue;
                                        }
                                }

                                if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
                                        p = startswith(line, "CapInh:");
                                        if (p) {
                                                r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
                                                if (r < 0)
                                                        return r;

                                                c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
                                                continue;
                                        }
                                }

                                if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
                                        p = startswith(line, "CapBnd:");
                                        if (p) {
                                                r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
                                                if (r < 0)
                                                        return r;

                                                c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
                                                continue;
                                        }
                                }
                        }
                }
        }
Exemplo n.º 27
0
/* Go through the file and parse each line */
int config_parse(
                const char *filename,
                FILE *f,
                const char *sections,
                ConfigItemLookup lookup,
                void *table,
                bool relaxed,
                void *userdata) {

        unsigned line = 0;
        char *section = NULL;
        int r;
        bool ours = false;
        char *continuation = NULL;

        assert(filename);
        assert(lookup);

        if (!f) {
                f = fopen(filename, "re");
                if (!f) {
                        r = -errno;
                        log_error("Failed to open configuration file '%s': %s", filename, strerror(-r));
                        goto finish;
                }

                ours = true;
        }

        while (!feof(f)) {
                char l[LINE_MAX], *p, *c = NULL, *e;
                bool escaped = false;

                if (!fgets(l, sizeof(l), f)) {
                        if (feof(f))
                                break;

                        r = -errno;
                        log_error("Failed to read configuration file '%s': %s", filename, strerror(-r));
                        goto finish;
                }

                truncate_nl(l);

                if (continuation) {
                        c = strappend(continuation, l);
                        if (!c) {
                                r = -ENOMEM;
                                goto finish;
                        }

                        free(continuation);
                        continuation = NULL;
                        p = c;
                } else
                        p = l;

                for (e = p; *e; e++) {
                        if (escaped)
                                escaped = false;
                        else if (*e == '\\')
                                escaped = true;
                }

                if (escaped) {
                        *(e-1) = ' ';

                        if (c)
                                continuation = c;
                        else {
                                continuation = strdup(l);
                                if (!continuation) {
                                        r = -ENOMEM;
                                        goto finish;
                                }
                        }

                        continue;
                }

                r = parse_line(filename,
                                ++line,
                                sections,
                                lookup,
                                table,
                                relaxed,
                                &section,
                                p,
                                userdata);
                free(c);

                if (r < 0)
                        goto finish;
        }

        r = 0;

finish:
        free(section);
        free(continuation);

        if (f && ours)
                fclose(f);

        return r;
}
Exemplo n.º 28
0
static int test_string_util_truncate_nl_newline_only(void)
{
	char str[] = "\n";
	truncate_nl(str);
	return strcmp(str, "");
}