Tizen 2.1 base
[external/device-mapper.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         while ((s = strchr(s, '/')) != NULL) {
31                 *s = '\0';
32                 if (*orig) {
33                         rc = mkdir(orig, 0777);
34                         if (rc < 0 && errno != EEXIST) {
35                                 if (errno != EROFS)
36                                         log_sys_error("mkdir", orig);
37                                 goto out;
38                         }
39                 }
40                 *s++ = '/';
41         }
42
43         /* Create final directory */
44         rc = mkdir(dir, 0777);
45         if (rc < 0 && errno != EEXIST) {
46                 if (errno != EROFS)
47                         log_sys_error("mkdir", orig);
48                 goto out;
49         }
50
51         r = 1;
52 out:
53         dm_free(orig);
54         return r;
55 }
56
57 int dm_create_dir(const char *dir)
58 {
59         struct stat info;
60
61         if (!*dir)
62                 return 1;
63
64         if (stat(dir, &info) < 0)
65                 return _create_dir_recursive(dir);
66
67         if (S_ISDIR(info.st_mode))
68                 return 1;
69
70         log_error("Directory \"%s\" not found", dir);
71         return 0;
72 }
73
74 int dm_fclose(FILE *stream)
75 {
76         int prev_fail = ferror(stream);
77         int fclose_fail = fclose(stream);
78
79         /* If there was a previous failure, but fclose succeeded,
80            clear errno, since ferror does not set it, and its value
81            may be unrelated to the ferror-reported failure.  */
82         if (prev_fail && !fclose_fail)
83                 errno = 0;
84
85         return prev_fail || fclose_fail ? EOF : 0;
86 }
87
88 int dm_create_lockfile(const char *lockfile)
89 {
90         int fd, value;
91         size_t bufferlen;
92         ssize_t write_out;
93         struct flock lock;
94         char buffer[50];
95         int retries = 0;
96
97         if((fd = open(lockfile, O_CREAT | O_WRONLY,
98                       (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) {
99                 log_error("Cannot open lockfile [%s], error was [%s]",
100                           lockfile, strerror(errno));
101                 return 0;
102         }
103
104         lock.l_type = F_WRLCK;
105         lock.l_start = 0;
106         lock.l_whence = SEEK_SET;
107         lock.l_len = 0;
108 retry_fcntl:
109         if (fcntl(fd, F_SETLK, &lock) < 0) {
110                 switch (errno) {
111                 case EINTR:
112                         goto retry_fcntl;
113                         break;
114                 case EACCES:
115                 case EAGAIN:
116                         if (retries == 20) {
117                                 log_error("Cannot lock lockfile [%s], error was [%s]",
118                                           lockfile, strerror(errno));
119                                 break;
120                         } else {
121                                 ++ retries;
122                                 usleep(1000);
123                                 goto retry_fcntl;
124                         }
125                 default:
126                         log_error("process is already running");
127                 }
128
129                 goto fail_close;
130         }
131
132         if (ftruncate(fd, 0) < 0) {
133                 log_error("Cannot truncate pidfile [%s], error was [%s]",
134                           lockfile, strerror(errno));
135
136                 goto fail_close_unlink;
137         }
138
139         memset(buffer, 0, sizeof(buffer));
140         snprintf(buffer, sizeof(buffer)-1, "%u\n", getpid());
141
142         bufferlen = strlen(buffer);
143         write_out = write(fd, buffer, bufferlen);
144
145         if ((write_out < 0) || (write_out == 0 && errno)) {
146                 log_error("Cannot write pid to pidfile [%s], error was [%s]",
147                           lockfile, strerror(errno));
148
149                 goto fail_close_unlink;
150         }
151
152         if ((write_out == 0) || (write_out < bufferlen)) {
153                 log_error("Cannot write pid to pidfile [%s], shortwrite of"
154                           "[%" PRIsize_t "] bytes, expected [%" PRIsize_t "]\n",
155                           lockfile, write_out, bufferlen);
156
157                 goto fail_close_unlink;
158         }
159
160         if ((value = fcntl(fd, F_GETFD, 0)) < 0) {
161                 log_error("Cannot get close-on-exec flag from pidfile [%s], "
162                           "error was [%s]", lockfile, strerror(errno));
163
164                 goto fail_close_unlink;
165         }
166         value |= FD_CLOEXEC;
167         if (fcntl(fd, F_SETFD, value) < 0) {
168                 log_error("Cannot set close-on-exec flag from pidfile [%s], "
169                           "error was [%s]", lockfile, strerror(errno));
170
171                 goto fail_close_unlink;
172         }
173
174         return 1;
175
176 fail_close_unlink:
177         if (unlink(lockfile))
178                 stack;
179 fail_close:
180         if (close(fd))
181                 stack;
182
183         return 0;
184 }
185
186 int dm_daemon_is_running(const char* lockfile)
187 {
188        int fd;
189        struct flock lock;
190
191        if((fd = open(lockfile, O_RDONLY)) < 0)
192                return 0;
193
194        lock.l_type = F_WRLCK;
195        lock.l_start = 0;
196        lock.l_whence = SEEK_SET;
197        lock.l_len = 0;
198        if (fcntl(fd, F_GETLK, &lock) < 0) {
199                log_error("Cannot check lock status of lockfile [%s], error was [%s]",
200                          lockfile, strerror(errno));
201                if (close(fd))
202                        stack;
203                return 0;
204        }
205
206        if (close(fd))
207                stack;
208
209        return (lock.l_type == F_UNLCK) ? 0 : 1;
210 }