diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2017-01-31 21:01:14 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2017-01-31 21:01:14 -0500 |
commit | 538e4b2054e9802ebc860943e0a43baf2ee46741 (patch) | |
tree | 70993ee6abf4d7cc0642bf55a5ea1d7edda4ce05 /util.c | |
parent | ab64ca5d29147385b099edb8874d6e101b48c1e0 (diff) | |
download | bfs-538e4b2054e9802ebc860943e0a43baf2ee46741.tar.xz |
Don't trust st_size when reading symlinks
Linux /proc, for example, reports a st_size of 0 for everything. It's
nice to be able to use -lname on them anyway.
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 30 |
1 files changed, 30 insertions, 0 deletions
@@ -29,6 +29,36 @@ int xreaddir(DIR *dir, struct dirent **de) { } } +char *xreadlinkat(int fd, const char *path, size_t size) { + ++size; // NUL-terminator + ssize_t len; + char *name = NULL; + + while (true) { + char *new_name = realloc(name, size); + if (!new_name) { + goto error; + } + name = new_name; + + len = readlinkat(fd, path, name, size); + if (len < 0) { + goto error; + } else if (len >= size) { + size *= 2; + } else { + break; + } + } + + name[len] = '\0'; + return name; + +error: + free(name); + return NULL; +} + bool isopen(int fd) { return fcntl(fd, F_GETFD) >= 0 || errno != EBADF; } |