aboutsummaryrefslogtreecommitdiffstats
path: root/src/repo/s6-rc-set-commit.c
blob: 07ddbfbc82b5b6ce34ac34242b0ee936b9df51bc (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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* ISC license. */

#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

#include <skalibs/uint64.h>
#include <skalibs/posixplz.h>
#include <skalibs/stat.h>
#include <skalibs/prog.h>
#include <skalibs/allreadwrite.h>
#include <skalibs/strerr.h>
#include <skalibs/gol.h>
#include <skalibs/tai.h>
#include <skalibs/stralloc.h>
#include <skalibs/genalloc.h>
#include <skalibs/djbunix.h>

#include <s6-rc/config.h>
#include <s6-rc/s6rc.h>

#define USAGE "s6-rc-set-commit [ -v verbosity ] [ -r repo ] [ -D defaultbundle ] [ -h fdhuser ] [ -K ] set"
#define dieusage() strerr_dieusage(100, USAGE)

enum golb_e
{
  GOLB_KEEPOLD = 0x01
} ;

enum gola_e
{
  GOLA_VERBOSITY,
  GOLA_REPODIR,
  GOLA_DEFBUNDLE,
  GOLA_FDHUSER,
  GOLA_N
} ;

static gol_bool const rgolb[] =
{
  { .so = 'K', .lo = "keep-old", .clear = 0, .set = GOLB_KEEPOLD }
} ;

static gol_arg const rgola[] =
{
  { .so = 'v', .lo = "verbosity", .i = GOLA_VERBOSITY },
  { .so = 'r', .lo = "repodir", .i = GOLA_REPODIR },
  { .so = 'D', .lo = "default-bundle", .i = GOLA_DEFBUNDLE },
  { .so = 'h', .lo = "fd-holder-user", .i = GOLA_FDHUSER }
} ;

static uint64_t wgolb = 0 ;

static void check_set (char const *repo, char const *set)
{
  struct stat st ;
  size_t repolen = strlen(repo) ;
  size_t setlen = strlen(set) ;
  char fn[repolen + 10 + setlen] ;
  memcpy(fn, repo, repolen) ;
  memcpy(fn + repolen, "/sources/", 9) ;
  memcpy(fn + repolen + 9, set, setlen + 1) ;
  if (stat(fn, &st) == -1)
  {
    if (errno == ENOENT)
      strerr_dief4x(3, "set ", set, " does not exist in repository ", repo) ;
    else strerr_diefu2sys(111, "stat ", fn) ;
  }
  if (!S_ISDIR(st.st_mode))
    strerr_dief3x(102, "file ", fn, " is not a directory") ;
}

int main (int argc, char const *const *argv)
{
  int fdlock ;
  unsigned int verbosity = 1 ;
  char const *wgola[GOLA_N] = { 0 } ;
  unsigned int golc ;
  int r ;

  PROG = "s6-rc-set-commit" ;
  wgola[GOLA_REPODIR] = S6RC_REPO_BASE ;
  wgola[GOLA_DEFBUNDLE] = "default" ;

  golc = GOL_main(argc, argv, rgolb, rgola, &wgolb, wgola) ;
  argc -= golc ; argv += golc ;
  if (wgola[GOLA_VERBOSITY] && !uint0_scan(wgola[GOLA_VERBOSITY], &verbosity))
    strerr_dief1x(100, "verbosity needs to be an unsigned integer") ;
  if (!argc) dieusage() ;
  if (strchr(argv[0], '/') || strchr(argv[0], '\n'))
    strerr_dief1x(100, "set names cannot contain / or newlines") ;

  fdlock = s6rc_repo_lock(wgola[GOLA_REPODIR], 1) ;
  if (fdlock == -1) strerr_diefu2sys(111, "lock ", wgola[GOLA_REPODIR]) ;
  check_set(wgola[GOLA_REPODIR], argv[0]) ;
  tain_now_g() ;

  size_t oldclen = S6RC_REPO_COMPILE_BUFLEN(strlen(wgola[GOLA_REPODIR]), strlen(argv[0])) ;
  char oldc[oldclen] ;

  r = s6rc_repo_setcompile(wgola[GOLA_REPODIR], argv[0], wgola[GOLA_DEFBUNDLE], oldc, verbosity, wgola[GOLA_FDHUSER]) ;
  if (r == -1) _exit(111) ;
  if (!r) _exit(1) ;
  if (r == 2) 
  {
    if (wgolb & GOLB_KEEPOLD)
    {
      oldc[oldclen - 1] = '\n' ;
      if (allwrite(1, oldc, oldclen) < oldclen)
        strerr_diefu1sys(111, "write to stdout") ;
      oldc[oldclen - 1] = 0 ;
    }
    else rm_rf(oldc) ;
  }
  _exit(0) ;
}