Print this page
NEX-9323 cfgadm FC plugin allocates insufficient memory for internal
buffers
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/cfgadm_plugins/fp/common/cfga_rep.c
+++ new/usr/src/lib/cfgadm_plugins/fp/common/cfga_rep.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
23 24 * Use is subject to license terms.
24 25 */
25 26
26 27
27 28
28 29 #include <libgen.h>
30 +#include <limits.h>
29 31 #include "cfga_fp.h"
30 32
31 33 /* The following are used by update_fabric_wwn_list() */
32 34 #define COPY_EXT ".cpy." /* Extn used in naming backup file */
33 35 #define TMP_EXT ".tmp." /* Extn used in naming temp file */
34 36 static char *HDR =
35 37 "#\n"
36 38 "# fabric_WWN_map\n"
37 39 "#\n"
38 40 "# The physical ap_id list of configured fabric devices.\n"
39 41 "# Do NOT edit this file by hand -- refer to the cfgadm_fp(1M)\n"
40 42 "# man page and use cfgadm(1m) instead.\n"
41 43 "#\n";
42 44
43 45 /*
44 46 * This function searches for "srch_str" (of length "slen") in "buf" (of length
45 47 * "buflen"). If it is not found, "write_offset" has the offset in "buf" where
46 48 * "srch_str" would have to be added in "buf". If "srch_str" is found in "buf",
47 49 * "write_offset" has its offset in "buf"
48 50 *
49 51 * ARGUMENTS :
50 52 * buf - buffer to search in
51 53 * buflen - length of buffer
52 54 * srch_str - string to search
53 55 * slen - length of srch_str
54 56 * write_offset - Set in function on exit
55 57 * - It is the offset in buf where srch_str is or should be
56 58 * bytes_left - Set in function on exit
57 59 * - It is the # of bytes left beyond write_offset in buf
58 60 *
59 61 * Notes :
60 62 * - This function assumes "buf" is sorted in ascending order
61 63 * - If 'buflen' is > 0, it assumes it has a header on top and skips it
62 64 * - "srch_str" has '\n' at the end, but when update_fabric_wwn_list() calls
63 65 * this function, 'slen' does not include the last `\n'
64 66 *
65 67 * RETURN VALUES :
66 68 * Zero - "srch_str" found in "buf"... "write_offset" has offset in "buf"
67 69 * > 0 - "srch_str" NOT found in "buf" ... "write_offset" has offset in "buf"
68 70 * where "srch_str" can fit in.
69 71 * "buf" had contents > "srch_str"
70 72 * < 0 - "srch_str" NOT found in "buf" ... "write_offset" has offset in "buf"
71 73 * where "srch_str" can fit in.
72 74 * "buf" had contents < "srch_str"
73 75 */
74 76 static int
75 77 search_line(char *buf, int buflen, char *srch_str, int slen,
76 78 int *write_offset, int *bytes_left)
77 79 {
78 80 int retval, sizeof_rep_hdr = strlen(HDR);
79 81 char *sol; /* Pointer to Start-Of-Line */
80 82 char *cur_pos; /* current position */
81 83
82 84 *bytes_left = buflen;
83 85 *write_offset = 0;
84 86
85 87 if (buf == NULL || *buf == NULL || buflen <= 0)
86 88 return (-2); /* Arbitrary -ve val. srch_str not found */
87 89
88 90 if (srch_str == NULL || *srch_str == NULL || slen <= 0)
89 91 return (0); /* This says srch_str was found */
90 92
91 93 sol = cur_pos = buf;
92 94 if (buflen >= sizeof_rep_hdr) {
93 95 /* skip header */
94 96 sol = cur_pos = buf + sizeof_rep_hdr;
95 97 *bytes_left -= sizeof_rep_hdr;
96 98 }
97 99
98 100 while (*bytes_left >= slen) {
99 101 if ((retval = strncmp(sol, srch_str, slen)) >= 0) {
100 102 /* strncmp will pass if srch_str is a substring */
101 103 if ((retval == 0) && (*bytes_left > slen) &&
102 104 (*(sol+slen) != '\n'))
103 105 retval = 1; /* Force it to be > 0 */
104 106 *write_offset = sol - buf;
105 107 return (retval);
106 108 }
107 109
108 110 /* retval < 0 */
109 111 if ((cur_pos = strchr(sol, (int)'\n')) == NULL) {
110 112 *write_offset = buflen;
111 113 return (retval);
112 114 }
113 115
114 116 /* Get the length of this line */
115 117 *cur_pos = '\0'; /* kludge to get string length */
116 118 *bytes_left -= (strlen(sol) + 1);
117 119 *cur_pos = '\n'; /* Put back the original char */
118 120
119 121 sol = cur_pos = cur_pos + 1;
120 122 }
121 123
122 124 if (*bytes_left > 0) {
123 125 /* In this case the bytes left will be less than slen */
124 126 if ((retval = strncmp(sol, srch_str, *bytes_left)) >= 0) {
125 127 *write_offset = sol - buf;
126 128 } else {
127 129 *write_offset = buflen;
128 130 }
129 131 return (retval);
130 132 }
131 133 *write_offset = sol - buf;
132 134 /* Should return a value < 0 to show that search string goes to eof */
133 135 return (-1);
134 136 }
135 137
136 138 /*
137 139 * This function sets an advisory lock on the file pointed to by the argument
138 140 * fd, which is a file descriptor. The lock is set using fcntl() which uses
139 141 * flock structure.
140 142 */
141 143 int
142 144 lock_register(int fd, int cmd, int type, off_t offset, int whence, off_t len)
143 145 {
144 146 struct flock lock;
145 147
146 148 lock.l_type = type;
147 149 lock.l_start = offset;
148 150 lock.l_whence = whence;
149 151 lock.l_len = len;
150 152
151 153 return (fcntl(fd, cmd, &lock));
152 154 }
153 155
154 156 /* Lot of places to cleanup - Less chance of missing out using this macro */
155 157 #define CLEANUP_N_RET(ret) \
156 158 if (fd != -1) { \
157 159 close(fd); \
158 160 } \
159 161 if (copy_fd != -1) { \
160 162 close(copy_fd); \
161 163 } \
162 164 if (tmp_fd != -1) { \
163 165 close(tmp_fd); \
164 166 } \
165 167 if (copy_rep != NULL) { \
166 168 remove(copy_rep); \
167 169 free(copy_rep); \
168 170 } \
169 171 if (tmp_rep != NULL) { \
170 172 remove(tmp_rep); \
171 173 free(tmp_rep); \
172 174 } \
173 175 if (upd_str != NULL) { \
174 176 free(upd_str); \
175 177 } \
176 178 if (repbuf != NULL) { \
177 179 munmap(repbuf, filesize); \
178 180 } \
179 181 if (c_repbuf != NULL) { \
180 182 munmap(c_repbuf, filesize); \
181 183 } \
182 184 if (t_repbuf != NULL) { \
183 185 munmap(t_repbuf, size); \
184 186 } \
185 187 return (ret)
186 188
187 189 /*
188 190 * INPUTS:
189 191 * cmd - ADD_ENTRY or REMOVE_ENTRY
190 192 * update_str - string for repository operation
191 193 * - Assumed NOT to have a '\n' and that it is null terminated
192 194 * errstring - Pointer that will be updated by this function
193 195 * - Any error msgs that has to be sent back to caller
194 196 *
195 197 * RETURNS :
196 198 * FPCFGA_OK on success
197 199 * FPCFGA_LIB_ERR on error
198 200 *
199 201 * SYNOPSIS:
200 202 * This function adds or deletes 'update_str' from FAB_REPOSITORY based on
201 203 * value of 'cmd'. The repository has a warning line on the top to disallow
202 204 * manual editing of the file. If the repository is being created fresh or if
203 205 * it is of zero length or if it has only warning lines in it, the operation
204 206 * speicified by 'cmd' is performed and returned. If the repository exists
205 207 * and has some data, it is expected to be of atleast the size of the lenght
206 208 * of the warning header. This is the only check that is performed on the
207 209 * validity of the file. No other checks are performed. On a valid
208 210 * repository, to perform the update, this function basically makes use of
209 211 * 3 buffers - the original buffer (repbuf), a copy buffer (c_repbuf) and a
210 212 * temp buffer (t_repbuf).
211 213 * The contents of the repository are mmap-ed into the repbuf and then
212 214 * copied into the c_repbuf. All further operations are done using the copy.
213 215 * t_repbuf is created to be the size of c_repbuf +/- 'slen' (based on
214 216 * whether it is add or remove operation). After adding/removing the
|
↓ open down ↓ |
176 lines elided |
↑ open up ↑ |
215 217 * 'update_str', the c_repbuf is copied to a OLD_FAB_REPOSITORY and t_repbuf
216 218 * is made FAB_REPOSITORY.
217 219 *
218 220 */
219 221 int
220 222 update_fabric_wwn_list(int cmd, const char *update_str, char **errstring)
221 223 {
222 224 int fd, copy_fd, tmp_fd, new_file_flag = 0;
223 225 int len, write_offset, bytes_left;
224 226 int sizeof_rep_hdr = strlen(HDR);
227 + int pid_maxlen = snprintf(NULL, 0, "%d", PID_MAX) + 1;
225 228 char *repbuf, *c_repbuf, *t_repbuf;
226 229 char *copy_rep, *tmp_rep, *upd_str;
227 230 off_t filesize, size;
228 231 struct stat stbuf;
229 232
230 233 /* Do some initializations */
231 234 fd = copy_fd = tmp_fd = -1;
232 235 repbuf = c_repbuf = t_repbuf = NULL;
233 236 copy_rep = tmp_rep = upd_str = NULL;
234 237 size = filesize = write_offset = bytes_left = 0;
235 238
236 239 /*
237 240 * Set the mode to read only. Root user can still open as RDWR.
238 241 * We ignore errors in general here. But, just notice ENOENTs
239 242 */
240 243 if ((chmod(FAB_REPOSITORY, S_IRUSR|S_IRGRP|S_IROTH) == -1) &&
241 244 (errno == ENOENT)) {
242 245 new_file_flag = 1;
243 246 mkdirp(FAB_REPOSITORY_DIR,
244 247 S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
245 248 }
246 249
247 250 /* Create the repository if its not there */
248 251 if ((fd = open(FAB_REPOSITORY, O_RDWR | O_CREAT)) == -1) {
249 252 cfga_err(errstring, errno, ERR_UPD_REP, 0);
250 253 return (FPCFGA_LIB_ERR);
251 254 }
252 255
253 256 /* Now try to chmod again. This time we dont ignore errors */
254 257 if (fchmod(fd, S_IRUSR | S_IRGRP | S_IROTH) < 0) {
255 258 close(fd);
256 259 cfga_err(errstring, errno, ERR_UPD_REP, 0);
257 260 return (FPCFGA_LIB_ERR);
258 261 }
259 262
260 263 if (lock_register(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
261 264 close(fd);
262 265 cfga_err(errstring, 0, ERR_UPD_REP, 0);
263 266 return (FPCFGA_LIB_ERR);
264 267 }
265 268
266 269 if (fstat(fd, &stbuf) == -1) {
267 270 close(fd);
268 271 cfga_err(errstring, errno, ERR_UPD_REP, 0);
269 272 return (FPCFGA_LIB_ERR);
270 273 }
271 274
272 275 filesize = size = stbuf.st_size;
273 276
274 277 /* A very Minimal check on repository */
275 278 if (filesize && filesize < sizeof_rep_hdr) {
276 279 /*
277 280 * If there is some data, it should be atleast the size of
278 281 * the header
279 282 */
280 283 close(fd);
281 284 cfga_err(errstring, errno, ERR_UPD_REP, 0);
282 285 return (FPCFGA_LIB_ERR);
283 286 }
284 287
285 288 if ((len = strlen(update_str)) == 0) {
286 289 /*
287 290 * We are trying to add/remove a NULL string.
288 291 * Just return success
289 292 */
290 293 close(fd);
291 294 return (FPCFGA_OK);
292 295 }
293 296
294 297 if ((upd_str = calloc(1, len + 2)) == NULL) {
295 298 close(fd);
|
↓ open down ↓ |
61 lines elided |
↑ open up ↑ |
296 299 cfga_err(errstring, errno, ERR_UPD_REP, 0);
297 300 return (FPCFGA_LIB_ERR);
298 301 }
299 302
300 303 strcpy(upd_str, update_str);
301 304 strcat(upd_str, "\n"); /* Append a new line char */
302 305 len = strlen(upd_str);
303 306
304 307 if (filesize > 0) {
305 308 if ((copy_rep = (char *)calloc(1, strlen(FAB_REPOSITORY) +
306 - sizeof (COPY_EXT) + sizeof (pid_t))) == NULL) {
309 + sizeof (COPY_EXT) + pid_maxlen)) == NULL) {
307 310 cfga_err(errstring, errno, ERR_UPD_REP, 0);
308 311 CLEANUP_N_RET(FPCFGA_LIB_ERR);
309 312 }
310 313
311 314 (void) sprintf(copy_rep, "%s%s%ld", FAB_REPOSITORY, COPY_EXT,
312 315 getpid());
313 316
314 317 if ((copy_fd = open(copy_rep, O_RDWR | O_CREAT | O_TRUNC,
315 318 S_IRUSR | S_IWUSR)) < 0) {
316 319 cfga_err(errstring, errno, ERR_UPD_REP, 0);
317 320 CLEANUP_N_RET(FPCFGA_LIB_ERR);
318 321 }
319 322
320 323 if ((repbuf = (char *)mmap(0, filesize, PROT_READ,
321 324 MAP_SHARED, fd, 0)) == MAP_FAILED) {
322 325 close(fd);
323 326 free(upd_str);
324 327 cfga_err(errstring, errno, ERR_UPD_REP, 0);
325 328 return (FPCFGA_LIB_ERR);
326 329 }
327 330
328 331 if (lseek(copy_fd, filesize - 1, SEEK_SET) == -1) {
329 332 cfga_err(errstring, errno, ERR_UPD_REP, 0);
330 333 CLEANUP_N_RET(FPCFGA_LIB_ERR);
331 334 }
332 335
333 336 if (write(copy_fd, "", 1) != 1) {
334 337 cfga_err(errstring, errno, ERR_UPD_REP, 0);
335 338 CLEANUP_N_RET(FPCFGA_LIB_ERR);
336 339 }
337 340
338 341 if ((c_repbuf = (char *)mmap(0, filesize,
339 342 PROT_READ | PROT_WRITE,
340 343 MAP_SHARED, copy_fd, 0)) == MAP_FAILED) {
341 344 cfga_err(errstring, errno, ERR_UPD_REP, 0);
342 345 CLEANUP_N_RET(FPCFGA_LIB_ERR);
343 346 }
344 347
345 348 memcpy(c_repbuf, repbuf, filesize);
346 349 /*
347 350 * We cannot close the repository since we hold a lock
348 351 * But we'll free up the mmap-ed area.
349 352 */
350 353 munmap(repbuf, filesize);
351 354 repbuf = NULL;
352 355 }
353 356
354 357 /*
355 358 * If we just created this file, or it was an empty repository file
356 359 * add a header to the beginning of file.
357 360 * If it had was a repository file with just the header,
358 361 */
359 362 if (new_file_flag != 0 || filesize == 0 || filesize == sizeof_rep_hdr) {
360 363 if ((filesize != sizeof_rep_hdr) &&
361 364 (write(fd, HDR, sizeof_rep_hdr) != sizeof_rep_hdr)) {
362 365 cfga_err(errstring, errno, ERR_UPD_REP, 0);
363 366 CLEANUP_N_RET(FPCFGA_LIB_ERR);
364 367 }
365 368
366 369 /*
367 370 * We know its a new file, empty file or a file with only a
368 371 * header so lets get the update operation done with
369 372 */
370 373 switch (cmd) {
371 374 case ADD_ENTRY:
372 375 /* If there is a header, we have to skip it */
373 376 if (lseek(fd, 0, SEEK_END) == -1) {
374 377 cfga_err(errstring, errno, ERR_UPD_REP, 0);
375 378 CLEANUP_N_RET(FPCFGA_LIB_ERR);
376 379 }
377 380
378 381 if (write(fd, upd_str, len) != len) {
379 382 cfga_err(errstring, errno, ERR_UPD_REP, 0);
380 383 CLEANUP_N_RET(FPCFGA_LIB_ERR);
381 384 }
382 385
383 386 if (filesize > 0) {
384 387 /* Now create the '.old' file */
385 388 if (msync(c_repbuf, filesize, MS_SYNC) == -1) {
386 389 cfga_err(errstring, errno,
387 390 ERR_UPD_REP, 0);
388 391 CLEANUP_N_RET(FPCFGA_LIB_ERR);
389 392 }
390 393
391 394 if (fchmod(copy_fd,
392 395 S_IRUSR | S_IRGRP | S_IROTH) < 0) {
393 396 cfga_err(errstring, errno,
394 397 ERR_UPD_REP, 0);
395 398 CLEANUP_N_RET(FPCFGA_LIB_ERR);
396 399 }
397 400 rename(copy_rep, OLD_FAB_REPOSITORY);
398 401 }
399 402
400 403 CLEANUP_N_RET(FPCFGA_OK);
401 404
402 405 case REMOVE_ENTRY:
403 406 /*
404 407 * So, the side effect of a remove on an empty or
405 408 * non-existing repository is that the repository got
406 409 * created
407 410 */
408 411 CLEANUP_N_RET(FPCFGA_OK);
409 412
410 413 default:
411 414 cfga_err(errstring, 0, ERR_UPD_REP, 0);
412 415 CLEANUP_N_RET(FPCFGA_LIB_ERR);
413 416 }
414 417 }
415 418
416 419 /* Now, size and filesize are > sizeof_rep_hdr */
417 420
418 421 switch (cmd) {
419 422 case ADD_ENTRY:
420 423 size += len;
421 424 /*
422 425 * We'll search the full repository, header included, since
|
↓ open down ↓ |
106 lines elided |
↑ open up ↑ |
423 426 * we dont expect upd_str to match anything in the header.
424 427 */
425 428 if (search_line(c_repbuf, filesize, upd_str,
426 429 len - 1, &write_offset, &bytes_left) == 0) {
427 430 /* line already exists in repository or len == 0 */
428 431 CLEANUP_N_RET(FPCFGA_OK); /* SUCCESS */
429 432 }
430 433
431 434 /* construct temp file name using pid. */
432 435 if ((tmp_rep = (char *)calloc(1, strlen(FAB_REPOSITORY) +
433 - sizeof (TMP_EXT) + sizeof (pid_t))) == NULL) {
436 + sizeof (TMP_EXT) + pid_maxlen)) == NULL) {
434 437 cfga_err(errstring, errno, ERR_UPD_REP, 0);
435 438 CLEANUP_N_RET(FPCFGA_LIB_ERR);
436 439 }
437 440
438 441 (void) sprintf(tmp_rep, "%s%s%ld", FAB_REPOSITORY,
439 442 TMP_EXT, getpid());
440 443
441 444 /* Open tmp repository file in absolute mode */
442 445 if ((tmp_fd = open(tmp_rep, O_RDWR|O_CREAT|O_TRUNC,
443 446 S_IRUSR | S_IWUSR)) < 0) {
444 447 cfga_err(errstring, errno, ERR_UPD_REP, 0);
445 448 CLEANUP_N_RET(FPCFGA_LIB_ERR);
446 449 }
447 450
448 451 if (lseek(tmp_fd, size - 1, SEEK_SET) == -1) {
449 452 cfga_err(errstring, errno, ERR_UPD_REP, 0);
450 453 CLEANUP_N_RET(FPCFGA_LIB_ERR);
451 454 }
452 455
453 456 if (write(tmp_fd, "", 1) != 1) {
454 457 cfga_err(errstring, errno, ERR_UPD_REP, 0);
455 458 CLEANUP_N_RET(FPCFGA_LIB_ERR);
456 459 }
457 460
458 461 if ((t_repbuf = (char *)mmap(0, size, PROT_READ|PROT_WRITE,
459 462 MAP_SHARED, tmp_fd, 0)) == MAP_FAILED) {
460 463 cfga_err(errstring, errno, ERR_UPD_REP, 0);
461 464 CLEANUP_N_RET(FPCFGA_LIB_ERR);
462 465 }
463 466
464 467 memcpy(t_repbuf, c_repbuf, write_offset);
465 468 strncpy(t_repbuf + write_offset, upd_str, len);
466 469 if (write_offset != filesize) {
467 470 memcpy(t_repbuf + write_offset + len,
468 471 c_repbuf + write_offset, bytes_left);
469 472 }
470 473
471 474 /*
472 475 * we are using the copy of FAB_REPOSITORY and will
473 476 * do msync first since it will be renamed to '.old' file.
474 477 */
475 478 if (msync(c_repbuf, filesize, MS_SYNC) == -1) {
476 479 cfga_err(errstring, errno, ERR_UPD_REP, 0);
477 480 CLEANUP_N_RET(FPCFGA_LIB_ERR);
478 481 }
479 482
480 483 if (fchmod(copy_fd, S_IRUSR | S_IRGRP | S_IROTH) < 0) {
481 484 cfga_err(errstring, errno, ERR_UPD_REP, 0);
482 485 CLEANUP_N_RET(FPCFGA_LIB_ERR);
483 486 }
484 487
485 488 if (msync(t_repbuf, size, MS_SYNC) == -1) {
486 489 cfga_err(errstring, errno, ERR_UPD_REP, 0);
487 490 CLEANUP_N_RET(FPCFGA_LIB_ERR);
488 491 }
489 492
490 493 if (fchmod(tmp_fd, S_IRUSR | S_IRGRP | S_IROTH) < 0) {
491 494 cfga_err(errstring, errno, ERR_UPD_REP, 0);
492 495 CLEANUP_N_RET(FPCFGA_LIB_ERR);
493 496 }
494 497
495 498 close(copy_fd); copy_fd = -1;
496 499 close(tmp_fd); tmp_fd = -1;
497 500
498 501 /* here we do rename and rename before close fd */
499 502 rename(copy_rep, OLD_FAB_REPOSITORY);
500 503 rename(tmp_rep, FAB_REPOSITORY);
501 504
502 505 if (lock_register(fd, F_SETLK, F_UNLCK, 0, SEEK_SET, 0) < 0) {
503 506 cfga_err(errstring, errno, ERR_UPD_REP, 0);
504 507 CLEANUP_N_RET(FPCFGA_LIB_ERR);
505 508 }
506 509
507 510 CLEANUP_N_RET(FPCFGA_OK);
508 511
509 512 case REMOVE_ENTRY:
510 513 if (size >= sizeof_rep_hdr + len - 1) {
511 514 size -= len;
512 515 /*
513 516 * No need to init the 'else' part (size < len) because
514 517 * in that case, there will be nothing to delete from
515 518 * the file and so 'size' will not be used in the code
516 519 * below since search_line() will not find upd_str.
517 520 */
|
↓ open down ↓ |
74 lines elided |
↑ open up ↑ |
518 521 }
519 522
520 523 if (search_line(c_repbuf, filesize, upd_str, len - 1,
521 524 &write_offset, &bytes_left) != 0) {
522 525 /* this line does not exists - nothing to remove */
523 526 CLEANUP_N_RET(FPCFGA_OK); /* SUCCESS */
524 527 }
525 528
526 529 /* construct temp file name using pid. */
527 530 if ((tmp_rep = (char *)calloc(1, strlen(FAB_REPOSITORY) +
528 - sizeof (TMP_EXT) + sizeof (pid_t))) == NULL) {
531 + sizeof (TMP_EXT) + pid_maxlen)) == NULL) {
529 532 cfga_err(errstring, errno, ERR_UPD_REP, 0);
530 533 CLEANUP_N_RET(FPCFGA_LIB_ERR);
531 534 }
532 535
533 536 (void) sprintf(tmp_rep, "%s%s%ld", FAB_REPOSITORY,
534 537 TMP_EXT, getpid());
535 538
536 539 /* Open tmp repository file in absolute mode */
537 540 if ((tmp_fd = open(tmp_rep, O_RDWR|O_CREAT|O_TRUNC,
538 541 S_IRUSR | S_IWUSR)) < 0) {
539 542 cfga_err(errstring, errno, ERR_UPD_REP, 0);
540 543 CLEANUP_N_RET(FPCFGA_LIB_ERR);
541 544 }
542 545
543 546 if (size > 0) {
544 547 if (lseek(tmp_fd, size - 1, SEEK_SET) == -1) {
545 548 cfga_err(errstring, errno, ERR_UPD_REP, 0);
546 549 CLEANUP_N_RET(FPCFGA_LIB_ERR);
547 550 }
548 551
549 552 if (write(tmp_fd, "", 1) != 1) {
550 553 cfga_err(errstring, errno, ERR_UPD_REP, 0);
551 554 CLEANUP_N_RET(FPCFGA_LIB_ERR);
552 555 }
553 556
554 557 if ((t_repbuf = (char *)mmap(0, size,
555 558 PROT_READ|PROT_WRITE,
556 559 MAP_SHARED, tmp_fd, 0)) == MAP_FAILED) {
557 560 cfga_err(errstring, errno, ERR_UPD_REP, 0);
558 561 CLEANUP_N_RET(FPCFGA_LIB_ERR);
559 562 }
560 563
561 564 memcpy(t_repbuf, c_repbuf, write_offset);
562 565 if ((bytes_left - len) > 0) {
563 566 memcpy(t_repbuf + write_offset,
564 567 c_repbuf + write_offset + len,
565 568 bytes_left - len);
566 569 }
567 570
568 571 if (msync(t_repbuf, size, MS_SYNC) == -1) {
569 572 cfga_err(errstring, errno, ERR_UPD_REP, 0);
570 573 CLEANUP_N_RET(FPCFGA_LIB_ERR);
571 574 }
572 575 }
573 576
574 577 if (fchmod(tmp_fd, S_IRUSR | S_IRGRP | S_IROTH) < 0) {
575 578 cfga_err(errstring, errno, ERR_UPD_REP, 0);
576 579 CLEANUP_N_RET(FPCFGA_LIB_ERR);
577 580 }
578 581
579 582 /*
580 583 * we are using the copy of FAB_REPOSITORY and will
581 584 * do msync first since it will be renamed to bak file.
582 585 */
583 586 if (msync(c_repbuf, filesize, MS_SYNC) == -1) {
584 587 cfga_err(errstring, errno, ERR_UPD_REP, 0);
585 588 CLEANUP_N_RET(FPCFGA_LIB_ERR);
586 589 }
587 590
588 591 if (fchmod(copy_fd, S_IRUSR | S_IRGRP | S_IROTH) < 0) {
589 592 cfga_err(errstring, errno, ERR_UPD_REP, 0);
590 593 CLEANUP_N_RET(FPCFGA_LIB_ERR);
591 594 }
592 595
593 596 /* Close and invalidate the fd's */
594 597 close(copy_fd); copy_fd = -1;
595 598 close(tmp_fd); tmp_fd = -1;
596 599
597 600 /* here we do rename and rename before close fd */
598 601 rename(copy_rep, OLD_FAB_REPOSITORY);
599 602 rename(tmp_rep, FAB_REPOSITORY);
600 603
601 604 if (lock_register(fd, F_SETLK, F_UNLCK, 0, SEEK_SET, 0) < 0) {
602 605 cfga_err(errstring, errno, ERR_UPD_REP, 0);
603 606 CLEANUP_N_RET(FPCFGA_LIB_ERR);
604 607 }
605 608
606 609 CLEANUP_N_RET(FPCFGA_OK);
607 610
608 611 default:
609 612 /* Unexpected - just getout */
610 613 break;
611 614 }
612 615
613 616 CLEANUP_N_RET(FPCFGA_OK); /* SUCCESS */
614 617 }
|
↓ open down ↓ |
76 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX