isdir.c revision 9781:ccf49524d5dc
1343181Sdim/* 2343181Sdim * CDDL HEADER START 3353358Sdim * 4353358Sdim * The contents of this file are subject to the terms of the 5353358Sdim * Common Development and Distribution License (the "License"). 6343181Sdim * You may not use this file except in compliance with the License. 7343181Sdim * 8343181Sdim * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9343181Sdim * or http://www.opensolaris.org/os/licensing. 10343181Sdim * See the License for the specific language governing permissions 11343181Sdim * and limitations under the License. 12343181Sdim * 13343181Sdim * When distributing Covered Code, include this CDDL HEADER in each 14343181Sdim * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15343181Sdim * If applicable, add the following below this CDDL HEADER, with the 16343181Sdim * fields enclosed by brackets "[]" replaced with your own identifying 17343181Sdim * information: Portions Copyright [yyyy] [name of copyright owner] 18343181Sdim * 19343181Sdim * CDDL HEADER END 20343181Sdim */ 21343181Sdim 22343181Sdim/* 23343181Sdim * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24343181Sdim * Use is subject to license terms. 25343181Sdim */ 26343181Sdim 27343181Sdim/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28343181Sdim/* All Rights Reserved */ 29343181Sdim 30343181Sdim 31343181Sdim#include <stdio.h> 32343181Sdim#include <sys/types.h> 33343181Sdim#include <sys/stat.h> 34343181Sdim#include <archives.h> 35343181Sdim#include <errno.h> 36343181Sdim#include <fcntl.h> 37343181Sdim#include <limits.h> 38343181Sdim#include <stdlib.h> 39343181Sdim#include <unistd.h> 40343181Sdim#include <string.h> 41343181Sdim#include "pkglocale.h" 42343181Sdim#include "pkglibmsgs.h" 43343181Sdim 44343181Sdim/* 45343181Sdim * Defines for cpio/compression checks. 46343181Sdim */ 47343181Sdim#define BIT_MASK 0x1f 48343181Sdim#define BLOCK_MASK 0x80 49343181Sdim 50343181Sdim#define MASK_CK(x, y) (((x) & (y)) == (y)) 51343181Sdim#define ISCOMPCPIO ((unsigned char) cm.c_mag[0] == m_h[0] && \ 52343181Sdim (unsigned char) cm.c_mag[1] == m_h[1] && \ 53343181Sdim (MASK_CK((unsigned char) cm.c_mag[2], BLOCK_MASK) || \ 54343181Sdim MASK_CK((unsigned char) cm.c_mag[2], BIT_MASK))) 55343181Sdim 56343181Sdim#define ISCPIO (cm.b_mag != CMN_BIN && \ 57343181Sdim (strcmp(cm.c_mag, CMS_ASC) == 0) && \ 58343181Sdim (strcmp(cm.c_mag, CMS_CHR) == 0) && \ 59343181Sdim (strcmp(cm.c_mag, CMS_CRC) == 0)) 60343181Sdim 61343181Sdim/* location of distributed file system types database */ 62343181Sdim 63343181Sdim#define REMOTE_FS_DBFILE "/etc/dfs/fstypes" 64343181Sdim 65343181Sdim/* character array used to hold dfs types database contents */ 66343181Sdim 67343181Sdimstatic long numRemoteFstypes = -1; 68343181Sdimstatic char **remoteFstypes = (char **)NULL; 69343181Sdim 70343181Sdim/* forward declarations */ 71343181Sdim 72343181Sdimstatic void _InitRemoteFstypes(void); 73343181Sdim 74343181Sdimint isFdRemote(int a_fd); 75343181Sdimint isPathRemote(char *a_path); 76343181Sdimint isFstypeRemote(char *a_fstype); 77343181Sdimint isdir(char *path); 78343181Sdimint isfile(char *dir, char *file); 79343181Sdimint iscpio(char *path, int *iscomp); 80343181Sdim 81343181Sdim/* 82343181Sdim * Name: isdir 83343181Sdim * Description: determine if specified path exists and is a directory 84343181Sdim * Arguments: path - pointer to string representing the path to verify 85343181Sdim * returns: 0 - directory exists 86343181Sdim * 1 - directory does not exist or is not a directory 87343181Sdim * NOTE: errno is set appropriately 88343181Sdim */ 89343181Sdim 90343181Sdimint 91343181Sdimisdir(char *path) 92343181Sdim{ 93343181Sdim struct stat statbuf; 94343181Sdim 95343181Sdim /* return error if path does not exist */ 96343181Sdim 97343181Sdim if (stat(path, &statbuf) != 0) { 98343181Sdim return (1); 99343181Sdim } 100343181Sdim 101343181Sdim /* return error if path is not a directory */ 102343181Sdim 103343181Sdim if ((statbuf.st_mode & S_IFMT) != S_IFDIR) { 104343181Sdim errno = ENOTDIR; 105343181Sdim return (1); 106343181Sdim } 107343181Sdim 108343181Sdim return (0); 109343181Sdim} 110343181Sdim 111343181Sdim/* 112343181Sdim * Name: isfile 113343181Sdim * Description: determine if specified path exists and is a directory 114343181Sdim * Arguments: dir - pointer to string representing the directory where 115343181Sdim * the file is located 116343181Sdim * == NULL - use "file" argument only 117343181Sdim * file - pointer to string representing the file to verify 118343181Sdim * Returns: 0 - success - file exists 119343181Sdim * 1 - failure - file does not exist OR is not a file 120343181Sdim * NOTE: errno is set appropriately 121343181Sdim */ 122343181Sdim 123343181Sdimint 124343181Sdimisfile(char *dir, char *file) 125343181Sdim{ 126343181Sdim struct stat statbuf; 127343181Sdim char path[PATH_MAX]; 128343181Sdim 129343181Sdim /* construct full path if directory specified */ 130360784Sdim 131360784Sdim if (dir) { 132360784Sdim (void) snprintf(path, sizeof (path), "%s/%s", dir, file); 133360784Sdim file = path; 134343181Sdim } 135343181Sdim 136343181Sdim /* return error if path does not exist */ 137343181Sdim 138343181Sdim if (stat(file, &statbuf) != 0) { 139343181Sdim return (1); 140343181Sdim } 141343181Sdim 142343181Sdim /* return error if path is a directory */ 143343181Sdim 144343181Sdim if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { 145343181Sdim errno = EISDIR; 146343181Sdim return (1); 147343181Sdim } 148343181Sdim 149343181Sdim /* return error if path is not a file */ 150343181Sdim 151343181Sdim if ((statbuf.st_mode & S_IFMT) != S_IFREG) { 152343181Sdim errno = EINVAL; 153343181Sdim return (1); 154343181Sdim } 155343181Sdim 156343181Sdim return (0); 157343181Sdim} 158343181Sdim 159343181Sdimint 160343181Sdimiscpio(char *path, int *iscomp) 161343181Sdim{ 162343181Sdim /* 163343181Sdim * Compressed File Header. 164343181Sdim */ 165343181Sdim unsigned char m_h[] = { "\037\235" }; /* 1F 9D */ 166343181Sdim 167343181Sdim static union { 168343181Sdim short int b_mag; 169343181Sdim char c_mag[CMS_LEN]; 170343181Sdim } cm; 171343181Sdim 172343181Sdim struct stat statb; 173343181Sdim int fd; 174343181Sdim 175343181Sdim 176343181Sdim *iscomp = 0; 177343181Sdim 178343181Sdim if ((fd = open(path, O_RDONLY, 0)) == -1) { 179343181Sdim if (errno != ENOENT) { 180343181Sdim perror(""); 181343181Sdim (void) fprintf(stderr, pkg_gt(ERR_ISCPIO_OPEN), path); 182343181Sdim } 183343181Sdim return (0); 184343181Sdim } else { 185343181Sdim if (fstat(fd, &statb) == -1) { 186343181Sdim perror(""); 187343181Sdim (void) fprintf(stderr, pkg_gt(ERR_ISCPIO_FSTAT), path); 188343181Sdim (void) close(fd); 189343181Sdim return (0); 190343181Sdim } else { 191343181Sdim if (S_ISREG(statb.st_mode)) { /* Must be a file */ 192343181Sdim if (read(fd, cm.c_mag, sizeof (cm.c_mag)) != 193343181Sdim sizeof (cm.c_mag)) { 194343181Sdim perror(""); 195343181Sdim (void) fprintf(stderr, 196343181Sdim pkg_gt(ERR_ISCPIO_READ), path); 197343181Sdim (void) close(fd); 198343181Sdim return (0); 199343181Sdim } 200343181Sdim /* 201343181Sdim * Try to determine if the file is a compressed 202343181Sdim * file, if that fails, try to determine if it 203343181Sdim * is a cpio archive, if that fails, then we 204343181Sdim * fail! 205343181Sdim */ 206343181Sdim if (ISCOMPCPIO) { 207343181Sdim *iscomp = 1; 208343181Sdim (void) close(fd); 209343181Sdim return (1); 210343181Sdim } else if (ISCPIO) { 211343181Sdim (void) fprintf(stderr, 212343181Sdim pkg_gt(ERR_ISCPIO_NOCPIO), 213343181Sdim path); 214343181Sdim (void) close(fd); 215343181Sdim return (0); 216343181Sdim } 217343181Sdim (void) close(fd); 218343181Sdim return (1); 219343181Sdim } else { 220343181Sdim (void) close(fd); 221343181Sdim return (0); 222343181Sdim } 223343181Sdim } 224343181Sdim } 225343181Sdim} 226343181Sdim 227343181Sdim/* 228343181Sdim * Name: isPathRemote 229343181Sdim * Description: determine if a path object is local or remote 230343181Sdim * Arguments: a_path - [RO, *RO] - (char *) 231343181Sdim * Pointer to string representing the path to check 232343181Sdim * Returns: int 233343181Sdim * 1 - the path is remote 234343181Sdim * 0 - the path is local to this system 235343181Sdim * -1 - cannot determine if path is remote or local 236343181Sdim */ 237343181Sdim 238343181Sdimint 239343181SdimisPathRemote(char *a_path) 240343181Sdim{ 241 int r; 242 struct stat statbuf; 243 244 r = lstat(a_path, &statbuf); 245 if (r < 0) { 246 return (-1); 247 } 248 249 return (isFstypeRemote(statbuf.st_fstype)); 250} 251 252/* 253 * Name: isFdRemote 254 * Description: determine if an open file is local or remote 255 * Arguments: a_fd - [RO, *RO] - (int) 256 * Integer representing open file to check 257 * Returns: int 258 * 1 - the path is remote 259 * 0 - the path is local to this system 260 * -1 - cannot determine if path is remote or local 261 */ 262 263int 264isFdRemote(int a_fd) 265{ 266 int r; 267 struct stat statbuf; 268 269 r = fstat(a_fd, &statbuf); 270 if (r < 0) { 271 return (-1); 272 } 273 274 return (isFstypeRemote(statbuf.st_fstype)); 275} 276 277/* 278 * Name: isFstypeRemote 279 * Description: determine if a file system type is remote (distributed) 280 * Arguments: a_fstype - [RO, *RO] - (char *) 281 * Pointer to string representing the file system type 282 * to check 283 * Returns: int 284 * 1 - the file system type is remote 285 * 0 - the file system type is local to this system 286 */ 287 288int 289isFstypeRemote(char *a_fstype) 290{ 291 int i; 292 293 /* initialize the list if it is not yet initialized */ 294 295 _InitRemoteFstypes(); 296 297 /* scan the list looking for the specified type */ 298 299 for (i = 0; i < numRemoteFstypes; i++) { 300 if (strcmp(remoteFstypes[i], a_fstype) == 0) { 301 return (1); 302 } 303 } 304 305 /* type not found in remote file system type list - is not remote */ 306 307 return (0); 308} 309 310/* 311 * Name: _InitRemoteFstypes 312 * Description: initialize table of remote file system type names 313 * Arguments: none 314 * Returns: none 315 * Side Effects: 316 * - The global array "(char **)remoteFstypes" is set to the 317 * address of an array of string pointers, each of which represents 318 * a single remote file system type 319 * - The global variable "(long) numRemoteFstypes" is set to the total 320 * number of remote file system type strings (names) that are 321 * contained in the "remoteFstypes" global array. 322 * - numRemoteFstypes is initialized to "-1" before any attempt has been 323 * made to read the remote file system type name database. 324 */ 325static void 326_InitRemoteFstypes(void) 327{ 328 FILE *fp; 329 char line_buf[LINE_MAX]; 330 331 /* return if already initialized */ 332 333 if (numRemoteFstypes > 0) { 334 return; 335 } 336 337 /* if list is uninitialized, start with zero */ 338 339 if (numRemoteFstypes == -1) { 340 numRemoteFstypes = 0; 341 } 342 343 /* open the remote file system type database file */ 344 345 if ((fp = fopen(REMOTE_FS_DBFILE, "r")) == NULL) { 346 /* no remote type database: use predefined remote types */ 347 remoteFstypes = (char **)realloc(remoteFstypes, 348 sizeof (char *) * (numRemoteFstypes+3)); 349 remoteFstypes[numRemoteFstypes++] = "nfs"; /* +1 */ 350 remoteFstypes[numRemoteFstypes++] = "autofs"; /* +2 */ 351 remoteFstypes[numRemoteFstypes++] = "cachefs"; /* +3 */ 352 return; 353 } 354 355 /* 356 * Read the remote file system type database; from fstypes(4): 357 * 358 * fstypes resides in directory /etc/dfs and lists distributed file 359 * system utilities packages installed on the system. For each installed 360 * distributed file system type, there is a line that begins with the 361 * file system type name (for example, ``nfs''), followed by white space 362 * and descriptive text. 363 * 364 * Lines will look at lot like this: 365 * 366 * nfs NFS Utilities 367 * autofs AUTOFS Utilities 368 * cachefs CACHEFS Utilities 369 */ 370 371 while (fgets(line_buf, sizeof (line_buf), fp) != NULL) { 372 char buf[LINE_MAX]; 373 static char format[128] = {'\0'}; 374 375 if (format[0] == '\0') { 376 /* create bounded format: %ns */ 377 (void) snprintf(format, sizeof (format), 378 "%%%ds", sizeof (buf)-1); 379 } 380 381 (void) sscanf(line_buf, format, buf); 382 383 remoteFstypes = realloc(remoteFstypes, 384 sizeof (char *) * (numRemoteFstypes+1)); 385 remoteFstypes[numRemoteFstypes++] = strdup(buf); 386 } 387 388 /* close database file and return */ 389 390 (void) fclose(fp); 391} 392