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