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