[BACK]Return to fs.c CVS log [TXT][DIR] Up to [Development] / xfs-cmds / xfsdump / common

File: [Development] / xfs-cmds / xfsdump / common / fs.c (download)

Revision 1.2, Fri Jan 25 02:16:52 2002 UTC (15 years, 8 months ago) by nathans
Branch: MAIN
Changes since 1.1: +3 -3 lines

effectively no-op change (cleanup) - switch over to using
XFS_IOC_FSGEOMETRY instead of XFS_IOC_GETFSUUID ioctl, so
we can deprecate that "special" UUID ioctl at some point
in the distant future.

/*
 * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it would be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * 
 * Further, this software is distributed without any warranty that it is
 * free of the rightful claim of any third person regarding infringement
 * or the like.  Any license provided herein, whether implied or
 * otherwise, applies only to this software file.  Patent licenses, if
 * any, provided herein do not apply to combinations of this program with
 * other software, or any other product whatsoever.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write the Free Software Foundation, Inc., 59
 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
 * 
 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
 * Mountain View, CA  94043, or:
 * 
 * http://www.sgi.com 
 * 
 * For further information regarding this notice, see: 
 * 
 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
 */

#include <libxfs.h>
#include <jdm.h>

#include <sys/stat.h>
#include <sys/statvfs.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <mntent.h>
#include <sys/ioctl.h>

#include "types.h"
#include "mlog.h"
#include "fs.h"


/* fs_info - a magic, highly heuristic function to convert a user-supplied
 * string into a file system type, character special device pathname,
 * a mount point, and file system ID (uuid). The primary source of information
 * is the getmntent(3) routines. Correspondence between "standard" disk
 * block and character device pathnames is used. The fstyp(1) utility
 * may be invoked as well.
 *
 * returns BOOL_TRUE on success, BOOL_FALSE on failure.
 *
 * coding rules: to make this very complex and lengthy decision tree
 * more graspable, some very strict coding rules were followed:
 *
 *	1) function arguments are ordered reference returns first, input
 *	parameters second.
 *
 *	2) all buffer-like refence return arguments are followed by a
 *	caller-supplied buffer size.
 *
 *	3) wherever possible functions return the result buffer pointer.
 *
 *	4) boolean functions return TRUE on success, FALSE on failure.
 *
 * all variables, parameters, and structure members are named as follows:
 *	object types:
 *		usr - user-specified mystery
 *		typ - file system type
 *		mnt - mount point pathname
 *		blk - block device pathname
 *		chr - character device pathname
 *		id - file system ID
 *		stat - stat buffer
 *		te - file system table entry
 *	object modifiers: appended to object type:
 *		b - buffer
 *		s - string
 *		d - default string
 *		p - pointer
 *	object size indication modifiers: appended to a modified object type:
 *		z - buffer size
 *		l - string length
 */

/* declarations of externally defined global variables
 */


/* definitions used locally
 */
struct fs_tab_ent {
	char *fte_blks;
	char *fte_mnts;
	char *fte_typs;
	struct fs_tab_ent *fte_nextp;
};

typedef struct fs_tab_ent fs_tab_ent_t;

static	fs_tab_ent_t *fs_tabp;

/* forward declarations
 */
static void fs_tab_build( void );
static void fs_tab_free( void );
static fs_tab_ent_t *fs_tab_ent_build( struct mntent * );
static void fs_tab_ent_free( fs_tab_ent_t * );
static fs_tab_ent_t *fs_tab_lookup_blk( char * );
static fs_tab_ent_t *fs_tab_lookup_mnt( char * );

/* ARGSUSED */
bool_t
fs_info( char *typb,		/* out */
	 intgen_t typbz,
	 char *typd,
	 char *blkb,		/* out */
	 intgen_t blkbz,
	 char *mntb,		/* out */
	 intgen_t mntbz,
	 uuid_t *idb,		/* out */
	 char *usrs )		/* in */
{
	struct stat64 statb;
	fs_tab_ent_t *tep;
	char *blks;
	char *mnts;
	char *typs;
	bool_t canstat;
	bool_t ok = BOOL_UNKNOWN;

	fs_tab_build( );

	canstat = ( stat64( usrs, &statb ) == 0 );
	if ( canstat && ( statb.st_mode & S_IFMT ) == S_IFBLK ) {
		if ( ( tep = fs_tab_lookup_blk( usrs )) != 0 ) {
			blks = tep->fte_blks;
			ASSERT( strlen( blks ) < ( size_t )blkbz );
			strcpy( blkb, blks );
			mnts = tep->fte_mnts;
			if ( mnts ) {
				ASSERT( strlen( mnts ) < ( size_t )mntbz );
				strcpy( mntb, mnts );
			} else {
				mntb[ 0 ] = 0;
			}
			if ( ( typs = tep->fte_typs ) == 0 ) {
				typs = typd;
			}
			ASSERT( strlen( typs ) < ( size_t )typbz );
			strcpy( typb, typs );
			ok = BOOL_TRUE;
		} else {
			ok = BOOL_FALSE;
		}
	} else if ( ( tep = fs_tab_lookup_mnt( usrs )) != 0 ) {
		blks = tep->fte_blks;
		ASSERT( strlen( blks ) < ( size_t )blkbz );
		strcpy( blkb, blks );
		mnts = tep->fte_mnts;
		ASSERT( strlen( mnts ) < ( size_t )mntbz );
		strcpy( mntb, mnts );
		typs = tep->fte_typs;
		ASSERT( strlen( typs ) < ( size_t )typbz );
		strcpy( typb, typs );
		ok = BOOL_TRUE;
	} else {
		ok = BOOL_FALSE;
	}

	fs_tab_free( );
	ASSERT( ok != BOOL_UNKNOWN );

	if ( ok == BOOL_TRUE ) {
		intgen_t rval = fs_getid( mntb, idb );
		if ( rval ) {
			mlog( MLOG_NORMAL,
			      "unable to determine uuid of fs mounted at %s: "
			      "%s\n",
			      mntb,
			      strerror( errno ));
		}
		{
			u_char_t string_uuid[37];
			uuid_unparse( *idb, string_uuid );
			mlog( MLOG_DEBUG,
			      "fs %s uuid [%s]\n",
			      mntb,
			      string_uuid );
		}
	}

	return ok;
}

