/*
* Copyright 1988 by Rayan S. Zachariassen, all rights reserved.
* This will be free software, but only when it is finished.
*
* Also Guy Middleton, and Matti Aarnio have hacked this piece -- 1993
*
* In 1996 Matti Aarnio <mea@nic.funet.fi> converted this to GNU autoconf
* and did serious rewriteing...
*/
/*LINTLIBRARY*/
#include "hostenv.h"
#include <stdio.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <string.h>
#include "mail.h"
#include "libc.h"
#ifdef MOUNTED_GETMNT /* DEC Ultrix */
#include <sys/param.h>
#include <sys/mount.h>
#endif
#ifdef MOUNTED_GETMNTINFO /* DEC OSF/1 */
#include <sys/types.h>
#include <sys/mount.h>
#endif
#ifdef MOUNTED_GETMNTENT2
#include <sys/mnttab.h>
#include <sys/mntent.h>
#define MNTTYPE struct mnttab
#endif
#ifdef MOUNTED_GETMNTENT1
#include <mntent.h>
#define MNTTYPE struct mntent
#endif
#ifdef MOUNTED_VMOUNT /* AIX */
#include <sys/vfs.h>
#include <fshelp.h>
#endif
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif /* MAXHOSTNAMELEN */
static char hostname[MAXHOSTNAMELEN+1];
/*
* Given a name like /usr/src/etc/foo.c returns the mount point
* for the file system it lives in, or NULL in case of any error.
*/
#ifdef MOUNTED_GETMNT /* Ultrix */
char *
whathost(file)
const char *file;
{
int mountind, nummount;
static struct fs_data mounts[1];
struct stat filestat, dirstat;
char *s;
if (stat(file, &filestat) < 0) {
perror(file);
return(NULL);
}
mountind = 0;
while ((nummount = getmountent(&mountind, mounts, 1)) > 0) {
if ((stat(mounts[0].fd_path, &dirstat) >= 0) &&
(filestat.st_dev == dirstat.st_dev)) {
strncpy(hostname,hmounts[0].fd_devname,sizeof(hostname));
hostname[sizeof(hostname)-1] = 0;
s = strchr(hostname,':');
if (s != NULL) {
*s = 0;
return hostname;
}
return "localhost";
}
}
if (nummount == -1)
perror("Can't get mount information");
return NULL;
}
#else
#ifdef MOUNTED_GETMNTINFO /* DEC OSF/1 */
char *
whathost(file)
const char *file;
{
int nummount, i;
struct statfs *mounts;
struct stat filestat, dirstat;
char *s;
if (stat(file, &filestat) < 0) {
perror(file);
return(NULL);
}
mounts = NULL;
if ((nummount = getmntinfo(&mounts, MNT_NOWAIT)) == 0) {
perror("Can't get mount information");
return NULL;
}
*hostname = 0;
for (i=0; i<nummount; i++) {
if ((stat(mounts[i].f_mntonname, &dirstat) >= 0) &&
(filestat.st_dev == dirstat.st_dev)) {
s = strchr(mounts[i].f_mntfromname, ':');
if (s != NULL) {
*s = 0;
strncpy(hostname,mounts[i].f_mntfromname,sizeof(hostname));
hostname[sizeof(hostname)-1] = 0;
if (strncmp(s+1,"(pid",4) == 0) {
/* Umm.. Most likely this is an automount mountpoint!
Lets try to find the real one, if we can! */
continue;
}
} else {
strcpy(hostname,"localhost");
}
break;
}
}
/*free(mounts);*/ /* DONT FREE IT! */
if (*hostname != 0)
return hostname;
return NULL;
}
#else
#ifdef MOUNTED_GETMNTENT1
char *
whathost(file)
const char *file;
{
FILE *mntp;
MNTTYPE *mnt = NULL;
struct stat filestat, dirstat;
char *s;
int rc, e, retries = 0;
const char *errstr = NULL;
retry:
e = errno;
++retries;
if (retries > 1) sleep(1);
if (retries > 4) {
errno = e;
perror(errstr ? errstr : "<unknown>");
return NULL;
}
if (stat(file, &filestat) < 0) {
errstr = file;
goto retry;
}
if ((mntp = setmntent(MOUNTED, "r")) == NULL) {
errstr = MOUNTED;
goto retry;
}
while ((mnt = getmntent(mntp)) != 0) {
if (strcmp(mnt->mnt_type, MNTTYPE_IGNORE) == 0 ||
strcmp(mnt->mnt_type, MNTTYPE_SWAP) == 0)
continue;
rc = stat(mnt->mnt_dir, &dirstat);
if (rc < 0) {
e = errno;
endmntent(mntp);
errstr = mnt->mnt_dir;
errno = e;
goto retry;
}
if ((rc >= 0) && (filestat.st_dev == dirstat.st_dev)) {
s = strchr(mnt->mnt_fsname,':');
if (s != NULL) {
*s = 0;
strncpy(hostname,mnt->mnt_fsname,sizeof(hostname)-1);
hostname[sizeof(hostname)-1] = 0;
} else
strcpy(hostname,"localhost");
endmntent(mntp);
return hostname;
}
}
endmntent(mntp);
return NULL;
}
#else
#ifdef MOUNTED_GETMNTENT2
char *
whathost(file)
const char *file;
{
FILE *mntp;
MNTTYPE *mnt;
static MNTTYPE rmnt;
struct stat filestat, dirstat;
char *s;
const char *errstr = NULL;
int retries = 0;
int rc, e;
retry:
e = errno;
++retries;
if (retries > 1) sleep(1);
if (retries > 8) {
errno = e;
perror(errstr ? errstr : "<unknown>");
return NULL;
}
if (stat(file, &filestat) < 0) {
errstr = file;
goto retry;
}
mnt = &rmnt;
if ((mntp = fopen(MNTTAB, "r")) == NULL) {
errstr = MNTTAB;
goto retry;
}
*hostname = 0;
while (getmntent(mntp, mnt) == 0) {
if (strcmp(mnt->mnt_fstype, MNTTYPE_SWAP) == 0)
continue;
rc = stat(mnt->mnt_mountp, &dirstat);
if (rc < 0) {
errstr = mnt->mnt_mountp;
goto retry;
}
if ((rc >= 0) && (filestat.st_dev == dirstat.st_dev)) {
/* So ok, filestat matches, but it may be an automount/autofs
mountpoint, try to recognize it too */
s = strchr(mnt->mnt_special,':');
if (s != NULL) {
*s = 0;
strncpy(hostname,mnt->mnt_special,sizeof(hostname)-1);
hostname[sizeof(hostname)-1] = 0;
if (strcmp(mnt->mnt_fstype,"autofs") == 0 /* Solaris */ ||
strncmp(s+1,"(pid",4) == 0 /* Other automounters */ )
continue;
} else {
strcpy(hostname,"localhost");
if (strcmp(mnt->mnt_fstype, "autofs") == 0)
continue;
}
fclose(mntp);
return hostname;
}
}
fclose(mntp);
if (*hostname != 0)
return hostname;
return NULL;
}
#else
#if defined(MOUNTED_VMOUNT) /* AIX */
/* Much of the following code is from GNU fileutils 3.13 */
char *
whathost(file)
const char *file;
{
struct stat dirstat, statb;
int bufsize;
char *entries, *thisent;
struct vmount *vmp;
char *dir, *host;
/* Stat the file, is it a regular file, or a directory ? */
if (stat(file, &statb) < 0)
return NULL;
if (statb.st_mode & S_IFMT & (S_IFREG|S_IFDIR) == 0)
return NULL;
/* Ask how many bytes to allocate for the mounted filesystem info. */
mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
#ifdef USE_ALLOCA
entries = alloca (bufsize);
#else
entries = malloc (bufsize);
if (entries == NULL) return NULL; /* Ah well... */
#endif
/* Get the list of mounted filesystems. */
mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
vmp = NULL;
for (thisent = entries; thisent < entries + bufsize;
thisent += vmp->vmt_length) {
vmp = (struct vmount *) thisent;
if (vmp->vmt_flags == -1) break;
dir = thisent + vmp->vmt_data[VMT_STUB].vmt_off;
/* Stat it; Is it at same device as the file/dir ? */
if (stat(dir,&dirstat) < 0 ||
dirstat.st_dev != statb.st_dev)
continue;
/* Now the mount-point device does match with the file device;
we know the mount-point where our file is located at! */
if (vmp->vmt_flags & MNT_REMOTE) {
/* A remote system! Return the hostname */
host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
strncpy(hostname,host,sizeof(hostname));
hostname[sizeof(hostname)-1] = 0;
#ifndef USE_ALLOCA
free(entries);
#endif
return hostname;
} else {
#ifndef USE_ALLOCA
free(entries);
#endif
return "localhost";
}
}
#ifndef USE_ALLOCA
free(entries);
#endif
return NULL;
}
#else /* Not AIX -- all other systems .. */
error:error:error: Unknown/unimplemented filesystem mount-info method
#endif
#endif
#endif
#endif
#endif
syntax highlighted by Code2HTML, v. 0.9.1