chiark / gitweb /
journal: when sending journal data via file, place it in /dev/shm, to allow early...
[elogind.git] / src / util.c
index b4c5e2e65aaaef18d3c3212a39d7f20e440e7601..8004bebbd1c0f0af997924e8d95a97e7deaef66a 100644 (file)
@@ -1119,6 +1119,57 @@ int get_process_exe(pid_t pid, char **name) {
         return r;
 }
 
+int get_process_uid(pid_t pid, uid_t *uid) {
+        char *p;
+        FILE *f;
+        int r;
+
+        assert(uid);
+
+        if (pid == 0)
+                return getuid();
+
+        if (asprintf(&p, "/proc/%lu/status", (unsigned long) pid) < 0)
+                return -ENOMEM;
+
+        f = fopen(p, "re");
+        free(p);
+
+        if (!f)
+                return -errno;
+
+        while (!feof(f)) {
+                char line[LINE_MAX], *l;
+
+                if (!fgets(line, sizeof(line), f)) {
+                        if (feof(f))
+                                break;
+
+                        r = -errno;
+                        goto finish;
+                }
+
+                l = strstrip(line);
+
+                if (startswith(l, "Uid:")) {
+                        l += 4;
+                        l += strspn(l, WHITESPACE);
+
+                        l[strcspn(l, WHITESPACE)] = 0;
+
+                        r = parse_uid(l, uid);
+                        goto finish;
+                }
+        }
+
+        r = -EIO;
+
+finish:
+        fclose(f);
+
+        return r;
+}
+
 char *strnappend(const char *s, const char *suffix, size_t b) {
         size_t a;
         char *r;
@@ -2416,14 +2467,14 @@ int ask(char *ret, const char *replies, const char *text, ...) {
                 bool need_nl = true;
 
                 if (on_tty)
-                        fputs("\x1B[1m", stdout);
+                        fputs(ANSI_HIGHLIGHT_ON, stdout);
 
                 va_start(ap, text);
                 vprintf(text, ap);
                 va_end(ap);
 
                 if (on_tty)
-                        fputs("\x1B[0m", stdout);
+                        fputs(ANSI_HIGHLIGHT_OFF, stdout);
 
                 fflush(stdout);
 
@@ -3026,6 +3077,8 @@ int parse_bytes(const char *t, off_t *bytes) {
                 { "M", 1024ULL*1024ULL },
                 { "G", 1024ULL*1024ULL*1024ULL },
                 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
+                { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
+                { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
                 { "", 1 },
         };
 
@@ -3430,7 +3483,9 @@ static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) {
                         }
 
                         if (honour_sticky)
-                                keep_around = st.st_uid == 0 && (st.st_mode & S_ISVTX);
+                                keep_around =
+                                        (st.st_uid == 0 || st.st_uid == getuid()) &&
+                                        (st.st_mode & S_ISVTX);
 
                         is_dir = S_ISDIR(st.st_mode);
 
@@ -3444,7 +3499,9 @@ static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) {
                                         continue;
                                 }
 
-                                keep_around = st.st_uid == 0 && (st.st_mode & S_ISVTX);
+                                keep_around =
+                                        (st.st_uid == 0 || st.st_uid == getuid()) &&
+                                        (st.st_mode & S_ISVTX);
                         }
 
                         is_dir = de->d_type == DT_DIR;
@@ -3506,7 +3563,7 @@ int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky
 
         if (delete_root) {
 
-                if (honour_sticky && file_is_sticky(path) > 0)
+                if (honour_sticky && file_is_priv_sticky(path) > 0)
                         return r;
 
                 if (rmdir(path) < 0 && errno != ENOENT) {
@@ -3525,11 +3582,13 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
          * first change the access mode and only then hand out
          * ownership to avoid a window where access is too open. */
 
-        if (chmod(path, mode) < 0)
-                return -errno;
+        if (mode != (mode_t) -1)
+                if (chmod(path, mode) < 0)
+                        return -errno;
 
-        if (chown(path, uid, gid) < 0)
-                return -errno;
+        if (uid != (uid_t) -1 || gid != (gid_t) -1)
+                if (chown(path, uid, gid) < 0)
+                        return -errno;
 
         return 0;
 }
@@ -4351,31 +4410,37 @@ int vtnr_from_tty(const char *tty) {
         return i;
 }
 
-const char *default_term_for_tty(const char *tty) {
+bool tty_is_vc_resolve(const char *tty) {
         char *active = NULL;
-        const char *term;
+        bool b;
 
         assert(tty);
 
         if (startswith(tty, "/dev/"))
                 tty += 5;
 
-        /* Resolve where /dev/console is pointing when determining
-         * TERM */
+        /* Resolve where /dev/console is pointing to */
         if (streq(tty, "console"))
                 if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
                         /* If multiple log outputs are configured the
                          * last one is what /dev/console points to */
-                        if ((tty = strrchr(active, ' ')))
+                        tty = strrchr(active, ' ');
+                        if (tty)
                                 tty++;
                         else
                                 tty = active;
                 }
 
-        term = tty_is_vc(tty) ? "TERM=linux" : "TERM=vt100";
+        b = tty_is_vc(tty);
         free(active);
 
-        return term;
+        return b;
+}
+
+const char *default_term_for_tty(const char *tty) {
+        assert(tty);
+
+        return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt100";
 }
 
 bool dirent_is_file(const struct dirent *de) {
@@ -5751,7 +5816,7 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
         return -ENOENT;
 }
 
-int file_is_sticky(const char *p) {
+int file_is_priv_sticky(const char *p) {
         struct stat st;
 
         assert(p);
@@ -5760,7 +5825,7 @@ int file_is_sticky(const char *p) {
                 return -errno;
 
         return
-                st.st_uid == 0 &&
+                (st.st_uid == 0 || st.st_uid == getuid()) &&
                 (st.st_mode & S_ISVTX);
 }
 
@@ -6025,6 +6090,8 @@ char *format_bytes(char *buf, size_t l, off_t t) {
                 const char *suffix;
                 off_t factor;
         } table[] = {
+                { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
+                { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
                 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
                 { "G", 1024ULL*1024ULL*1024ULL },
                 { "M", 1024ULL*1024ULL },