4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
45 #include <sys/types.h>
49 * consolidation pkg command library includes
55 * local pkg command library includes
62 #include "pkginstall.h"
65 * forward declarations
68 static int write_file(char **r_linknam
, int a_ctrl
, mode_t a_mode
,
70 static int create_path(int a_ctrl
, char *a_file
);
74 * Description: copy a path object (install new file on system)
76 * - a_cntrl - determine how the destination file mode is set:
77 * |= MODE_0666 - force mode to 0666
78 * |= MODE_SET - mode is a_mode (no mask SET?ID bits)
79 * |= MODE_SRC - mode from source file (mask SET?ID bits)
80 * |= DIR_DISPLAY - display "%s <implied directory>" if directory created
81 * - a_srcPath - path to source to copy
82 * - a_dstPath - path to copy source to
83 * - a_mode - mode to set a_dstpath to (mode controlled by a_ctrl)
90 cppath(int a_ctrl
, char *a_srcPath
, char *a_dstPath
, mode_t a_mode
)
92 char *linknam
= (char *)NULL
;
97 struct stat srcStatbuf
;
100 /* entry debugging info */
102 echoDebug(DBG_CPPATH_ENTRY
, a_ctrl
, a_mode
, a_srcPath
, a_dstPath
);
104 /* open source file for reading */
106 srcFd
= open(a_srcPath
, O_RDONLY
);
108 progerr(ERR_OPEN_READ
, a_srcPath
,
109 errno
, strerror(errno
));
113 /* obtain file status of source file */
115 if (fstat(srcFd
, &srcStatbuf
) != 0) {
116 progerr(ERR_FSTAT
, srcFd
, a_srcPath
, errno
, strerror(errno
));
122 * Determine the permissions mode for the destination:
123 * - if MODE_SET is specified:
124 * --> use a_mode (do not mask off any portion)
125 * --> If a_mode is unknown (? in the pkgmap), then the file gets
126 * --> installed with the default 0644 mode
127 * - if MODE_SRC is specified:
128 * --> use the mode of the source (srcStatbuf.st_mode) but mask off all
129 * --> non-access mode bits (remove SET?UID bits)
134 if (a_ctrl
& MODE_SET
) {
137 usemode
= (a_mode
^ BADMODE
) ? a_mode
: 0644;
138 if (a_mode
!= usemode
&& usemode
== 0644) {
139 logerr(WRN_DEF_MODE
, a_dstPath
);
142 } else if (a_ctrl
& MODE_SRC
) {
143 a_mode
= (srcStatbuf
.st_mode
& S_IAMB
);
149 * Get fd of newly created destination file or, if this
150 * is an overwrite, a temporary file (linknam).
153 dstFd
= write_file(&linknam
, a_ctrl
, a_mode
, a_dstPath
);
160 * source and target files are open: copy data
163 status
= copyFile(srcFd
, dstFd
, a_srcPath
, a_dstPath
, &srcStatbuf
, 0);
169 progerr(ERR_INPUT
, a_srcPath
, errno
, strerror(errno
));
171 (void) remove(linknam
);
177 * If this is an overwrite, rename temp over original
180 if ((linknam
!= (char *)NULL
) && (rename(linknam
, a_dstPath
) != 0)) {
181 FILE *logfp
= (FILE *)NULL
;
182 char busylog
[PATH_MAX
];
184 /* output log message if busy else program error */
186 if (errno
== ETXTBSY
) {
187 logerr(MSG_PROCMV
, linknam
);
189 progerr(ERR_OUTPUT_WRITING
, a_dstPath
, errno
,
193 (void) remove(linknam
);
195 /* open the log file and append log entry */
197 len
= snprintf(busylog
, sizeof (busylog
),
198 "%s/textbusy", get_PKGADM());
199 if (len
> sizeof (busylog
)) {
200 progerr(ERR_CREATE_PATH_2
, get_PKGADM(),
203 logfp
= fopen(busylog
, "a");
205 progerr(ERR_LOG
, busylog
, errno
,
208 (void) fprintf(logfp
, "%s\n", linknam
);
209 (void) fclose(logfp
);
214 /* set access/modification times for target */
216 times
.actime
= srcStatbuf
.st_atime
;
217 times
.modtime
= srcStatbuf
.st_mtime
;
219 if (utime(a_dstPath
, ×
) != 0) {
220 progerr(ERR_MODTIM
, a_dstPath
, errno
, strerror(errno
));
230 * This function creates all of the directory components of the specified path.
233 create_path(int a_ctrl
, char *a_file
)
238 for (pt
= a_file
; *pt
; pt
++) {
239 /* continue if not at path separator or at start of path */
241 if ((*pt
!= '/') || (pt
== a_file
)) {
245 /* at '/' - terminate path at current entry */
249 /* continue if path element exists */
251 if (access(a_file
, F_OK
) == 0) {
256 /* create directory in path */
258 if (mkdir(a_file
, 0755)) {
259 progerr(ERR_MAKE_DIR
, a_file
, errno
, strerror(errno
));
264 /* display 'implied directory created' message */
266 if (a_ctrl
& DIR_DISPLAY
) {
267 echo(MSG_IMPDIR
, a_file
);
280 * Description: creates a new destination file if the file does not already
281 * exist; otherwise, creates a temporary file and places a
282 * pointer to the temporary file name in 'r_linknam'.
283 * Arguments: r_linknam - pointer to (char*) where name of temporary file
284 * created is returned
285 * a_ctrl - determine if the destination file name is displayed:
286 * |= DIR_DISPLAY - display "%s <implied directory>"
287 * if directory created
288 * a_mode - permissions mode to set a_file to
289 * a_file - name of destination file to open
291 * success - file descriptor of the file it opened.
292 * failure - returns -1
296 write_file(char **r_linknam
, int a_ctrl
, mode_t a_mode
, char *a_file
)
300 static char loc_link
[PATH_MAX
];
302 /* entry debugging */
304 echoDebug(DBG_WRITEFILE_ENTRY
, a_ctrl
, a_mode
, a_file
);
306 /* reset pointer to returned 'temporary file name' */
308 *r_linknam
= (char *)NULL
;
311 * If we are overwriting an existing file, arrange to replace
315 if (access(a_file
, F_OK
) == 0) {
317 * link the file to be copied to a temporary name in case
318 * it is executing or it is being written/used (e.g., a shell
319 * script currently being executed
322 if (!RELATIVE(a_file
)) {
323 len
= snprintf(loc_link
, sizeof (loc_link
),
325 if (len
> sizeof (loc_link
)) {
326 progerr(ERR_CREATE_PATH_2
, a_file
, "XXXXXX");
329 logerr(WRN_RELATIVE
, a_file
);
330 len
= snprintf(loc_link
, sizeof (loc_link
),
331 "./%sXXXXXX", a_file
);
332 if (len
> sizeof (loc_link
)) {
333 progerr(ERR_CREATE_PATH_3
, "./", a_file
,
338 /* create and open temporary file */
340 fd
= mkstemp(loc_link
);
342 progerr(ERR_MKTEMP
, loc_link
, errno
, strerror(errno
));
346 /* remember name of temporary file */
348 *r_linknam
= loc_link
;
350 /* make sure temporary file has correct mode */
352 if (fchmod(fd
, a_mode
) < 0) {
353 progerr(ERR_FCHMOD
, loc_link
, a_mode
, errno
,
361 * We are not overwriting an existing file, create a new one directly.
364 fd
= open(a_file
, O_WRONLY
| O_CREAT
| O_TRUNC
, a_mode
);
366 if (create_path(a_ctrl
, a_file
) == 0) {
367 fd
= open(a_file
, O_WRONLY
| O_CREAT
| O_TRUNC
, a_mode
);
372 progerr(ERR_OPEN_WRITE
, a_file
, errno
, strerror(errno
));