skalibs

Mirror/fork of https://skarnet.org/software/skalibs/
git clone https://ccx.te2000.cz/git/skalibs
Log | Files | Refs | README | LICENSE

atomic_symlink.c (903B)


      1 /* ISC license. */
      2 
      3 #include <string.h>
      4 #include <unistd.h>
      5 #include <errno.h>
      6 #include <stdio.h>
      7 
      8 #include <skalibs/posixplz.h>
      9 #include <skalibs/unix-transactional.h>
     10 
     11 int atomic_symlink (char const *target, char const *name, char const *suffix)
     12 {
     13   {
     14     int e = errno ;
     15     if (symlink(target, name) == 0) return 1 ;
     16     if (errno != EEXIST) return 0 ;
     17     errno = e ;
     18   }
     19   {
     20     size_t namelen = strlen(name) ;
     21     size_t suffixlen = suffix ? strlen(suffix) + 1 : 0 ;
     22     char tmp[namelen + suffixlen + 8] ;
     23     memcpy(tmp, name, namelen) ;
     24     if (suffix)
     25     {
     26       tmp[namelen] = ':' ;
     27       memcpy(tmp + namelen + 1, suffix, suffixlen - 1) ;
     28     }
     29     memcpy(tmp + namelen + suffixlen, ":XXXXXX", 7) ;
     30     tmp[namelen + suffixlen + 7] = 0 ;
     31     if (mkltemp(target, tmp) == -1) return 0 ;
     32     if (rename(tmp, name) < 0)
     33     {
     34       unlink_void(tmp) ;
     35       return 0 ;
     36     }
     37   }
     38   return 1 ;
     39 }