home *** CD-ROM | disk | FTP | other *** search
- /*
- * Name: mount.c
- * Description: Functions that do the NFS socket setup and NFS mount/unmount.
- * Parts of it are based on the mount module of p3nfs (Psion NFS).
- * Author: Christian Starkjohann <cs@hal.kph.tuwien.ac.at>
- * Date: 1996-11-14
- * Copyright: GNU-GPL
- * Tabsize: 4
- */
- #include <libc.h>
-
- #define NFSCLIENT
- #include <rpc/rpc.h>
- #include "nfs_prot.h"
- #include <errno.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/mount.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include <arpa/inet.h>
- #include <nfs/nfs_mount.h>
- #include <mntent.h>
- #include "my_defines.h"
-
- #define DPRINTF(arg) if(debug_mode & DEBUG_NFS) dprintf arg
- #define DDPRINTF(arg) if(debug_mode & DEBUG_DISPATCH) dprintf arg
-
- static char *mntdir = NULL;
- static int do_exit = 0;
- static int do_nfsumount = 0;
- extern int errno;
-
- #define MTAB_TMP (MOUNTED ".tmp")
-
- /* ------------------------------------------------------------------------- */
-
- static void my_perror(char *s)
- {
- eprintf("%s: [%d] %s\n", s, errno, strerror(errno));
- }
-
- /* ------------------------------------------------------------------------- */
-
- static int nfs_unmount(int forced)
- {
- FILE *fpout, *fpin;
- struct mntent *ent;
- char tempfile[2048];
-
- if(mntdir == NULL) /* not mounted until now! */
- return 1;
- dprintf("Trying to unmount NFS...\n");
- if(forced)
- while(unmount(mntdir)){
- if(errno != ENOENT)
- my_perror(mntdir);
- if(errno != EBUSY){
- break;
- }
- sleep(1);
- }
- else if(unmount(mntdir) != 0 && errno == EBUSY)
- return 0;
- /* update mtab */
- sprintf(tempfile, "%s-%d", MTAB_TMP, getpid());
- lock_mtab();
- if((fpout = setmntent(tempfile, "w")) == NULL){
- my_perror(tempfile);
- }else if((fpin = setmntent(MOUNTED, "r")) == NULL){
- endmntent(fpout);
- unlink(tempfile);
- my_perror(MOUNTED);
- }else{
- while ((ent = getmntent(fpin)) != NULL){
- if(strcmp(ent->mnt_dir, mntdir) != 0)
- addmntent(fpout, ent);
- }
- endmntent(fpin);
- endmntent(fpout);
- if(rename(tempfile, MOUNTED) != 0){
- my_perror(MOUNTED);
- unlink(tempfile);
- }
- }
- unlock_mtab();
- dprintf("NFS unmounted.\n");
- return 1;
- }
-
- /* ------------------------------------------------------------------------- */
-
- void terminate(int exitcode)
- {
- nfs_unmount(1);
- exit(exitcode);
- }
-
- /* ------------------------------------------------------------------------- */
-
- void do_unmount(int signr)
- {
- static volatile int in_handler = 0;
-
- if(in_handler){
- eprintf("** caught signal %d, during handler!!\n", signr);
- eprintf("** aborting immediately!!\n");
- exit(2);
- }
- in_handler = 1;
- do_exit = 1;
- do_nfsumount = 1;
- switch(signr){
- case SIGHUP: case SIGINT: case SIGQUIT:
- case SIGUSR1: case SIGUSR2:
- dprintf("** caught signal %d, preparing for unmount\n", signr);
- break; /* if the signal was user-induced: unmount nfs from mainloop */
- default:
- eprintf("** caught signal %d, unmounting\n", signr);
- do_nfsumount = 0;
- nfs_unmount(1);
- }
- in_handler = 0;
- }
-
- /* ------------------------------------------------------------------------- */
-
- static void dispatch_loop(void)
- {
- fd_set readfd;
- struct timeval tv;
-
- for(;;){
- readfd = svc_fdset;
- tv.tv_sec = 1; tv.tv_usec = 0;
-
- DDPRINTF(("- going into select\n"));
- if(select(FD_SETSIZE, &readfd, NULL, NULL, &tv) > 0){
- DDPRINTF(("- executing request\n"));
- svc_getreqset(&readfd);
- }
- if(do_exit){
- DDPRINTF(("- doing exit\n"));
- if(!do_nfsumount || nfs_unmount(0)){
- if(wr_enable){
- dprintf("Going to unmount disk...\n");
- my_unmount();
- dprintf("Disk unmounted.\n");
- }
- close(my_fd);
- eprintf("Exiting.\n");
- exit(0);
- }
- }
- DDPRINTF(("- checking for regular jobs()\n"));
- dummies_regular(); /* calls all other regulars */
- }
- }
-
- /* ------------------------------------------------------------------------- */
-
- void mount_and_dispatch(char *dir, void (*proc)(), void *proot_fh, int bg, char *options)
- {
- int sock, port, child_pid, parent_pid, other_pid;
- struct sockaddr_in sain;
- SVCXPRT *nfsxprt;
- int bufsiz = 0xc000; /* room for a few biods */
- struct nfs_args nfs_args;
- nfs_fh *root_fh = proot_fh;
-
- signal(SIGHUP, do_unmount);
- signal(SIGINT, do_unmount);
- signal(SIGQUIT, do_unmount);
- signal(SIGILL, do_unmount);
- signal(SIGIOT, do_unmount);
- signal(SIGTRAP, do_unmount);
- signal(SIGEMT, do_unmount);
- signal(SIGFPE, do_unmount);
- signal(SIGBUS, do_unmount);
- signal(SIGSEGV, do_unmount);
- signal(SIGSYS, do_unmount);
- signal(SIGPIPE, do_unmount);
- signal(SIGTERM, do_unmount);
- signal(SIGUSR1, do_unmount);
- signal(SIGUSR2, do_unmount);
- bzero(&sain, sizeof(struct sockaddr_in));
- bzero(&nfs_args, sizeof(struct nfs_args));
-
- /*** First part: set up the rpc service */
- /* Create udp socket */
- sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if(setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&bufsiz,sizeof(bufsiz)))
- my_perror("setsockopt");
-
- /* Bind it to a reserved port */
- sain.sin_family = AF_INET;
- sain.sin_addr.s_addr = inet_addr("127.0.0.1");
- /*sain.sin_addr.s_addr = htonl(INADDR_ANY);gec*/
- for(port = IPPORT_RESERVED-1; port > IPPORT_RESERVED/2; port--){
- DPRINTF(("trying to use port %d\n", port));
- sain.sin_port = htons(port);
- if(bind(sock, (struct sockaddr *) &sain, sizeof(sain)) >= 0)
- break;
- }
- dprintf("Using port %d for NFS.\n", port);
- if(port <= IPPORT_RESERVED/2){
- my_perror("bind to reserved port"); exit(1);
- }
- if((nfsxprt = svcudp_create(sock)) == 0){
- my_perror("svcudp_create"); exit(1);
- }
- if(!svc_register(nfsxprt, NFS_PROGRAM, NFS_VERSION, proc, 0)){
- my_perror("svc_register"); exit(1);
- }
-
- /*** Second part: mount the directory */
-
- nfs_args.wsize = 32768;
- nfs_args.rsize = 32768;
- nfs_args.addr = &sain;
- nfs_args.fh = (char *)root_fh;
- nfs_args.retrans = 0;
- nfs_args.timeo = 200; /* 20s timeout */
- nfs_args.hostname = "vmount";
- nfs_args.netname = "net";
- nfs_args.flags = NFSMNT_SOFT | NFSMNT_HOSTNAME |
- NFSMNT_RETRANS | NFSMNT_TIMEO |
- NFSMNT_WSIZE | NFSMNT_RSIZE;
-
- mntdir = dir;
- parent_pid = getpid();
- use_syslog = 1; /* we will reset this in the parent */
- if((child_pid = fork()) == -1){
- use_syslog = 0;
- my_perror("fork");
- exit(1);
- }
- if(child_pid != 0 || !bg){ /* we are the parent || not background */
- use_syslog = 0;
- }
- if((child_pid == 0 && bg) || (child_pid != 0 && !bg)){
- dispatch_loop();
- }else{
- DPRINTF(("Going to mount...\n"));
- other_pid = child_pid == 0 ? parent_pid : child_pid;
-
- if(mount(MOUNT_NFS, dir, wr_enable ? 0:M_RDONLY,(caddr_t)&nfs_args)<0){
- eprintf("nfs mount %s: [%d] %s\n", dir, errno, strerror(errno));
- kill(other_pid, SIGKILL);
- }else{
- FILE *fp;
- struct mntent mnt;
- char typename[256];
-
- sprintf(typename, "vmount-%d", other_pid);
- mnt.mnt_fsname = device_name;
- mnt.mnt_dir = mntdir;
- mnt.mnt_type = typename;
- mnt.mnt_opts = options!=NULL && *options!=0 ? options : "default";
- mnt.mnt_freq = mnt.mnt_passno = 0;
- lock_mtab();
- if ((fp = setmntent(MOUNTED, "a")))
- addmntent(fp, &mnt);
- else
- my_perror(MOUNTED);
- endmntent(fp);
- unlock_mtab();
- }
- exit(0);
- }
- }
-