Low: unix: new qb_sys_unlink_or_truncate{,_at} helpers

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).
This commit is contained in:
Jan Pokorný 2016-11-04 19:02:50 +01:00
parent 189ca28db9
commit 7286215ec7
No known key found for this signature in database
GPG Key ID: 61BBB23A9E8F8DE2
3 changed files with 70 additions and 1 deletions

View File

@ -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])

View File

@ -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)
{

View File

@ -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,