summaryrefslogtreecommitdiff
path: root/src/libs6rc/s6rc_livedir_create.c
blob: e1fd8962be998bd2b76f01f9204762f9a1f53794 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/* ISC license. */

#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>  /* mkdtemp */
#include <skalibs/stralloc.h>
#include <skalibs/djbunix.h>
#include <s6-rc/s6rc-utils.h>

int s6rc_livedir_create (stralloc *sa, char const *live, char const *suffix, char const *scandir, char const *prefix, char const *compiled, unsigned char const *state, unsigned int statelen, size_t *dirlen)
{
  size_t newlen, ddirlen ;
  size_t sabase = sa->len ;
  int wasnull = !sa->s ;
  if (!s6rc_sanitize_dir(sa, live, &ddirlen)) return 0 ;
  if (!stralloc_cats(sa, ":")) goto err ;
  if (!stralloc_cats(sa, suffix)) goto err ;
  if (!stralloc_cats(sa, ":XXXXXX")) goto err ;
  if (!stralloc_0(sa)) goto err ;
  if (!mkdtemp(sa->s + sabase)) goto err ;
  newlen = sa->len-- ;
  if (chmod(sa->s + sabase, 0755) < 0) goto delerr ;
  if (!stralloc_catb(sa, "/servicedirs", 13)) goto delerr ;  /* allocates enough for the next strcpys */
  if (mkdir(sa->s + sabase, 0755) < 0) goto delerr ;
  strcpy(sa->s + newlen, "compiled") ;
  if (symlink(compiled, sa->s + sabase) < 0) goto delerr ;
  strcpy(sa->s + newlen, "scandir") ;
  if (symlink(scandir, sa->s + sabase) < 0) goto delerr ;
  strcpy(sa->s + newlen, "prefix") ;
  if (!openwritenclose_unsafe(sa->s + sabase, prefix, strlen(prefix))) goto delerr ;
  strcpy(sa->s + newlen, "state") ;
  if (!openwritenclose_unsafe(sa->s + sabase, (char const *)state, statelen)) goto delerr ;
  sa->len = newlen-1 ;
  sa->s[newlen-1] = 0 ;
  *dirlen = ddirlen ;
  return 1 ;

 delerr:
  {
    int e = errno ;
    sa->s[newlen] = 0 ;
    rm_rf_in_tmp(sa, sabase) ;
    errno = e ;
  }
 err:
  if (wasnull) stralloc_free(sa) ;
  else sa->len = sabase ;
  return 0 ;
}