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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Change the label of a file 30 */ 31 32 #include <ctype.h> 33 #include <locale.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <strings.h> 37 #include <errno.h> 38 39 #include <tsol/label.h> 40 41 #include "labeld.h" 42 #include <sys/tsol/label_macro.h> 43 44 #include <sys/types.h> 45 46 #include <zone.h> 47 #include <sys/zone.h> 48 #include <sys/param.h> 49 #include <string.h> 50 51 static int abspath(char *, const char *, char *); 52 53 /* 54 * setflabel(3TSOL) - set file label 55 * 56 * This is the library interface to the door call. 57 */ 58 59 #define clcall callp->param.acall.cargs.setfbcl_arg 60 #define clret callp->param.aret.rvals.setfbcl_ret 61 /* 62 * 63 * Exit error = If error reported, the error indicator, 64 * -1, Unable to access label encodings file; 65 * 0, Invalid binary label passed; 66 * >0, Position after the first character in 67 * string of error, 1 indicates entire string. 68 * Otherwise, unchanged. 69 * 70 * Returns 0, If error. 71 * 1, If successful. 72 * 73 * Calls __call_labeld(SETFLABEL) 74 * 75 */ 76 77 int 78 setflabel(const char *path, m_label_t *label) 79 { 80 labeld_data_t call; 81 labeld_data_t *callp = &call; 82 size_t bufsize = sizeof (labeld_data_t); 83 size_t datasize; 84 size_t path_len; 85 static char cwd[MAXPATHLEN]; 86 char canon[MAXPATHLEN]; 87 88 89 /* 90 * If path is relative and we haven't already determined the current 91 * working directory, do so now. Calculating the working directory 92 * here lets us do the work once, instead of (potentially) repeatedly 93 * in realpath(). 94 */ 95 if (*path != '/' && cwd[0] == '\0') { 96 if (getcwd(cwd, MAXPATHLEN) == NULL) { 97 cwd[0] = '\0'; 98 return (-1); 99 } 100 } 101 /* 102 * Find an absolute pathname in the native file system name space that 103 * corresponds to path, stuffing it into canon. 104 */ 105 if (abspath(cwd, path, canon) < 0) 106 return (-1); 107 108 path_len = strlen(canon) + 1; 109 110 datasize = CALL_SIZE(setfbcl_call_t, path_len - BUFSIZE); 111 datasize += 2; /* PAD */ 112 113 if (datasize > bufsize) { 114 if ((callp = (labeld_data_t *)malloc(datasize)) == NULL) { 115 return (-1); 116 } 117 bufsize = datasize; 118 } 119 120 callp->callop = SETFLABEL; 121 122 clcall.sl = *label; 123 (void) strcpy(clcall.pathname, canon); 124 125 if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) { 126 int err = callp->reterr; 127 128 if (callp != &call) { 129 /* free allocated buffer */ 130 free(callp); 131 } 132 /* 133 * reterr == 0, OK, 134 * reterr < 0, invalid binary label, 135 */ 136 if (err == 0) { 137 if (clret.status > 0) { 138 errno = clret.status; 139 return (-1); 140 } else { 141 return (0); 142 } 143 } else if (err < 0) { 144 err = 0; 145 } 146 errno = ECONNREFUSED; 147 return (-1); 148 } else { 149 if (callp != &call) { 150 /* free allocated buffer */ 151 free(callp); 152 } 153 /* server not present */ 154 errno = ECONNREFUSED; 155 return (-1); 156 } 157 } /* setflabel */ 158 159 #undef clcall 160 #undef clret 161 162 #define clcall callp->param.acall.cargs.zcopy_arg 163 #define clret callp->param.aret.rvals.zcopy_ret 164 /* 165 * 166 * Exit status = result of zone copy request 167 * -1, Copy not confirmed 168 * Otherwise, unchanged. 169 * 170 * Returns 0, If error. 171 * 1, If successful. 172 * 173 * Calls __call_labeld(ZCOPY) 174 * 175 */ 176 int 177 zonecopy(m_label_t *src_win_sl, char *remote_dir, char *filename, 178 char *local_dir, int transfer_mode) 179 { 180 labeld_data_t call; 181 labeld_data_t *callp = &call; 182 size_t bufsize = sizeof (labeld_data_t); 183 size_t datasize; 184 size_t strings; 185 size_t remote_dir_len; 186 size_t filename_len; 187 size_t local_dir_len; 188 size_t display_len; 189 char *display; 190 191 remote_dir_len = strlen(remote_dir) + 1; 192 filename_len = strlen(filename) + 1; 193 local_dir_len = strlen(local_dir) + 1; 194 195 if ((display = getenv("DISPLAY")) == NULL) 196 display = ""; 197 display_len = strlen(display) + 1; 198 199 strings = remote_dir_len + filename_len + local_dir_len + display_len; 200 201 datasize = CALL_SIZE(zcopy_call_t, strings - BUFSIZE); 202 203 datasize += 4; /* PAD */ 204 205 if (datasize > bufsize) { 206 if ((callp = (labeld_data_t *)malloc(datasize)) == NULL) { 207 return (NULL); 208 } 209 bufsize = datasize; 210 } 211 212 strings = 0; 213 callp->callop = ZCOPY; 214 215 clcall.src_win_sl = *src_win_sl; 216 clcall.transfer_mode = transfer_mode; 217 clcall.remote_dir = strings; 218 strings += remote_dir_len; 219 clcall.filename = strings; 220 strings += filename_len; 221 clcall.local_dir = strings; 222 strings += local_dir_len; 223 clcall.display = strings; 224 225 (void) strcpy(&clcall.buf[clcall.remote_dir], remote_dir); 226 (void) strcpy(&clcall.buf[clcall.filename], filename); 227 (void) strcpy(&clcall.buf[clcall.local_dir], local_dir); 228 (void) strcpy(&clcall.buf[clcall.display], display); 229 230 if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) { 231 int err = callp->reterr; 232 233 if (callp != &call) { 234 /* free allocated buffer */ 235 free(callp); 236 } 237 /* 238 * reterr == 0, OK, 239 * reterr < 0, transer not confirmed 240 */ 241 if (err == 0) { 242 return (clret.status); 243 } else if (err < 0) { 244 err = 0; 245 } 246 return (PIPEMSG_CANCEL); 247 } else { 248 if (callp != &call) { 249 /* free allocated buffer */ 250 free(callp); 251 } 252 /* server not present */ 253 return (PIPEMSG_CANCEL); 254 } 255 } 256 257 /* 258 * Convert the path given in raw to canonical, absolute, symlink-free 259 * form, storing the result in the buffer named by canon, which must be 260 * at least MAXPATHLEN bytes long. If wd is non-NULL, assume that it 261 * points to a path for the current working directory and use it instead 262 * of invoking getcwd; accepting this value as an argument lets our caller 263 * cache the value, so that realpath (called from this routine) doesn't have 264 * to recalculate it each time it's given a relative pathname. 265 * 266 * Return 0 on success, -1 on failure. 267 */ 268 int 269 abspath(char *wd, const char *raw, char *canon) 270 { 271 char absbuf[MAXPATHLEN]; 272 273 /* 274 * Preliminary sanity check. 275 */ 276 if (raw == NULL || canon == NULL) 277 return (-1); 278 279 /* 280 * If the path is relative, convert it to absolute form, 281 * using wd if it's been supplied. 282 */ 283 if (raw[0] != '/') { 284 char *limit = absbuf + sizeof (absbuf); 285 char *d; 286 287 /* Fill in working directory. */ 288 if (wd != NULL) 289 (void) strncpy(absbuf, wd, sizeof (absbuf)); 290 else if (getcwd(absbuf, strlen(absbuf)) == NULL) 291 return (-1); 292 293 /* Add separating slash. */ 294 d = absbuf + strlen(absbuf); 295 if (d < limit) 296 *d++ = '/'; 297 298 /* Glue on the relative part of the path. */ 299 while (d < limit && (*d++ = *raw++)) 300 continue; 301 302 raw = absbuf; 303 } 304 305 /* 306 * Call realpath to canonicalize and resolve symlinks. 307 */ 308 return (realpath(raw, canon) == NULL ? -1 : 0); 309 } 310