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
|
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include "strerr.h"
#include "error.h"
#include "buffer.h"
#define USAGE " dir"
#define SVDIR "/etc/runit/runsvdir"
#define VERSION "$Id$"
char *progname;
char *new;
void usage () { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); }
void fatal(char *m1, char *m2) {
strerr_die5sys(111, progname, ": fatal: ", m1, m2, ": ");
}
void fatalx(char *m1, char *m2) {
strerr_die4x(111, progname, ": fatal: ", m1, m2);
}
void warn(char *m1, char *m2) {
strerr_warn5(progname, ": fatal: ", m1, m2, ": ", &strerr_sys);
}
int main (int argc, char **argv) {
struct stat s;
int dev;
int ino;
progname =*argv++;
if (! argv || ! *argv) usage();
new =*argv;
if (new[0] == '.') fatalx(new, ": must not start with a dot.");
if (chdir(SVDIR) == -1) fatal("unable to chdir: ", SVDIR);
if (stat(new, &s) == -1) {
if (errno == error_noent) fatal(new, 0);
fatal("unable to stat: ", new);
}
if (! S_ISDIR(s.st_mode)) fatalx(new, "not a directory.");
ino =s.st_ino;
dev =s.st_dev;
if (stat("current", &s) == -1) fatal("unable to stat: ", "current");
if ((s.st_ino == ino) && (s.st_dev == dev)) {
buffer_puts(buffer_1, "runsvchdir: ");
buffer_puts(buffer_1, new);
buffer_puts(buffer_1, ": current.\n");
buffer_flush(buffer_1);
_exit(0);
}
if (unlink("current.new") == -1)
if (errno != error_noent) fatal("unable to unlink: ", "current.new");
if (symlink(new, "current.new") == -1)
fatal("unable to create: current.new -> ", new);
if (unlink("previous") == -1)
if (errno != error_noent) fatal("unable to unlink: ", "previous");
if (rename("current", "previous") == -1)
fatal("unable to copy: current to ", "previous");
if (rename("current.new", "current") == -1) {
warn("unable to move: current.new to ", "current");
if (rename("previous", "current") == -1)
fatal("unable to move previous back to ", "current");
_exit(111);
}
buffer_puts(buffer_1, "runsvchdir: ");
buffer_puts(buffer_1, new);
buffer_puts(buffer_1, ": now current.\n");
buffer_flush(buffer_1);
_exit(0);
}
|