Reduce the stack and heap memory usage of the helper by using a caller
provided buffer. This allows us to avoid copying the path, yet again,
within the caller.
Aside: readlink(3) returns -1 on all errors, it won't return the
prospective size if the output buffer is too small.
v2:
- swap fd_lookup_path() path/pathlen argument order
Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
Link: https://github.com/kmod-project/kmod/pull/345
Signed-off-by: Lucas De Marchi <lucas.de.marchi@gmail.com>
FILE *tmpfile_openat(int dirfd, mode_t mode, struct tmpfile *file)
{
- const char *tmpname_tmpl = "tmpfileXXXXXX";
+ const char *tmpname_tmpl = "/tmpfileXXXXXX";
const char *tmpname;
char tmpfile_path[PATH_MAX];
int fd, n;
- _cleanup_free_ char *targetdir;
FILE *fp;
- targetdir = fd_lookup_path(dirfd);
- if (targetdir == NULL)
+ n = fd_lookup_path(dirfd, tmpfile_path, sizeof(tmpfile_path));
+ if (n < 0)
goto create_fail;
- n = snprintf(tmpfile_path, sizeof(tmpfile_path), "%s/%s", targetdir, tmpname_tmpl);
- if (n < 0 || n >= (int)sizeof(tmpfile_path))
+ if (n + strlen(tmpname_tmpl) + 1 > sizeof(tmpfile_path))
goto create_fail;
+ memcpy(tmpfile_path + n, tmpname_tmpl, strlen(tmpname_tmpl) + 1);
+
fd = mkstemp(tmpfile_path);
if (fd < 0)
goto create_fail;
return mkdir_p(path, end - path, mode);
}
-char *fd_lookup_path(int fd)
+int fd_lookup_path(int fd, char *path, size_t pathlen)
{
char proc_path[PATH_MAX];
- char fd_path[PATH_MAX];
ssize_t len;
snprintf(proc_path, sizeof(proc_path), "/proc/self/fd/%d", fd);
* We are using mkstemp to create a temporary file. We need to read the link since
* the mkstemp creates file with an absolute path
*/
- len = readlink(proc_path, fd_path, sizeof(fd_path) - 1);
- if (len < 0 || len >= (ssize_t)sizeof(fd_path))
- return NULL;
+ len = readlink(proc_path, path, pathlen - 1);
+ if (len < 0)
+ return (int)len;
- fd_path[len] = '\0';
+ /* readlink(3), may null-terminate but should not be relied upon */
+ path[len] = '\0';
- return strdup(fd_path);
+ return len;
}
static unsigned long long ts_usec(const struct timespec *ts)
int mkdir_p(const char *path, int len, mode_t mode);
int mkdir_parents(const char *path, mode_t mode);
unsigned long long stat_mstamp(const struct stat *st);
-char *fd_lookup_path(int fd);
+_nonnull_all_ int fd_lookup_path(int fd, char *path, size_t pathlen);
/* time-related functions
* ************************************************************************ */