mtd-utils: update to 2.1.1
[oweals/openwrt.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 +       int pid;
76 +       int flags;
77 +       char pidstr[8];
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 +                       sprintf(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 +}