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