xref: /onnv-gate/usr/src/cmd/svr4pkg/pkginstall/cppath.c (revision 9781:ccf49524d5dc)
1*9781SMoriah.Waterland@Sun.COM /*
2*9781SMoriah.Waterland@Sun.COM  * CDDL HEADER START
3*9781SMoriah.Waterland@Sun.COM  *
4*9781SMoriah.Waterland@Sun.COM  * The contents of this file are subject to the terms of the
5*9781SMoriah.Waterland@Sun.COM  * Common Development and Distribution License (the "License").
6*9781SMoriah.Waterland@Sun.COM  * You may not use this file except in compliance with the License.
7*9781SMoriah.Waterland@Sun.COM  *
8*9781SMoriah.Waterland@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9781SMoriah.Waterland@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*9781SMoriah.Waterland@Sun.COM  * See the License for the specific language governing permissions
11*9781SMoriah.Waterland@Sun.COM  * and limitations under the License.
12*9781SMoriah.Waterland@Sun.COM  *
13*9781SMoriah.Waterland@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*9781SMoriah.Waterland@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9781SMoriah.Waterland@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*9781SMoriah.Waterland@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*9781SMoriah.Waterland@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*9781SMoriah.Waterland@Sun.COM  *
19*9781SMoriah.Waterland@Sun.COM  * CDDL HEADER END
20*9781SMoriah.Waterland@Sun.COM  */
21*9781SMoriah.Waterland@Sun.COM 
22*9781SMoriah.Waterland@Sun.COM /*
23*9781SMoriah.Waterland@Sun.COM  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*9781SMoriah.Waterland@Sun.COM  * Use is subject to license terms.
25*9781SMoriah.Waterland@Sun.COM  */
26*9781SMoriah.Waterland@Sun.COM 
27*9781SMoriah.Waterland@Sun.COM /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*9781SMoriah.Waterland@Sun.COM /* All Rights Reserved */
29*9781SMoriah.Waterland@Sun.COM 
30*9781SMoriah.Waterland@Sun.COM 
31*9781SMoriah.Waterland@Sun.COM /*
32*9781SMoriah.Waterland@Sun.COM  * System includes
33*9781SMoriah.Waterland@Sun.COM  */
34*9781SMoriah.Waterland@Sun.COM 
35*9781SMoriah.Waterland@Sun.COM #include <stdio.h>
36*9781SMoriah.Waterland@Sun.COM #include <string.h>
37*9781SMoriah.Waterland@Sun.COM #include <stdlib.h>
38*9781SMoriah.Waterland@Sun.COM #include <unistd.h>
39*9781SMoriah.Waterland@Sun.COM #include <utime.h>
40*9781SMoriah.Waterland@Sun.COM #include <locale.h>
41*9781SMoriah.Waterland@Sun.COM #include <libintl.h>
42*9781SMoriah.Waterland@Sun.COM #include <pkglocs.h>
43*9781SMoriah.Waterland@Sun.COM #include <errno.h>
44*9781SMoriah.Waterland@Sun.COM #include <fcntl.h>
45*9781SMoriah.Waterland@Sun.COM #include <sys/types.h>
46*9781SMoriah.Waterland@Sun.COM #include <sys/stat.h>
47*9781SMoriah.Waterland@Sun.COM 
48*9781SMoriah.Waterland@Sun.COM /*
49*9781SMoriah.Waterland@Sun.COM  * consolidation pkg command library includes
50*9781SMoriah.Waterland@Sun.COM  */
51*9781SMoriah.Waterland@Sun.COM 
52*9781SMoriah.Waterland@Sun.COM #include <pkglib.h>
53*9781SMoriah.Waterland@Sun.COM 
54*9781SMoriah.Waterland@Sun.COM /*
55*9781SMoriah.Waterland@Sun.COM  * local pkg command library includes
56*9781SMoriah.Waterland@Sun.COM  */
57*9781SMoriah.Waterland@Sun.COM 
58*9781SMoriah.Waterland@Sun.COM #include "libadm.h"
59*9781SMoriah.Waterland@Sun.COM #include "libinst.h"
60*9781SMoriah.Waterland@Sun.COM #include "install.h"
61*9781SMoriah.Waterland@Sun.COM #include "messages.h"
62*9781SMoriah.Waterland@Sun.COM #include "pkginstall.h"
63*9781SMoriah.Waterland@Sun.COM 
64*9781SMoriah.Waterland@Sun.COM /*
65*9781SMoriah.Waterland@Sun.COM  * forward declarations
66*9781SMoriah.Waterland@Sun.COM  */
67*9781SMoriah.Waterland@Sun.COM 
68*9781SMoriah.Waterland@Sun.COM static int	write_file(char **r_linknam, int a_ctrl, mode_t a_mode,
69*9781SMoriah.Waterland@Sun.COM 			char *a_file);
70*9781SMoriah.Waterland@Sun.COM static int	create_path(int a_ctrl, char *a_file);
71*9781SMoriah.Waterland@Sun.COM 
72*9781SMoriah.Waterland@Sun.COM /*
73*9781SMoriah.Waterland@Sun.COM  * Name:	cppath
74*9781SMoriah.Waterland@Sun.COM  * Description:	copy a path object (install new file on system)
75*9781SMoriah.Waterland@Sun.COM  * Arguments:
76*9781SMoriah.Waterland@Sun.COM  *    - a_cntrl - determine how the destination file mode is set:
77*9781SMoriah.Waterland@Sun.COM  *	|= MODE_0666 - force mode to 0666
78*9781SMoriah.Waterland@Sun.COM  *      |= MODE_SET - mode is a_mode (no mask SET?ID bits)
79*9781SMoriah.Waterland@Sun.COM  *      |= MODE_SRC - mode from source file (mask SET?ID bits)
80*9781SMoriah.Waterland@Sun.COM  *      |= DIR_DISPLAY - display "%s <implied directory>" if directory created
81*9781SMoriah.Waterland@Sun.COM  *    - a_srcPath - path to source to copy
82*9781SMoriah.Waterland@Sun.COM  *    - a_dstPath - path to copy source to
83*9781SMoriah.Waterland@Sun.COM  *    - a_mode - mode to set a_dstpath to (mode controlled by a_ctrl)
84*9781SMoriah.Waterland@Sun.COM  * Returns:	int
85*9781SMoriah.Waterland@Sun.COM  *	== 0 - success
86*9781SMoriah.Waterland@Sun.COM  *	!= 0 - failure
87*9781SMoriah.Waterland@Sun.COM  */
88*9781SMoriah.Waterland@Sun.COM 
89*9781SMoriah.Waterland@Sun.COM int
cppath(int a_ctrl,char * a_srcPath,char * a_dstPath,mode_t a_mode)90*9781SMoriah.Waterland@Sun.COM cppath(int a_ctrl, char *a_srcPath, char *a_dstPath, mode_t a_mode)
91*9781SMoriah.Waterland@Sun.COM {
92*9781SMoriah.Waterland@Sun.COM 	char		*linknam = (char *)NULL;
93*9781SMoriah.Waterland@Sun.COM 	int		dstFd;
94*9781SMoriah.Waterland@Sun.COM 	int		len;
95*9781SMoriah.Waterland@Sun.COM 	int		srcFd;
96*9781SMoriah.Waterland@Sun.COM 	long		status;
97*9781SMoriah.Waterland@Sun.COM 	struct stat	srcStatbuf;
98*9781SMoriah.Waterland@Sun.COM 	struct utimbuf	times;
99*9781SMoriah.Waterland@Sun.COM 
100*9781SMoriah.Waterland@Sun.COM 	/* entry debugging info */
101*9781SMoriah.Waterland@Sun.COM 
102*9781SMoriah.Waterland@Sun.COM 	echoDebug(DBG_CPPATH_ENTRY, a_ctrl, a_mode, a_srcPath, a_dstPath);
103*9781SMoriah.Waterland@Sun.COM 
104*9781SMoriah.Waterland@Sun.COM 	/* open source file for reading */
105*9781SMoriah.Waterland@Sun.COM 
106*9781SMoriah.Waterland@Sun.COM 	srcFd = open(a_srcPath, O_RDONLY);
107*9781SMoriah.Waterland@Sun.COM 	if (srcFd < 0) {
108*9781SMoriah.Waterland@Sun.COM 		progerr(ERR_OPEN_READ, a_srcPath,
109*9781SMoriah.Waterland@Sun.COM 				errno, strerror(errno));
110*9781SMoriah.Waterland@Sun.COM 		return (1);
111*9781SMoriah.Waterland@Sun.COM 	}
112*9781SMoriah.Waterland@Sun.COM 
113*9781SMoriah.Waterland@Sun.COM 	/* obtain file status of source file */
114*9781SMoriah.Waterland@Sun.COM 
115*9781SMoriah.Waterland@Sun.COM 	if (fstat(srcFd, &srcStatbuf) != 0) {
116*9781SMoriah.Waterland@Sun.COM 		progerr(ERR_FSTAT, srcFd, a_srcPath, errno, strerror(errno));
117*9781SMoriah.Waterland@Sun.COM 		(void) close(srcFd);
118*9781SMoriah.Waterland@Sun.COM 		return (1);
119*9781SMoriah.Waterland@Sun.COM 	}
120*9781SMoriah.Waterland@Sun.COM 
121*9781SMoriah.Waterland@Sun.COM 	/*
122*9781SMoriah.Waterland@Sun.COM 	 * Determine the permissions mode for the destination:
123*9781SMoriah.Waterland@Sun.COM 	 * - if MODE_SET is specified:
124*9781SMoriah.Waterland@Sun.COM 	 * --> use a_mode (do not mask off any portion)
125*9781SMoriah.Waterland@Sun.COM 	 * --> If a_mode is unknown (? in the pkgmap), then the file gets
126*9781SMoriah.Waterland@Sun.COM 	 * --> installed with the default 0644 mode
127*9781SMoriah.Waterland@Sun.COM 	 * - if MODE_SRC is specified:
128*9781SMoriah.Waterland@Sun.COM 	 * --> use the mode of the source (srcStatbuf.st_mode) but mask off all
129*9781SMoriah.Waterland@Sun.COM 	 * --> non-access mode bits (remove SET?UID bits)
130*9781SMoriah.Waterland@Sun.COM 	 * - otherwise:
131*9781SMoriah.Waterland@Sun.COM 	 * --> use 0666
132*9781SMoriah.Waterland@Sun.COM 	 */
133*9781SMoriah.Waterland@Sun.COM 
134*9781SMoriah.Waterland@Sun.COM 	if (a_ctrl & MODE_SET) {
135*9781SMoriah.Waterland@Sun.COM 		mode_t	usemode;
136*9781SMoriah.Waterland@Sun.COM 
137*9781SMoriah.Waterland@Sun.COM 		usemode = (a_mode ^ BADMODE) ? a_mode : 0644;
138*9781SMoriah.Waterland@Sun.COM 		if (a_mode != usemode && usemode == 0644) {
139*9781SMoriah.Waterland@Sun.COM 			logerr(WRN_DEF_MODE, a_dstPath);
140*9781SMoriah.Waterland@Sun.COM 			a_mode = usemode;
141*9781SMoriah.Waterland@Sun.COM 		}
142*9781SMoriah.Waterland@Sun.COM 	} else if (a_ctrl & MODE_SRC) {
143*9781SMoriah.Waterland@Sun.COM 		a_mode = (srcStatbuf.st_mode & S_IAMB);
144*9781SMoriah.Waterland@Sun.COM 	} else {
145*9781SMoriah.Waterland@Sun.COM 		a_mode = 0666;
146*9781SMoriah.Waterland@Sun.COM 	}
147*9781SMoriah.Waterland@Sun.COM 
148*9781SMoriah.Waterland@Sun.COM 	/*
149*9781SMoriah.Waterland@Sun.COM 	 * Get fd of newly created destination file or, if this
150*9781SMoriah.Waterland@Sun.COM 	 * is an overwrite,  a temporary file (linknam).
151*9781SMoriah.Waterland@Sun.COM 	 */
152*9781SMoriah.Waterland@Sun.COM 
153*9781SMoriah.Waterland@Sun.COM 	dstFd = write_file(&linknam, a_ctrl, a_mode, a_dstPath);
154*9781SMoriah.Waterland@Sun.COM 	if (dstFd < 0) {
155*9781SMoriah.Waterland@Sun.COM 		(void) close(srcFd);
156*9781SMoriah.Waterland@Sun.COM 		return (1);
157*9781SMoriah.Waterland@Sun.COM 	}
158*9781SMoriah.Waterland@Sun.COM 
159*9781SMoriah.Waterland@Sun.COM 	/*
160*9781SMoriah.Waterland@Sun.COM 	 * source and target files are open: copy data
161*9781SMoriah.Waterland@Sun.COM 	 */
162*9781SMoriah.Waterland@Sun.COM 
163*9781SMoriah.Waterland@Sun.COM 	status = copyFile(srcFd, dstFd, a_srcPath, a_dstPath, &srcStatbuf, 0);
164*9781SMoriah.Waterland@Sun.COM 
165*9781SMoriah.Waterland@Sun.COM 	(void) close(srcFd);
166*9781SMoriah.Waterland@Sun.COM 	(void) close(dstFd);
167*9781SMoriah.Waterland@Sun.COM 
168*9781SMoriah.Waterland@Sun.COM 	if (status != 0) {
169*9781SMoriah.Waterland@Sun.COM 		progerr(ERR_INPUT, a_srcPath, errno, strerror(errno));
170*9781SMoriah.Waterland@Sun.COM 		if (linknam) {
171*9781SMoriah.Waterland@Sun.COM 			(void) remove(linknam);
172*9781SMoriah.Waterland@Sun.COM 		}
173*9781SMoriah.Waterland@Sun.COM 		return (1);
174*9781SMoriah.Waterland@Sun.COM 	}
175*9781SMoriah.Waterland@Sun.COM 
176*9781SMoriah.Waterland@Sun.COM 	/*
177*9781SMoriah.Waterland@Sun.COM 	 * If this is an overwrite, rename temp over original
178*9781SMoriah.Waterland@Sun.COM 	 */
179*9781SMoriah.Waterland@Sun.COM 
180*9781SMoriah.Waterland@Sun.COM 	if ((linknam != (char *)NULL) && (rename(linknam, a_dstPath) != 0)) {
181*9781SMoriah.Waterland@Sun.COM 		FILE	*logfp = (FILE *)NULL;
182*9781SMoriah.Waterland@Sun.COM 		char	busylog[PATH_MAX];
183*9781SMoriah.Waterland@Sun.COM 
184*9781SMoriah.Waterland@Sun.COM 		/* output log message if busy else program error */
185*9781SMoriah.Waterland@Sun.COM 
186*9781SMoriah.Waterland@Sun.COM 		if (errno == ETXTBSY) {
187*9781SMoriah.Waterland@Sun.COM 			logerr(MSG_PROCMV, linknam);
188*9781SMoriah.Waterland@Sun.COM 		} else {
189*9781SMoriah.Waterland@Sun.COM 			progerr(ERR_OUTPUT_WRITING, a_dstPath, errno,
190*9781SMoriah.Waterland@Sun.COM 				strerror(errno));
191*9781SMoriah.Waterland@Sun.COM 		}
192*9781SMoriah.Waterland@Sun.COM 
193*9781SMoriah.Waterland@Sun.COM 		(void) remove(linknam);
194*9781SMoriah.Waterland@Sun.COM 
195*9781SMoriah.Waterland@Sun.COM 		/* open the log file and append log entry */
196*9781SMoriah.Waterland@Sun.COM 
197*9781SMoriah.Waterland@Sun.COM 		len = snprintf(busylog, sizeof (busylog),
198*9781SMoriah.Waterland@Sun.COM 				"%s/textbusy", get_PKGADM());
199*9781SMoriah.Waterland@Sun.COM 		if (len > sizeof (busylog)) {
200*9781SMoriah.Waterland@Sun.COM 			progerr(ERR_CREATE_PATH_2, get_PKGADM(),
201*9781SMoriah.Waterland@Sun.COM 				"textbusy");
202*9781SMoriah.Waterland@Sun.COM 		} else {
203*9781SMoriah.Waterland@Sun.COM 			logfp = fopen(busylog, "a");
204*9781SMoriah.Waterland@Sun.COM 			if (logfp == NULL) {
205*9781SMoriah.Waterland@Sun.COM 				progerr(ERR_LOG, busylog, errno,
206*9781SMoriah.Waterland@Sun.COM 					strerror(errno));
207*9781SMoriah.Waterland@Sun.COM 			} else {
208*9781SMoriah.Waterland@Sun.COM 				(void) fprintf(logfp, "%s\n", linknam);
209*9781SMoriah.Waterland@Sun.COM 				(void) fclose(logfp);
210*9781SMoriah.Waterland@Sun.COM 			}
211*9781SMoriah.Waterland@Sun.COM 		}
212*9781SMoriah.Waterland@Sun.COM 	}
213*9781SMoriah.Waterland@Sun.COM 
214*9781SMoriah.Waterland@Sun.COM 	/* set access/modification times for target */
215*9781SMoriah.Waterland@Sun.COM 
216*9781SMoriah.Waterland@Sun.COM 	times.actime = srcStatbuf.st_atime;
217*9781SMoriah.Waterland@Sun.COM 	times.modtime = srcStatbuf.st_mtime;
218*9781SMoriah.Waterland@Sun.COM 
219*9781SMoriah.Waterland@Sun.COM 	if (utime(a_dstPath, &times) != 0) {
220*9781SMoriah.Waterland@Sun.COM 		progerr(ERR_MODTIM, a_dstPath, errno, strerror(errno));
221*9781SMoriah.Waterland@Sun.COM 		return (1);
222*9781SMoriah.Waterland@Sun.COM 	}
223*9781SMoriah.Waterland@Sun.COM 
224*9781SMoriah.Waterland@Sun.COM 	/* success! */
225*9781SMoriah.Waterland@Sun.COM 
226*9781SMoriah.Waterland@Sun.COM 	return (0);
227*9781SMoriah.Waterland@Sun.COM }
228*9781SMoriah.Waterland@Sun.COM 
229*9781SMoriah.Waterland@Sun.COM /*
230*9781SMoriah.Waterland@Sun.COM  * This function creates all of the directory components of the specified path.
231*9781SMoriah.Waterland@Sun.COM  */
232*9781SMoriah.Waterland@Sun.COM static int
create_path(int a_ctrl,char * a_file)233*9781SMoriah.Waterland@Sun.COM create_path(int a_ctrl, char *a_file)
234*9781SMoriah.Waterland@Sun.COM {
235*9781SMoriah.Waterland@Sun.COM 	char	*pt;
236*9781SMoriah.Waterland@Sun.COM 	int	found = 0;
237*9781SMoriah.Waterland@Sun.COM 
238*9781SMoriah.Waterland@Sun.COM 	for (pt = a_file; *pt; pt++) {
239*9781SMoriah.Waterland@Sun.COM 		/* continue if not at path separator or at start of path */
240*9781SMoriah.Waterland@Sun.COM 
241*9781SMoriah.Waterland@Sun.COM 		if ((*pt != '/') || (pt == a_file)) {
242*9781SMoriah.Waterland@Sun.COM 			continue;
243*9781SMoriah.Waterland@Sun.COM 		}
244*9781SMoriah.Waterland@Sun.COM 
245*9781SMoriah.Waterland@Sun.COM 		/* at '/' - terminate path at current entry */
246*9781SMoriah.Waterland@Sun.COM 
247*9781SMoriah.Waterland@Sun.COM 		*pt = '\0';
248*9781SMoriah.Waterland@Sun.COM 
249*9781SMoriah.Waterland@Sun.COM 		/* continue if path element exists */
250*9781SMoriah.Waterland@Sun.COM 
251*9781SMoriah.Waterland@Sun.COM 		if (access(a_file, F_OK) == 0) {
252*9781SMoriah.Waterland@Sun.COM 			*pt = '/';
253*9781SMoriah.Waterland@Sun.COM 			continue;
254*9781SMoriah.Waterland@Sun.COM 		}
255*9781SMoriah.Waterland@Sun.COM 
256*9781SMoriah.Waterland@Sun.COM 		/* create directory in path */
257*9781SMoriah.Waterland@Sun.COM 
258*9781SMoriah.Waterland@Sun.COM 		if (mkdir(a_file, 0755)) {
259*9781SMoriah.Waterland@Sun.COM 			progerr(ERR_MAKE_DIR, a_file, errno, strerror(errno));
260*9781SMoriah.Waterland@Sun.COM 			*pt = '/';
261*9781SMoriah.Waterland@Sun.COM 			return (1);
262*9781SMoriah.Waterland@Sun.COM 		}
263*9781SMoriah.Waterland@Sun.COM 
264*9781SMoriah.Waterland@Sun.COM 		/* display 'implied directory created' message */
265*9781SMoriah.Waterland@Sun.COM 
266*9781SMoriah.Waterland@Sun.COM 		if (a_ctrl & DIR_DISPLAY) {
267*9781SMoriah.Waterland@Sun.COM 			echo(MSG_IMPDIR, a_file);
268*9781SMoriah.Waterland@Sun.COM 		}
269*9781SMoriah.Waterland@Sun.COM 
270*9781SMoriah.Waterland@Sun.COM 		found++;
271*9781SMoriah.Waterland@Sun.COM 
272*9781SMoriah.Waterland@Sun.COM 		*pt = '/';
273*9781SMoriah.Waterland@Sun.COM 	}
274*9781SMoriah.Waterland@Sun.COM 
275*9781SMoriah.Waterland@Sun.COM 	return (!found);
276*9781SMoriah.Waterland@Sun.COM }
277*9781SMoriah.Waterland@Sun.COM 
278*9781SMoriah.Waterland@Sun.COM /*
279*9781SMoriah.Waterland@Sun.COM  * Name:	write_file
280*9781SMoriah.Waterland@Sun.COM  * Description:	creates a new destination file if the file does not already
281*9781SMoriah.Waterland@Sun.COM  *		exist; otherwise, creates a temporary file and places a
282*9781SMoriah.Waterland@Sun.COM  *		pointer to the temporary file name in 'r_linknam'.
283*9781SMoriah.Waterland@Sun.COM  * Arguments:	r_linknam - pointer to (char*) where name of temporary file
284*9781SMoriah.Waterland@Sun.COM  *			created is returned
285*9781SMoriah.Waterland@Sun.COM  *		a_ctrl - determine if the destination file name is displayed:
286*9781SMoriah.Waterland@Sun.COM  *		     |= DIR_DISPLAY - display "%s <implied directory>"
287*9781SMoriah.Waterland@Sun.COM  *			if directory created
288*9781SMoriah.Waterland@Sun.COM  *		a_mode - permissions mode to set a_file to
289*9781SMoriah.Waterland@Sun.COM  *		a_file - name of destination file to open
290*9781SMoriah.Waterland@Sun.COM  * Returns:	int
291*9781SMoriah.Waterland@Sun.COM  *			success - file descriptor of the file it opened.
292*9781SMoriah.Waterland@Sun.COM  *			failure - returns -1
293*9781SMoriah.Waterland@Sun.COM  */
294*9781SMoriah.Waterland@Sun.COM 
295*9781SMoriah.Waterland@Sun.COM static int
write_file(char ** r_linknam,int a_ctrl,mode_t a_mode,char * a_file)296*9781SMoriah.Waterland@Sun.COM write_file(char **r_linknam, int a_ctrl, mode_t a_mode, char *a_file)
297*9781SMoriah.Waterland@Sun.COM {
298*9781SMoriah.Waterland@Sun.COM 	int		len;
299*9781SMoriah.Waterland@Sun.COM 	int		fd = -1;
300*9781SMoriah.Waterland@Sun.COM 	static char	loc_link[PATH_MAX];
301*9781SMoriah.Waterland@Sun.COM 
302*9781SMoriah.Waterland@Sun.COM 	/* entry debugging */
303*9781SMoriah.Waterland@Sun.COM 
304*9781SMoriah.Waterland@Sun.COM 	echoDebug(DBG_WRITEFILE_ENTRY, a_ctrl, a_mode, a_file);
305*9781SMoriah.Waterland@Sun.COM 
306*9781SMoriah.Waterland@Sun.COM 	/* reset pointer to returned 'temporary file name' */
307*9781SMoriah.Waterland@Sun.COM 
308*9781SMoriah.Waterland@Sun.COM 	*r_linknam = (char *)NULL;
309*9781SMoriah.Waterland@Sun.COM 
310*9781SMoriah.Waterland@Sun.COM 	/*
311*9781SMoriah.Waterland@Sun.COM 	 * If we are overwriting an existing file, arrange to replace
312*9781SMoriah.Waterland@Sun.COM 	 * it transparently.
313*9781SMoriah.Waterland@Sun.COM 	 */
314*9781SMoriah.Waterland@Sun.COM 
315*9781SMoriah.Waterland@Sun.COM 	if (access(a_file, F_OK) == 0) {
316*9781SMoriah.Waterland@Sun.COM 		/*
317*9781SMoriah.Waterland@Sun.COM 		 * link the file to be copied to a temporary name in case
318*9781SMoriah.Waterland@Sun.COM 		 * it is executing or it is being written/used (e.g., a shell
319*9781SMoriah.Waterland@Sun.COM 		 * script currently being executed
320*9781SMoriah.Waterland@Sun.COM 		 */
321*9781SMoriah.Waterland@Sun.COM 
322*9781SMoriah.Waterland@Sun.COM 		if (!RELATIVE(a_file)) {
323*9781SMoriah.Waterland@Sun.COM 			len = snprintf(loc_link, sizeof (loc_link),
324*9781SMoriah.Waterland@Sun.COM 					"%sXXXXXX", a_file);
325*9781SMoriah.Waterland@Sun.COM 			if (len > sizeof (loc_link)) {
326*9781SMoriah.Waterland@Sun.COM 				progerr(ERR_CREATE_PATH_2, a_file, "XXXXXX");
327*9781SMoriah.Waterland@Sun.COM 			}
328*9781SMoriah.Waterland@Sun.COM 		} else {
329*9781SMoriah.Waterland@Sun.COM 			logerr(WRN_RELATIVE, a_file);
330*9781SMoriah.Waterland@Sun.COM 			len = snprintf(loc_link, sizeof (loc_link),
331*9781SMoriah.Waterland@Sun.COM 					"./%sXXXXXX", a_file);
332*9781SMoriah.Waterland@Sun.COM 			if (len > sizeof (loc_link)) {
333*9781SMoriah.Waterland@Sun.COM 				progerr(ERR_CREATE_PATH_3, "./", a_file,
334*9781SMoriah.Waterland@Sun.COM 					"XXXXXX");
335*9781SMoriah.Waterland@Sun.COM 			}
336*9781SMoriah.Waterland@Sun.COM 		}
337*9781SMoriah.Waterland@Sun.COM 
338*9781SMoriah.Waterland@Sun.COM 		/* create and open temporary file */
339*9781SMoriah.Waterland@Sun.COM 
340*9781SMoriah.Waterland@Sun.COM 		fd = mkstemp(loc_link);
341*9781SMoriah.Waterland@Sun.COM 		if (fd == -1) {
342*9781SMoriah.Waterland@Sun.COM 			progerr(ERR_MKTEMP, loc_link, errno, strerror(errno));
343*9781SMoriah.Waterland@Sun.COM 			return (-1);
344*9781SMoriah.Waterland@Sun.COM 		}
345*9781SMoriah.Waterland@Sun.COM 
346*9781SMoriah.Waterland@Sun.COM 		/* remember name of temporary file */
347*9781SMoriah.Waterland@Sun.COM 
348*9781SMoriah.Waterland@Sun.COM 		*r_linknam = loc_link;
349*9781SMoriah.Waterland@Sun.COM 
350*9781SMoriah.Waterland@Sun.COM 		/* make sure temporary file has correct mode */
351*9781SMoriah.Waterland@Sun.COM 
352*9781SMoriah.Waterland@Sun.COM 		if (fchmod(fd, a_mode) < 0) {
353*9781SMoriah.Waterland@Sun.COM 			progerr(ERR_FCHMOD, loc_link, a_mode, errno,
354*9781SMoriah.Waterland@Sun.COM 				strerror(errno));
355*9781SMoriah.Waterland@Sun.COM 		}
356*9781SMoriah.Waterland@Sun.COM 
357*9781SMoriah.Waterland@Sun.COM 		return (fd);
358*9781SMoriah.Waterland@Sun.COM 	}
359*9781SMoriah.Waterland@Sun.COM 
360*9781SMoriah.Waterland@Sun.COM 	/*
361*9781SMoriah.Waterland@Sun.COM 	 * We are not overwriting an existing file, create a new one directly.
362*9781SMoriah.Waterland@Sun.COM 	 */
363*9781SMoriah.Waterland@Sun.COM 
364*9781SMoriah.Waterland@Sun.COM 	fd = open(a_file, O_WRONLY | O_CREAT | O_TRUNC, a_mode);
365*9781SMoriah.Waterland@Sun.COM 	if (fd == -1) {
366*9781SMoriah.Waterland@Sun.COM 		if (create_path(a_ctrl, a_file) == 0) {
367*9781SMoriah.Waterland@Sun.COM 			fd = open(a_file, O_WRONLY | O_CREAT | O_TRUNC, a_mode);
368*9781SMoriah.Waterland@Sun.COM 		}
369*9781SMoriah.Waterland@Sun.COM 	}
370*9781SMoriah.Waterland@Sun.COM 
371*9781SMoriah.Waterland@Sun.COM 	if (fd == -1) {
372*9781SMoriah.Waterland@Sun.COM 		progerr(ERR_OPEN_WRITE, a_file, errno, strerror(errno));
373*9781SMoriah.Waterland@Sun.COM 	}
374*9781SMoriah.Waterland@Sun.COM 
375*9781SMoriah.Waterland@Sun.COM 	return (fd);
376*9781SMoriah.Waterland@Sun.COM }
377