15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland  * CDDL HEADER START
35c51f124SMoriah Waterland  *
45c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland  *
85c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland  * See the License for the specific language governing permissions
115c51f124SMoriah Waterland  * and limitations under the License.
125c51f124SMoriah Waterland  *
135c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland  *
195c51f124SMoriah Waterland  * CDDL HEADER END
205c51f124SMoriah Waterland  */
215c51f124SMoriah Waterland 
22*2e10def1SPeter Tribble /*
23*2e10def1SPeter Tribble  * Copyright (c) 2017 Peter Tribble.
24*2e10def1SPeter Tribble  */
25*2e10def1SPeter Tribble 
265c51f124SMoriah Waterland /*
275c51f124SMoriah Waterland  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
285c51f124SMoriah Waterland  * Use is subject to license terms.
295c51f124SMoriah Waterland  */
305c51f124SMoriah Waterland 
315c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
325c51f124SMoriah Waterland /* All Rights Reserved */
335c51f124SMoriah Waterland 
345c51f124SMoriah Waterland 
355c51f124SMoriah Waterland #include <stdio.h>
365c51f124SMoriah Waterland #include <ctype.h>
375c51f124SMoriah Waterland #include <string.h>
385c51f124SMoriah Waterland #include <stdlib.h>
395c51f124SMoriah Waterland #include <unistd.h>
405c51f124SMoriah Waterland #include <sys/types.h>
415c51f124SMoriah Waterland #include <sys/param.h>
425c51f124SMoriah Waterland #include <sys/stat.h>
435c51f124SMoriah Waterland #include <sys/statvfs.h>
445c51f124SMoriah Waterland #include <limits.h>
455c51f124SMoriah Waterland #include <locale.h>
465c51f124SMoriah Waterland #include <libintl.h>
475c51f124SMoriah Waterland #include <pkgstrct.h>
485c51f124SMoriah Waterland #include "install.h"
495c51f124SMoriah Waterland #include <pkglib.h>
505c51f124SMoriah Waterland #include "libadm.h"
515c51f124SMoriah Waterland #include "libinst.h"
525c51f124SMoriah Waterland #include "pkginstall.h"
535c51f124SMoriah Waterland 
545c51f124SMoriah Waterland extern struct cfextra **extlist;
555c51f124SMoriah Waterland extern char	pkgloc[];
565c51f124SMoriah Waterland extern char	instdir[];
575c51f124SMoriah Waterland 
585c51f124SMoriah Waterland #define	LSIZE		256
595c51f124SMoriah Waterland #define	LIM_BFREE	150LL
605c51f124SMoriah Waterland #define	LIM_FFREE	25LL
615c51f124SMoriah Waterland 
625c51f124SMoriah Waterland #define	WRN_STATVFS	"WARNING: unable to stat filesystem mounted on <%s>"
635c51f124SMoriah Waterland 
645c51f124SMoriah Waterland #define	WRN_NOBLKS	"The %s filesystem has %llu free blocks. The current " \
655c51f124SMoriah Waterland 			"installation requires %llu blocks, which includes a " \
665c51f124SMoriah Waterland 			"required %llu block buffer for open " \
675c51f124SMoriah Waterland 			"deleted files. %llu more blocks are needed."
685c51f124SMoriah Waterland 
695c51f124SMoriah Waterland #define	WRN_NOFILES	"The %s filesystem has %llu free file nodes. The " \
705c51f124SMoriah Waterland 			"current installation requires %llu file nodes, " \
715c51f124SMoriah Waterland 			"which includes a required %llu file node buffer " \
725c51f124SMoriah Waterland 			"for temporary files. %llu more file nodes " \
735c51f124SMoriah Waterland 			"are needed."
745c51f124SMoriah Waterland 
755c51f124SMoriah Waterland #define	TYPE_BLCK	0
765c51f124SMoriah Waterland #define	TYPE_NODE	1
775c51f124SMoriah Waterland static void	warn(int type, char *name, fsblkcnt_t need, fsblkcnt_t avail,
785c51f124SMoriah Waterland 			fsblkcnt_t limit);
795c51f124SMoriah Waterland static int	fsys_stat(int n);
805c51f124SMoriah Waterland static int	readmap(int *error);
815c51f124SMoriah Waterland static int	readspace(char *spacefile, int *error);
825c51f124SMoriah Waterland 
835c51f124SMoriah Waterland int
dockspace(char * spacefile)845c51f124SMoriah Waterland dockspace(char *spacefile)
855c51f124SMoriah Waterland {
865c51f124SMoriah Waterland 	struct fstable *fs_tab;
875c51f124SMoriah Waterland 	int	i, error;
885c51f124SMoriah Waterland 
895c51f124SMoriah Waterland 	error = 0;
905c51f124SMoriah Waterland 
915c51f124SMoriah Waterland 	/*
925c51f124SMoriah Waterland 	 * Also, vanilla SVr4 code used the output from popen()
935c51f124SMoriah Waterland 	 * on the "/etc/mount" command.  However, we need to get more
945c51f124SMoriah Waterland 	 * information about mounted filesystems, so we use the C
955c51f124SMoriah Waterland 	 * interfaces to the mount table, which also happens to be
965c51f124SMoriah Waterland 	 * much faster than running another process.  Since several
975c51f124SMoriah Waterland 	 * of the pkg commands need access to the mount table, this
985c51f124SMoriah Waterland 	 * code is now in libinst.  However, mount table info is needed
995c51f124SMoriah Waterland 	 * at the time the base directory is determined, so the call
1005c51f124SMoriah Waterland 	 * to get the mount table information is in main.c
1015c51f124SMoriah Waterland 	 */
1025c51f124SMoriah Waterland 
1035c51f124SMoriah Waterland 	if (readmap(&error) || readspace(spacefile, &error))
1045c51f124SMoriah Waterland 		return (-1);
1055c51f124SMoriah Waterland 
1065c51f124SMoriah Waterland 	for (i = 0; fs_tab = get_fs_entry(i); ++i) {
1075c51f124SMoriah Waterland 		if ((!fs_tab->fused) && (!fs_tab->bused))
1085c51f124SMoriah Waterland 			continue; /* not used by us */
1095c51f124SMoriah Waterland 
1105c51f124SMoriah Waterland 		if (fs_tab->bfree < (LIM_BFREE + fs_tab->bused)) {
1115c51f124SMoriah Waterland 			warn(TYPE_BLCK, fs_tab->name, fs_tab->bused,
112*2e10def1SPeter Tribble 			    fs_tab->bfree, LIM_BFREE);
1135c51f124SMoriah Waterland 			error++;
1145c51f124SMoriah Waterland 		}
1155c51f124SMoriah Waterland 
1165c51f124SMoriah Waterland 		/* bug id 1091292 */
1175c51f124SMoriah Waterland 		if ((long)fs_tab->ffree == -1L)
1185c51f124SMoriah Waterland 			continue;
1195c51f124SMoriah Waterland 		if (fs_tab->ffree < (LIM_FFREE + fs_tab->fused)) {
1205c51f124SMoriah Waterland 			warn(TYPE_NODE, fs_tab->name, fs_tab->fused,
121*2e10def1SPeter Tribble 			    fs_tab->ffree, LIM_FFREE);
1225c51f124SMoriah Waterland 			error++;
1235c51f124SMoriah Waterland 		}
1245c51f124SMoriah Waterland 	}
1255c51f124SMoriah Waterland 	return (error);
1265c51f124SMoriah Waterland }
1275c51f124SMoriah Waterland 
1285c51f124SMoriah Waterland static void
warn(int type,char * name,fsblkcnt_t need,fsblkcnt_t avail,fsblkcnt_t limit)1295c51f124SMoriah Waterland warn(int type, char *name, fsblkcnt_t need, fsblkcnt_t avail, fsblkcnt_t limit)
1305c51f124SMoriah Waterland {
1315c51f124SMoriah Waterland 	logerr(gettext("WARNING:"));
1325c51f124SMoriah Waterland 	if (type == TYPE_BLCK) {
1335c51f124SMoriah Waterland 		logerr(gettext(WRN_NOBLKS), name, avail, (need + limit), limit,
1345c51f124SMoriah Waterland 		    (need + limit - avail));
1355c51f124SMoriah Waterland 	} else {
1365c51f124SMoriah Waterland 		logerr(gettext(WRN_NOFILES), name, avail, (need + limit), limit,
1375c51f124SMoriah Waterland 		    (need + limit - avail));
1385c51f124SMoriah Waterland 	}
1395c51f124SMoriah Waterland }
1405c51f124SMoriah Waterland 
1415c51f124SMoriah Waterland static int
fsys_stat(int n)1425c51f124SMoriah Waterland fsys_stat(int n)
1435c51f124SMoriah Waterland {
1445c51f124SMoriah Waterland 	struct statvfs64 svfsb;
1455c51f124SMoriah Waterland 	struct fstable *fs_tab;
1465c51f124SMoriah Waterland 
1475c51f124SMoriah Waterland 	if (n == BADFSYS)
1485c51f124SMoriah Waterland 		return (1);
1495c51f124SMoriah Waterland 
1505c51f124SMoriah Waterland 	fs_tab = get_fs_entry(n);
1515c51f124SMoriah Waterland 
1525c51f124SMoriah Waterland 	/*
1535c51f124SMoriah Waterland 	 * At this point, we know we need information
1545c51f124SMoriah Waterland 	 * about a particular filesystem, so we can do the
1555c51f124SMoriah Waterland 	 * statvfs() now.  For performance reasons, we only want to
1565c51f124SMoriah Waterland 	 * stat the filesystem once, at the first time we need to,
1575c51f124SMoriah Waterland 	 * and so we can key on whether or not we have the
1585c51f124SMoriah Waterland 	 * block size for that filesystem.
1595c51f124SMoriah Waterland 	 */
1605c51f124SMoriah Waterland 	if (fs_tab->bsize != 0)
1615c51f124SMoriah Waterland 		return (0);
1625c51f124SMoriah Waterland 
1635c51f124SMoriah Waterland 	if (statvfs64(fs_tab->name, &svfsb)) {
1645c51f124SMoriah Waterland 		logerr(gettext(WRN_STATVFS), fs_tab->name);
1655c51f124SMoriah Waterland 		return (1);
1665c51f124SMoriah Waterland 	}
1675c51f124SMoriah Waterland 
1685c51f124SMoriah Waterland 	/*
1695c51f124SMoriah Waterland 	 * statvfs returns number of fragment size blocks
1705c51f124SMoriah Waterland 	 * so will change this to number of 512 byte blocks
1715c51f124SMoriah Waterland 	 */
1725c51f124SMoriah Waterland 	fs_tab->bsize  = svfsb.f_bsize;
1735c51f124SMoriah Waterland 	fs_tab->frsize = svfsb.f_frsize;
1745c51f124SMoriah Waterland 	fs_tab->bfree  = ((svfsb.f_frsize > 0) ?
1755c51f124SMoriah Waterland 	    howmany(svfsb.f_frsize, DEV_BSIZE) :
1765c51f124SMoriah Waterland 	    howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bavail;
1775c51f124SMoriah Waterland 	fs_tab->ffree  = (svfsb.f_favail > 0) ? svfsb.f_favail : svfsb.f_ffree;
1785c51f124SMoriah Waterland 	return (0);
1795c51f124SMoriah Waterland }
1805c51f124SMoriah Waterland 
1815c51f124SMoriah Waterland /*
1825c51f124SMoriah Waterland  * This function reads all of the package objects, maps them to their target
1835c51f124SMoriah Waterland  * filesystems and adds up the amount of space used on each. Wherever you see
1845c51f124SMoriah Waterland  * "fsys_value", that's the apparent filesystem which could be a temporary
1855c51f124SMoriah Waterland  * loopback mount for the purpose of constructing the client filesystem. It
1865c51f124SMoriah Waterland  * isn't necessarily the real target filesystem. Where you see "fsys_base"
1875c51f124SMoriah Waterland  * that's the real filesystem to which fsys_value may just refer. If this is
1885c51f124SMoriah Waterland  * installing to a standalone or a server, fsys_value will almost always be
1895c51f124SMoriah Waterland  * the same as fsys_base.
1905c51f124SMoriah Waterland  */
1915c51f124SMoriah Waterland static int
readmap(int * error)1925c51f124SMoriah Waterland readmap(int *error)
1935c51f124SMoriah Waterland {
1945c51f124SMoriah Waterland 	struct fstable *fs_tab;
1955c51f124SMoriah Waterland 	struct cfextra *ext;
1965c51f124SMoriah Waterland 	struct cfent *ept;
1975c51f124SMoriah Waterland 	struct stat statbuf;
1985c51f124SMoriah Waterland 	char	tpath[PATH_MAX];
1995c51f124SMoriah Waterland 	fsblkcnt_t	blk;
200*2e10def1SPeter Tribble 	int	i;
2015c51f124SMoriah Waterland 
2025c51f124SMoriah Waterland 	/*
2035c51f124SMoriah Waterland 	 * Handle the installation files (ftype i) that are in the
2045c51f124SMoriah Waterland 	 * pkgmap/eptlist.
2055c51f124SMoriah Waterland 	 */
2065c51f124SMoriah Waterland 	for (i = 0; (ext = extlist[i]) != NULL; i++) {
2075c51f124SMoriah Waterland 		ept = &(ext->cf_ent);
2085c51f124SMoriah Waterland 
2095c51f124SMoriah Waterland 		if (ept->ftype != 'i')
2105c51f124SMoriah Waterland 			continue;
2115c51f124SMoriah Waterland 
2125c51f124SMoriah Waterland 		/*
2135c51f124SMoriah Waterland 		 * These paths are treated differently from the others
2145c51f124SMoriah Waterland 		 * since their full pathnames are not included in the
2155c51f124SMoriah Waterland 		 * pkgmap.
2165c51f124SMoriah Waterland 		 */
2175c51f124SMoriah Waterland 		if (strcmp(ept->path, "pkginfo") == 0)
2185c51f124SMoriah Waterland 			(void) sprintf(tpath, "%s/%s", pkgloc, ept->path);
2195c51f124SMoriah Waterland 		else
2205c51f124SMoriah Waterland 			(void) sprintf(tpath, "%s/install/%s", pkgloc,
2215c51f124SMoriah Waterland 			    ept->path);
2225c51f124SMoriah Waterland 
2235c51f124SMoriah Waterland 		/* If we haven't done an fsys() series, do one */
2245c51f124SMoriah Waterland 		if (ext->fsys_value == BADFSYS)
2255c51f124SMoriah Waterland 			ext->fsys_value = fsys(tpath);
2265c51f124SMoriah Waterland 
2275c51f124SMoriah Waterland 		/*
2285c51f124SMoriah Waterland 		 * Now check if this is a base or apparent filesystem. If
2295c51f124SMoriah Waterland 		 * it's just apparent, get the resolved filesystem entry,
2305c51f124SMoriah Waterland 		 * otherwise, base and value are the same.
2315c51f124SMoriah Waterland 		 */
2325c51f124SMoriah Waterland 		if (use_srvr_map_n(ext->fsys_value))
2335c51f124SMoriah Waterland 			ext->fsys_base = resolved_fsys(tpath);
2345c51f124SMoriah Waterland 		else
2355c51f124SMoriah Waterland 			ext->fsys_base = ext->fsys_value;
2365c51f124SMoriah Waterland 
2375c51f124SMoriah Waterland 		if (fsys_stat(ext->fsys_base)) {
2385c51f124SMoriah Waterland 			(*error)++;
2395c51f124SMoriah Waterland 			continue;
2405c51f124SMoriah Waterland 		}
2415c51f124SMoriah Waterland 
2425c51f124SMoriah Waterland 		/*
2435c51f124SMoriah Waterland 		 * Don't accumulate space requirements on read-only
2445c51f124SMoriah Waterland 		 * remote filesystems.
2455c51f124SMoriah Waterland 		 */
2465c51f124SMoriah Waterland 		if (is_remote_fs_n(ext->fsys_value) &&
2475c51f124SMoriah Waterland 		    !is_fs_writeable_n(ext->fsys_value))
2485c51f124SMoriah Waterland 			continue;
2495c51f124SMoriah Waterland 
2505c51f124SMoriah Waterland 		fs_tab = get_fs_entry(ext->fsys_base);
2515c51f124SMoriah Waterland 
2525c51f124SMoriah Waterland 		fs_tab->fused++;
2535c51f124SMoriah Waterland 		if (ept->cinfo.size != BADCONT)
2545c51f124SMoriah Waterland 			blk = nblk(ept->cinfo.size,
2555c51f124SMoriah Waterland 			    fs_tab->bsize,
2565c51f124SMoriah Waterland 			    fs_tab->frsize);
2575c51f124SMoriah Waterland 		else
2585c51f124SMoriah Waterland 			blk = 0;
2595c51f124SMoriah Waterland 		fs_tab->bused += blk;
2605c51f124SMoriah Waterland 	}
2615c51f124SMoriah Waterland 
2625c51f124SMoriah Waterland 	/*
2635c51f124SMoriah Waterland 	 * Handle the other files in the eptlist.
2645c51f124SMoriah Waterland 	 */
2655c51f124SMoriah Waterland 	for (i = 0; (ext = extlist[i]) != NULL; i++) {
2665c51f124SMoriah Waterland 		ept = &(extlist[i]->cf_ent);
2675c51f124SMoriah Waterland 
2685c51f124SMoriah Waterland 		if (ept->ftype == 'i')
2695c51f124SMoriah Waterland 			continue;
2705c51f124SMoriah Waterland 
2715c51f124SMoriah Waterland 		/*
2725c51f124SMoriah Waterland 		 * Don't recalculate package objects that are already in the
2735c51f124SMoriah Waterland 		 * table.
2745c51f124SMoriah Waterland 		 */
2755c51f124SMoriah Waterland 		if (ext->mstat.preloaded)
2765c51f124SMoriah Waterland 			continue;
2775c51f124SMoriah Waterland 
2785c51f124SMoriah Waterland 		/*
2795c51f124SMoriah Waterland 		 * Don't accumulate space requirements on read-only
2805c51f124SMoriah Waterland 		 * remote filesystems.
2815c51f124SMoriah Waterland 		 */
2825c51f124SMoriah Waterland 		if (is_remote_fs(ept->path, &(ext->fsys_value)) &&
2835c51f124SMoriah Waterland 		    !is_fs_writeable(ept->path, &(ext->fsys_value)))
2845c51f124SMoriah Waterland 			continue;
2855c51f124SMoriah Waterland 
2865c51f124SMoriah Waterland 		/*
2875c51f124SMoriah Waterland 		 * Now check if this is a base or apparent filesystem. If
2885c51f124SMoriah Waterland 		 * it's just apparent, get the resolved filesystem entry,
2895c51f124SMoriah Waterland 		 * otherwise, base and value are the same.
2905c51f124SMoriah Waterland 		 */
2915c51f124SMoriah Waterland 		if (use_srvr_map_n(ext->fsys_value))
2925c51f124SMoriah Waterland 			ext->fsys_base = resolved_fsys(tpath);
2935c51f124SMoriah Waterland 		else
2945c51f124SMoriah Waterland 			ext->fsys_base = ext->fsys_value;
2955c51f124SMoriah Waterland 
2965c51f124SMoriah Waterland 		/* At this point we know we have a good fsys_base. */
2975c51f124SMoriah Waterland 		if (fsys_stat(ext->fsys_base)) {
2985c51f124SMoriah Waterland 			(*error)++;
2995c51f124SMoriah Waterland 			continue;
3005c51f124SMoriah Waterland 		}
3015c51f124SMoriah Waterland 
3025c51f124SMoriah Waterland 		/*
3035c51f124SMoriah Waterland 		 * We have to stat this path based upon it's real location.
3045c51f124SMoriah Waterland 		 * If this is a server-remap, ept->path isn't the real
3055c51f124SMoriah Waterland 		 * location.
3065c51f124SMoriah Waterland 		 */
3075c51f124SMoriah Waterland 		if (use_srvr_map_n(ext->fsys_value))
3085c51f124SMoriah Waterland 			strcpy(tpath, server_map(ept->path, ext->fsys_value));
3095c51f124SMoriah Waterland 		else
3105c51f124SMoriah Waterland 			strcpy(tpath, ept->path);
3115c51f124SMoriah Waterland 
3125c51f124SMoriah Waterland 		fs_tab = get_fs_entry(ext->fsys_base);
3135c51f124SMoriah Waterland 		if (stat(tpath, &statbuf)) {
3145c51f124SMoriah Waterland 			/* path cannot be accessed */
3155c51f124SMoriah Waterland 			fs_tab->fused++;
3165c51f124SMoriah Waterland 			if (strchr("dxs", ept->ftype))
3175c51f124SMoriah Waterland 				blk =
3185c51f124SMoriah Waterland 				    nblk(fs_tab->bsize,
3195c51f124SMoriah Waterland 				    fs_tab->bsize,
3205c51f124SMoriah Waterland 				    fs_tab->frsize);
3215c51f124SMoriah Waterland 			else if (ept->cinfo.size != BADCONT)
3225c51f124SMoriah Waterland 				blk = nblk(ept->cinfo.size,
3235c51f124SMoriah Waterland 				    fs_tab->bsize,
3245c51f124SMoriah Waterland 				    fs_tab->frsize);
3255c51f124SMoriah Waterland 			else
3265c51f124SMoriah Waterland 				blk = 0;
3275c51f124SMoriah Waterland 		} else {
3285c51f124SMoriah Waterland 			/* path already exists */
3295c51f124SMoriah Waterland 			if (strchr("dxs", ept->ftype))
3305c51f124SMoriah Waterland 				blk = 0;
3315c51f124SMoriah Waterland 			else if (ept->cinfo.size != BADCONT) {
3325c51f124SMoriah Waterland 				fsblkcnt_t new_size, old_size;
3335c51f124SMoriah Waterland 				new_size = nblk(ept->cinfo.size,
3345c51f124SMoriah Waterland 				    fs_tab->bsize,
3355c51f124SMoriah Waterland 				    fs_tab->frsize);
3365c51f124SMoriah Waterland 				old_size = nblk(statbuf.st_size,
3375c51f124SMoriah Waterland 				    fs_tab->bsize,
3385c51f124SMoriah Waterland 				    fs_tab->frsize);
3395c51f124SMoriah Waterland 				/*
3405c51f124SMoriah Waterland 				 * negative blocks show room freed, but since
3415c51f124SMoriah Waterland 				 * order of installation is uncertain show
3425c51f124SMoriah Waterland 				 * 0 blocks usage
3435c51f124SMoriah Waterland 				 */
3445c51f124SMoriah Waterland 				if (new_size < old_size)
3455c51f124SMoriah Waterland 					blk = 0;
3465c51f124SMoriah Waterland 				else
3475c51f124SMoriah Waterland 					blk = new_size - old_size;
3485c51f124SMoriah Waterland 			} else
3495c51f124SMoriah Waterland 				blk = 0;
3505c51f124SMoriah Waterland 		}
3515c51f124SMoriah Waterland 		fs_tab->bused += blk;
3525c51f124SMoriah Waterland 	}
3535c51f124SMoriah Waterland 	return (0);
3545c51f124SMoriah Waterland }
3555c51f124SMoriah Waterland 
3565c51f124SMoriah Waterland static int
readspace(char * spacefile,int * error)3575c51f124SMoriah Waterland readspace(char *spacefile, int *error)
3585c51f124SMoriah Waterland {
3595c51f124SMoriah Waterland 	FILE	*fp;
3605c51f124SMoriah Waterland 	char	line[LSIZE];
3615c51f124SMoriah Waterland 	long	blocks, nodes;
3625c51f124SMoriah Waterland 	int	n;
3635c51f124SMoriah Waterland 
3645c51f124SMoriah Waterland 	if (spacefile == NULL)
3655c51f124SMoriah Waterland 		return (0);
3665c51f124SMoriah Waterland 
3675c51f124SMoriah Waterland 	if ((fp = fopen(spacefile, "r")) == NULL) {
3685c51f124SMoriah Waterland 		progerr(gettext("unable to open spacefile %s"), spacefile);
3695c51f124SMoriah Waterland 		return (-1);
3705c51f124SMoriah Waterland 	}
3715c51f124SMoriah Waterland 
3725c51f124SMoriah Waterland 	while (fgets(line, LSIZE, fp)) {
3735c51f124SMoriah Waterland 		struct fstable *fs_tab;
3745c51f124SMoriah Waterland 		char *pt, path[PATH_MAX];
3755c51f124SMoriah Waterland 
3765c51f124SMoriah Waterland 		blocks = nodes = 0;
3775c51f124SMoriah Waterland 		for (pt = line; isspace(*pt); /* void */)
3785c51f124SMoriah Waterland 			pt++;
3795c51f124SMoriah Waterland 		if (*pt == '#' || *pt == '\0')
3805c51f124SMoriah Waterland 			continue;
3815c51f124SMoriah Waterland 
3825c51f124SMoriah Waterland 		(void) sscanf(line, "%s %ld %ld", path, &blocks, &nodes);
3835c51f124SMoriah Waterland 		mappath(2, path);
3845c51f124SMoriah Waterland 		basepath(path, get_basedir(), get_inst_root());
3855c51f124SMoriah Waterland 		canonize(path);
3865c51f124SMoriah Waterland 
3875c51f124SMoriah Waterland 		n = resolved_fsys(path);
3885c51f124SMoriah Waterland 		if (fsys_stat(n)) {
3895c51f124SMoriah Waterland 			(*error)++;
3905c51f124SMoriah Waterland 			continue;
3915c51f124SMoriah Waterland 		}
3925c51f124SMoriah Waterland 
3935c51f124SMoriah Waterland 		/*
3945c51f124SMoriah Waterland 		 * Don't accumulate space requirements on read-only
3955c51f124SMoriah Waterland 		 * remote filesystems. NOTE: For some reason, this
3965c51f124SMoriah Waterland 		 * used to check for !remote && read only. If this
3975c51f124SMoriah Waterland 		 * blows up later, then maybe that was correct -- JST
3985c51f124SMoriah Waterland 		 */
3995c51f124SMoriah Waterland 		if (is_remote_fs_n(n) && !is_fs_writeable_n(n))
4005c51f124SMoriah Waterland 			continue;
4015c51f124SMoriah Waterland 
4025c51f124SMoriah Waterland 		fs_tab = get_fs_entry(n);
4035c51f124SMoriah Waterland 
4045c51f124SMoriah Waterland 		fs_tab->bused += blocks;
4055c51f124SMoriah Waterland 		fs_tab->fused += nodes;
4065c51f124SMoriah Waterland 	}
4075c51f124SMoriah Waterland 	(void) fclose(fp);
4085c51f124SMoriah Waterland 	return (0);
4095c51f124SMoriah Waterland }
410