cdesktopenv/cde/programs/dtmail/libDtMail/Common/DetermineFileLocality.C

193 lines
5.7 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
*+SNOTICE
*
* $TOG: DetermineFileLocality.C /main/9 1997/12/22 16:30:59 bill $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
*
*+ENOTICE
*/
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#if defined(SVR4)
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/mnttab.h>
#include <sys/mntent.h>
#include <sys/param.h>
#endif
#include <DtMail/DtMail.hh>
/*
* Returns: length of second argument if it is a prefix of the
* first argument, otherwise zero.
*/
static int
preflen(char * str, char * pref)
{
int len;
assert(str != NULL);
assert(pref != NULL);
len = strlen(pref);
if (strncmp(str, pref, len) == 0)
return (len);
return (0);
}
// DetermineFileLocality -- determine if specified path object is local
// or remote to the current system
// Arguments:
// const char * path -- -> path to object whose locality is to be determined
// Outputs:
// None.
// Returns:
// (DtmFileLocality) -- determined locality of the specified path object:
// FL_UNKNOWN -- locality of object cannot be determined
// FL_LOCAL -- the path object is local to this system
// FL_REMOTE -- the path object is remote to this system
// -- (such as an NFS mounted file system object)
// FL_LOCAL_AND_REMOTE -- the path object is locally available, yet
// -- it resides remotely (such as a CACHEFS object)
//
enum DtmFileLocality
DtMail::DetermineFileLocality(const char * path)
{
#if defined(SVR4)
FILE *mfp;
struct mnttab *mnt;
struct mnttab sysvmnt;
int fsTypeLen = 0;
int len;
char realPath[MAXPATHLEN]; // resolved symbolic link
char linkname[MAXPATHLEN]; // for symbolic link chasing
char fsType[MAXPATHLEN]; // fs type for name put here
struct statvfs statbuf;
int statvfs_successful = 0;
// Make sure the inputs to this function are correct
//
assert(path); // path must be specified
assert(strlen(path)); // cannot have a zero length
// Resolve all symbolic links in path so that we have a handle
// on the name of the actual file to check up on
//
(void) strncpy(realPath, path, MAXPATHLEN-1);
while (1) {
if ((len = readlink(realPath, linkname, sizeof (linkname)-1)) < 0)
break;
linkname[len] = '\0';
(void) strncpy(realPath, linkname, MAXPATHLEN-1);
}
// Try and determine where this file is located relative to here
//
for (int i = 0; ; i++)
{
fsTypeLen = 0;
switch (i)
{
case 0: // first instance -- try statvfs
statbuf.f_files = 0;
if (statvfs (realPath, &statbuf) == -1)
continue;
statvfs_successful++;
fsTypeLen = strlen(statbuf.f_basetype);
(void) strncpy(fsType, statbuf.f_basetype, MAXPATHLEN-1);
break;
case 1: // second instance -- scan mount table
if ( (mfp = fopen(MNTTAB, "r")) == NULL )
continue;
mnt = &sysvmnt;
while ((getmntent(mfp, mnt)) >= 0) {
len = preflen(realPath, mnt->mnt_mountp);
if (len >= fsTypeLen) {
fsTypeLen = len;
(void) strncpy(
fsType,
mnt->mnt_fstype ? mnt->mnt_fstype : "unknown-fstype",
MAXPATHLEN-1);
}
}
fclose(mfp);
break;
default: // run out of major options
if (statvfs_successful) // if statvfs successful, infer results
return(statbuf.f_files == -1 ? Dtm_FL_REMOTE : Dtm_FL_LOCAL);
return(Dtm_FL_UNKNOWN);
}
// At this point, if fsTypeLen > 0 then we have found a match.
// Return the proper Dtm_FL_xxx code according to the type of file system
// path object is located on
//
if (fsTypeLen == 0) // nothing found??
continue; // nope - try next pass
if (!strcmp(fsType, "cachefs")) // cached from anonymous source?
return(Dtm_FL_LOCAL_AND_REMOTE); // yes: file is local and remote
else if (!strcmp(fsType, "nfs")) // nfs resource?
return (Dtm_FL_REMOTE); // yes: file is remote only
else if (!strcmp(fsType, "ufs")) // ufs type file system?
return (Dtm_FL_LOCAL); // yes: file is local only
else if (!strcmp(fsType, "tmpfs")) // tmpfs local but transient file?
return (Dtm_FL_LOCAL); // yes: file is local
else if (!strcmp(fsType, "autofs")) // automounter mounting point??
return (Dtm_FL_REMOTE); // yes: file is remote
// no type that we recognize - try next pass
//
}
#else
int len = (int) strlen(path);
return(Dtm_FL_UNKNOWN);
#endif
}