1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <stdio.h> 27 #include <strings.h> 28 #include <sys/stat.h> 29 #include <sys/types.h> 30 #include <sys/mount.h> 31 #include <sys/mntent.h> 32 #include <unistd.h> 33 34 /* 35 * This program aids the Solaris 10 patch tools (specifically 36 * /usr/lib/patch/patch_common_lib) in DAP patching. 37 * 38 * Whenever the patch tools replace a critical system component (e.g., 39 * /lib/libc.so.1), they move the old component to a temporary location, 40 * move the new component to where the old component was, and establish 41 * an overlay mount of the old component on top of the new component. 42 * The patch tools do this with a shell script; consequently, the three 43 * operations occur in three processes. 44 * 45 * This doesn't work inside Solaris 10 Containers (S10Cs). Suppose the 46 * patch tools need to replace /lib/libc.so.1. The tools will move the old 47 * libc.so.1 to a temporary location. But when they try to move the new 48 * libc.so.1, they fork a mv(1) process, which loads the solaris10 brand's 49 * emulation library. The emulation library will try to load the zone's 50 * libc.so.1, but the library no longer exists; consequently, the emulation 51 * library aborts and the zone's users won't be able to start any processes. 52 * 53 * This program solves the problem by combining the move and mount operations 54 * into a single process. The emulation library will already have loaded 55 * libc.so.1 for the process by the time the process starts to replace 56 * libc.so.1. 57 * 58 * This program takes six parameters that correspond to six variables within 59 * /usr/lib/patch/patch_common_lib:InstallSafemodeObject(): 60 * 61 * argv[1] - dstActual (the path to the file that will be replaced) 62 * argv[2] - tmp_file (the temporary location to which the file will be 63 * moved) 64 * argv[3] - tmpDst (the path to the replacement file) 65 * argv[4] - tmpFile (the path to a temporary copy of the running system's 66 * version of the file being replaced; the source [special] of 67 * the overlay mount) 68 * argv[5] - cksumTmpDst (checksum of the file represented by tmpDst) 69 * argv[6] - cksumTmpFile (checksum of the file represented by tmpFile) 70 * 71 * NOTE: This program will only establish an overlay mount if argv[4] or argv[5] 72 * is emtpy or if argv[4] and argv[5] differ. 73 * 74 * This program returns zero when it succeeds. Non-negative values indicate 75 * failure. 76 */ 77 int 78 main(int argc, char **argv) 79 { 80 struct stat statbuf; 81 char mntoptions[MAX_MNTOPT_STR]; 82 83 /* 84 * Check the number of arguments that were passed to s10_replacefile. 85 */ 86 if (argc != 7) { 87 (void) fprintf(stderr, "Usage: %s dstActual tmp_file tmpDst " 88 "tmpFile cksumTmpDst cksumTmpFile\n", argv[0]); 89 return (1); 90 } 91 92 /* 93 * Move the destination file (dstActual) out of the way and move the 94 * new file (tmpDst) into its place. 95 * 96 * NOTE: s10_replacefile won't print error messages here because 97 * the Solaris 10 patch tools will. 98 */ 99 if (rename(argv[1], argv[2]) != 0) 100 return (2); 101 if (rename(argv[3], argv[1]) != 0) 102 return (3); 103 104 /* 105 * If there was a lofs mount on dstActual (which we just moved), then 106 * s10_replacefile should reestablish the lofs mount. A lofs mount 107 * existed if tmpFile exists. 108 */ 109 if (stat(argv[4], &statbuf) == 0 && (statbuf.st_mode & S_IFREG)) { 110 /* 111 * Create a lofs overlay mount only if the checksums of the 112 * old file at dstActual and the new file at dstActual differ. 113 */ 114 if (argv[5][0] == '\0' || argv[6][0] == '\0' || 115 strcmp(argv[5], argv[6]) != 0) { 116 mntoptions[0] = '\0'; 117 if (mount(argv[4], argv[1], MS_OVERLAY | MS_OPTIONSTR, 118 MNTTYPE_LOFS, NULL, 0, mntoptions, 119 sizeof (mntoptions)) != 0) { 120 /* 121 * Although the patch tools will print error 122 * messages, the tools won't know that 123 * s10_replacefile failed to establish an 124 * overlay mount. Printing an error message 125 * here clarifies the problem for the user. 126 */ 127 (void) fprintf(stderr, "ERROR: Failed to " 128 "overlay mount %s onto %s\n", argv[4], 129 argv[1]); 130 return (4); 131 } 132 } else { 133 /* 134 * dstActual does not need an overlay mount. Delete 135 * tmpFile. 136 */ 137 (void) unlink(argv[4]); 138 } 139 } 140 return (0); 141 } 142