source: MondoRescue/branches/3.3/mindi-busybox/util-linux/flock.c@ 3625

Last change on this file since 3625 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 2.7 KB
Line 
1/*
2 * Copyright (C) 2010 Timo Teras <timo.teras@iki.fi>
3 *
4 * This is free software, licensed under the GNU General Public License v2.
5 */
6
7//usage:#define flock_trivial_usage
8//usage: "[-sxun] FD|{FILE [-c] PROG ARGS}"
9//usage:#define flock_full_usage "\n\n"
10//usage: "[Un]lock file descriptor, or lock FILE, run PROG\n"
11//usage: "\n -s Shared lock"
12//usage: "\n -x Exclusive lock (default)"
13//usage: "\n -u Unlock FD"
14//usage: "\n -n Fail rather than wait"
15
16#include <sys/file.h>
17#include "libbb.h"
18
19int flock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
20int flock_main(int argc UNUSED_PARAM, char **argv)
21{
22 int mode, opt, fd;
23 enum {
24 OPT_s = (1 << 0),
25 OPT_x = (1 << 1),
26 OPT_n = (1 << 2),
27 OPT_u = (1 << 3),
28 OPT_c = (1 << 4),
29 };
30
31#if ENABLE_LONG_OPTS
32 static const char getopt_longopts[] ALIGN1 =
33 "shared\0" No_argument "s"
34 "exclusive\0" No_argument "x"
35 "unlock\0" No_argument "u"
36 "nonblock\0" No_argument "n"
37 ;
38 applet_long_options = getopt_longopts;
39#endif
40 opt_complementary = "-1";
41
42 opt = getopt32(argv, "+sxnu");
43 argv += optind;
44
45 if (argv[1]) {
46 fd = open(argv[0], O_RDONLY|O_NOCTTY|O_CREAT, 0666);
47 if (fd < 0 && errno == EISDIR)
48 fd = open(argv[0], O_RDONLY|O_NOCTTY);
49 if (fd < 0)
50 bb_perror_msg_and_die("can't open '%s'", argv[0]);
51 //TODO? close_on_exec_on(fd);
52 } else {
53 fd = xatoi_positive(argv[0]);
54 }
55 argv++;
56
57 /* If it is "flock FILE -c PROG", then -c isn't caught by getopt32:
58 * we use "+" in order to support "flock -opt FILE PROG -with-opts",
59 * we need to remove -c by hand.
60 */
61 if (argv[0]
62 && argv[0][0] == '-'
63 && ( (argv[0][1] == 'c' && !argv[0][2])
64 || (ENABLE_LONG_OPTS && strcmp(argv[0] + 1, "-command") == 0)
65 )
66 ) {
67 argv++;
68 if (argv[1])
69 bb_error_msg_and_die("-c takes only one argument");
70 opt |= OPT_c;
71 }
72
73 if (OPT_s == LOCK_SH && OPT_x == LOCK_EX && OPT_n == LOCK_NB && OPT_u == LOCK_UN) {
74 /* With suitably matched constants, mode setting is much simpler */
75 mode = opt & (LOCK_SH + LOCK_EX + LOCK_NB + LOCK_UN);
76 if (!(mode & ~LOCK_NB))
77 mode |= LOCK_EX;
78 } else {
79 if (opt & OPT_u)
80 mode = LOCK_UN;
81 else if (opt & OPT_s)
82 mode = LOCK_SH;
83 else
84 mode = LOCK_EX;
85 if (opt & OPT_n)
86 mode |= LOCK_NB;
87 }
88
89 if (flock(fd, mode) != 0) {
90 if (errno == EWOULDBLOCK)
91 return EXIT_FAILURE;
92 bb_perror_nomsg_and_die();
93 }
94
95 if (argv[0]) {
96 int rc;
97 if (opt & OPT_c) {
98 /* -c 'PROG ARGS' means "run sh -c 'PROG ARGS'" */
99 argv -= 2;
100 argv[0] = (char*)get_shell_name();
101 argv[1] = (char*)"-c";
102 /* argv[2] = "PROG ARGS"; */
103 /* argv[3] = NULL; */
104 }
105 rc = spawn_and_wait(argv);
106 if (rc < 0)
107 bb_simple_perror_msg(argv[0]);
108 return rc;
109 }
110
111 return EXIT_SUCCESS;
112}
Note: See TracBrowser for help on using the repository browser.