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