3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27
28 #include <libgen.h>
29 #include "cfga_fp.h"
30
31 /* The following are used by update_fabric_wwn_list() */
32 #define COPY_EXT ".cpy." /* Extn used in naming backup file */
33 #define TMP_EXT ".tmp." /* Extn used in naming temp file */
34 static char *HDR =
35 "#\n"
36 "# fabric_WWN_map\n"
37 "#\n"
38 "# The physical ap_id list of configured fabric devices.\n"
39 "# Do NOT edit this file by hand -- refer to the cfgadm_fp(1M)\n"
40 "# man page and use cfgadm(1m) instead.\n"
41 "#\n";
42
43 /*
44 * This function searches for "srch_str" (of length "slen") in "buf" (of length
45 * "buflen"). If it is not found, "write_offset" has the offset in "buf" where
46 * "srch_str" would have to be added in "buf". If "srch_str" is found in "buf",
47 * "write_offset" has its offset in "buf"
48 *
205 * and has some data, it is expected to be of atleast the size of the lenght
206 * of the warning header. This is the only check that is performed on the
207 * validity of the file. No other checks are performed. On a valid
208 * repository, to perform the update, this function basically makes use of
209 * 3 buffers - the original buffer (repbuf), a copy buffer (c_repbuf) and a
210 * temp buffer (t_repbuf).
211 * The contents of the repository are mmap-ed into the repbuf and then
212 * copied into the c_repbuf. All further operations are done using the copy.
213 * t_repbuf is created to be the size of c_repbuf +/- 'slen' (based on
214 * whether it is add or remove operation). After adding/removing the
215 * 'update_str', the c_repbuf is copied to a OLD_FAB_REPOSITORY and t_repbuf
216 * is made FAB_REPOSITORY.
217 *
218 */
219 int
220 update_fabric_wwn_list(int cmd, const char *update_str, char **errstring)
221 {
222 int fd, copy_fd, tmp_fd, new_file_flag = 0;
223 int len, write_offset, bytes_left;
224 int sizeof_rep_hdr = strlen(HDR);
225 char *repbuf, *c_repbuf, *t_repbuf;
226 char *copy_rep, *tmp_rep, *upd_str;
227 off_t filesize, size;
228 struct stat stbuf;
229
230 /* Do some initializations */
231 fd = copy_fd = tmp_fd = -1;
232 repbuf = c_repbuf = t_repbuf = NULL;
233 copy_rep = tmp_rep = upd_str = NULL;
234 size = filesize = write_offset = bytes_left = 0;
235
236 /*
237 * Set the mode to read only. Root user can still open as RDWR.
238 * We ignore errors in general here. But, just notice ENOENTs
239 */
240 if ((chmod(FAB_REPOSITORY, S_IRUSR|S_IRGRP|S_IROTH) == -1) &&
241 (errno == ENOENT)) {
242 new_file_flag = 1;
243 mkdirp(FAB_REPOSITORY_DIR,
244 S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
286 /*
287 * We are trying to add/remove a NULL string.
288 * Just return success
289 */
290 close(fd);
291 return (FPCFGA_OK);
292 }
293
294 if ((upd_str = calloc(1, len + 2)) == NULL) {
295 close(fd);
296 cfga_err(errstring, errno, ERR_UPD_REP, 0);
297 return (FPCFGA_LIB_ERR);
298 }
299
300 strcpy(upd_str, update_str);
301 strcat(upd_str, "\n"); /* Append a new line char */
302 len = strlen(upd_str);
303
304 if (filesize > 0) {
305 if ((copy_rep = (char *)calloc(1, strlen(FAB_REPOSITORY) +
306 sizeof (COPY_EXT) + sizeof (pid_t))) == NULL) {
307 cfga_err(errstring, errno, ERR_UPD_REP, 0);
308 CLEANUP_N_RET(FPCFGA_LIB_ERR);
309 }
310
311 (void) sprintf(copy_rep, "%s%s%ld", FAB_REPOSITORY, COPY_EXT,
312 getpid());
313
314 if ((copy_fd = open(copy_rep, O_RDWR | O_CREAT | O_TRUNC,
315 S_IRUSR | S_IWUSR)) < 0) {
316 cfga_err(errstring, errno, ERR_UPD_REP, 0);
317 CLEANUP_N_RET(FPCFGA_LIB_ERR);
318 }
319
320 if ((repbuf = (char *)mmap(0, filesize, PROT_READ,
321 MAP_SHARED, fd, 0)) == MAP_FAILED) {
322 close(fd);
323 free(upd_str);
324 cfga_err(errstring, errno, ERR_UPD_REP, 0);
325 return (FPCFGA_LIB_ERR);
326 }
413 }
414 }
415
416 /* Now, size and filesize are > sizeof_rep_hdr */
417
418 switch (cmd) {
419 case ADD_ENTRY:
420 size += len;
421 /*
422 * We'll search the full repository, header included, since
423 * we dont expect upd_str to match anything in the header.
424 */
425 if (search_line(c_repbuf, filesize, upd_str,
426 len - 1, &write_offset, &bytes_left) == 0) {
427 /* line already exists in repository or len == 0 */
428 CLEANUP_N_RET(FPCFGA_OK); /* SUCCESS */
429 }
430
431 /* construct temp file name using pid. */
432 if ((tmp_rep = (char *)calloc(1, strlen(FAB_REPOSITORY) +
433 sizeof (TMP_EXT) + sizeof (pid_t))) == NULL) {
434 cfga_err(errstring, errno, ERR_UPD_REP, 0);
435 CLEANUP_N_RET(FPCFGA_LIB_ERR);
436 }
437
438 (void) sprintf(tmp_rep, "%s%s%ld", FAB_REPOSITORY,
439 TMP_EXT, getpid());
440
441 /* Open tmp repository file in absolute mode */
442 if ((tmp_fd = open(tmp_rep, O_RDWR|O_CREAT|O_TRUNC,
443 S_IRUSR | S_IWUSR)) < 0) {
444 cfga_err(errstring, errno, ERR_UPD_REP, 0);
445 CLEANUP_N_RET(FPCFGA_LIB_ERR);
446 }
447
448 if (lseek(tmp_fd, size - 1, SEEK_SET) == -1) {
449 cfga_err(errstring, errno, ERR_UPD_REP, 0);
450 CLEANUP_N_RET(FPCFGA_LIB_ERR);
451 }
452
453 if (write(tmp_fd, "", 1) != 1) {
508
509 case REMOVE_ENTRY:
510 if (size >= sizeof_rep_hdr + len - 1) {
511 size -= len;
512 /*
513 * No need to init the 'else' part (size < len) because
514 * in that case, there will be nothing to delete from
515 * the file and so 'size' will not be used in the code
516 * below since search_line() will not find upd_str.
517 */
518 }
519
520 if (search_line(c_repbuf, filesize, upd_str, len - 1,
521 &write_offset, &bytes_left) != 0) {
522 /* this line does not exists - nothing to remove */
523 CLEANUP_N_RET(FPCFGA_OK); /* SUCCESS */
524 }
525
526 /* construct temp file name using pid. */
527 if ((tmp_rep = (char *)calloc(1, strlen(FAB_REPOSITORY) +
528 sizeof (TMP_EXT) + sizeof (pid_t))) == NULL) {
529 cfga_err(errstring, errno, ERR_UPD_REP, 0);
530 CLEANUP_N_RET(FPCFGA_LIB_ERR);
531 }
532
533 (void) sprintf(tmp_rep, "%s%s%ld", FAB_REPOSITORY,
534 TMP_EXT, getpid());
535
536 /* Open tmp repository file in absolute mode */
537 if ((tmp_fd = open(tmp_rep, O_RDWR|O_CREAT|O_TRUNC,
538 S_IRUSR | S_IWUSR)) < 0) {
539 cfga_err(errstring, errno, ERR_UPD_REP, 0);
540 CLEANUP_N_RET(FPCFGA_LIB_ERR);
541 }
542
543 if (size > 0) {
544 if (lseek(tmp_fd, size - 1, SEEK_SET) == -1) {
545 cfga_err(errstring, errno, ERR_UPD_REP, 0);
546 CLEANUP_N_RET(FPCFGA_LIB_ERR);
547 }
548
|
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28
29 #include <libgen.h>
30 #include <limits.h>
31 #include "cfga_fp.h"
32
33 /* The following are used by update_fabric_wwn_list() */
34 #define COPY_EXT ".cpy." /* Extn used in naming backup file */
35 #define TMP_EXT ".tmp." /* Extn used in naming temp file */
36 static char *HDR =
37 "#\n"
38 "# fabric_WWN_map\n"
39 "#\n"
40 "# The physical ap_id list of configured fabric devices.\n"
41 "# Do NOT edit this file by hand -- refer to the cfgadm_fp(1M)\n"
42 "# man page and use cfgadm(1m) instead.\n"
43 "#\n";
44
45 /*
46 * This function searches for "srch_str" (of length "slen") in "buf" (of length
47 * "buflen"). If it is not found, "write_offset" has the offset in "buf" where
48 * "srch_str" would have to be added in "buf". If "srch_str" is found in "buf",
49 * "write_offset" has its offset in "buf"
50 *
207 * and has some data, it is expected to be of atleast the size of the lenght
208 * of the warning header. This is the only check that is performed on the
209 * validity of the file. No other checks are performed. On a valid
210 * repository, to perform the update, this function basically makes use of
211 * 3 buffers - the original buffer (repbuf), a copy buffer (c_repbuf) and a
212 * temp buffer (t_repbuf).
213 * The contents of the repository are mmap-ed into the repbuf and then
214 * copied into the c_repbuf. All further operations are done using the copy.
215 * t_repbuf is created to be the size of c_repbuf +/- 'slen' (based on
216 * whether it is add or remove operation). After adding/removing the
217 * 'update_str', the c_repbuf is copied to a OLD_FAB_REPOSITORY and t_repbuf
218 * is made FAB_REPOSITORY.
219 *
220 */
221 int
222 update_fabric_wwn_list(int cmd, const char *update_str, char **errstring)
223 {
224 int fd, copy_fd, tmp_fd, new_file_flag = 0;
225 int len, write_offset, bytes_left;
226 int sizeof_rep_hdr = strlen(HDR);
227 int pid_maxlen = snprintf(NULL, 0, "%d", PID_MAX) + 1;
228 char *repbuf, *c_repbuf, *t_repbuf;
229 char *copy_rep, *tmp_rep, *upd_str;
230 off_t filesize, size;
231 struct stat stbuf;
232
233 /* Do some initializations */
234 fd = copy_fd = tmp_fd = -1;
235 repbuf = c_repbuf = t_repbuf = NULL;
236 copy_rep = tmp_rep = upd_str = NULL;
237 size = filesize = write_offset = bytes_left = 0;
238
239 /*
240 * Set the mode to read only. Root user can still open as RDWR.
241 * We ignore errors in general here. But, just notice ENOENTs
242 */
243 if ((chmod(FAB_REPOSITORY, S_IRUSR|S_IRGRP|S_IROTH) == -1) &&
244 (errno == ENOENT)) {
245 new_file_flag = 1;
246 mkdirp(FAB_REPOSITORY_DIR,
247 S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
289 /*
290 * We are trying to add/remove a NULL string.
291 * Just return success
292 */
293 close(fd);
294 return (FPCFGA_OK);
295 }
296
297 if ((upd_str = calloc(1, len + 2)) == NULL) {
298 close(fd);
299 cfga_err(errstring, errno, ERR_UPD_REP, 0);
300 return (FPCFGA_LIB_ERR);
301 }
302
303 strcpy(upd_str, update_str);
304 strcat(upd_str, "\n"); /* Append a new line char */
305 len = strlen(upd_str);
306
307 if (filesize > 0) {
308 if ((copy_rep = (char *)calloc(1, strlen(FAB_REPOSITORY) +
309 sizeof (COPY_EXT) + pid_maxlen)) == NULL) {
310 cfga_err(errstring, errno, ERR_UPD_REP, 0);
311 CLEANUP_N_RET(FPCFGA_LIB_ERR);
312 }
313
314 (void) sprintf(copy_rep, "%s%s%ld", FAB_REPOSITORY, COPY_EXT,
315 getpid());
316
317 if ((copy_fd = open(copy_rep, O_RDWR | O_CREAT | O_TRUNC,
318 S_IRUSR | S_IWUSR)) < 0) {
319 cfga_err(errstring, errno, ERR_UPD_REP, 0);
320 CLEANUP_N_RET(FPCFGA_LIB_ERR);
321 }
322
323 if ((repbuf = (char *)mmap(0, filesize, PROT_READ,
324 MAP_SHARED, fd, 0)) == MAP_FAILED) {
325 close(fd);
326 free(upd_str);
327 cfga_err(errstring, errno, ERR_UPD_REP, 0);
328 return (FPCFGA_LIB_ERR);
329 }
416 }
417 }
418
419 /* Now, size and filesize are > sizeof_rep_hdr */
420
421 switch (cmd) {
422 case ADD_ENTRY:
423 size += len;
424 /*
425 * We'll search the full repository, header included, since
426 * we dont expect upd_str to match anything in the header.
427 */
428 if (search_line(c_repbuf, filesize, upd_str,
429 len - 1, &write_offset, &bytes_left) == 0) {
430 /* line already exists in repository or len == 0 */
431 CLEANUP_N_RET(FPCFGA_OK); /* SUCCESS */
432 }
433
434 /* construct temp file name using pid. */
435 if ((tmp_rep = (char *)calloc(1, strlen(FAB_REPOSITORY) +
436 sizeof (TMP_EXT) + pid_maxlen)) == NULL) {
437 cfga_err(errstring, errno, ERR_UPD_REP, 0);
438 CLEANUP_N_RET(FPCFGA_LIB_ERR);
439 }
440
441 (void) sprintf(tmp_rep, "%s%s%ld", FAB_REPOSITORY,
442 TMP_EXT, getpid());
443
444 /* Open tmp repository file in absolute mode */
445 if ((tmp_fd = open(tmp_rep, O_RDWR|O_CREAT|O_TRUNC,
446 S_IRUSR | S_IWUSR)) < 0) {
447 cfga_err(errstring, errno, ERR_UPD_REP, 0);
448 CLEANUP_N_RET(FPCFGA_LIB_ERR);
449 }
450
451 if (lseek(tmp_fd, size - 1, SEEK_SET) == -1) {
452 cfga_err(errstring, errno, ERR_UPD_REP, 0);
453 CLEANUP_N_RET(FPCFGA_LIB_ERR);
454 }
455
456 if (write(tmp_fd, "", 1) != 1) {
511
512 case REMOVE_ENTRY:
513 if (size >= sizeof_rep_hdr + len - 1) {
514 size -= len;
515 /*
516 * No need to init the 'else' part (size < len) because
517 * in that case, there will be nothing to delete from
518 * the file and so 'size' will not be used in the code
519 * below since search_line() will not find upd_str.
520 */
521 }
522
523 if (search_line(c_repbuf, filesize, upd_str, len - 1,
524 &write_offset, &bytes_left) != 0) {
525 /* this line does not exists - nothing to remove */
526 CLEANUP_N_RET(FPCFGA_OK); /* SUCCESS */
527 }
528
529 /* construct temp file name using pid. */
530 if ((tmp_rep = (char *)calloc(1, strlen(FAB_REPOSITORY) +
531 sizeof (TMP_EXT) + pid_maxlen)) == NULL) {
532 cfga_err(errstring, errno, ERR_UPD_REP, 0);
533 CLEANUP_N_RET(FPCFGA_LIB_ERR);
534 }
535
536 (void) sprintf(tmp_rep, "%s%s%ld", FAB_REPOSITORY,
537 TMP_EXT, getpid());
538
539 /* Open tmp repository file in absolute mode */
540 if ((tmp_fd = open(tmp_rep, O_RDWR|O_CREAT|O_TRUNC,
541 S_IRUSR | S_IWUSR)) < 0) {
542 cfga_err(errstring, errno, ERR_UPD_REP, 0);
543 CLEANUP_N_RET(FPCFGA_LIB_ERR);
544 }
545
546 if (size > 0) {
547 if (lseek(tmp_fd, size - 1, SEEK_SET) == -1) {
548 cfga_err(errstring, errno, ERR_UPD_REP, 0);
549 CLEANUP_N_RET(FPCFGA_LIB_ERR);
550 }
551
|