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