diff options
Diffstat (limited to 'usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_util.c')
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_util.c | 88 |
1 files changed, 86 insertions, 2 deletions
diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_util.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_util.c index 8ef9a09e3d..704dab2d36 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_util.c +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_util.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -33,8 +32,12 @@ #include <stdio.h> #include <syslog.h> #include <stdarg.h> +#include <unistd.h> +#include <errno.h> #include "ipmgmt_impl.h" +#define IPMGMT_BUFSIZ 1024 + void ipmgmt_log(int pri, const char *fmt, ...) { @@ -44,3 +47,84 @@ ipmgmt_log(int pri, const char *fmt, ...) vsyslog(pri, fmt, alist); va_end(alist); } + +/* + * Copy a source file to a new destination. The source file will be + * removed if rdonly is false (i.e., used when the source file resides + * on a read-only file system). + * + * Returns 0 on success and errno on failure. + */ +int +ipmgmt_cpfile(const char *src, const char *dst, boolean_t rdonly) +{ + struct stat statbuf; + FILE *sfp, *dfp; + char buf[IPMGMT_BUFSIZ]; + size_t bytes; + int err = 0; + + /* + * Attempt to open the destination file first since we + * want to optimize for the case where it is read-only + * and will return EROFS. + */ + if ((dfp = fopen(dst, "w+")) == NULL) + return (errno); + + /* + * Require that the source file exists. + */ + if (stat(src, &statbuf) != 0) { + err = errno; + (void) fclose(dfp); + return (err); + } + if ((sfp = fopen(src, "r")) == NULL) { + err = errno; + (void) fclose(dfp); + return (err); + } + + /* + * Copy the file. + */ + while (((bytes = fread(buf, 1, sizeof (buf), sfp)) != 0) && + (errno == 0)) { + (void) fwrite(buf, bytes, 1, dfp); + if (errno != 0) + break; + } + if (errno != 0) + err = errno; + + (void) fclose(sfp); + (void) fclose(dfp); + + /* + * If any error occurred, then remove the destination file. + */ + if (err != 0) { + (void) unlink(dst); + return (err); + } + + /* + * Make sure the file attributes are correct. + */ + if (chmod(dst, IPADM_FILE_MODE) != 0 || + chown(dst, UID_NETADM, GID_NETADM) != 0) { + err = errno; + (void) unlink(dst); + return (err); + } + + /* + * If the source file does not reside on a read-only file system + * then remove it. + */ + if (!rdonly) + (void) unlink(src); + + return (0); +} |