/*
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License."
*
* @APPLE_LICENSE_HEADER_END@
*/
#define kUseExistingMount 0x00000001
#define kNoNewMount 0x00000002
#define kMountAtMountdir 0x00000004
#define kMarkAutomounted 0x00000008
#import "Controller.h"
#import "automount.h"
#import "Server.h"
#import "AMString.h"
#import "AMVnode.h"
#import "FstabMap.h"
#import "FileMap.h"
#import "NIMap.h"
#import "log.h"
#import <unistd.h>
#import <stdio.h>
#import <syslog.h>
#import <stdlib.h>
#import <string.h>
#import <errno.h>
#import <sys/socket.h>
#import <sys/param.h>
#import <sys/types.h>
#import <sys/wait.h>
#import <grp.h>
#import <sys/stat.h>
#import "nfs_prot.h"
#import <arpa/nameser.h>
#import <netinfo/ni.h>
#import <resolv.h>
#ifdef __APPLE__
extern int mount(const char *, const char *, int, void *);
extern int unmount(const char *, int);
#else
#import <libc.h>
#import <sys/file.h>
extern int getpid(void);
extern int mkdir(const char *, int);
extern int chdir(const char *);
#endif
#define HOSTINFO "/usr/bin/hostinfo"
#define OS_NEXTSTEP 0
#define OS_OPENSTEP 1
#define OS_MACOSX 2
#define OS_DARWIN 3
extern void nfs_program_2();
int afp_LLMount(const char* inFullURL, const char* inMountDir, size_t inMaxPath, char* outMountPoint, unsigned int inOptions);
static gid_t gidForGroup(char *grpName)
{
struct group *namedGroup;
gid_t retVal = 0;
namedGroup = getgrnam(grpName);
if (namedGroup) {
retVal = namedGroup->gr_gid;
}
sys_msg(debug, LOG_DEBUG, "Got gid for name grpName, retVal);
if (retVal == 0) {
sys_msg(debug, LOG_ERR, "Could not determine the gid for group =
}
return retVal;
}
@implementation Controller
- (Controller *)init:(char *)dir
{
Vnode *root;
char str[1024], *p;
FILE *pf;
float vers;
[super init];
node_table_count = 0;
server_table_count = 0;
map_table_count = 0;
node_id = 2;
controller = self;
mountDirectory = [String uniqueString:dir];
rootMap = [[Map alloc] initWithParent:nil directory:mountDirectory];
root = [rootMap root];
transp = svcudp_create(RPC_ANYSOCK);
if (transp == NULL)
{
sys_msg(debug, LOG_ERR, "Cannot create UDP service");
[self release];
return nil;
}
if (!svc_register(transp, NFS_PROGRAM, NFS_VERSION, nfs_program_2, 0))
{
sys_msg(debug, LOG_ERR, "svc_register failed");
[self release];
return nil;
}
gethostname(str, 1024);
p = strchr(str, '.');
if (p != NULL) *p = '\0';
hostName = [String uniqueString:str];
hostDNSDomain = nil;
res_init();
if (_res.options & RES_INIT)
{
hostDNSDomain = [String uniqueString:_res.defdname];
}
#if defined (__ARCHITECTURE__)
hostArchitecture = [String uniqueString:__ARCHITECTURE__];
#elif defined(__ppc__)
hostArchitecture = [String uniqueString:"ppc"];
#elif defined(__i386__)
hostArchitecture = [String uniqueString:"i386"];
#else
#error Unknown architecture
#endif
hostByteOrder = nil;
#ifdef __BIG_ENDIAN__
hostByteOrder = [String uniqueString:"big"];
#else
hostByteOrder = [String uniqueString:"little"];
#endif
pf = popen(HOSTINFO, "r");
fscanf(pf, " fscanf(pf, " pclose(pf);
vers = 0.0;
hostOS = NULL;
p = strchr(str, ':');
if (p != NULL)
{
p = strrchr(str, ' ');
if (p != NULL)
{
sscanf(p+1, " }
}
p = strchr(str, ' ');
if (p != NULL)
{
p++;
if (!strncmp(p, "NeXT", 4))
{
if (vers > 3.3)
{
hostOS = [String uniqueString:"openstep"];
osType = OS_OPENSTEP;
}
else
{
hostOS = [String uniqueString:"nextstep"];
osType = OS_NEXTSTEP;
}
}
else if (!strncmp(p, "Darwin", 6))
{
hostOS = [String uniqueString:"darwin"];
osType = OS_DARWIN;
}
else if (!strncmp(p, "Kernel", 6))
{
hostOS = [String uniqueString:"macosx"];
osType = OS_MACOSX;
}
}
if (hostOS == NULL) hostOS = [String uniqueString:"macosx"];
sprintf(str, " hostOSVersion = [String uniqueString:str];
hostOSVersionMajor = vers;
p = strchr(str, '.');
if (p == NULL) hostOSVersionMinor = 0;
else hostOSVersionMinor = atoi(p+1);
return self;
}
- (BOOL)createPath:(String *)path
{
return [self createPath:path withUid:0];
}
- (BOOL)createPath:(String *)path withUid:(int)uid
{
int i, p;
char *s, t[1024];
int status;
if (path == nil) return YES;
if ([path length] == 0) return YES;
p = 0;
s = [path value];
chdir("/");
while (s != NULL)
{
if (s[0] == '/')
{
p++;
s++;
}
for (i = 0; (s[i] != '/') && (s[i] != '\0'); i++) t[i] = s[i];
t[i] = '\0';
if (i == 0)
{
s = [path scan:'/' pos:&p];
continue;
}
status = mkdir(t, 0755);
if (status == -1)
{
if (errno == EEXIST) status = 0;
if (errno == EISDIR) status = 0;
}
if (status != 0) return NO;
chdir(t);
s = [path scan:'/' pos:&p];
}
chdir("/");
return YES;
}
- (void)registerVnode:(Vnode *)v
{
[v setNodeID:node_id];
if (node_table_count == 0)
node_table = (node_table_entry *)malloc(sizeof(node_table_entry));
else
node_table = (node_table_entry *)realloc(node_table,
(node_table_count + 1) * sizeof(node_table_entry));
node_table[node_table_count].node_id = node_id;
node_table[node_table_count].node = v;
node_table_count++;
node_id++;
}
- (Vnode *)vnodeWithID:(unsigned int)n
{
int i;
Vnode *v;
for (i = 0; i < node_table_count; i++)
{
if (node_table[i].node_id == n)
{
v = node_table[i].node;
[v resetTime];
return v;
}
}
return nil;
}
- (void)destroyVnode:(Vnode *)v
{
int i;
unsigned int n, count;
BOOL searching;
Array *kids;
Vnode *p;
n = [v nodeID];
searching = YES;
for (i = 0; (i < node_table_count) && searching; i++)
{
if (node_table[i].node == v) searching = NO;
}
if (searching)
{
sys_msg(debug, LOG_ERR, "Unreferenced Vnode n, [[v path] value]);
return;
}
for(; i < node_table_count; i++) node_table[i-1] = node_table[i];
node_table_count--;
if (node_table_count == 0)
free(node_table);
else
node_table = (node_table_entry *)realloc(node_table,
node_table_count * sizeof(node_table_entry));
kids = [v children];
if (kids == nil) count = 0;
else count = [kids count];
for (i = count - 1; i >= 0; i--)
[self destroyVnode:[kids objectAtIndex:i]];
p = [v parent];
if (p != nil) [p removeChild:v];
[v release];
}
- (unsigned int)automount:(Vnode *)v directory:(String *)dir args:(int)mntargs
{
struct nfs_args args;
struct sockaddr_in sin;
struct file_handle fh;
char str[MAXPATHLEN + 64];
String *src;
int status;
[self createPath:dir];
src = [v source];
bzero(&sin, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = htons(transp->xp_port);
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
bzero(&args, sizeof(args));
#ifdef __APPLE__
args.addr = (struct sockaddr *)&sin;
args.version = NFS_ARGSVERSION;
args.addrlen = sizeof(struct sockaddr_in);
args.sotype = SOCK_DGRAM;
args.proto = IPPROTO_UDP;
args.readdirsize = NFS_READDIRSIZE;
args.maxgrouplist = NFS_MAXGRPS;
args.readahead = NFS_DEFRAHEAD;
args.fhsize = sizeof(nfs_fh);
args.flags = NFSMNT_INT | NFSMNT_TIMEO | NFSMNT_RETRANS;
args.wsize = NFS_WSIZE;
args.rsize = NFS_RSIZE;
#else
args.addr = (struct sockaddr_in *)&sin;
args.flags = NFSMNT_INT | NFSMNT_TIMEO | NFSMNT_RETRANS;
args.wsize = NFS_WSIZE;
args.rsize = NFS_RSIZE;
#endif
args.timeo = 1;
args.retrans = 5;
bzero(&fh, sizeof(nfs_fh));
fh.node_id = [v nodeID];
args.fh = (u_char *)&fh;
sprintf(str, "automount args.hostname = str;
sys_msg(debug, LOG_DEBUG, "Mounting map [src value], [dir value]);
#ifdef __APPLE__
status = mount("nfs", [dir value], mntargs, &args);
#else
status = mount(MOUNT_NFS, [dir value], mntargs, (caddr_t)&args);
#endif
if (status != 0)
{
sys_msg(debug, LOG_ERR, "Can't mount map [src value], [dir value], strerror(errno));
return 1;
}
[v setMounted:YES];
#ifndef __APPLE__
[self mtabUpdate:v];
#endif
return 0;
}
- (BOOL)isFile:(String *)name
{
struct stat sb;
int status;
if (name == nil) return NO;
status = stat([name value], &sb);
if (status != 0)
{
sys_msg(debug, LOG_ERR, " return NO;
}
if (!(sb.st_mode & S_IFREG))
{
sys_msg(debug, LOG_ERR, " return NO;
}
return YES;
}
- (unsigned int)autoMap:(Map *)map name:(String *)name directory:(String *)dir
{
Vnode *maproot;
unsigned int status;
maproot = [map root];
[maproot setSource:name];
[maproot setLink:dir];
if (map_table_count == 0)
map_table = (map_table_entry *)malloc(sizeof(map_table_entry));
else
map_table = (map_table_entry *)realloc(map_table,
(map_table_count + 1) * sizeof(map_table_entry));
map_table[map_table_count].name = [name retain];
map_table[map_table_count].dir = [dir retain];
map_table[map_table_count].map = map;
map_table_count++;
status = [self automount:maproot directory:dir args:[map mountArgs]];
if (status != 0) return status;
status = [map didAutoMount];
return status;
}
- (unsigned int)mountmap:(String *)mapname directory:(String *)dir
{
Vnode *root, *p;
Map *map;
char *s, *t;
String *parent, *mountpt;
root = [rootMap root];
s = malloc([dir length] + 1);
sprintf(s, " t = strrchr(s, '/');
if (t == NULL)
{
sys_msg(debug, LOG_ERR, "Invalid directory \" free(s);
return 1;
}
*t++ = '\0';
parent = [String uniqueString:s];
mountpt = [String uniqueString:t];
free(s);
p = [rootMap createVnodePath:parent from:root];
[parent release];
sys_msg(debug, LOG_DEBUG, "Initializing map \" if (strcmp([mapname value], "-fstab") == 0)
{
map = [[FstabMap alloc]
initWithParent:p directory:mountpt from:mapname];
}
else if (strncmp([mapname value], "/", 1))
{
map = [[NIMap alloc]
initWithParent:p directory:mountpt from:mapname];
}
else if ([self isFile:mapname])
{
map = [[FileMap alloc]
initWithParent:p directory:mountpt from:mapname];
}
else if (strcmp([mapname value], "-null") == 0)
{
map = [[Map alloc] initWithParent:p directory:mountpt];
}
else
{
sys_msg(debug, LOG_ERR, "Unknown map \" return 1;
}
[mountpt release];
if (map == nil)
{
sys_msg(debug, LOG_ERR, "Map \" [mapname value]);
return 1;
}
return [self autoMap:map name:mapname directory:dir];
}
- (Map *)rootMap
{
return rootMap;
}
- (unsigned int)nfsmount:(Vnode *)v withUid:(int)uid
{
struct sockaddr_in sin;
struct nfs_args args;
char str[1024];
struct file_handle fh;
Server *s;
unsigned int status;
unsigned int vers, proto;
unsigned short port;
String *urlMountType;
urlMountType = [String uniqueString:"url"];
#ifndef __APPLE__
unsigned int fhsize;
#endif
if ([v mounted])
{
sys_msg(debug_mount, LOG_DEBUG, " [[v link] value]);
[v setNfsStatus:NFS_OK];
return 0;
}
if ([v source] == nil)
{
[v setMounted:YES];
return 0;
}
s = [v server];
if (s == nil)
{
sys_msg(debug, LOG_ERR, "No file server for [v setNfsStatus:NFSERR_NXIO];
return 1;
}
if (![v mountPathCreated])
{
if (![self createPath:[v link] withUid:uid])
{
sys_msg(debug, LOG_ERR, "Can't create mount point [[v link] value]);
[v setNfsStatus:NFSERR_IO];
return 1;
}
[v setMountPathCreated:YES];
}
sprintf(str, "
[s setTimeout:[v mntTimeout]];
args = [v nfsArgs];
args.hostname = str;
sys_msg(debug, LOG_DEBUG, "Mounting str, [[v link] value]);
#ifdef __APPLE__
vers = [v forcedNFSVersion];
proto = [v forcedProtocol];
if ([[v vfsType] equal:urlMountType]) { // afp or http
char path[1024];
char mountDir[1024];
char retString[1024];
uid_t effuid = geteuid();
gid_t storedgid = getgid();
gid_t storedegid = getegid();
// system("/Volumes/MacOS9/HomeDir/Projects/afpLoad/afpLoad");
sprintf(path, " sprintf(mountDir, "/private/
// chown the path to the passed in UID
chown([[v link] value], uid, gidForGroup("nobody"));
sys_msg(debug_mount, LOG_DEBUG, "Attempting to automount url: \n\tpath =
setreuid(getuid(), uid);
setgid(gidForGroup("unknown")); // unknown
setegid(gidForGroup("unknown")); // unknown
status = afp_LLMount(path, [[v link] value], 1024, retString, 0x000003C);
setreuid(getuid(), effuid);
setgid(storedgid);
setegid(storedegid);
if (status) {
sys_msg(debug_mount, LOG_DEBUG, "Recieved status = }
} else { // nfs
status = 1;
if ((vers == 3) || (vers == 0))
{
/* Try NFS Version 3 */
args.flags |= NFSMNT_NFSV3;
if ((proto == IPPROTO_UDP) || (proto == 0))
{
/* Try UDP */
args.proto = IPPROTO_UDP;
args.sotype = SOCK_DGRAM;
sys_msg(debug_mount, LOG_DEBUG,
"Fetching NFS_V3/UDP filehandle for
status = [s getHandle:(nfs_fh *)&fh size:&args.fhsize port:&port forFile:[v source] version:3 protocol:IPPROTO_UDP];
if ((status != 0) && (vers == 3) && (proto != 0))
{
[v setNfsStatus:status];
return 1;
}
}
if ((status != 0) && ((proto == IPPROTO_TCP) || (proto == 0)))
{
/* Try TCP */
args.proto = IPPROTO_TCP;
args.sotype = SOCK_STREAM;
sys_msg(debug_mount, LOG_DEBUG,
"Fetching NFS_V3/TCP filehandle for
status = [s getHandle:(nfs_fh *)&fh size:&args.fhsize port:&port forFile:[v source] version:3 protocol:IPPROTO_TCP];
if ((status != 0) && (vers == 3))
{
[v setNfsStatus:status];
return 1;
}
}
}
if (status != 0)
{
/* Try NFS Version 2 */
args.flags &= (~NFSMNT_NFSV3);
if ((proto == IPPROTO_UDP) || (proto == 0))
{
/* Try UDP */
args.proto = IPPROTO_UDP;
args.sotype = SOCK_DGRAM;
sys_msg(debug_mount, LOG_DEBUG,
"Fetching NFS_V2/UDP filehandle for
status = [s getHandle:(nfs_fh *)&fh size:&args.fhsize port:&port forFile:[v source] version:2 protocol:IPPROTO_UDP];
if ((status != 0) && (proto != 0))
{
[v setNfsStatus:status];
return 1;
}
}
if ((status != 0) && ((proto == IPPROTO_TCP) || (proto == 0)))
{
/* Try TCP */
args.proto = IPPROTO_TCP;
args.sotype = SOCK_STREAM;
sys_msg(debug_mount, LOG_DEBUG,
"Fetching NFS_V2/TCP filehandle for
status = [s getHandle:(nfs_fh *)&fh size:&args.fhsize port:&port forFile:[v source] version:2 protocol:IPPROTO_TCP];
}
}
if (status != 0)
{
[v setNfsStatus:status];
return 1;
}
args.fh = (u_char *)&fh;
proto = args.proto;
vers = 2;
if (args.flags & NFSMNT_NFSV3) vers = 3;
bzero(&sin, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = [s address];
args.addr = (struct sockaddr *)&sin;
status = mount("nfs", [[v link] value], [v mntArgs], &args);
}
#else
if ([[v vfsType] equal:urlMountType] ) {
status = 1; // fail
} else {
vers = 2;
proto = IPPROTO_UDP;
args.flags &= (~NFSMNT_NFSV3);
sys_msg(debug_mount, LOG_DEBUG,
"Fetching filehandle for
status = [s getHandle:(nfs_fh *)&fh size:&fhsize port:&port forFile:[v source] version:vers protocol:proto];
if (status != 0)
{
[v setNfsStatus:status];
return 1;
}
args.fh = (u_char *)&fh;
bzero(&sin, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = port;
sin.sin_addr.s_addr = [s address];
args.addr = (struct sockaddr_in *)&sin;
status = mount(MOUNT_NFS, [[v link] value], [v mntArgs], (caddr_t)&args);
}
#endif
if (status != 0)
{
sys_msg(debug, LOG_ERR, "Can't mount str, [[v link] value], strerror(errno));
[v setNfsStatus:NFSERR_IO];
return 1;
}
sys_msg(debug_mount, LOG_DEBUG, "Mounted str, [[v link] value], vers,
(proto == IPPROTO_UDP) ? "UDP" : "TCP");
/* Tell the node that it was mounted */
[v setMounted:YES];
#ifndef __APPLE__
[self mtabUpdate:v];
#endif
[urlMountType release];
return 0;
}
- (Server *)serverWithName:(String *)name
{
int i;
Server *s;
for (i = 0; i < server_table_count; i++)
{
if ([name equal:server_table[i].name])
return server_table[i].server;
}
s = [[Server alloc] initWithName:name];
if (s == nil)
{
sys_msg(debug, LOG_ERR, "Unknown server: return nil;
}
if (server_table_count == 0)
server_table = (server_table_entry *)malloc(sizeof(server_table_entry));
else
server_table = (server_table_entry *)realloc(server_table,
(server_table_count + 1) * sizeof(server_table_entry));
server_table[server_table_count].name = [name retain];
server_table[server_table_count].server = s;
server_table_count++;
return s;
}
- (void)timeout
{
int i;
/* Tell maps to try to unmount */
for (i = 0; i < map_table_count; i++) [map_table[i].map timeout];
}
- (void)showNode:(int)n
{
char msg[1024];
Vnode *v;
v = node_table[n].node;
msg[0] = '\0';
sprintf(msg, " strcat(msg, ": ");
strcat(msg, [[v name] value]);
if ([v type] == NFLNK)
{
if ([v mounted]) strcat(msg, " <-- ");
else strcat(msg, " ... ");
strcat(msg, [[[v server] name] value]);
strcat(msg, ":");
strcat(msg, [[v source] value]);
}
sys_msg(debug, LOG_DEBUG, "}
- (void)reInit
{
}
- (void)dealloc
{
int i;
int status;
Vnode *v;
chdir("/");
/* unmount normal NFS mounts */
for (i = node_table_count - 1; i >= 0; i--)
{
v = node_table[i].node;
if ([v server] == nil) continue;
if ([v source] == nil) [v setMounted:NO];
if ([v fakeMount]) [v setMounted:NO];
if ([[v server] isLocalHost]) [v setMounted:NO];
if (![v mounted]) continue;
#ifdef __APPLE__
status = unmount([[v link] value], 0);
if (status != 0)
{
status = unmount([[v link] value], MNT_FORCE);
}
#else
status = unmount([[v link] value]);
#endif
if (status == 0)
{
[v setMounted:NO];
#ifndef __APPLE__
[self mtabUpdate:v];
#endif
sys_msg(debug, LOG_DEBUG, "Unmounted }
else
{
sys_msg(debug, LOG_DEBUG, "Unmount failed for [[v link] value], strerror(errno));
}
}
/* unmount automounter */
for (i = node_table_count - 1; i >= 0; i--)
{
v = node_table[i].node;
if ([v fakeMount]) continue;
if ([v server] != nil) continue;
if (![v mounted]) continue;
if ([v link] == nil) continue;
#ifdef __APPLE__
status = unmount([[v link] value], 0);
if (status != 0)
{
status = unmount([[v link] value], MNT_FORCE);
}
#else
status = unmount([[v link] value]);
#endif
if (status == 0)
{
[v setMounted:NO];
#ifndef __APPLE__
[self mtabUpdate:v];
#endif
sys_msg(debug, LOG_DEBUG, "Unmounted }
else
{
sys_msg(debug, LOG_DEBUG, "Unmount failed for [[v link] value], strerror(errno));
}
}
for (i = 0; i < map_table_count; i++)
{
[map_table[i].name release];
[map_table[i].dir release];
[map_table[i].map release];
}
free(map_table);
for (i = 0; i < node_table_count; i++)
{
[node_table[i].node release];
}
free(node_table);
for (i = 0; i < server_table_count; i++)
{
[server_table[i].name release];
[server_table[i].server release];
}
free(server_table);
if (hostName != nil) [hostName release];
if (hostDNSDomain != nil) [hostDNSDomain release];
if (hostArchitecture != nil) [hostArchitecture release];
if (hostByteOrder != nil) [hostByteOrder release];
if (hostOS != nil) [hostOS release];
if (hostOSVersion != nil) [hostOSVersion release];
[super dealloc];
}
- (unsigned int)attemptUnmount:(Vnode *)v
{
int status;
if (v == nil) return EINVAL;
if (![v mounted]) return 0;
if ([v type] != NFLNK) return EINVAL;
if ([v source] == nil)
{
[v setMounted:NO];
return 0;
}
sys_msg(debug_mount, LOG_DEBUG, "Attempting to unmount [[v link] value]);
#ifdef __APPLE__
status = unmount([[v link] value], 0);
#else
status = unmount([[v link] value]);
#endif
if (status == 0)
{
sys_msg(debug, LOG_DEBUG, "Unmounted [v setMounted:NO];
#ifndef __APPLE__
[self mtabUpdate:v];
#endif
return 0;
}
sys_msg(debug_mount, LOG_DEBUG, "Unmount [[v link] value], strerror(errno));
[v resetMountTime];
return 1;
}
- (void)printTree
{
int i;
for (i = 0; i < map_table_count; i++)
{
sys_msg(debug, LOG_DEBUG, "Map [map_table[i].name value], [map_table[i].dir value]);
[self printNode:[map_table[i].map root] level:0];
}
}
- (void)printNode:(Vnode *)v level:(unsigned int)l
{
unsigned int i, len;
Array *kids;
char msg[1024];
if (v == nil) return;
msg[0] = '\0';
strcat(msg, " ");
len = l * 4;
for (i = 0; i < len; i++) strcat(msg, " ");
strcat(msg, [[v name] value]);
if ([v type] == NFLNK)
{
if ([v mounted]) strcat(msg, " <-- ");
else strcat(msg, " ... ");
strcat(msg, [[[v server] name] value]);
if ([v source] != nil)
{
strcat(msg, ":");
strcat(msg, [[v source] value]);
}
}
sys_msg(debug, LOG_DEBUG, "
kids = [v children];
len = 0;
if (kids != nil) len = [kids count];
for (i = 0; i < len; i++)
{
[self printNode:[kids objectAtIndex:i] level:l+1];
usleep(100);
}
}
- (String *)mountDirectory
{
return mountDirectory;
}
- (String *)hostName
{
return hostName;
}
- (String *)hostDNSDomain
{
return hostDNSDomain;
}
- (String *)hostArchitecture
{
return hostArchitecture;
}
- (String *)hostByteOrder
{
return hostByteOrder;
}
- (String *)hostOS
{
return hostOS;
}
- (String *)hostOSVersion
{
return hostOSVersion;
}
- (int)hostOSVersionMajor
{
return hostOSVersionMajor;
}
- (int)hostOSVersionMinor
{
return hostOSVersionMinor;
}
#ifndef __APPLE__
- (void)mtabUpdate:(Vnode *)v
{
FILE *f, *g;
char line[1024], target[1024];
unsigned int vid, pid, len;
vid = [v nodeID];
pid = getpid();
if ([v server] == nil)
{
sprintf(target, "<automount>: [[[v map] name] value], [[v link] value], vid, pid);
}
else
{
sprintf(target, " [[[v server] name] value], [[v source] value],
[[v link] value], vid, pid);
}
if ([v mounted])
{
f = fopen("/etc/mtab", "a");
if (f == NULL)
{
sys_msg(debug, LOG_ERR, "Can't write /etc/mtab: strerror(errno));
return;
}
fprintf(f, " fclose(f);
return;
}
f = fopen("/etc/mtab", "r");
if (f == NULL)
{
sys_msg(debug, LOG_ERR, "Can't read /etc/mtab: return;
}
g = fopen("/etc/auto_mtab", "w");
if (f == NULL)
{
sys_msg(debug, LOG_ERR, "Can't create /etc/auto_mtab: strerror(errno));
return;
}
len = strlen(target);
while (fgets(line, 1024, f))
{
if (strncmp(line, target, len)) fprintf(g, " }
fclose(f);
fclose(g);
rename("/etc/auto_mtab", "/etc/mtab");
}
#endif
@end