2 * Copyright (c) 2005 Christophe Varoqui
3 * Copyright (c) 2005 Benjamin Marzinski, Redhat
22 * significant parts of this file were taken from iscsi-bindings.c of the
23 * linux-iscsi project.
24 * Copyright (C) 2002 Cisco Systems, Inc.
26 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published
28 * by the Free Software Foundation; either version 2 of the License, or
29 * (at your option) any later version.
31 * This program is distributed in the hope that it will be useful, but
32 * WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 * General Public License for more details.
36 * See the file COPYING included with this distribution for more details.
40 ensure_directories_exist(char *str, mode_t dir_mode)
46 pathname = strdup(str);
48 condlog(0, "Cannot copy bindings file pathname : %s",
53 /* skip leading slashes */
54 while (end && *end && (*end == '/'))
57 while ((end = strchr(end, '/'))) {
58 /* if there is another slash, make the dir. */
60 err = mkdir(pathname, dir_mode);
61 if (err && errno != EEXIST) {
62 condlog(0, "Cannot make directory [%s] : %s",
63 pathname, strerror(errno));
68 condlog(3, "Created dir [%s]", pathname);
83 lock_bindings_file(int fd)
85 struct sigaction act, oldact;
90 memset(&lock, 0, sizeof(lock));
91 lock.l_type = F_WRLCK;
92 lock.l_whence = SEEK_SET;
94 act.sa_handler = sigalrm;
95 sigemptyset(&act.sa_mask);
98 sigaddset(&set, SIGALRM);
100 sigaction(SIGALRM, &act, &oldact);
101 sigprocmask(SIG_UNBLOCK, &set, &oldset);
103 alarm(BINDINGS_FILE_TIMEOUT);
104 err = fcntl(fd, F_SETLKW, &lock);
109 condlog(0, "Cannot lock bindings file : %s",
112 condlog(0, "Bindings file is locked. Giving up.");
115 sigprocmask(SIG_SETMASK, &oldset, NULL);
116 sigaction(SIGALRM, &oldact, NULL);
123 open_bindings_file(char *file, int *can_write)
128 if (ensure_directories_exist(file, 0700))
131 fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
133 if (errno == EROFS) {
135 condlog(3, "Cannot open bindings file [%s] read/write. "
136 " trying readonly", file);
137 fd = open(file, O_RDONLY);
139 condlog(0, "Cannot open bindings file [%s] "
140 "readonly : %s", file, strerror(errno));
145 condlog(0, "Cannot open bindings file [%s] : %s", file,
150 if (*can_write && lock_bindings_file(fd) < 0)
153 memset(&s, 0, sizeof(s));
154 if (fstat(fd, &s) < 0){
155 condlog(0, "Cannot stat bindings file : %s", strerror(errno));
158 if (s.st_size == 0) {
161 /* If bindings file is empty, write the header */
162 size_t len = strlen(BINDINGS_FILE_HEADER);
163 if (write_all(fd, BINDINGS_FILE_HEADER, len) != len) {
165 "Cannot write header to bindings file : %s",
167 /* cleanup partially written header */
172 condlog(3, "Initialized new bindings file [%s]", file);
183 format_devname(char *name, int id, int len, char *prefix)
186 int prefix_len = strlen(prefix);
189 strcpy(name, prefix);
190 for (pos = len - 1; pos >= prefix_len; pos--) {
191 name[pos] = 'a' + id % 26;
197 memmove(name + prefix_len, name + pos, len - pos);
198 name[prefix_len + len - pos] = '\0';
199 return (prefix_len + len - pos);
203 scan_devname(char *alias, char *prefix)
208 if (!prefix || strncmp(alias, prefix, strlen(prefix)))
211 c = alias + strlen(prefix);
212 while (*c != '\0' && *c != ' ' && *c != '\t') {
216 if (*c < 'a' || *c > 'z')
225 lookup_binding(FILE *f, char *map_wwid, char **map_alias, char *prefix)
228 unsigned int line_nr = 0;
233 while (fgets(buf, LINE_MAX, f)) {
234 char *c, *alias, *wwid;
238 c = strpbrk(buf, "#\n\r");
241 alias = strtok(buf, " \t");
242 if (!alias) /* blank line */
244 curr_id = scan_devname(alias, prefix);
247 wwid = strtok(NULL, "");
250 "Ignoring malformed line %u in bindings file",
254 if (strcmp(wwid, map_wwid) == 0){
255 condlog(3, "Found matching wwid [%s] in bindings file."
256 " Setting alias to %s", wwid, alias);
257 *map_alias = strdup(alias);
258 if (*map_alias == NULL)
259 condlog(0, "Cannot copy alias from bindings "
260 "file : %s", strerror(errno));
264 condlog(3, "No matching wwid [%s] in bindings file.", map_wwid);
269 rlookup_binding(FILE *f, char **map_wwid, char *map_alias)
272 unsigned int line_nr = 0;
277 while (fgets(buf, LINE_MAX, f)) {
278 char *c, *alias, *wwid;
282 c = strpbrk(buf, "#\n\r");
285 alias = strtok(buf, " \t");
286 if (!alias) /* blank line */
288 curr_id = scan_devname(alias, NULL); /* TBD: Why this call? */
291 wwid = strtok(NULL, " \t");
294 "Ignoring malformed line %u in bindings file",
298 if (strcmp(alias, map_alias) == 0){
299 condlog(3, "Found matching alias [%s] in bindings file."
300 "\nSetting wwid to %s", alias, wwid);
301 *map_wwid = strdup(wwid);
302 if (*map_wwid == NULL)
303 condlog(0, "Cannot copy alias from bindings "
304 "file : %s", strerror(errno));
308 condlog(3, "No matching alias [%s] in bindings file.", map_alias);
313 allocate_binding(int fd, char *wwid, int id, char *prefix)
321 condlog(0, "Bindings file full. Cannot allocate new binding");
325 i = format_devname(buf, id, LINE_MAX, prefix);
327 snprintf(c,LINE_MAX - i, " %s\n", wwid);
328 buf[LINE_MAX - 1] = '\0';
330 offset = lseek(fd, 0, SEEK_END);
332 condlog(0, "Cannot seek to end of bindings file : %s",
336 if (write_all(fd, buf, strlen(buf)) != strlen(buf)){
337 condlog(0, "Cannot write binding to bindings file : %s",
339 /* clear partial write */
340 ftruncate(fd, offset);
343 c = strchr(buf, ' ');
347 condlog(0, "cannot copy new alias from bindings file : %s",
350 condlog(3, "Created new binding [%s] for WWID [%s]", alias,
356 get_user_friendly_alias(char *wwid, char *file, char *prefix)
363 if (!wwid || *wwid == '\0') {
364 condlog(3, "Cannot find binding for empty WWID");
368 fd = open_bindings_file(file, &can_write);
374 condlog(0, "Cannot dup bindings file descriptor : %s",
380 f = fdopen(scan_fd, "r");
382 condlog(0, "cannot fdopen on bindings file descriptor : %s",
389 id = lookup_binding(f, wwid, &alias, prefix);
397 if (!alias && can_write)
398 alias = allocate_binding(fd, wwid, id, prefix);
407 get_user_friendly_wwid(char *alias, char *file)
410 int fd, scan_fd, id, unused;
413 if (!alias || *alias == '\0') {
414 condlog(3, "Cannot find binding for empty alias");
418 fd = open_bindings_file(file, &unused);
424 condlog(0, "Cannot dup bindings file descriptor : %s",
430 f = fdopen(scan_fd, "r");
432 condlog(0, "cannot fdopen on bindings file descriptor : %s",
439 id = rlookup_binding(f, &wwid, alias);