5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER START
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The contents of this file are subject to the terms of the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Common Development and Distribution License (the "License").
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You may not use this file except in compliance with the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * or http://www.opensolaris.org/os/licensing.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * See the License for the specific language governing permissions
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and limitations under the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If applicable, add the following below this CDDL HEADER, with the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER END
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Use is subject to license terms.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* All Rights Reserved */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * System includes
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdio.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <string.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdlib.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <unistd.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <utime.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <locale.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <libintl.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <pkglocs.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <errno.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <fcntl.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/types.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/stat.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * consolidation pkg command library includes
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <pkglib.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * local pkg command library includes
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "libadm.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "libinst.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "install.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "messages.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "pkginstall.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * forward declarations
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int write_file(char **r_linknam, int a_ctrl, mode_t a_mode,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *a_file);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int create_path(int a_ctrl, char *a_file);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: cppath
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: copy a path object (install new file on system)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - a_cntrl - determine how the destination file mode is set:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * |= MODE_0666 - force mode to 0666
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * |= MODE_SET - mode is a_mode (no mask SET?ID bits)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * |= MODE_SRC - mode from source file (mask SET?ID bits)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * |= DIR_DISPLAY - display "%s <implied directory>" if directory created
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - a_srcPath - path to source to copy
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - a_dstPath - path to copy source to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - a_mode - mode to set a_dstpath to (mode controlled by a_ctrl)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == 0 - success
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - failure
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandcppath(int a_ctrl, char *a_srcPath, char *a_dstPath, mode_t a_mode)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *linknam = (char *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int dstFd;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int len;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int srcFd;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland long status;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct stat srcStatbuf;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct utimbuf times;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* entry debugging info */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland echoDebug(DBG_CPPATH_ENTRY, a_ctrl, a_mode, a_srcPath, a_dstPath);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* open source file for reading */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland srcFd = open(a_srcPath, O_RDONLY);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (srcFd < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(ERR_OPEN_READ, a_srcPath,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno, strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* obtain file status of source file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fstat(srcFd, &srcStatbuf) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(ERR_FSTAT, srcFd, a_srcPath, errno, strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(srcFd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Determine the permissions mode for the destination:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - if MODE_SET is specified:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * --> use a_mode (do not mask off any portion)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * --> If a_mode is unknown (? in the pkgmap), then the file gets
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * --> installed with the default 0644 mode
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - if MODE_SRC is specified:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * --> use the mode of the source (srcStatbuf.st_mode) but mask off all
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * --> non-access mode bits (remove SET?UID bits)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - otherwise:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * --> use 0666
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_ctrl & MODE_SET) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland mode_t usemode;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland usemode = (a_mode ^ BADMODE) ? a_mode : 0644;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_mode != usemode && usemode == 0644) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(WRN_DEF_MODE, a_dstPath);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_mode = usemode;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (a_ctrl & MODE_SRC) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_mode = (srcStatbuf.st_mode & S_IAMB);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_mode = 0666;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Get fd of newly created destination file or, if this
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * is an overwrite, a temporary file (linknam).
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland dstFd = write_file(&linknam, a_ctrl, a_mode, a_dstPath);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (dstFd < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(srcFd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * source and target files are open: copy data
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland status = copyFile(srcFd, dstFd, a_srcPath, a_dstPath, &srcStatbuf, 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(srcFd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(dstFd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (status != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(ERR_INPUT, a_srcPath, errno, strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (linknam) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) remove(linknam);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If this is an overwrite, rename temp over original
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((linknam != (char *)NULL) && (rename(linknam, a_dstPath) != 0)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland FILE *logfp = (FILE *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char busylog[PATH_MAX];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* output log message if busy else program error */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno == ETXTBSY) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(MSG_PROCMV, linknam);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(ERR_OUTPUT_WRITING, a_dstPath, errno,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) remove(linknam);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* open the log file and append log entry */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland len = snprintf(busylog, sizeof (busylog),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "%s/textbusy", get_PKGADM());
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (len > sizeof (busylog)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(ERR_CREATE_PATH_2, get_PKGADM(),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "textbusy");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logfp = fopen(busylog, "a");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (logfp == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(ERR_LOG, busylog, errno,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fprintf(logfp, "%s\n", linknam);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fclose(logfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* set access/modification times for target */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland times.actime = srcStatbuf.st_atime;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland times.modtime = srcStatbuf.st_mtime;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (utime(a_dstPath, &times) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(ERR_MODTIM, a_dstPath, errno, strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* success! */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This function creates all of the directory components of the specified path.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandcreate_path(int a_ctrl, char *a_file)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *pt;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int found = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (pt = a_file; *pt; pt++) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* continue if not at path separator or at start of path */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((*pt != '/') || (pt == a_file)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland continue;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* at '/' - terminate path at current entry */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *pt = '\0';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* continue if path element exists */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (access(a_file, F_OK) == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *pt = '/';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland continue;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* create directory in path */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (mkdir(a_file, 0755)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(ERR_MAKE_DIR, a_file, errno, strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *pt = '/';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* display 'implied directory created' message */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_ctrl & DIR_DISPLAY) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland echo(MSG_IMPDIR, a_file);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland found++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *pt = '/';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (!found);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: write_file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: creates a new destination file if the file does not already
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * exist; otherwise, creates a temporary file and places a
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * pointer to the temporary file name in 'r_linknam'.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: r_linknam - pointer to (char*) where name of temporary file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * created is returned
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_ctrl - determine if the destination file name is displayed:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * |= DIR_DISPLAY - display "%s <implied directory>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if directory created
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_mode - permissions mode to set a_file to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_file - name of destination file to open
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * success - file descriptor of the file it opened.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * failure - returns -1
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandwrite_file(char **r_linknam, int a_ctrl, mode_t a_mode, char *a_file)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int len;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int fd = -1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland static char loc_link[PATH_MAX];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* entry debugging */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland echoDebug(DBG_WRITEFILE_ENTRY, a_ctrl, a_mode, a_file);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset pointer to returned 'temporary file name' */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_linknam = (char *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If we are overwriting an existing file, arrange to replace
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * it transparently.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (access(a_file, F_OK) == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * link the file to be copied to a temporary name in case
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * it is executing or it is being written/used (e.g., a shell
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * script currently being executed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (!RELATIVE(a_file)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland len = snprintf(loc_link, sizeof (loc_link),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "%sXXXXXX", a_file);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (len > sizeof (loc_link)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(ERR_CREATE_PATH_2, a_file, "XXXXXX");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(WRN_RELATIVE, a_file);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland len = snprintf(loc_link, sizeof (loc_link),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "./%sXXXXXX", a_file);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (len > sizeof (loc_link)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(ERR_CREATE_PATH_3, "./", a_file,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "XXXXXX");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* create and open temporary file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland fd = mkstemp(loc_link);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fd == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(ERR_MKTEMP, loc_link, errno, strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* remember name of temporary file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_linknam = loc_link;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* make sure temporary file has correct mode */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fchmod(fd, a_mode) < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(ERR_FCHMOD, loc_link, a_mode, errno,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (fd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * We are not overwriting an existing file, create a new one directly.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland fd = open(a_file, O_WRONLY | O_CREAT | O_TRUNC, a_mode);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fd == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (create_path(a_ctrl, a_file) == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland fd = open(a_file, O_WRONLY | O_CREAT | O_TRUNC, a_mode);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fd == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(ERR_OPEN_WRITE, a_file, errno, strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (fd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}