"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "chironfs-1.1.1/src/chirctl.c" of archive chironfs-1.1.1.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /* Copyright 2005-2008 Luis Furquim
    2  *
    3  *
    4  * This program is free software; you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation; version 3 of the License.
    7  *
    8  * This program is distributed in the hope that it will be useful,
    9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11  * GNU General Public License for more details.
   12  *
   13  * You should have received a copy of the GNU General Public License
   14  * along with this program; if not, write to the Free Software
   15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   16  *
   17  */
   18 
   19 
   20 
   21 //
   22 // The lines below are from a patch contributed by Yen-Ming Lee,
   23 // porting ChironFS to FreeBSD
   24 //
   25 #include <fuse.h>
   26 #if defined(linux) || defined(__FreeBSD__)
   27 
   28 #include <fuse/fuse.h>
   29 #include <fuse/fuse_opt.h>
   30 
   31 #else
   32 
   33 typedef  uint64_t cpuset_t;
   34 
   35 //
   36 // The lines below are from a patch contributed by Antti Kantee
   37 // to make ChironFS run on NetBSD
   38 //
   39 
   40 #include <fuse_opt.h>
   41 
   42 #endif
   43 //
   44 // End of BSD patches
   45 //
   46 
   47 #include <stdlib.h>
   48 #include <stdio.h>
   49 #include <string.h>
   50 #include <stdarg.h>
   51 #include <unistd.h>
   52 #include <fcntl.h>
   53 #include <dirent.h>
   54 #include <errno.h>
   55 #include <time.h>
   56 #include <sys/time.h>
   57 
   58 #include <sys/statvfs.h>
   59 
   60 #include <sys/stat.h>
   61 
   62 #include <stdint.h>
   63 #include <pwd.h>
   64 #include <grp.h>
   65 
   66 
   67 #ifdef __linux__
   68 
   69 #define _REENTRANT
   70 
   71 #ifndef _POSIX_SOURCE
   72 #define _POSIX_SOURCE
   73 #endif
   74 
   75 /* for LinuxThreads */
   76 #define _P __P
   77 
   78 #endif
   79 
   80 #include <pthread.h>
   81 
   82 #include "config.h"
   83 
   84 #include "chiron-types.h"
   85 #include "chirondbg.h"
   86 #define _CHIRON_CTL_H_
   87 #include "chirctl.h"
   88 #include "chironfn.h"
   89 
   90 
   91 
   92 
   93 ctlfs_entry_t mkstatnod(char *path, unsigned long mode, unsigned short uid, unsigned short gid)
   94 {
   95    ctlfs_entry_t c;
   96 
   97    memset(&c,0,sizeof(ctlfs_entry_t));
   98    c.path                  = path;
   99    c.attr.st_mode          = mode;
  100    c.attr.st_ino           = ++inode_count;
  101    c.attr.st_dev           = 0;
  102    c.attr.st_nlink         = 0;
  103    c.attr.st_uid           = uid;
  104    c.attr.st_gid           = gid;
  105    c.attr.st_size          = 1;
  106    c.attr.st_atime         = 0;
  107    c.attr.st_mtime         = 0;
  108    c.attr.st_ctime         = 0;
  109    c.attr.st_blocks        = 0;
  110    c.attr.st_blksize       = 0;
  111    c.ctlfs                 = NULL;
  112    return(c);
  113 }
  114 
  115 void free_ctlnode(ctlfs_entry_t *ctlroot)
  116 {
  117    ctlfs_entry_t *c = ctlroot;
  118    for(;c->path!=NULL;++c) {
  119       if (c->ctlfs!=NULL) {
  120          free_ctlnode(c->ctlfs);
  121       }
  122       free(c->path);
  123    }
  124    free(ctlroot);
  125 }
  126 
  127 int mkctlfs()
  128 {
  129    int         i;
  130    struct stat st;
  131 //   uid_t       uid = geteuid();
  132 //   gid_t       gid = getegid();
  133 
  134 
  135    i = stat(chironctl_mountpoint,&st);
  136    if (i) {
  137       return(-1);
  138    }
  139 
  140    ctlfs[0]       = mkstatnod("/",S_IFDIR | S_IREAD | S_IEXEC | ((S_IREAD | S_IEXEC)>>3),st.st_uid,st.st_gid);
  141    ctlfs[0].ctlfs = malloc(sizeof(ctlfs_entry_t)*max_replica+1);
  142    if (ctlfs[0].ctlfs==NULL) {
  143       return(-1);
  144    }
  145    ctlfs[1].path = NULL;
  146                                                                         dbg(("\nalloced"));
  147 
  148    for(i=0;i<max_replica;++i) {
  149       ctlfs->ctlfs[i] = mkstatnod(malloc(sizeof(char) * (2+strlen(paths[i].path))),
  150                              S_IFDIR | S_IREAD | S_IEXEC | ((S_IREAD | S_IEXEC)>>3),
  151                              st.st_uid,st.st_gid);
  152       if (ctlfs->ctlfs[i].path == NULL) {
  153          free_ctlnode(ctlfs->ctlfs);
  154                                                                         dbg(("\nctl out of mem"));
  155          return(-1);
  156       }
  157       sprintf(ctlfs->ctlfs[i].path,"%s",paths[i].path);
  158                            dbg(("\nctl: path=%s, path2=%s ino=%d",paths[i].path, ctlfs->ctlfs[i].path, ctlfs->ctlfs[i].attr.st_ino));
  159 
  160       // replica subdir
  161       ctlfs->ctlfs[i].ctlfs = malloc(sizeof(ctlfs_entry_t)*3);
  162       if (ctlfs->ctlfs[i].ctlfs==NULL) {
  163          free_ctlnode(ctlfs->ctlfs);
  164          return(-1);
  165       }
  166       // end of the list
  167       ctlfs->ctlfs[i].ctlfs[2].path = NULL;
  168       // status file
  169       ctlfs->ctlfs[i].ctlfs[0] = mkstatnod(malloc(sizeof(char) * (2+strlen(status_fname))),
  170                              S_IFREG | S_IREAD | S_IWRITE | ((S_IREAD | S_IWRITE)>>3),
  171                              st.st_uid,st.st_gid);
  172       if (ctlfs->ctlfs[i].ctlfs[0].path == NULL) {
  173          free_ctlnode(ctlfs->ctlfs);
  174                                                                            dbg(("\nctl out of mem"));
  175          return(-1);
  176       }
  177       sprintf(ctlfs->ctlfs[i].ctlfs[0].path,status_fname);
  178                                  dbg(("\nctl: status ino=%d",ctlfs->ctlfs[i].ctlfs[0].attr.st_ino));
  179       // nagios plugin script
  180       ctlfs->ctlfs[i].ctlfs[1] = mkstatnod(malloc(sizeof(char) * (2+strlen(nagios_fname))),
  181                              S_IFREG | S_IREAD | S_IEXEC | ((S_IREAD | S_IEXEC)>>3),
  182                              st.st_uid,st.st_gid);
  183       if (ctlfs->ctlfs[i].ctlfs[1].path == NULL) {
  184          free_ctlnode(ctlfs->ctlfs);
  185          dbg(("\nctl out of mem"));
  186          return(-1);
  187       }
  188       ctlfs->ctlfs[i].ctlfs[1].attr.st_size = strlen(nagios_script);
  189       sprintf(ctlfs->ctlfs[i].ctlfs[1].path,nagios_fname);
  190                            dbg(("\nctl: status ino=%d",ctlfs->ctlfs[i].ctlfs[1].attr.st_ino));
  191    }
  192    ctlfs->ctlfs[i].path = NULL;
  193 
  194    return(0);
  195 }
  196 
  197 ctlfs_search_t find_path(const char *path, ctlfs_entry_t *c, int deep)
  198 {
  199    ctlfs_search_t res;
  200    size_t         s;
  201    int            i;
  202 
  203    for(i=0;c[i].path!=NULL;++i) {
  204       if (!strcmp(path,c[i].path)) {
  205          res.ctlfs = c;
  206          res.i     = i;
  207          return(res);
  208       }
  209       s = strlen(c[i].path);
  210       if ((!strncmp(path,c[i].path,s)) && (path[s]=='/') && (c[i].ctlfs!=NULL)) {
  211          if (!deep) {
  212             res.ctlfs = c;
  213             res.i     = i;
  214             return(res);
  215          }
  216          return(find_path(path+s, c[i].ctlfs,deep-1));
  217       }
  218    }
  219    res.ctlfs = NULL;
  220    res.i     = 0;
  221    return(res);
  222 }
  223 
  224 char *get_daddy(const char *path)
  225 {
  226    char *s, *p;
  227 
  228    if (path[1]=='\0') {
  229       s = strdup("");
  230       return(s);
  231    }
  232    s = strdup(path);
  233    if (s==NULL) {
  234       return(s);
  235    }
  236    p = strrchr(s,'/');
  237    if (p==s) {
  238       s[1] = '\0';
  239    } else {
  240       (*p) = '\0';
  241    }
  242    return(s);
  243 }
  244 
  245 ////////////////////////////////////////////////////////////////////////////
  246 ////////////////////////////////////////////////////////////////////////////
  247 //
  248 //
  249 //  P E R M I S S I O N   C H E C K   F U N C T I O N S
  250 //
  251 //
  252 ////////////////////////////////////////////////////////////////////////////
  253 ////////////////////////////////////////////////////////////////////////////
  254 
  255 int get_perm(uid_t uid, gid_t gid, struct stat st)
  256 {
  257    int   i, res=0;
  258    char *buffer;
  259    struct group result_buf, *result=NULL;
  260    struct passwd *pw;
  261    char         **member;
  262                                              dbg(("\ncuid:%d\tstuid:%d",uid,st.st_uid));
  263    if (uid==st.st_uid) {
  264       return((st.st_mode&0700) >> 6);
  265    }
  266    if (gid==st.st_gid) {
  267       return((st.st_mode&070) >> 3);
  268    }
  269    i = 1024;
  270    do {
  271       buffer     = calloc(i,sizeof(char));
  272       if (buffer!=NULL) {
  273          res = getgrgid_r(st.st_gid,&result_buf,buffer,i,&result);
  274          if (res==ERANGE) {
  275             free(buffer);
  276             i <<= 1;
  277          }
  278       }
  279    } while ((res==ERANGE) && (buffer!=NULL));
  280    if (buffer==NULL) {
  281       errno = ENOMEM;
  282       return(-1);
  283    }
  284    if (result!=NULL) {
  285       member = result->gr_mem;
  286       while (*member) {
  287         pw = getpwnam(*member);
  288         if (pw->pw_uid==uid) {
  289            free(buffer);
  290            return((st.st_mode&070) >> 3);
  291         }
  292         member++;
  293       }
  294    }
  295    free(buffer);
  296    return(st.st_mode&7);
  297 }
  298 
  299 int get_path_perm(const char *path)
  300 {
  301    ctlfs_search_t res, path_res;
  302 
  303    static struct fuse_context *context;
  304    int           perm, path_perm;
  305 
  306    context  = fuse_get_context();
  307 
  308    if ((!context->uid) || (!context->gid)) {
  309       return(7);
  310    }
  311 
  312    perm = get_perm(context->uid,context->gid,ctlfs[0].attr);
  313 
  314    if (path[1]=='\0') {
  315                                              dbg(("\nperm (/):%d",perm));
  316       return(perm);
  317    }
  318 
  319    if (perm&1) {
  320       path_perm = perm;
  321 
  322       res = find_path(path,ctlfs->ctlfs,0);
  323       if (res.ctlfs==NULL) {
  324          return(-ENOENT);
  325       }
  326       perm = get_perm(context->uid,context->gid,res.ctlfs->attr);
  327       path_res = res;
  328 
  329       res = find_path(path,ctlfs->ctlfs,1);
  330       if ((res.ctlfs==path_res.ctlfs) && (res.i==path_res.i)) {
  331                                              dbg(("\nperm:%d",perm));
  332          return(perm);
  333       }
  334       if (perm&1) {
  335          perm = get_perm(context->uid,context->gid,res.ctlfs->attr);
  336                                              dbg(("\nperm:%d",perm));
  337          return(perm);
  338       }
  339    }
  340    return(0);
  341 }
  342 
  343 
  344 ////////////////////////////////////////////////////////////////////////////
  345 ////////////////////////////////////////////////////////////////////////////
  346 //
  347 //
  348 //  W R A P P E R   F U N C T I O N S
  349 //
  350 //
  351 ////////////////////////////////////////////////////////////////////////////
  352 ////////////////////////////////////////////////////////////////////////////
  353 
  354 
  355 static int chironctl_statfs(const char *path, struct statvfs *stbuf)
  356 {
  357    (void) path;
  358    stbuf->f_bsize  = 4096;
  359    stbuf->f_frsize = 4096;
  360    stbuf->f_bsize  = 4096;
  361    stbuf->f_frsize = 4096;
  362    stbuf->f_blocks = 0xFFFFF;
  363    stbuf->f_bfree  = 0xFFFFF;
  364    stbuf->f_bavail = 0xFFFFF;
  365    stbuf->f_files  = 0xFFFF;
  366    stbuf->f_ffree  = 0xFFFF;
  367    stbuf->f_favail = 0xFFFF;
  368    stbuf->f_fsid   = -1047;
  369    stbuf->f_flag   = 1024;
  370    stbuf->f_namemax= 255;
  371    return(0);
  372 }
  373 
  374 
  375 static int chironctl_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
  376                        off_t offset, struct fuse_file_info *fi)
  377 {
  378    ctlfs_entry_t *dir;
  379    ctlfs_search_t res;
  380 
  381    (void) offset;
  382    (void) fi;
  383                                                         dbg(("\nctlreaddir: %s, offset: %ld\n",path,offset));
  384    if ((get_path_perm(path)&5)!=5) {
  385       return(-EACCES);
  386    }
  387 
  388    if (path[1]=='\0') {
  389       dir = ctlfs;
  390    } else {
  391       res = find_path(path,ctlfs->ctlfs,-1);
  392       if (res.ctlfs==NULL) {
  393          return(-ENOENT);
  394       }
  395       dir = res.ctlfs+res.i;
  396    }
  397    filler(buf, ".", &(dir->attr), 0);
  398 //   lstat(chironctl_parentdir,&st);
  399 //   filler(buf, "..", &st, 0);
  400    for(dir = dir->ctlfs;dir->path!=NULL;++dir) {
  401       if (filler(buf, dir->path+1, &(dir->attr), 0)) {
  402 //                                                        dbg(("\nctlreaddir: i=%d\n",i));
  403          return 0;
  404       }
  405    }
  406    return 0;
  407 }
  408 
  409 static void chironctl_destroy(void *notused)
  410 {
  411    (void) notused;
  412 }
  413 
  414 static int chironctl_truncate(const char *path_orig, off_t size)
  415 {
  416                                                          dbg(("\ntruncate: %s\n",path_orig));
  417    (void) path_orig;
  418    (void) size;
  419    return(0);
  420 }
  421 
  422 static int chironctl_getattr(const char *path, struct stat *stbuf)
  423 {
  424                                                       dbg(("\nctlgetattr: %s\n",path));
  425    ctlfs_entry_t  *dir;
  426    ctlfs_search_t  res;
  427    char           *p;
  428    int             perm;
  429 
  430    p = get_daddy(path);
  431    if (p==NULL) {
  432       return(-ENOMEM);
  433    }
  434                                                       dbg(("\nctlgetattr-daddy: %s\n",p));
  435 
  436    if (p[0]) {
  437       perm = get_path_perm(p);
  438                                                       dbg(("\nctlgetattr-perm: %d\n",perm));
  439       if ((perm&5)!=5) {
  440          return(-EACCES);
  441       }
  442    } else {
  443       if ((get_path_perm(path)&5)!=5) {
  444          return(-EACCES);
  445       }
  446    }
  447 
  448                                                 dbg(("\nctlgetattr-perm: ok, path=%s\n",path));
  449 
  450    if (path[1]=='\0') {
  451       dir = ctlfs;
  452    } else {
  453       res = find_path(path,ctlfs->ctlfs,-1);
  454       if (res.ctlfs==NULL) {
  455                                                       dbg(("\nctlgetattr-404: notfound\n"));
  456          return(-ENOENT);
  457       }
  458       dir = res.ctlfs+res.i;
  459    }
  460                                                       dbg(("\nctlgetattr: mode=%o\n",dir->attr.st_mode));
  461 
  462    memcpy(stbuf, &(dir->attr), sizeof(struct stat));
  463    return(0);
  464 }
  465 
  466 static int chironctl_open(const char *path, struct fuse_file_info *fi)
  467 {
  468    int perm = 0, perm_mask = 0;
  469    ctlfs_search_t res;
  470    (void) fi;
  471 
  472    if (fi->flags&O_CREAT) {
  473       return(-EACCES);
  474    }
  475 
  476    if (fi->flags&(O_WRONLY|O_TRUNC|O_APPEND)) {
  477       perm_mask = 2;
  478    } else if (fi->flags&O_RDWR) {
  479       perm_mask = 6;
  480    } else if ((fi->flags&(O_RDONLY|O_EXCL)) == (O_RDONLY)) {
  481       perm_mask = 4;
  482    }
  483    perm = get_path_perm(path);
  484    if (((perm&perm_mask)!=perm_mask) || (!perm_mask) || (!perm)) {
  485       return(-EACCES);
  486    }
  487 
  488    if (path[1]!='\0') {
  489       res = find_path(path,ctlfs->ctlfs,-1);
  490       if (res.ctlfs==NULL) {
  491          return(-ENOENT);
  492       }
  493    }
  494    return 0;
  495 }
  496 
  497 static int chironctl_read(const char *path, char *buf, size_t size, off_t offset,
  498                     struct fuse_file_info *fi)
  499 {
  500    int sz, rep, someerr, fname;
  501    ctlfs_search_t res;
  502    ctlfs_entry_t *cmd;
  503    char          *chbuf = NULL;
  504 
  505    (void) fi;
  506 
  507    if ((get_path_perm(path)&4)!=4) {
  508       return(-EACCES);
  509    }
  510 
  511    if (path[1]=='\0') {
  512       return(-ENOSYS);
  513    }
  514    res = find_path(path,ctlfs->ctlfs,-1);
  515    if (res.ctlfs==NULL) {
  516       return(-ENOENT);
  517    }
  518    cmd = res.ctlfs+res.i;
  519 
  520    res = find_path(path,ctlfs->ctlfs,0);
  521    rep = res.i;
  522                                             dbg(("\nctlread: rep: %d, cmd: %s\n",rep,cmd->path));
  523    fname = (!strcmp(cmd->path,status_fname))
  524            ? 1
  525            : (
  526               (!strcmp(cmd->path,nagios_fname))
  527               ? 2
  528               : 0
  529              );
  530    if (fname) {
  531       pthread_mutex_lock(&comm);
  532 
  533       fprintf(tochironfs,"0007stat:%02X",res.i);
  534       fflush(tochironfs);
  535       someerr = read_a_line(&chbuf,&sz,fromchironfs);
  536       pthread_mutex_unlock(&comm);
  537       if (someerr) {
  538          return (-EIO);
  539       }
  540                                        dbg(("\nctlread: rep: %d, cmd: %s=%s\n",rep,cmd->path,chbuf));
  541 
  542       if (fname==1) {
  543          sprintf(buf,"%c",chbuf[0]);
  544          free(chbuf);
  545          return(1);
  546       }
  547       if (fname==2) {
  548          sz = strlen(nagios_script) - offset;
  549          if (sz<0) {
  550             sz = 0;
  551          }
  552          sz = min(sz,(int)size);
  553 
  554          memcpy(nagios_script+538,status_msgs[chbuf[0]-'0'],strlen(status_msgs[chbuf[0]-'0']));
  555          nagios_script[602] = chbuf[0];
  556          memcpy(buf,nagios_script+offset,sz);
  557          free(chbuf);
  558          return(sz);
  559       }
  560    }
  561 
  562    return(-ENOSYS);
  563 }
  564 
  565 static int chironctl_write(const char *path, const char *buf, size_t size,
  566                      off_t offset, struct fuse_file_info *fi)
  567 {
  568    int sz, rep, someerr;
  569    ctlfs_search_t res;
  570    ctlfs_entry_t *cmd;
  571    char          *chbuf = NULL;
  572 
  573    (void) fi;
  574    (void) offset;
  575                                                          dbg(("\nctlwrite: %d=%s\n",size,buf));
  576    if ((get_path_perm(path)&2)!=2) {
  577       return(-EACCES);
  578    }
  579 
  580    if (path[1]=='\0') {
  581       return(-ENOSYS);
  582    }
  583    res = find_path(path,ctlfs->ctlfs,-1);
  584    if (res.ctlfs==NULL) {
  585       return(-ENOENT);
  586    }
  587    cmd = res.ctlfs+res.i;
  588 
  589    res = find_path(path,ctlfs->ctlfs,0);
  590    rep = res.i;
  591 
  592    if (!strcmp(cmd->path,status_fname)) {
  593       if ((size>2)
  594       || ((size==2) && (buf[1]!='\n'))
  595 //      || ((buf[0]!='0') && (buf[0]!='1') && (buf[0]!='2'))
  596       || ((buf[0]!='0') && (buf[0]!='2'))
  597       ) {
  598          return(-ENOSYS);
  599       }
  600       pthread_mutex_lock(&comm);
  601 
  602       if (buf[0]=='0') {
  603          fprintf(tochironfs,"0008trust:%02X",res.i);
  604       } else if (buf[0]=='1') {
  605          fprintf(tochironfs,"0009enable:%02X",res.i);
  606       } else if (buf[0]=='2') {
  607          fprintf(tochironfs,"000Adisable:%02X",res.i);
  608       }
  609       fflush(tochironfs);
  610       someerr = read_a_line(&chbuf,&sz,fromchironfs);
  611       pthread_mutex_unlock(&comm);
  612       if (someerr) {
  613          return (-EIO);
  614       }
  615                                        dbg(("\nctlwrite: rep: %d, cmd: %s=%s\n",rep,cmd->path,chbuf));
  616 
  617       if ((chbuf[0]=='O') && (chbuf[1]=='K')) {
  618          free(chbuf);
  619          return(size);
  620       }
  621       free(chbuf);
  622       return(-EIO);
  623    }
  624 
  625    return(-ENOSYS);
  626 }
  627 
  628 struct fuse_operations chironctl_oper = {
  629     .readdir      = chironctl_readdir,
  630     .statfs       = chironctl_statfs,
  631     .destroy      = chironctl_destroy,
  632     .getattr      = chironctl_getattr,
  633     .open         = chironctl_open,
  634     .read         = chironctl_read,
  635     .write        = chironctl_write,
  636     .truncate     = chironctl_truncate,
  637 };
  638 
  639 
  640 void free_vars(void)
  641 {
  642    int i;
  643    if (chironctl_parentdir!=NULL) {
  644       free(chironctl_parentdir);
  645    }
  646    if (chironctl_mountpoint!=NULL) {
  647       free(chironctl_mountpoint);
  648    }
  649    if (mount_point!=NULL) {
  650       free(mount_point);
  651    }
  652    if (paths!=NULL) {
  653       for(i=0;i<max_replica;++i) {
  654          if (paths[i].path != NULL) {
  655             free(paths[i].path);
  656          }
  657       }
  658       free(paths);
  659    }
  660 }
  661 
  662 int main(int argc, char *argv[])
  663 {
  664    int res, sz, someerr, i, j, l;
  665    char *buf= NULL, *ptr;
  666    char *fuse_argv[4];
  667 
  668    (void) argc;
  669                                                                        dbg(("chironctl: started"));
  670    printf("0004info");
  671    fflush(stdout);
  672    someerr = read_a_line(&buf,&sz,stdin);
  673    if (someerr) {
  674       exit(-1);
  675    }
  676                                                                     dbg(("chironfs mnt: %s",buf));
  677    mount_point = strdup(buf);
  678    if (mount_point==NULL) {
  679                                                                        dbg(("no mem"));
  680       free(buf);
  681       exit(-1);
  682    }
  683    someerr = read_a_line(&buf,&sz,stdin);
  684    if (someerr) {
  685       free_vars();
  686       exit(-1);
  687    }
  688                                                                     dbg(("chironctl mnt: %s",buf));
  689    chironctl_mountpoint = strdup(buf);
  690    if (chironctl_mountpoint==NULL) {
  691                                                                        dbg(("no mem"));
  692       free(buf);
  693       free_vars();
  694       exit(-1);
  695    }
  696 
  697    ptr = strrchr(chironctl_mountpoint,'/');
  698    if (ptr==chironctl_mountpoint) {
  699       chironctl_parentdir = strdup("/");
  700    } else {
  701       chironctl_parentdir = malloc(sizeof(char) * ((ptr-chironctl_mountpoint)+1));
  702       if (chironctl_parentdir!=NULL) {
  703          strncpy(chironctl_parentdir,chironctl_mountpoint,ptr-chironctl_mountpoint);
  704       }
  705    }
  706    if (chironctl_parentdir==NULL) {
  707       free(buf);
  708       free_vars();
  709       exit(-1);
  710    }
  711 
  712    someerr = read_a_line(&buf,&sz,stdin);
  713    if (someerr) {
  714       free_vars();
  715       exit(-1);
  716    }
  717    sscanf(buf,"%X",&max_replica);
  718                                                                     dbg(("max-replica: %s (%d)",buf,max_replica));
  719    paths = malloc(sizeof(path_t)*max_replica);
  720    if (paths==NULL) {
  721                                                                        dbg(("no mem"));
  722       free(buf);
  723       free_vars();
  724       exit(-1);
  725    }
  726    for(i=0;i<max_replica;++i) {
  727       paths[i].path = NULL;
  728    }
  729    for(i=0;i<max_replica;++i) {
  730       someerr = read_a_line(&buf,&sz,stdin);
  731       if (someerr) {
  732          free_vars();
  733          exit(-1);
  734       }
  735                                                                     dbg(("replica: %s",buf));
  736       paths[i].path = malloc(sizeof(char) * strlen(buf) + 2);
  737       if (paths[i].path==NULL) {
  738                                                                     dbg(("no mem"));
  739          free(buf);
  740          free_vars();
  741          exit(-1);
  742       }
  743       paths[i].path[0]='/';
  744       for(l=strlen(buf),j=0;j<l;++j) {
  745          if (buf[j]=='/') {
  746             paths[i].path[j+1] = '_';
  747          } else {
  748             paths[i].path[j+1] = buf[j];
  749          }
  750       }
  751    }
  752 
  753    if ((res = mkctlfs())) {
  754                                                                     dbg(("%s",buf));
  755       free(buf);
  756       free_vars();
  757       exit(-res);
  758    }
  759 
  760    fromchironfs = fdopen(STDIN_FILENO,"r");
  761    tochironfs   = fdopen(STDOUT_FILENO,"a");
  762    close(STDERR_FILENO);
  763 
  764    fuse_argv[0] = argv[0];
  765    fuse_argv[1] = chironctl_mountpoint;
  766    fuse_argv[2] = fuse_options;
  767    fuse_argv[3] = NULL;
  768                                                                     dbg(("starting fuse"));
  769    res = fuse_main(3, fuse_argv, &chironctl_oper);
  770                                                                     dbg(("ending fuse: %d", res));
  771    free(buf);
  772    free_vars();
  773    return(res);
  774 }
  775