ath79: update WA/XC devices UBNT_VERSION to 8.7.4
[openwrt/staging/wigyori.git] / package / utils / busybox / patches / 220-add_lock_util.patch
1 --- /dev/null
2 +++ b/miscutils/lock.c
3 @@ -0,0 +1,155 @@
4 +/*
5 + * Copyright (C) 2006 Felix Fietkau <nbd@nbd.name>
6 + *
7 + * This is free software, licensed under the GNU General Public License v2.
8 + */
9 +
10 +//config:config LOCK
11 +//config: bool "lock"
12 +//config: default n
13 +//config: help
14 +//config: Small utility for using locks in scripts
15 +
16 +//applet:IF_LOCK(APPLET(lock, BB_DIR_BIN, BB_SUID_DROP))
17 +
18 +//kbuild:lib-$(CONFIG_LOCK) += lock.o
19 +
20 +//usage:#define lock_trivial_usage NOUSAGE_STR
21 +//usage:#define lock_full_usage ""
22 +
23 +#include <sys/types.h>
24 +#include <sys/file.h>
25 +#include <sys/stat.h>
26 +#include <signal.h>
27 +#include <fcntl.h>
28 +#include <unistd.h>
29 +#include <stdio.h>
30 +#include "busybox.h"
31 +
32 +static int unlock = 0;
33 +static int shared = 0;
34 +static int waitonly = 0;
35 +static int try_lock = 0;
36 +static int fd;
37 +static char *file;
38 +
39 +static void usage(char *name)
40 +{
41 + fprintf(stderr, "Usage: %s [-suw] <filename>\n"
42 + " -s Use shared locking\n"
43 + " -u Unlock\n"
44 + " -w Wait for the lock to become free, don't acquire lock\n"
45 + " -n Don't wait for the lock to become free. Fail with exit code\n"
46 + "\n", name);
47 + exit(1);
48 +}
49 +
50 +static void exit_unlock(int sig)
51 +{
52 + flock(fd, LOCK_UN);
53 + exit(0);
54 +}
55 +
56 +static int do_unlock(void)
57 +{
58 + FILE *f;
59 + int i;
60 +
61 + if ((f = fopen(file, "r")) == NULL)
62 + return 0;
63 +
64 + fscanf(f, "%d", &i);
65 + if (i > 0)
66 + kill(i, SIGTERM);
67 +
68 + fclose(f);
69 +
70 + return 0;
71 +}
72 +
73 +static int do_lock(void)
74 +{
75 + pid_t pid;
76 + int flags;
77 + char pidstr[12];
78 +
79 + if ((fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0700)) < 0) {
80 + if ((fd = open(file, O_RDWR)) < 0) {
81 + fprintf(stderr, "Can't open %s\n", file);
82 + return 1;
83 + }
84 + }
85 +
86 + flags = shared ? LOCK_SH : LOCK_EX;
87 + flags |= try_lock ? LOCK_NB : 0;
88 +
89 + if (flock(fd, flags) < 0) {
90 + fprintf(stderr, "Can't lock %s\n", file);
91 + return 1;
92 + }
93 +
94 + pid = fork();
95 +
96 + if (pid < 0)
97 + return -1;
98 +
99 + if (pid == 0) {
100 + signal(SIGKILL, exit_unlock);
101 + signal(SIGTERM, exit_unlock);
102 + signal(SIGINT, exit_unlock);
103 + if (waitonly)
104 + exit_unlock(0);
105 + else
106 + while (1)
107 + sleep(1);
108 + } else {
109 + if (!waitonly) {
110 + lseek(fd, 0, SEEK_SET);
111 + ftruncate(fd, 0);
112 + snprintf(pidstr, sizeof(pidstr), "%d\n", pid);
113 + write(fd, pidstr, strlen(pidstr));
114 + close(fd);
115 + }
116 +
117 + return 0;
118 + }
119 + return 0;
120 +}
121 +
122 +int lock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
123 +int lock_main(int argc, char **argv)
124 +{
125 + char **args = &argv[1];
126 + int c = argc - 1;
127 +
128 + while ((*args != NULL) && (*args)[0] == '-') {
129 + char *ch = *args;
130 + while (*(++ch) > 0) {
131 + switch(*ch) {
132 + case 'w':
133 + waitonly = 1;
134 + break;
135 + case 's':
136 + shared = 1;
137 + break;
138 + case 'u':
139 + unlock = 1;
140 + break;
141 + case 'n':
142 + try_lock = 1;
143 + break;
144 + }
145 + }
146 + c--;
147 + args++;
148 + }
149 +
150 + if (c != 1)
151 + usage(argv[0]);
152 +
153 + file = *args;
154 + if (unlock)
155 + return do_unlock();
156 + else
157 + return do_lock();
158 +}