176 lines
3.8 KiB
C
176 lines
3.8 KiB
C
# ifdef lint
|
|
static char sccsid[] = "@(#)where.c 1.1 94/10/31 Copyr 1985 Sun Micro";
|
|
# endif lint
|
|
|
|
/*
|
|
* where.c - get full pathname including host:
|
|
*
|
|
* Copyright (c) 1985 Sun Microsystems, Inc.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <exportent.h>
|
|
#include <mntent.h>
|
|
#include <sys/param.h>
|
|
#include <sys/stat.h>
|
|
|
|
extern errno, sys_nerr;
|
|
extern char *sys_errlist[];
|
|
#define errstr() (errno < sys_nerr ? sys_errlist[errno] : "unknown error")
|
|
|
|
/*
|
|
* where(pn, host, fsname, within)
|
|
*
|
|
* pn is the pathname we are looking for,
|
|
* host gets the name of the host owning the file system,
|
|
* fsname gets the file system name on the host,
|
|
* within gets whatever is left from the pathname
|
|
*
|
|
* Returns: 0 if ERROR, 1 if OK
|
|
*/
|
|
where(pn, host, fsname, within)
|
|
char *pn;
|
|
char *host;
|
|
char *fsname;
|
|
char *within;
|
|
{
|
|
struct stat sb;
|
|
char curdir[MAXPATHLEN];
|
|
char qualpn[MAXPATHLEN];
|
|
char *p, *rindex();
|
|
|
|
if (stat(pn, &sb) < 0) {
|
|
strcpy(within, errstr());
|
|
return (0);
|
|
}
|
|
/*
|
|
* first get the working directory,
|
|
*/
|
|
if (getwd(curdir) == 0) {
|
|
sprintf(within, "Unable to get working directory (%s)",
|
|
curdir);
|
|
return (0);
|
|
}
|
|
if (chdir(pn) == 0) {
|
|
getwd(qualpn);
|
|
chdir(curdir);
|
|
} else {
|
|
if (p = rindex(pn, '/')) {
|
|
*p = 0;
|
|
chdir(pn);
|
|
(void) getwd(qualpn);
|
|
chdir(curdir);
|
|
strcat(qualpn, "/");
|
|
strcat(qualpn, p+1);
|
|
} else {
|
|
strcpy(qualpn, curdir);
|
|
strcat(qualpn, "/");
|
|
strcat(qualpn, pn);
|
|
}
|
|
}
|
|
return findmount(qualpn, host, fsname, within);
|
|
}
|
|
|
|
/*
|
|
* findmount(qualpn, host, fsname, within)
|
|
*
|
|
* Searches the mount table to find the appropriate file system
|
|
* for a given absolute path name.
|
|
* host gets the name of the host owning the file system,
|
|
* fsname gets the file system name on the host,
|
|
* within gets whatever is left from the pathname
|
|
*
|
|
* Returns: 0 on failure, 1 on success.
|
|
*/
|
|
findmount(qualpn, host, fsname, within)
|
|
char *qualpn;
|
|
char *host;
|
|
char *fsname;
|
|
char *within;
|
|
{
|
|
FILE *mfp;
|
|
char bestname[MAXPATHLEN];
|
|
int bestlen = 0, bestnfs = 0;
|
|
struct exportent *exp;
|
|
struct mntent *mnt;
|
|
char *endhost; /* points past the colon in name */
|
|
extern char *index();
|
|
int i, len;
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
mfp = setmntent("/etc/mtab", "r");
|
|
if (mfp != NULL)
|
|
break;
|
|
sleep(1);
|
|
}
|
|
if (mfp == NULL) {
|
|
sprintf(within, "mount table problem");
|
|
return (0);
|
|
}
|
|
while ((mnt = getmntent(mfp)) != NULL) {
|
|
len = preflen(qualpn, mnt->mnt_dir);
|
|
if (qualpn[len] != '/' && qualpn[len] != '\0' && len > 1)
|
|
/*
|
|
* If the last matching character is neither / nor
|
|
* the end of the pathname, not a real match
|
|
* (except for matching root, len==1)
|
|
*/
|
|
continue;
|
|
if (len > bestlen) {
|
|
bestlen = len;
|
|
strncpy(bestname, mnt->mnt_fsname, sizeof(bestname));
|
|
}
|
|
}
|
|
endmntent(mfp);
|
|
endhost = index(bestname,':');
|
|
/*
|
|
* If the file system was of type NFS, then there should already
|
|
* be a host name, otherwise, use ours.
|
|
*/
|
|
if (endhost) {
|
|
*endhost++ = 0;
|
|
strncpy(host, bestname, MAXHOSTNAMELEN);
|
|
strncpy(fsname, endhost, MAXPATHLEN);
|
|
/*
|
|
* special case to keep the "/" when we match root
|
|
*/
|
|
if (bestlen == 1)
|
|
bestlen = 0;
|
|
} else {
|
|
gethostname(host, MAXHOSTNAMELEN);
|
|
|
|
/*
|
|
* If this is our file system, try for an even longer
|
|
* match from /etc/xtab.
|
|
*/
|
|
if (mfp = setexportent()) {
|
|
while (exp = getexportent(mfp))
|
|
if (len = preflen(qualpn, exp->xent_dirname))
|
|
if (len > bestlen) {
|
|
bestlen = len;
|
|
strncpy(bestname, exp->xent_dirname, sizeof(bestname));
|
|
}
|
|
endexportent(mfp);
|
|
}
|
|
strncpy(fsname,qualpn,bestlen);
|
|
fsname[bestlen] = 0;
|
|
}
|
|
strncpy(within, qualpn + bestlen, MAXPATHLEN);
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Returns: length of second argument if it is a prefix of the
|
|
* first argument, otherwise zero.
|
|
*/
|
|
preflen(str, pref)
|
|
char *str, *pref;
|
|
{
|
|
int len;
|
|
|
|
len = strlen(pref);
|
|
if (strncmp(str, pref, len) == 0)
|
|
return (len);
|
|
return (0);
|
|
}
|