chiark / gitweb /
always use the same code for creating temporary files
[elogind.git] / src / shared / util.c
index f452431c6701a2ea56398de2c62116d7b513475b..2b91ef8a8f9b203f71304c26bc50b420f5a52274 100644 (file)
@@ -3835,12 +3835,13 @@ char* hostname_cleanup(char *s, bool lowercase) {
 }
 
 int pipe_eof(int fd) {
 }
 
 int pipe_eof(int fd) {
-        int r;
         struct pollfd pollfd = {
                 .fd = fd,
                 .events = POLLIN|POLLHUP,
         };
 
         struct pollfd pollfd = {
                 .fd = fd,
                 .events = POLLIN|POLLHUP,
         };
 
+        int r;
+
         r = poll(&pollfd, 1, 0);
         if (r < 0)
                 return -errno;
         r = poll(&pollfd, 1, 0);
         if (r < 0)
                 return -errno;
@@ -3892,7 +3893,7 @@ int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
         t[k] = '.';
         stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
 
         t[k] = '.';
         stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
 
-        fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
+        fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
         if (fd < 0) {
                 free(t);
                 return -errno;
         if (fd < 0) {
                 free(t);
                 return -errno;
@@ -6111,25 +6112,35 @@ int writev_safe(int fd, const struct iovec *w, int j) {
 }
 
 int mkostemp_safe(char *pattern, int flags) {
 }
 
 int mkostemp_safe(char *pattern, int flags) {
-        char *s = pattern + strlen(pattern) - 6;
-        uint64_t tries = TMP_MAX;
-        int randfd, fd, i;
+        unsigned long tries = TMP_MAX;
+        char *s;
+        int r;
+        _cleanup_umask_ mode_t u;
 
 
-        assert(streq(s, "XXXXXX"));
+        assert(pattern);
 
 
-        randfd = open("/dev/urandom", O_RDONLY);
-        if (randfd < 0)
-                return -ENOSYS;
+        u = umask(077);
+
+        /* This is much like like mkostemp() but avoids using any
+         * static variables, thus is async signal safe. Also, it's not
+         * subject to umask(). */
+
+        s = endswith(pattern, "XXXXXX");
+        if (!s)
+                return -EINVAL;
 
         while (tries--) {
 
         while (tries--) {
-                fd = read(randfd, s, 6);
-                if (fd == 0)
-                        return -ENOSYS;
+                unsigned i;
+                int fd;
+
+                r = dev_urandom(s, 6);
+                if (r < 0)
+                        return r;
 
                 for (i = 0; i < 6; i++)
 
                 for (i = 0; i < 6; i++)
-                        s[i] = ALPHANUMERICAL[(unsigned) s[i] % strlen(ALPHANUMERICAL)];
+                        s[i] = ALPHANUMERICAL[(unsigned) s[i] % (sizeof(ALPHANUMERICAL)-1)];
 
 
-                fd = open(pattern, flags|O_EXCL|O_CREAT, S_IRUSR|S_IWUSR);
+                fd = open(pattern, flags|O_EXCL|O_CREAT|O_NOCTTY|O_NOFOLLOW, S_IRUSR|S_IWUSR);
                 if (fd >= 0)
                         return fd;
                 if (!IN_SET(errno, EEXIST, EINTR))
                 if (fd >= 0)
                         return fd;
                 if (!IN_SET(errno, EEXIST, EINTR))
@@ -6140,17 +6151,22 @@ int mkostemp_safe(char *pattern, int flags) {
 }
 
 int open_tmpfile(const char *path, int flags) {
 }
 
 int open_tmpfile(const char *path, int flags) {
-        int fd;
         char *p;
         char *p;
+        int fd;
+
+        assert(path);
 
 #ifdef O_TMPFILE
 
 #ifdef O_TMPFILE
+        /* Try O_TMPFILE first, if it is supported */
         fd = open(path, flags|O_TMPFILE, S_IRUSR|S_IWUSR);
         if (fd >= 0)
                 return fd;
 #endif
         fd = open(path, flags|O_TMPFILE, S_IRUSR|S_IWUSR);
         if (fd >= 0)
                 return fd;
 #endif
+
+        /* Fall back to unguessable name + unlinking */
         p = strappenda(path, "/systemd-tmp-XXXXXX");
 
         p = strappenda(path, "/systemd-tmp-XXXXXX");
 
-        fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC);
+        fd = mkostemp_safe(p, flags);
         if (fd < 0)
                 return fd;
 
         if (fd < 0)
                 return fd;