diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2017-12-03 20:09:22 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2017-12-03 20:09:22 +0000 |
commit | 11f210ecaa0e085612058b459523fa2003578aa5 (patch) | |
tree | cc19339f86a926a85fc4ea08352a4b693b9b59ee /src | |
parent | 74e6ee2aad79665806facb88fca3185cb664582c (diff) | |
download | skalibs-11f210ecaa0e085612058b459523fa2003578aa5.tar.xz |
Add atomic_symlink(), prepare for 2.6.3.0
Diffstat (limited to 'src')
-rw-r--r-- | src/include/skalibs/unix-transactional.h | 1 | ||||
-rw-r--r-- | src/libunixonacid/atomic_symlink.c | 41 |
2 files changed, 42 insertions, 0 deletions
diff --git a/src/include/skalibs/unix-transactional.h b/src/include/skalibs/unix-transactional.h index d548f78..1037e92 100644 --- a/src/include/skalibs/unix-transactional.h +++ b/src/include/skalibs/unix-transactional.h @@ -39,6 +39,7 @@ extern size_t openwritevnclose_at (int, char const *, struct iovec const *, unsi extern int mkdir_unique (stralloc *, char const *, unsigned int) ; extern int atomic_rm_rf (char const *) ; extern int atomic_rm_rf_tmp (char const *, stralloc *) ; +extern int atomic_symlink (char const *, char const *, char const *) ; typedef struct dirdescriptor_s dirdescriptor_t, *dirdescriptor_t_ref ; diff --git a/src/libunixonacid/atomic_symlink.c b/src/libunixonacid/atomic_symlink.c new file mode 100644 index 0000000..660e4d3 --- /dev/null +++ b/src/libunixonacid/atomic_symlink.c @@ -0,0 +1,41 @@ +/* ISC license. */ + +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <skalibs/random.h> +#include <skalibs/unix-transactional.h> + +int atomic_symlink (char const *target, char const *name, char const *suffix) +{ + { + int e = errno ; + if (symlink(target, name) == 0) return 1 ; + if (errno != EEXIST) return 0 ; + errno = e ; + } + { + size_t namelen = strlen(name) ; + size_t suffixlen = suffix ? strlen(suffix) : 8 ; + char tmp[namelen + suffixlen + 2] ; + memcpy(tmp, name, namelen) ; + tmp[namelen] = ':' ; + if (suffix) + memcpy(tmp + namelen + 1, suffix, suffixlen + 1) ; + else + { + random_name(tmp + namelen + 1, 8) ; + tmp[namelen + 9] = 0 ; + } + if (symlink(target, tmp) < 0) return 0 ; + if (rename(tmp, name) < 0) + { + int e = errno ; + unlink(tmp) ; + errno = e ; + return 0 ; + } + } + return 1 ; +} |