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