Skip to content

Commit

Permalink
Low: unix: new qb_sys_unlink_or_truncate{,_at} helpers
Browse files Browse the repository at this point in the history
These are intended for subsequent qb_rb_{force_,}close refactorization
and utilization of this new truncate as a fallback after unlink failure
as detailed in the commit to follow.

For newer POSIX revision compliant systems, there's "at" variant using
openat/unlinkat functions so that paths do not have to be traversed
in full anew when not needed (as both unlink and truncate operate on
the same path).
  • Loading branch information
jnpkrn committed Nov 4, 2016
1 parent 189ca28 commit 7286215
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 1 deletion.
3 changes: 2 additions & 1 deletion configure.ac
Expand Up @@ -217,7 +217,8 @@ AC_CHECK_FUNCS([alarm clock_gettime ftruncate gettimeofday \
pthread_mutexattr_setpshared \
pthread_condattr_setpshared \
sem_timedwait semtimedop \
getpeerucred getpeereid])
getpeerucred getpeereid \
openat unlinkat])

AM_CONDITIONAL(HAVE_SEM_TIMEDWAIT,
[test "x$ac_cv_func_sem_timedwait" = xyes])
Expand Down
49 changes: 49 additions & 0 deletions lib/unix.c
Expand Up @@ -255,6 +255,55 @@ qb_sys_fd_nonblock_cloexec_set(int32_t fd)
return res;
}

int32_t
qb_sys_unlink_or_truncate(const char *path, int32_t truncate_fallback)
{
int32_t res = 0;

if (unlink(path) == -1) {
res = errno;
qb_util_perror(LOG_DEBUG,
"Unlinking file: %s",
path);
if (res != ENOENT && truncate_fallback) {
res = errno = 0;
if (truncate(path, 0) == -1) {
res = errno;
qb_util_perror(LOG_DEBUG,
"Truncating file: %s", path);
}
}
}
return -res;
}

#if defined(HAVE_OPENAT) && defined(HAVE_UNLINKAT)
int32_t
qb_sys_unlink_or_truncate_at(int32_t dirfd, const char *path,
int32_t truncate_fallback)
{
int32_t fd, res = 0;

if (unlinkat(dirfd, path, 0) == -1) {
res = errno;
qb_util_perror(LOG_DEBUG,
"Unlinking file at dir: %s", path);
if (res != ENOENT && truncate_fallback) {
res = errno = 0;
if ((fd = openat(dirfd, path, O_WRONLY|O_TRUNC)) == -1) {
res = errno;
qb_util_perror(LOG_DEBUG,
"Truncating file at dir: %s",
path);
} else {
close(fd);
}
}
}
return -res;
}
#endif

void
qb_sigpipe_ctl(enum qb_sigpipe_ctl ctl)
{
Expand Down
19 changes: 19 additions & 0 deletions lib/util_int.h
Expand Up @@ -83,6 +83,25 @@ int32_t qb_sys_circular_mmap(int32_t fd, void **buf, size_t bytes);
*/
int32_t qb_sys_fd_nonblock_cloexec_set(int32_t fd);

/**
* Try to unlink file, and possibly truncate it as a fallback.
* @param path the file to be unlinked or truncated.
* @param truncate_fallback whether to truncate the file when unlink fails.
* @return 0 (success) or -errno
*/
int32_t qb_sys_unlink_or_truncate(const char *path, int32_t truncate_fallback);

#if defined(HAVE_OPENAT) && defined(HAVE_UNLINKAT)
/**
* Try to unlinkat file, and possibly truncate it as a fallback ("at" variant).
* @param path the file to be unlinked or truncated.
* @param truncate_fallback whether to truncate the file when unlink fails.
* @return 0 (success) or -errno
*/
int32_t qb_sys_unlink_or_truncate_at(int32_t dirfd, const char *path,
int32_t truncate_fallback);
#endif

enum qb_sigpipe_ctl {
QB_SIGPIPE_IGNORE,
QB_SIGPIPE_DEFAULT,
Expand Down

0 comments on commit 7286215

Please sign in to comment.