]> sourceware.org Git - lvm2.git/blob - libdm/libdm-file.c
dmsetup: allow --noflush with status/wait for thin
[lvm2.git] / libdm / libdm-file.c
1 /*
2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
4 *
5 * This file is part of the device-mapper userspace tools.
6 *
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions
9 * of the GNU Lesser General Public License v.2.1.
10 *
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, write to the Free Software Foundation,
13 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 */
15
16 #include "dmlib.h"
17
18 #include <sys/file.h>
19 #include <fcntl.h>
20 #include <dirent.h>
21
22 static int _create_dir_recursive(const char *dir)
23 {
24 char *orig, *s;
25 int rc, r = 0;
26
27 log_verbose("Creating directory \"%s\"", dir);
28 /* Create parent directories */
29 orig = s = dm_strdup(dir);
30 if (!s) {
31 log_error("Failed to duplicate directory name.");
32 return 0;
33 }
34
35 while ((s = strchr(s, '/')) != NULL) {
36 *s = '\0';
37 if (*orig) {
38 rc = mkdir(orig, 0777);
39 if (rc < 0 && errno != EEXIST) {
40 if (errno != EROFS)
41 log_sys_error("mkdir", orig);
42 goto out;
43 }
44 }
45 *s++ = '/';
46 }
47
48 /* Create final directory */
49 rc = mkdir(dir, 0777);
50 if (rc < 0 && errno != EEXIST) {
51 if (errno != EROFS)
52 log_sys_error("mkdir", orig);
53 goto out;
54 }
55
56 r = 1;
57 out:
58 dm_free(orig);
59 return r;
60 }
61
62 int dm_create_dir(const char *dir)
63 {
64 struct stat info;
65
66 if (!*dir)
67 return 1;
68
69 if (stat(dir, &info) < 0)
70 return _create_dir_recursive(dir);
71
72 if (S_ISDIR(info.st_mode))
73 return 1;
74
75 log_error("Directory \"%s\" not found", dir);
76 return 0;
77 }
78
79 int dm_is_empty_dir(const char *dir)
80 {
81 struct dirent *dirent;
82 DIR *d;
83
84 if (!(d = opendir(dir))) {
85 log_sys_error("opendir", dir);
86 return 0;
87 }
88
89 while ((dirent = readdir(d)))
90 if (strcmp(dirent->d_name, ".") && strcmp(dirent->d_name, ".."))
91 break;
92
93 if (closedir(d))
94 log_sys_error("closedir", dir);
95
96 return dirent ? 0 : 1;
97 }
98
99 int dm_fclose(FILE *stream)
100 {
101 int prev_fail = ferror(stream);
102 int fclose_fail = fclose(stream);
103
104 /* If there was a previous failure, but fclose succeeded,
105 clear errno, since ferror does not set it, and its value
106 may be unrelated to the ferror-reported failure. */
107 if (prev_fail && !fclose_fail)
108 errno = 0;
109
110 return prev_fail || fclose_fail ? EOF : 0;
111 }
112
113 int dm_create_lockfile(const char *lockfile)
114 {
115 int fd, value;
116 size_t bufferlen;
117 ssize_t write_out;
118 struct flock lock;
119 char buffer[50];
120 int retries = 0;
121
122 if((fd = open(lockfile, O_CREAT | O_WRONLY,
123 (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) {
124 log_error("Cannot open lockfile [%s], error was [%s]",
125 lockfile, strerror(errno));
126 return 0;
127 }
128
129 lock.l_type = F_WRLCK;
130 lock.l_start = 0;
131 lock.l_whence = SEEK_SET;
132 lock.l_len = 0;
133 retry_fcntl:
134 if (fcntl(fd, F_SETLK, &lock) < 0) {
135 switch (errno) {
136 case EINTR:
137 goto retry_fcntl;
138 case EACCES:
139 case EAGAIN:
140 if (retries == 20) {
141 log_error("Cannot lock lockfile [%s], error was [%s]",
142 lockfile, strerror(errno));
143 break;
144 } else {
145 ++ retries;
146 usleep(1000);
147 goto retry_fcntl;
148 }
149 default:
150 log_error("process is already running");
151 }
152
153 goto fail_close;
154 }
155
156 if (ftruncate(fd, 0) < 0) {
157 log_error("Cannot truncate pidfile [%s], error was [%s]",
158 lockfile, strerror(errno));
159
160 goto fail_close_unlink;
161 }
162
163 memset(buffer, 0, sizeof(buffer));
164 snprintf(buffer, sizeof(buffer)-1, "%u\n", getpid());
165
166 bufferlen = strlen(buffer);
167 write_out = write(fd, buffer, bufferlen);
168
169 if ((write_out < 0) || (write_out == 0 && errno)) {
170 log_error("Cannot write pid to pidfile [%s], error was [%s]",
171 lockfile, strerror(errno));
172
173 goto fail_close_unlink;
174 }
175
176 if ((write_out == 0) || ((size_t)write_out < bufferlen)) {
177 log_error("Cannot write pid to pidfile [%s], shortwrite of"
178 "[%" PRIsize_t "] bytes, expected [%" PRIsize_t "]\n",
179 lockfile, write_out, bufferlen);
180
181 goto fail_close_unlink;
182 }
183
184 if ((value = fcntl(fd, F_GETFD, 0)) < 0) {
185 log_error("Cannot get close-on-exec flag from pidfile [%s], "
186 "error was [%s]", lockfile, strerror(errno));
187
188 goto fail_close_unlink;
189 }
190 value |= FD_CLOEXEC;
191 if (fcntl(fd, F_SETFD, value) < 0) {
192 log_error("Cannot set close-on-exec flag from pidfile [%s], "
193 "error was [%s]", lockfile, strerror(errno));
194
195 goto fail_close_unlink;
196 }
197
198 return 1;
199
200 fail_close_unlink:
201 if (unlink(lockfile))
202 stack;
203 fail_close:
204 if (close(fd))
205 stack;
206
207 return 0;
208 }
209
210 int dm_daemon_is_running(const char* lockfile)
211 {
212 int fd;
213 struct flock lock;
214
215 if((fd = open(lockfile, O_RDONLY)) < 0)
216 return 0;
217
218 lock.l_type = F_WRLCK;
219 lock.l_start = 0;
220 lock.l_whence = SEEK_SET;
221 lock.l_len = 0;
222 if (fcntl(fd, F_GETLK, &lock) < 0) {
223 log_error("Cannot check lock status of lockfile [%s], error was [%s]",
224 lockfile, strerror(errno));
225 if (close(fd))
226 stack;
227 return 0;
228 }
229
230 if (close(fd))
231 stack;
232
233 return (lock.l_type == F_UNLCK) ? 0 : 1;
234 }
This page took 0.046355 seconds and 5 git commands to generate.