1*5c51f124SMoriah Waterland /* 2*5c51f124SMoriah Waterland * CDDL HEADER START 3*5c51f124SMoriah Waterland * 4*5c51f124SMoriah Waterland * The contents of this file are subject to the terms of the 5*5c51f124SMoriah Waterland * Common Development and Distribution License (the "License"). 6*5c51f124SMoriah Waterland * You may not use this file except in compliance with the License. 7*5c51f124SMoriah Waterland * 8*5c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing. 10*5c51f124SMoriah Waterland * See the License for the specific language governing permissions 11*5c51f124SMoriah Waterland * and limitations under the License. 12*5c51f124SMoriah Waterland * 13*5c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each 14*5c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the 16*5c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying 17*5c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner] 18*5c51f124SMoriah Waterland * 19*5c51f124SMoriah Waterland * CDDL HEADER END 20*5c51f124SMoriah Waterland */ 21*5c51f124SMoriah Waterland 22*5c51f124SMoriah Waterland /* 23*5c51f124SMoriah Waterland * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*5c51f124SMoriah Waterland * Use is subject to license terms. 25*5c51f124SMoriah Waterland */ 26*5c51f124SMoriah Waterland 27*5c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*5c51f124SMoriah Waterland /* All Rights Reserved */ 29*5c51f124SMoriah Waterland 30*5c51f124SMoriah Waterland 31*5c51f124SMoriah Waterland #include <stdio.h> 32*5c51f124SMoriah Waterland #include <sys/types.h> 33*5c51f124SMoriah Waterland #include <sys/stat.h> 34*5c51f124SMoriah Waterland #include <archives.h> 35*5c51f124SMoriah Waterland #include <errno.h> 36*5c51f124SMoriah Waterland #include <fcntl.h> 37*5c51f124SMoriah Waterland #include <limits.h> 38*5c51f124SMoriah Waterland #include <stdlib.h> 39*5c51f124SMoriah Waterland #include <unistd.h> 40*5c51f124SMoriah Waterland #include <string.h> 41*5c51f124SMoriah Waterland #include "pkglocale.h" 42*5c51f124SMoriah Waterland #include "pkglibmsgs.h" 43*5c51f124SMoriah Waterland 44*5c51f124SMoriah Waterland /* 45*5c51f124SMoriah Waterland * Defines for cpio/compression checks. 46*5c51f124SMoriah Waterland */ 47*5c51f124SMoriah Waterland #define BIT_MASK 0x1f 48*5c51f124SMoriah Waterland #define BLOCK_MASK 0x80 49*5c51f124SMoriah Waterland 50*5c51f124SMoriah Waterland #define MASK_CK(x, y) (((x) & (y)) == (y)) 51*5c51f124SMoriah Waterland #define ISCOMPCPIO ((unsigned char) cm.c_mag[0] == m_h[0] && \ 52*5c51f124SMoriah Waterland (unsigned char) cm.c_mag[1] == m_h[1] && \ 53*5c51f124SMoriah Waterland (MASK_CK((unsigned char) cm.c_mag[2], BLOCK_MASK) || \ 54*5c51f124SMoriah Waterland MASK_CK((unsigned char) cm.c_mag[2], BIT_MASK))) 55*5c51f124SMoriah Waterland 56*5c51f124SMoriah Waterland #define ISCPIO (cm.b_mag != CMN_BIN && \ 57*5c51f124SMoriah Waterland (strcmp(cm.c_mag, CMS_ASC) == 0) && \ 58*5c51f124SMoriah Waterland (strcmp(cm.c_mag, CMS_CHR) == 0) && \ 59*5c51f124SMoriah Waterland (strcmp(cm.c_mag, CMS_CRC) == 0)) 60*5c51f124SMoriah Waterland 61*5c51f124SMoriah Waterland /* location of distributed file system types database */ 62*5c51f124SMoriah Waterland 63*5c51f124SMoriah Waterland #define REMOTE_FS_DBFILE "/etc/dfs/fstypes" 64*5c51f124SMoriah Waterland 65*5c51f124SMoriah Waterland /* character array used to hold dfs types database contents */ 66*5c51f124SMoriah Waterland 67*5c51f124SMoriah Waterland static long numRemoteFstypes = -1; 68*5c51f124SMoriah Waterland static char **remoteFstypes = (char **)NULL; 69*5c51f124SMoriah Waterland 70*5c51f124SMoriah Waterland /* forward declarations */ 71*5c51f124SMoriah Waterland 72*5c51f124SMoriah Waterland static void _InitRemoteFstypes(void); 73*5c51f124SMoriah Waterland 74*5c51f124SMoriah Waterland int isFdRemote(int a_fd); 75*5c51f124SMoriah Waterland int isPathRemote(char *a_path); 76*5c51f124SMoriah Waterland int isFstypeRemote(char *a_fstype); 77*5c51f124SMoriah Waterland int isdir(char *path); 78*5c51f124SMoriah Waterland int isfile(char *dir, char *file); 79*5c51f124SMoriah Waterland int iscpio(char *path, int *iscomp); 80*5c51f124SMoriah Waterland 81*5c51f124SMoriah Waterland /* 82*5c51f124SMoriah Waterland * Name: isdir 83*5c51f124SMoriah Waterland * Description: determine if specified path exists and is a directory 84*5c51f124SMoriah Waterland * Arguments: path - pointer to string representing the path to verify 85*5c51f124SMoriah Waterland * returns: 0 - directory exists 86*5c51f124SMoriah Waterland * 1 - directory does not exist or is not a directory 87*5c51f124SMoriah Waterland * NOTE: errno is set appropriately 88*5c51f124SMoriah Waterland */ 89*5c51f124SMoriah Waterland 90*5c51f124SMoriah Waterland int 91*5c51f124SMoriah Waterland isdir(char *path) 92*5c51f124SMoriah Waterland { 93*5c51f124SMoriah Waterland struct stat statbuf; 94*5c51f124SMoriah Waterland 95*5c51f124SMoriah Waterland /* return error if path does not exist */ 96*5c51f124SMoriah Waterland 97*5c51f124SMoriah Waterland if (stat(path, &statbuf) != 0) { 98*5c51f124SMoriah Waterland return (1); 99*5c51f124SMoriah Waterland } 100*5c51f124SMoriah Waterland 101*5c51f124SMoriah Waterland /* return error if path is not a directory */ 102*5c51f124SMoriah Waterland 103*5c51f124SMoriah Waterland if ((statbuf.st_mode & S_IFMT) != S_IFDIR) { 104*5c51f124SMoriah Waterland errno = ENOTDIR; 105*5c51f124SMoriah Waterland return (1); 106*5c51f124SMoriah Waterland } 107*5c51f124SMoriah Waterland 108*5c51f124SMoriah Waterland return (0); 109*5c51f124SMoriah Waterland } 110*5c51f124SMoriah Waterland 111*5c51f124SMoriah Waterland /* 112*5c51f124SMoriah Waterland * Name: isfile 113*5c51f124SMoriah Waterland * Description: determine if specified path exists and is a directory 114*5c51f124SMoriah Waterland * Arguments: dir - pointer to string representing the directory where 115*5c51f124SMoriah Waterland * the file is located 116*5c51f124SMoriah Waterland * == NULL - use "file" argument only 117*5c51f124SMoriah Waterland * file - pointer to string representing the file to verify 118*5c51f124SMoriah Waterland * Returns: 0 - success - file exists 119*5c51f124SMoriah Waterland * 1 - failure - file does not exist OR is not a file 120*5c51f124SMoriah Waterland * NOTE: errno is set appropriately 121*5c51f124SMoriah Waterland */ 122*5c51f124SMoriah Waterland 123*5c51f124SMoriah Waterland int 124*5c51f124SMoriah Waterland isfile(char *dir, char *file) 125*5c51f124SMoriah Waterland { 126*5c51f124SMoriah Waterland struct stat statbuf; 127*5c51f124SMoriah Waterland char path[PATH_MAX]; 128*5c51f124SMoriah Waterland 129*5c51f124SMoriah Waterland /* construct full path if directory specified */ 130*5c51f124SMoriah Waterland 131*5c51f124SMoriah Waterland if (dir) { 132*5c51f124SMoriah Waterland (void) snprintf(path, sizeof (path), "%s/%s", dir, file); 133*5c51f124SMoriah Waterland file = path; 134*5c51f124SMoriah Waterland } 135*5c51f124SMoriah Waterland 136*5c51f124SMoriah Waterland /* return error if path does not exist */ 137*5c51f124SMoriah Waterland 138*5c51f124SMoriah Waterland if (stat(file, &statbuf) != 0) { 139*5c51f124SMoriah Waterland return (1); 140*5c51f124SMoriah Waterland } 141*5c51f124SMoriah Waterland 142*5c51f124SMoriah Waterland /* return error if path is a directory */ 143*5c51f124SMoriah Waterland 144*5c51f124SMoriah Waterland if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { 145*5c51f124SMoriah Waterland errno = EISDIR; 146*5c51f124SMoriah Waterland return (1); 147*5c51f124SMoriah Waterland } 148*5c51f124SMoriah Waterland 149*5c51f124SMoriah Waterland /* return error if path is not a file */ 150*5c51f124SMoriah Waterland 151*5c51f124SMoriah Waterland if ((statbuf.st_mode & S_IFMT) != S_IFREG) { 152*5c51f124SMoriah Waterland errno = EINVAL; 153*5c51f124SMoriah Waterland return (1); 154*5c51f124SMoriah Waterland } 155*5c51f124SMoriah Waterland 156*5c51f124SMoriah Waterland return (0); 157*5c51f124SMoriah Waterland } 158*5c51f124SMoriah Waterland 159*5c51f124SMoriah Waterland int 160*5c51f124SMoriah Waterland iscpio(char *path, int *iscomp) 161*5c51f124SMoriah Waterland { 162*5c51f124SMoriah Waterland /* 163*5c51f124SMoriah Waterland * Compressed File Header. 164*5c51f124SMoriah Waterland */ 165*5c51f124SMoriah Waterland unsigned char m_h[] = { "\037\235" }; /* 1F 9D */ 166*5c51f124SMoriah Waterland 167*5c51f124SMoriah Waterland static union { 168*5c51f124SMoriah Waterland short int b_mag; 169*5c51f124SMoriah Waterland char c_mag[CMS_LEN]; 170*5c51f124SMoriah Waterland } cm; 171*5c51f124SMoriah Waterland 172*5c51f124SMoriah Waterland struct stat statb; 173*5c51f124SMoriah Waterland int fd; 174*5c51f124SMoriah Waterland 175*5c51f124SMoriah Waterland 176*5c51f124SMoriah Waterland *iscomp = 0; 177*5c51f124SMoriah Waterland 178*5c51f124SMoriah Waterland if ((fd = open(path, O_RDONLY, 0)) == -1) { 179*5c51f124SMoriah Waterland if (errno != ENOENT) { 180*5c51f124SMoriah Waterland perror(""); 181*5c51f124SMoriah Waterland (void) fprintf(stderr, pkg_gt(ERR_ISCPIO_OPEN), path); 182*5c51f124SMoriah Waterland } 183*5c51f124SMoriah Waterland return (0); 184*5c51f124SMoriah Waterland } else { 185*5c51f124SMoriah Waterland if (fstat(fd, &statb) == -1) { 186*5c51f124SMoriah Waterland perror(""); 187*5c51f124SMoriah Waterland (void) fprintf(stderr, pkg_gt(ERR_ISCPIO_FSTAT), path); 188*5c51f124SMoriah Waterland (void) close(fd); 189*5c51f124SMoriah Waterland return (0); 190*5c51f124SMoriah Waterland } else { 191*5c51f124SMoriah Waterland if (S_ISREG(statb.st_mode)) { /* Must be a file */ 192*5c51f124SMoriah Waterland if (read(fd, cm.c_mag, sizeof (cm.c_mag)) != 193*5c51f124SMoriah Waterland sizeof (cm.c_mag)) { 194*5c51f124SMoriah Waterland perror(""); 195*5c51f124SMoriah Waterland (void) fprintf(stderr, 196*5c51f124SMoriah Waterland pkg_gt(ERR_ISCPIO_READ), path); 197*5c51f124SMoriah Waterland (void) close(fd); 198*5c51f124SMoriah Waterland return (0); 199*5c51f124SMoriah Waterland } 200*5c51f124SMoriah Waterland /* 201*5c51f124SMoriah Waterland * Try to determine if the file is a compressed 202*5c51f124SMoriah Waterland * file, if that fails, try to determine if it 203*5c51f124SMoriah Waterland * is a cpio archive, if that fails, then we 204*5c51f124SMoriah Waterland * fail! 205*5c51f124SMoriah Waterland */ 206*5c51f124SMoriah Waterland if (ISCOMPCPIO) { 207*5c51f124SMoriah Waterland *iscomp = 1; 208*5c51f124SMoriah Waterland (void) close(fd); 209*5c51f124SMoriah Waterland return (1); 210*5c51f124SMoriah Waterland } else if (ISCPIO) { 211*5c51f124SMoriah Waterland (void) fprintf(stderr, 212*5c51f124SMoriah Waterland pkg_gt(ERR_ISCPIO_NOCPIO), 213*5c51f124SMoriah Waterland path); 214*5c51f124SMoriah Waterland (void) close(fd); 215*5c51f124SMoriah Waterland return (0); 216*5c51f124SMoriah Waterland } 217*5c51f124SMoriah Waterland (void) close(fd); 218*5c51f124SMoriah Waterland return (1); 219*5c51f124SMoriah Waterland } else { 220*5c51f124SMoriah Waterland (void) close(fd); 221*5c51f124SMoriah Waterland return (0); 222*5c51f124SMoriah Waterland } 223*5c51f124SMoriah Waterland } 224*5c51f124SMoriah Waterland } 225*5c51f124SMoriah Waterland } 226*5c51f124SMoriah Waterland 227*5c51f124SMoriah Waterland /* 228*5c51f124SMoriah Waterland * Name: isPathRemote 229*5c51f124SMoriah Waterland * Description: determine if a path object is local or remote 230*5c51f124SMoriah Waterland * Arguments: a_path - [RO, *RO] - (char *) 231*5c51f124SMoriah Waterland * Pointer to string representing the path to check 232*5c51f124SMoriah Waterland * Returns: int 233*5c51f124SMoriah Waterland * 1 - the path is remote 234*5c51f124SMoriah Waterland * 0 - the path is local to this system 235*5c51f124SMoriah Waterland * -1 - cannot determine if path is remote or local 236*5c51f124SMoriah Waterland */ 237*5c51f124SMoriah Waterland 238*5c51f124SMoriah Waterland int 239*5c51f124SMoriah Waterland isPathRemote(char *a_path) 240*5c51f124SMoriah Waterland { 241*5c51f124SMoriah Waterland int r; 242*5c51f124SMoriah Waterland struct stat statbuf; 243*5c51f124SMoriah Waterland 244*5c51f124SMoriah Waterland r = lstat(a_path, &statbuf); 245*5c51f124SMoriah Waterland if (r < 0) { 246*5c51f124SMoriah Waterland return (-1); 247*5c51f124SMoriah Waterland } 248*5c51f124SMoriah Waterland 249*5c51f124SMoriah Waterland return (isFstypeRemote(statbuf.st_fstype)); 250*5c51f124SMoriah Waterland } 251*5c51f124SMoriah Waterland 252*5c51f124SMoriah Waterland /* 253*5c51f124SMoriah Waterland * Name: isFdRemote 254*5c51f124SMoriah Waterland * Description: determine if an open file is local or remote 255*5c51f124SMoriah Waterland * Arguments: a_fd - [RO, *RO] - (int) 256*5c51f124SMoriah Waterland * Integer representing open file to check 257*5c51f124SMoriah Waterland * Returns: int 258*5c51f124SMoriah Waterland * 1 - the path is remote 259*5c51f124SMoriah Waterland * 0 - the path is local to this system 260*5c51f124SMoriah Waterland * -1 - cannot determine if path is remote or local 261*5c51f124SMoriah Waterland */ 262*5c51f124SMoriah Waterland 263*5c51f124SMoriah Waterland int 264*5c51f124SMoriah Waterland isFdRemote(int a_fd) 265*5c51f124SMoriah Waterland { 266*5c51f124SMoriah Waterland int r; 267*5c51f124SMoriah Waterland struct stat statbuf; 268*5c51f124SMoriah Waterland 269*5c51f124SMoriah Waterland r = fstat(a_fd, &statbuf); 270*5c51f124SMoriah Waterland if (r < 0) { 271*5c51f124SMoriah Waterland return (-1); 272*5c51f124SMoriah Waterland } 273*5c51f124SMoriah Waterland 274*5c51f124SMoriah Waterland return (isFstypeRemote(statbuf.st_fstype)); 275*5c51f124SMoriah Waterland } 276*5c51f124SMoriah Waterland 277*5c51f124SMoriah Waterland /* 278*5c51f124SMoriah Waterland * Name: isFstypeRemote 279*5c51f124SMoriah Waterland * Description: determine if a file system type is remote (distributed) 280*5c51f124SMoriah Waterland * Arguments: a_fstype - [RO, *RO] - (char *) 281*5c51f124SMoriah Waterland * Pointer to string representing the file system type 282*5c51f124SMoriah Waterland * to check 283*5c51f124SMoriah Waterland * Returns: int 284*5c51f124SMoriah Waterland * 1 - the file system type is remote 285*5c51f124SMoriah Waterland * 0 - the file system type is local to this system 286*5c51f124SMoriah Waterland */ 287*5c51f124SMoriah Waterland 288*5c51f124SMoriah Waterland int 289*5c51f124SMoriah Waterland isFstypeRemote(char *a_fstype) 290*5c51f124SMoriah Waterland { 291*5c51f124SMoriah Waterland int i; 292*5c51f124SMoriah Waterland 293*5c51f124SMoriah Waterland /* initialize the list if it is not yet initialized */ 294*5c51f124SMoriah Waterland 295*5c51f124SMoriah Waterland _InitRemoteFstypes(); 296*5c51f124SMoriah Waterland 297*5c51f124SMoriah Waterland /* scan the list looking for the specified type */ 298*5c51f124SMoriah Waterland 299*5c51f124SMoriah Waterland for (i = 0; i < numRemoteFstypes; i++) { 300*5c51f124SMoriah Waterland if (strcmp(remoteFstypes[i], a_fstype) == 0) { 301*5c51f124SMoriah Waterland return (1); 302*5c51f124SMoriah Waterland } 303*5c51f124SMoriah Waterland } 304*5c51f124SMoriah Waterland 305*5c51f124SMoriah Waterland /* type not found in remote file system type list - is not remote */ 306*5c51f124SMoriah Waterland 307*5c51f124SMoriah Waterland return (0); 308*5c51f124SMoriah Waterland } 309*5c51f124SMoriah Waterland 310*5c51f124SMoriah Waterland /* 311*5c51f124SMoriah Waterland * Name: _InitRemoteFstypes 312*5c51f124SMoriah Waterland * Description: initialize table of remote file system type names 313*5c51f124SMoriah Waterland * Arguments: none 314*5c51f124SMoriah Waterland * Returns: none 315*5c51f124SMoriah Waterland * Side Effects: 316*5c51f124SMoriah Waterland * - The global array "(char **)remoteFstypes" is set to the 317*5c51f124SMoriah Waterland * address of an array of string pointers, each of which represents 318*5c51f124SMoriah Waterland * a single remote file system type 319*5c51f124SMoriah Waterland * - The global variable "(long) numRemoteFstypes" is set to the total 320*5c51f124SMoriah Waterland * number of remote file system type strings (names) that are 321*5c51f124SMoriah Waterland * contained in the "remoteFstypes" global array. 322*5c51f124SMoriah Waterland * - numRemoteFstypes is initialized to "-1" before any attempt has been 323*5c51f124SMoriah Waterland * made to read the remote file system type name database. 324*5c51f124SMoriah Waterland */ 325*5c51f124SMoriah Waterland static void 326*5c51f124SMoriah Waterland _InitRemoteFstypes(void) 327*5c51f124SMoriah Waterland { 328*5c51f124SMoriah Waterland FILE *fp; 329*5c51f124SMoriah Waterland char line_buf[LINE_MAX]; 330*5c51f124SMoriah Waterland 331*5c51f124SMoriah Waterland /* return if already initialized */ 332*5c51f124SMoriah Waterland 333*5c51f124SMoriah Waterland if (numRemoteFstypes > 0) { 334*5c51f124SMoriah Waterland return; 335*5c51f124SMoriah Waterland } 336*5c51f124SMoriah Waterland 337*5c51f124SMoriah Waterland /* if list is uninitialized, start with zero */ 338*5c51f124SMoriah Waterland 339*5c51f124SMoriah Waterland if (numRemoteFstypes == -1) { 340*5c51f124SMoriah Waterland numRemoteFstypes = 0; 341*5c51f124SMoriah Waterland } 342*5c51f124SMoriah Waterland 343*5c51f124SMoriah Waterland /* open the remote file system type database file */ 344*5c51f124SMoriah Waterland 345*5c51f124SMoriah Waterland if ((fp = fopen(REMOTE_FS_DBFILE, "r")) == NULL) { 346*5c51f124SMoriah Waterland /* no remote type database: use predefined remote types */ 347*5c51f124SMoriah Waterland remoteFstypes = (char **)realloc(remoteFstypes, 348*5c51f124SMoriah Waterland sizeof (char *) * (numRemoteFstypes+3)); 349*5c51f124SMoriah Waterland remoteFstypes[numRemoteFstypes++] = "nfs"; /* +1 */ 350*5c51f124SMoriah Waterland remoteFstypes[numRemoteFstypes++] = "autofs"; /* +2 */ 351*5c51f124SMoriah Waterland remoteFstypes[numRemoteFstypes++] = "cachefs"; /* +3 */ 352*5c51f124SMoriah Waterland return; 353*5c51f124SMoriah Waterland } 354*5c51f124SMoriah Waterland 355*5c51f124SMoriah Waterland /* 356*5c51f124SMoriah Waterland * Read the remote file system type database; from fstypes(4): 357*5c51f124SMoriah Waterland * 358*5c51f124SMoriah Waterland * fstypes resides in directory /etc/dfs and lists distributed file 359*5c51f124SMoriah Waterland * system utilities packages installed on the system. For each installed 360*5c51f124SMoriah Waterland * distributed file system type, there is a line that begins with the 361*5c51f124SMoriah Waterland * file system type name (for example, ``nfs''), followed by white space 362*5c51f124SMoriah Waterland * and descriptive text. 363*5c51f124SMoriah Waterland * 364*5c51f124SMoriah Waterland * Lines will look at lot like this: 365*5c51f124SMoriah Waterland * 366*5c51f124SMoriah Waterland * nfs NFS Utilities 367*5c51f124SMoriah Waterland * autofs AUTOFS Utilities 368*5c51f124SMoriah Waterland * cachefs CACHEFS Utilities 369*5c51f124SMoriah Waterland */ 370*5c51f124SMoriah Waterland 371*5c51f124SMoriah Waterland while (fgets(line_buf, sizeof (line_buf), fp) != NULL) { 372*5c51f124SMoriah Waterland char buf[LINE_MAX]; 373*5c51f124SMoriah Waterland static char format[128] = {'\0'}; 374*5c51f124SMoriah Waterland 375*5c51f124SMoriah Waterland if (format[0] == '\0') { 376*5c51f124SMoriah Waterland /* create bounded format: %ns */ 377*5c51f124SMoriah Waterland (void) snprintf(format, sizeof (format), 378*5c51f124SMoriah Waterland "%%%ds", sizeof (buf)-1); 379*5c51f124SMoriah Waterland } 380*5c51f124SMoriah Waterland 381*5c51f124SMoriah Waterland (void) sscanf(line_buf, format, buf); 382*5c51f124SMoriah Waterland 383*5c51f124SMoriah Waterland remoteFstypes = realloc(remoteFstypes, 384*5c51f124SMoriah Waterland sizeof (char *) * (numRemoteFstypes+1)); 385*5c51f124SMoriah Waterland remoteFstypes[numRemoteFstypes++] = strdup(buf); 386*5c51f124SMoriah Waterland } 387*5c51f124SMoriah Waterland 388*5c51f124SMoriah Waterland /* close database file and return */ 389*5c51f124SMoriah Waterland 390*5c51f124SMoriah Waterland (void) fclose(fp); 391*5c51f124SMoriah Waterland } 392