/* * 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@ */ #import "automount.h" #import "NFSHeaders.h" #import #import #import #import #import "Controller.h" #import "AMMap.h" #import "log.h" #import "AMVnode.h" #import "AMString.h" #ifndef __APPLE__ #define nfsproc_create_2_svc nfsproc_create_2 #define nfsproc_getattr_2_svc nfsproc_getattr_2 #define nfsproc_link_2_svc nfsproc_link_2 #define nfsproc_lookup_2_svc nfsproc_lookup_2 #define nfsproc_mkdir_2_svc nfsproc_mkdir_2 #define nfsproc_null_2_svc nfsproc_null_2 #define nfsproc_read_2_svc nfsproc_read_2 #define nfsproc_readdir_2_svc nfsproc_readdir_2 #define nfsproc_readlink_2_svc nfsproc_readlink_2 #define nfsproc_remove_2_svc nfsproc_remove_2 #define nfsproc_rename_2_svc nfsproc_rename_2 #define nfsproc_rmdir_2_svc nfsproc_rmdir_2 #define nfsproc_root_2_svc nfsproc_root_2 #define nfsproc_setattr_2_svc nfsproc_setattr_2 #define nfsproc_statfs_2_svc nfsproc_statfs_2 #define nfsproc_symlink_2_svc nfsproc_symlink_2 #define nfsproc_write_2_svc nfsproc_write_2 #define nfsproc_writecache_2_svc nfsproc_writecache_2 #endif int _rpcpmstart; /* Started by a port monitor ? */ int _rpcfdtype; /* Whether Stream or Datagram ? */ int _rpcsvcdirty; /* Still serving ? */ extern void send_pid_to_parent(void); extern int doing_timeout; extern int debug; extern int debug_proc; Vnode *new_mount_dir; #import struct debug_file_handle { unsigned int i[8]; }; char * fhtoc(nfs_fh *fh) { static char str[32]; struct debug_file_handle *dfh; dfh = (struct debug_file_handle *)fh; sprintf(str, "%u", dfh->i[0]); return str; } /* * add up sizeof (valid + fileid + name + cookie) - strlen(name) */ #define ENTRYSIZE (3 * BYTES_PER_XDR_UNIT + NFS_COOKIESIZE) /* * sizeof(status + eof) */ #define JUNKSIZE (2 * BYTES_PER_XDR_UNIT) attrstat * nfsproc_getattr_2_svc(nfs_fh *fh, struct svc_req *req) { static attrstat astat; struct file_handle *ifh; Vnode *n; ifh = (struct file_handle *)fh; sys_msg(debug_proc, LOG_DEBUG, "-> getattr"); sys_msg(debug_proc, LOG_DEBUG, " fh = %s", fhtoc(fh)); n = [controller vnodeWithID:ifh->node_id]; if (n == nil) { sys_msg(debug, LOG_ERR, "getattr for non-existent file handle %s", fhtoc(fh)); astat.status = NFSERR_NOENT; } else astat.status = [n nfsStatus]; if (astat.status != NFS_OK) { sys_msg(debug_proc, LOG_DEBUG, "<- getattr (error %d)", astat.status); return(&astat); } sys_msg(debug_proc, LOG_DEBUG, " name = %s", [[n name] value]); astat.attrstat_u.attributes = [n attributes]; sys_msg(debug_proc, LOG_DEBUG, "<- getattr"); return(&astat); } /* Does something */ diropres * nfsproc_lookup_2_svc(diropargs *args, struct svc_req *req) { static diropres res; struct file_handle *ifh; Vnode *n; String *s; ifh = (struct file_handle *)&(args->dir); sys_msg(debug_proc, LOG_DEBUG, "-> lookup"); sys_msg(debug_proc, LOG_DEBUG, " dir fh = %s", fhtoc(&(args->dir))); sys_msg(debug_proc, LOG_DEBUG, " file = %s", args->name); n = [controller vnodeWithID:ifh->node_id]; if (n == nil) { sys_msg(debug, LOG_ERR, "lookup for non-existent file handle %s", fhtoc(&(args->dir))); res.status = NFSERR_NOENT; } else res.status = [n nfsStatus]; if (res.status != NFS_OK) { sys_msg(debug_proc, LOG_DEBUG, "<- lookup (error %d)", res.status); return(&res); } s = [String uniqueString:args->name]; n = [n lookup:s]; [s release]; if (n == nil) res.status = NFSERR_NOENT; else res.status = [n nfsStatus]; if (res.status != NFS_OK) { sys_msg(debug_proc, LOG_DEBUG, "<- lookup (res=%d)", res.status); return(&res); } [n getFileHandle:(nfs_fh *)&res.diropres_u.diropres.file]; sys_msg(debug_proc, LOG_DEBUG, " return fh = %s", fhtoc(&res.diropres_u.diropres.file)); res.diropres_u.diropres.attributes = [n attributes]; sys_msg(debug_proc, LOG_DEBUG, "<- lookup"); return(&res); } readlinkres * nfsproc_readlink_2_svc(nfs_fh *fh, struct svc_req *req) { static readlinkres res; struct file_handle *ifh; Vnode *n; unsigned int status; struct authunix_parms *aup; int uid; uid = -2; if (req->rq_cred.oa_flavor == AUTH_UNIX) { aup = (struct authunix_parms *)req->rq_clntcred; uid = aup->aup_uid; sys_msg(debug_proc, LOG_DEBUG, "\t uid %d requested a new link check", uid); } else { sys_msg(debug_proc, LOG_DEBUG, "\t uid unknown requested a new link check"); } ifh = (struct file_handle *)fh; sys_msg(debug_proc, LOG_DEBUG, "-> readlink"); sys_msg(debug_proc, LOG_DEBUG, " fh = %s", fhtoc(fh)); if (doing_timeout) return NULL; n = [controller vnodeWithID:ifh->node_id]; if (n == nil) { sys_msg(debug, LOG_ERR, "readlink for non-existent file handle %s", fhtoc(fh)); res.status = NFSERR_NOENT; } else if ([n type] != NFLNK) res.status = NFSERR_ISDIR; else res.status = [n nfsStatus]; if (res.status != NFS_OK) { return(&res); sys_msg(debug_proc, LOG_DEBUG, "<- readlink (1)"); } status = 0; #warning test here for a bad afp mount ... (i.e. disconnected) if ([n type] == NFLNK) { sys_msg(debug_proc, LOG_DEBUG, " NFLNK"); } if (([n type] == NFLNK) && (![n mounted])) { sys_msg(debug_proc, LOG_DEBUG, " not mounted"); status = [[n map] mount:n withUid:uid]; if (status != 0) { res.status = NFSERR_NOENT; sys_msg(debug_proc, LOG_DEBUG, "<- readlink (2)"); return(&res); } } sys_msg(debug_proc, LOG_DEBUG, " name = %s", [[n name] value]); sys_msg(debug_proc, LOG_DEBUG, " link = %s", [[n link] value]); res.readlinkres_u.data = [[n link] value]; sys_msg(debug_proc, LOG_DEBUG, "<- readlink"); return(&res); } /* Does something */ readdirres * nfsproc_readdir_2_svc(readdirargs *args, struct svc_req *req) { static readdirres res; Vnode *n, *v; struct entry *e, *nexte; struct entry **entp; unsigned int cookie, count, entrycount, i, nlist; struct file_handle *ifh; Array *list; String *s; ifh = (struct file_handle *)&(args->dir); cookie = *(unsigned int*)args->cookie; sys_msg(debug_proc, LOG_DEBUG, "-> readdir"); sys_msg(debug_proc, LOG_DEBUG, " dir fh = %s", fhtoc(&(args->dir))); sys_msg(debug_proc, LOG_DEBUG, " cookie = %u", cookie); sys_msg(debug_proc, LOG_DEBUG, " count = %u", args->count); /* * Free up old stuff */ e = res.readdirres_u.reply.entries; while (e != NULL) { nexte = e->nextentry; free(e); e = nexte; } res.readdirres_u.reply.entries = NULL; n = [controller vnodeWithID:ifh->node_id]; if (n == nil) { sys_msg(debug, LOG_ERR, "readdir for non-existent file handle %s", fhtoc(&(args->dir))); res.status = NFSERR_NOENT; } else if ([n type] != NFDIR) res.status = NFSERR_NOTDIR; else res.status = [n nfsStatus]; if (res.status != NFS_OK) { sys_msg(debug_proc, LOG_DEBUG, "<- readdir (1)"); return(&res); } sys_msg(debug_proc, LOG_DEBUG, " name = %s", [[n name] value]); list = [n dirlist]; nlist = [list count]; count = JUNKSIZE; entrycount = 0; entp = &res.readdirres_u.reply.entries; for (i = cookie; i < nlist; i++) { v = [list objectAtIndex:i]; if (i == 0) s = dot; else if (i == 1) s = dotdot; else s = [v name]; count += ENTRYSIZE; count += [s length]; if (count > args->count) { sys_msg(debug_proc, LOG_DEBUG, " BREAK"); break; } sys_msg(debug_proc, LOG_DEBUG, " %4u: %u %s", cookie, [v nodeID], [s value]); *entp = (struct entry *) malloc(sizeof(struct entry)); bzero(*entp, sizeof(struct entry)); (*entp)->fileid = [v nodeID]; (*entp)->name = [s value]; *(unsigned int*)((*entp)->cookie) = ++cookie; (*entp)->nextentry = NULL; entp = &(*entp)->nextentry; } if (i < nlist) res.readdirres_u.reply.eof = FALSE; else res.readdirres_u.reply.eof = TRUE; sys_msg(debug_proc, LOG_DEBUG, " eof = %s", res.readdirres_u.reply.eof ? "TRUE" : "FALSE"); [list release]; sys_msg(debug_proc, LOG_DEBUG, "<- readdir"); return(&res); } statfsres * nfsproc_statfs_2_svc(nfs_fh *fh, struct svc_req *req) { static statfsres res; sys_msg(debug_proc, LOG_DEBUG, "-> statfs"); res.status = NFS_OK; res.statfsres_u.reply.tsize = 512; res.statfsres_u.reply.bsize = 512; res.statfsres_u.reply.blocks = 0; res.statfsres_u.reply.bfree = 0; res.statfsres_u.reply.bavail = 0; sys_msg(debug_proc, LOG_DEBUG, "<- statfs"); return(&res); } /* * These routines do nothing - they should never even be called! */ void * nfsproc_null_2_svc(void *x, struct svc_req *req) { sys_msg(debug_proc, LOG_DEBUG, "-- null"); return((void *)NULL); } attrstat * nfsproc_setattr_2_svc(sattrargs *args, struct svc_req *req) { static attrstat astat; sys_msg(debug_proc, LOG_DEBUG, "-- setattr"); astat.status = NFSERR_ROFS; return(&astat); } void * nfsproc_root_2_svc(void *x, struct svc_req *req) { sys_msg(debug_proc, LOG_DEBUG, "-- root"); return(NULL); } readres * nfsproc_read_2_svc(readargs *args, struct svc_req *req) { static readres res; sys_msg(debug_proc, LOG_DEBUG, "-- read"); res.status = NFSERR_ISDIR; /* XXX: should return better error */ return(&res); } void * nfsproc_writecache_2_svc(void *x, struct svc_req *req) { sys_msg(debug_proc, LOG_DEBUG, "-- writecache"); return(NULL); } attrstat * nfsproc_write_2_svc(writeargs *args, struct svc_req *req) { static attrstat res; sys_msg(debug_proc, LOG_DEBUG, "-- write"); res.status = NFSERR_ROFS; /* XXX: should return better error */ return(&res); } diropres * nfsproc_create_2_svc(createargs *args, struct svc_req *req) { static diropres res; sys_msg(debug_proc, LOG_DEBUG, "-- create"); res.status = NFSERR_ROFS; return(&res); } nfsstat * nfsproc_remove_2_svc(diropargs *args, struct svc_req *req) { static nfsstat status; sys_msg(debug_proc, LOG_DEBUG, "-- remove"); status = NFSERR_ROFS; return(&status); } nfsstat * nfsproc_rename_2_svc(renameargs *args, struct svc_req *req) { static nfsstat status; sys_msg(debug_proc, LOG_DEBUG, "-- rename"); status = NFSERR_ROFS; return(&status); } nfsstat * nfsproc_link_2_svc(linkargs *args, struct svc_req *req) { static nfsstat status; sys_msg(debug_proc, LOG_DEBUG, "-- link"); status = NFSERR_ROFS; return(&status); } nfsstat * nfsproc_symlink_2_svc(symlinkargs *args, struct svc_req *req) { static nfsstat status; sys_msg(debug_proc, LOG_DEBUG, "-- symlink"); status = NFSERR_ROFS; return(&status); } diropres * nfsproc_mkdir_2_svc(createargs *args, struct svc_req *req) { static diropres res; sys_msg(debug_proc, LOG_DEBUG, "-- mkdir"); res.status = NFSERR_ROFS; return(&res); } nfsstat * nfsproc_rmdir_2_svc(diropargs *args, struct svc_req *req) { static nfsstat status; sys_msg(debug_proc, LOG_DEBUG, "-- rmdir"); status = NFSERR_ROFS; return(&status); }