Back to index

avfs  1.0.1
avfscoda.c
Go to the documentation of this file.
00001 /*
00002     AVFS: A Virtual File System Library
00003     Copyright (C) 1998-2001  Miklos Szeredi <miklos@szeredi.hu>
00004 
00005     This program can be distributed under the terms of the GNU GPL.
00006     See the file COPYING.
00007 */
00008 
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <string.h>
00012 #include <errno.h>
00013 #include <fcntl.h>
00014 #include <signal.h>
00015 #include <unistd.h>
00016 #include <sys/wait.h>
00017 #include <sys/stat.h>
00018 
00019 #include "avfscoda.h"
00020 
00021 #define DEFAULT_DEV "/dev/cfs0"
00022 #define SECONDARY_DEV "/dev/cfs1"
00023 #define DEFAULT_DEVFS_DEV "/dev/coda/0"
00024 #define SECONDARY_DEVFS_DEV "/dev/coda/1"
00025 #define DEFAULT_DIR "/overlay"
00026 
00027 static pid_t mount_pid = -1;
00028 static pid_t main_pid = -1;
00029 
00030 void clean_exit(int status)
00031 {
00032     /* Just in case */
00033     if(getpid() != main_pid) exit(status);
00034 
00035     run_exit();
00036 
00037     if(mount_pid != -1) kill(mount_pid, SIGKILL);
00038 
00039     exit(status);
00040 }
00041 
00042 
00043 static void exit_handler(int sig)
00044 {
00045     clean_exit(0);
00046 }
00047 
00048 static void child_handler(int sig)
00049 {
00050     int status;
00051     pid_t pid;
00052     
00053     pid = wait(&status);
00054     if(pid == -1) {
00055        perror("Error calling wait()");
00056        return;
00057     }
00058     
00059     if(pid != mount_pid) {
00060        user_child(pid);
00061     }
00062     else {
00063        if(!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
00064            
00065            fprintf(stderr, "Mount child exited with an error\n");
00066            clean_exit(1);
00067        }
00068        mount_pid = -1;
00069     }
00070 
00071 }
00072 
00073 void set_signal_handlers()
00074 {
00075     struct sigaction sa;
00076 
00077     sa.sa_handler = exit_handler;
00078     sigemptyset(&(sa.sa_mask));
00079     sa.sa_flags = 0;
00080 
00081     if (sigaction(SIGHUP, &sa, NULL) == -1 || 
00082        sigaction(SIGINT, &sa, NULL) == -1 || 
00083        sigaction(SIGTERM, &sa, NULL) == -1) {
00084        
00085        perror("Cannot set exit signal handlers");
00086        clean_exit(1);
00087     }
00088 
00089     sa.sa_handler = SIG_IGN;
00090     
00091     if(sigaction(SIGPIPE, &sa, NULL) == -1) {
00092        perror("Cannot set ignored signals");
00093        clean_exit(1);
00094     }
00095 
00096 }
00097 
00098 static void turn_off_avfs()
00099 {
00100     struct stat stbuf;
00101 
00102     if(stat("/@avfs-off", &stbuf) == -1 && errno == EEXIST) 
00103         fprintf(stderr, "Succesfuly turned off AVFS\n");
00104     else
00105         fprintf(stderr, "AVFS cannot be turned off\n");
00106     
00107 
00108 #if 0    
00109     if(stat("/@avfsstat", &stbuf) == 0) {
00110         fprintf(stderr, "Cannot start, because AVFS is already loaded\n");
00111         exit(1);
00112     }
00113 #endif
00114 
00115 }
00116 
00117 static const char *progname;
00118 
00119 static void usage()
00120 {
00121     fprintf(stderr,
00122             "usage: %s [-h] [-d] [coda_dev [dir]]\n"
00123             "   -h         print this help\n"
00124             "   -d         debug mode (do not run in background)\n"
00125             "   coda_dev   coda device (default: %s)\n"
00126             "   dir        mountpoint (default: %s)\n",
00127             progname, DEFAULT_DEV, DEFAULT_DIR);
00128 
00129     exit(1);
00130 }
00131 
00132 int main(int argc, char *argv[])
00133 {
00134     int cfs;
00135     int res;
00136     pid_t pid;
00137     const char *codadev = DEFAULT_DEV;
00138     const char *codadir = DEFAULT_DIR;
00139     struct sigaction sa;
00140     int devnull;
00141     int ctr;
00142     int debugmode = 0;
00143 
00144     progname = argv[0];
00145 
00146     ctr = 1;
00147 
00148     if(argc > ctr && argv[ctr][0] == '-') {
00149         if(argv[ctr][1] == 'h')
00150             usage();
00151         else if(argv[ctr][1] == 'd')
00152             debugmode = 1;
00153         else
00154             usage();
00155 
00156         ctr++;
00157     }
00158     
00159     if(argc > ctr) {
00160        codadev = argv[ctr];
00161         ctr++;
00162     }
00163     
00164     if(argc > ctr) {
00165        codadir = argv[ctr];
00166         ctr++;
00167     }
00168     
00169     if(!debugmode) {
00170         setsid();
00171         /* Run in background */
00172         
00173         devnull = open("/dev/null", O_RDWR);
00174         if(devnull == -1) {
00175             perror("Could not open '/dev/null'");
00176             exit(1);
00177         }
00178         
00179         pid = fork();
00180         if(pid == -1) {
00181             perror("Could not fork");
00182             exit(1);
00183         }
00184         else if(pid != 0) {
00185             /* parent */
00186             return 0;
00187         }
00188         
00189         dup2(devnull, 0);
00190         dup2(devnull, 1);
00191         dup2(devnull, 2);
00192     }
00193 
00194     turn_off_avfs();
00195 
00196     unmount_coda(codadir, 1);
00197 
00198     cfs = open(codadev, O_RDWR);
00199 
00200     if(cfs == -1 && errno == ENODEV) {
00201        /* try inserting module first */
00202        
00203        mount_coda(codadev, codadir, 0, 1);
00204        cfs = open(codadev, O_RDWR);
00205     }
00206 
00207     if(cfs == -1) {
00208        codadev = SECONDARY_DEV;
00209        cfs = open(codadev, O_RDWR);
00210     }
00211 
00212     if(cfs == -1) {
00213        codadev = DEFAULT_DEVFS_DEV;
00214        cfs = open(codadev, O_RDWR);
00215     }
00216 
00217     if(cfs == -1) {
00218        codadev = SECONDARY_DEVFS_DEV;
00219        cfs = open(codadev, O_RDWR);
00220     }
00221 
00222     if(cfs == -1) {
00223        fprintf(stderr, "Error opening '%s': %s\n", codadev, strerror(errno));
00224        exit(1);
00225     }
00226 
00227     sa.sa_handler = child_handler;
00228     sigemptyset(&(sa.sa_mask));
00229     sa.sa_flags = SA_NOCLDSTOP;
00230     
00231     if(sigaction(SIGCHLD, &sa, NULL) == -1) {
00232        perror("Cannot set SIGCHLD handler");
00233        exit(1);
00234     }
00235 
00236     pid = mount_pid = fork();
00237     if(pid == -1) {
00238        perror("fork() failed");
00239        close(cfs);
00240        exit(1);
00241     }
00242 
00243     if(pid == 0) {
00244        /* Child */
00245        
00246        res = mount_coda(codadev, codadir, cfs, 0);
00247        if(res == -1)
00248             exit(1);
00249        
00250        exit(0);
00251     }
00252 
00253     fprintf(stderr, "Mount pid: %i\n", mount_pid);
00254 
00255     main_pid = getpid();
00256     fprintf(stderr, "Main pid: %i\n", main_pid);
00257 
00258     run(cfs, codadir, debugmode);
00259 
00260     return 0;
00261 }