/* fs_mounted - a predicate determining if the specified file system
 * is actually currently mounted at its mount point.
 * will not take time to code this now - just check if mntpt is non-NULL.
 */
/* ARGSUSED */
bool_t
fs_mounted( char *typs, char *chrs, char *mnts, uuid_t *idp )
{
	return strlen( mnts ) > 0 ? BOOL_TRUE : BOOL_FALSE;
}

intgen_t
fs_getid( char *mnts, uuid_t *idb )
{
	xfs_fsop_geom_t geo;
	int fd;

	fd = open( mnts, O_RDONLY );
	if ( fd < 0 ) {
		uuid_clear( *idb );
		return -1;
	}
	if ( ioctl(fd, XFS_IOC_FSGEOMETRY, &geo ) ) {
		uuid_clear( *idb );
		close(fd);
		return -1;
	}
	close(fd);
	uuid_copy( *idb, geo.uuid );

	return 0;
}

size_t
fs_getinocnt( char *mnts )
{
	struct statvfs vfsstat;
	intgen_t rval;

	rval = statvfs( mnts, &vfsstat );
	if ( rval ) {
		return 0;
	}

	if ( vfsstat.f_files < vfsstat.f_ffree ) {
		return 0;
	}

	return ( size_t )( vfsstat.f_files - vfsstat.f_ffree );
}

static void
fs_tab_build( void )
{
	register struct mntent *mntentp;
	fs_tab_ent_t *tep;
	FILE *fp;

	fs_tabp = 0;
	fp = setmntent( MOUNTED, "r" );
        if ( fp == NULL ) {
		mlog( MLOG_NORMAL,
		      "Can't open %s for mount information\n",
		      MOUNTED );
		return;
	}
	while ( ( mntentp = getmntent( fp )) != 0 ) {
		tep = fs_tab_ent_build( mntentp );
		tep->fte_nextp = fs_tabp;
		fs_tabp = tep;
	}
	endmntent( fp );
}

static void
fs_tab_free( void )
{
	fs_tab_ent_t *tep;
	fs_tab_ent_t *otep;

	for ( tep = fs_tabp
	      ;
	      tep
	      ;
	      otep = tep, tep = tep->fte_nextp, fs_tab_ent_free( otep ) )

		;
}

static fs_tab_ent_t *
fs_tab_ent_build( struct mntent *mntentp )
{
	fs_tab_ent_t *tep;
	char *cp;

	tep = ( fs_tab_ent_t * )calloc( 1, sizeof( fs_tab_ent_t ));
	ASSERT( tep );

	if ( mntentp->mnt_dir ) {
		cp = calloc( 1, strlen( mntentp->mnt_dir ) + 1 );
		ASSERT( cp );
		( void )strcpy( cp, mntentp->mnt_dir );
		tep->fte_mnts = cp;
	} else {
		tep->fte_mnts = 0;
	}

	if ( mntentp->mnt_type ) {
		cp = calloc( 1, strlen( mntentp->mnt_type ) + 1 );
		ASSERT( cp );
		( void )strcpy( cp, mntentp->mnt_type );
		tep->fte_typs = cp;
	} else {
		tep->fte_typs = 0;
	}

	if ( mntentp->mnt_fsname ) {
		cp = calloc( 1, strlen( mntentp->mnt_fsname ) + 1 );
		ASSERT( cp );
		( void )strcpy( cp, mntentp->mnt_fsname );
		tep->fte_blks = cp;
	} else {
		tep->fte_blks = 0;
	}

	return tep;
}

static void
fs_tab_ent_free( fs_tab_ent_t *tep )
{
	if ( tep->fte_blks ) free( tep->fte_blks );
	if ( tep->fte_mnts ) free( tep->fte_mnts );
	if ( tep->fte_typs ) free( tep->fte_typs );
	memset( ( void * )tep, 0, sizeof( *tep )); /* bug catcher */
	free( tep );
}

static fs_tab_ent_t *
fs_tab_lookup_blk( char *blks )
{
	fs_tab_ent_t *tep;

	for ( tep = fs_tabp ; tep ; tep = tep->fte_nextp ) {
		struct stat64 stata;
		bool_t aok;
		struct stat64 statb;
		bool_t bok;

		if ( ! tep->fte_blks ) {
			continue;
		}

		if ( ! strcmp( tep->fte_blks, blks )) {
			return tep;
		}

		aok = ! stat64( blks, &stata );
		bok = ! stat64( tep->fte_blks, &statb );
		if ( aok && bok && stata.st_rdev == statb.st_rdev ) {
			return tep;
		}
	}
	return 0;
}

static fs_tab_ent_t *
fs_tab_lookup_mnt( char *mnts )
{
	fs_tab_ent_t *tep;

	for ( tep = fs_tabp ; tep ; tep = tep->fte_nextp ) {
		if ( tep->fte_mnts && ! strcmp( tep->fte_mnts, mnts )) {
			return tep;
		}
	}
	return 0;
}