mysqlfs.c

Go to the documentation of this file.
00001 /*
00002   mysqlfs - MySQL Filesystem
00003   Copyright (C) 2006 Tsukasa Hamano <code@cuspy.org>
00004   $Id: mysqlfs.c,v 1.18 2006/09/17 11:09:32 ludvigm Exp $
00005 
00006   This program can be distributed under the terms of the GNU GPL.
00007   See the file COPYING.
00008 */
00009 
00010 #ifdef HAVE_CONFIG_H
00011 #include "config.h"
00012 #endif
00013 
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <unistd.h>
00018 #include <errno.h>
00019 #include <fcntl.h>
00020 #include <libgen.h>
00021 #include <fuse/fuse.h>
00022 #ifdef HAVE_MYSQL_MYSQL_H
00023 #include <mysql/mysql.h>
00024 #endif
00025 #ifdef HAVE_MYSQL_H
00026 #include <mysql.h>
00027 #endif
00028 #include <pthread.h>
00029 #include <sys/stat.h>
00030 
00031 #ifdef DEBUG
00032 #include <mcheck.h>
00033 #endif
00034 #include <stddef.h>
00035 
00036 #include "mysqlfs.h"
00037 #include "query.h"
00038 #include "pool.h"
00039 #include "log.h"
00040 
00042 static char *status_filename = ".status";
00043 static char *status_pathname = "/.status";
00044 
00045 static int mysqlfs_getattr(const char *path, struct stat *stbuf)
00046 {
00047     int ret;
00048     MYSQL *dbconn;
00049 
00050     // This is called far too often
00051     log_printf(LOG_D_CALL, "mysqlfs_getattr(\"%s\")\n", path);
00052 
00053     memset(stbuf, 0, sizeof(struct stat));
00054 
00055     if ((dbconn = pool_get()) == NULL)
00056       return -EMFILE;
00057 
00058     ret = query_getattr(dbconn, path, stbuf);
00059 
00060     if(ret){
00061         if (ret != -ENOENT)
00062             log_printf(LOG_ERROR, "Error: query_getattr()\n");
00063         pool_put(dbconn);
00064         return ret;
00065     }else{
00066         long inode = query_inode(dbconn, path);
00067         if(inode < 0){
00068             log_printf(LOG_ERROR, "Error: query_inode()\n");
00069             pool_put(dbconn);
00070             return inode;
00071         }
00072 
00073         stbuf->st_size = query_size(dbconn, inode);
00074     }
00075 
00076     pool_put(dbconn);
00077 
00078     return ret;
00079 }
00080 
00081 static int mysqlfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
00082                            off_t offset, struct fuse_file_info *fi)
00083 {
00084     (void) offset;
00085     (void) fi;
00086     int ret;
00087     MYSQL *dbconn;
00088     long inode;
00089 
00090     log_printf(LOG_D_CALL, "mysqlfs_readdir(\"%s\")\n", path);
00091 
00092     if ((dbconn = pool_get()) == NULL)
00093       return -EMFILE;
00094 
00095     inode = query_inode(dbconn, path);
00096     if(inode < 0){
00097         log_printf(LOG_ERROR, "Error: query_inode()\n");
00098         pool_put(dbconn);
00099         return inode;
00100     }
00101 
00102     
00103     filler(buf, ".", NULL, 0);
00104     filler(buf, "..", NULL, 0);
00105     if (0 == strcmp (path, "/"))
00106         filler(buf, status_filename, NULL, 0);
00107     else if (0 == strcmp (path, status_pathname))
00108     {
00109         char *stubs[] = {"txt","xml"};
00110         int i;
00111 
00112         for (i = 0; i < (sizeof(stubs)/sizeof(stubs[0])); i++)
00113             filler(buf, stubs[i], NULL, 0);
00114     }
00115 
00116     ret = query_readdir(dbconn, inode, buf, filler);
00117     pool_put(dbconn);
00118 
00119     return 0;
00120 }
00121 
00123 static int mysqlfs_mknod(const char *path, mode_t mode, dev_t rdev)
00124 {
00125     int ret;
00126     MYSQL *dbconn;
00127     long parent_inode;
00128     char dir_path[PATH_MAX];
00129 
00130     log_printf(LOG_D_CALL, "mysqlfs_mknod(\"%s\", %o): %s\n", path, mode,
00131                S_ISREG(mode) ? "file" :
00132                S_ISDIR(mode) ? "directory" :
00133                S_ISLNK(mode) ? "symlink" :
00134                "other");
00135 
00136     if(!(strlen(path) < PATH_MAX)){
00137         log_printf(LOG_ERROR, "Error: Filename too long\n");
00138         return -ENAMETOOLONG;
00139     }
00140     strncpy(dir_path, path, PATH_MAX);
00141     dirname(dir_path);
00142 
00143     if ((dbconn = pool_get()) == NULL)
00144       return -EMFILE;
00145 
00146     parent_inode = query_inode(dbconn, dir_path);
00147     if(parent_inode < 0){
00148         pool_put(dbconn);
00149         return -ENOENT;
00150     }
00151 
00152     ret = query_mknod(dbconn, path, mode, rdev, parent_inode, S_ISREG(mode) || S_ISLNK(mode));
00153     if(ret < 0){
00154         pool_put(dbconn);
00155         return ret;
00156     }
00157 
00158     pool_put(dbconn);
00159     return 0;
00160 }
00161 
00162 static int mysqlfs_mkdir(const char *path, mode_t mode){
00163     int ret;
00164     MYSQL *dbconn;
00165     long inode;
00166     char dir_path[PATH_MAX];
00167 
00168     log_printf(LOG_D_CALL, "mysqlfs_mkdir(\"%s\", 0%o)\n", path, mode);
00169     
00170     if(!(strlen(path) < PATH_MAX)){
00171         log_printf(LOG_ERROR, "Error: Filename too long\n");
00172         return -ENAMETOOLONG;
00173     }
00174     strncpy(dir_path, path, PATH_MAX);
00175     dirname(dir_path);
00176 
00177     if ((dbconn = pool_get()) == NULL)
00178       return -EMFILE;
00179 
00180     inode = query_inode(dbconn, dir_path);
00181     if(inode < 0){
00182         pool_put(dbconn);
00183         return -ENOENT;
00184     }
00185 
00186     ret = query_mkdir(dbconn, path, mode, inode);
00187     if(ret < 0){
00188         log_printf(LOG_ERROR, "Error: query_mkdir()\n");
00189         pool_put(dbconn);
00190         return ret;
00191     }
00192 
00193     pool_put(dbconn);
00194     return 0;
00195 }
00196 
00197 static int mysqlfs_unlink(const char *path)
00198 {
00199     int ret;
00200     long inode, parent, nlinks;
00201     char name[PATH_MAX];
00202     MYSQL *dbconn;
00203 
00204     log_printf(LOG_D_CALL, "mysqlfs_unlink(\"%s\")\n", path);
00205 
00206     if ((dbconn = pool_get()) == NULL)
00207       return -EMFILE;
00208 
00209     ret = query_inode_full(dbconn, path, name, sizeof(name),
00210                            &inode, &parent, &nlinks);
00211     if (ret < 0) {
00212         if (ret != -ENOENT)
00213             log_printf(LOG_ERROR, "Error: query_inode_full(%s): %s\n",
00214                        path, strerror(ret));
00215         goto err_out;
00216     }
00217 
00218     ret = query_rmdirentry(dbconn, name, parent);
00219     if (ret < 0) {
00220         log_printf(LOG_ERROR, "Error: query_rmdirentry()\n");
00221         goto err_out;
00222     }
00223 
00224     /* Only the last unlink() must set deleted flag. 
00225      * This is a shortcut - query_set_deleted() wouldn't
00226      * set the flag if there is still an existing direntry
00227      * anyway. But we'll save some DB processing here. */
00228     if (nlinks > 1)
00229         return 0;
00230     
00231     ret = query_set_deleted(dbconn, inode);
00232     if (ret < 0) {
00233         log_printf(LOG_ERROR, "Error: query_set_deleted()\n");
00234         goto err_out;
00235     }
00236 
00237     ret = query_purge_deleted(dbconn, inode);
00238     if (ret < 0) {
00239         log_printf(LOG_ERROR, "Error: query_purge_deleted()\n");
00240         goto err_out;
00241     }
00242 
00243     pool_put(dbconn);
00244 
00245     return 0;
00246 
00247 err_out:
00248     pool_put(dbconn);
00249     return ret;
00250 }
00251 
00252 static int mysqlfs_chmod(const char* path, mode_t mode)
00253 {
00254     int ret;
00255     long inode;
00256     MYSQL *dbconn;
00257 
00258     log_printf(LOG_D_CALL, "mysql_chmod(\"%s\", 0%3o)\n", path, mode);
00259 
00260     if ((dbconn = pool_get()) == NULL)
00261       return -EMFILE;
00262 
00263     inode = query_inode(dbconn, path);
00264     if (inode < 0) {
00265         pool_put(dbconn);
00266         return inode;
00267     }
00268 
00269     ret = query_chmod(dbconn, inode, mode);
00270     if(ret){
00271         log_printf(LOG_ERROR, "Error: query_chmod()\n");
00272         pool_put(dbconn);
00273         return -EIO;
00274     }
00275 
00276     pool_put(dbconn);
00277 
00278     return ret;
00279 }
00280 
00281 static int mysqlfs_chown(const char *path, uid_t uid, gid_t gid)
00282 {
00283     int ret;
00284     long inode;
00285     MYSQL *dbconn;
00286 
00287     log_printf(LOG_D_CALL, "mysql_chown(\"%s\", %ld, %ld)\n", path, uid, gid);
00288 
00289     if ((dbconn = pool_get()) == NULL)
00290       return -EMFILE;
00291 
00292     inode = query_inode(dbconn, path);
00293     if (inode < 0) {
00294         pool_put(dbconn);
00295         return inode;
00296     }
00297 
00298     ret = query_chown(dbconn, inode, uid, gid);
00299     if(ret){
00300         log_printf(LOG_ERROR, "Error: query_chown()\n");
00301         pool_put(dbconn);
00302         return -EIO;
00303     }
00304 
00305     pool_put(dbconn);
00306 
00307     return ret;
00308 }
00309 
00310 static int mysqlfs_truncate(const char* path, off_t length)
00311 {
00312     int ret;
00313     MYSQL *dbconn;
00314 
00315     log_printf(LOG_D_CALL, "mysql_truncate(\"%s\"): len=%lld\n", path, length);
00316 
00317     if ((dbconn = pool_get()) == NULL)
00318       return -EMFILE;
00319 
00320     ret = query_truncate(dbconn, path, length);
00321     if (ret < 0) {
00322         log_printf(LOG_ERROR, "Error: query_length()\n");
00323         pool_put(dbconn);
00324         return -EIO;
00325     }
00326 
00327     pool_put(dbconn);
00328 
00329     return 0;
00330 }
00331 
00332 static int mysqlfs_utime(const char *path, struct utimbuf *time)
00333 {
00334     int ret;
00335     long inode;
00336     MYSQL *dbconn;
00337 
00338     log_printf(LOG_D_CALL, "mysql_utime(\"%s\")\n", path);
00339 
00340     if ((dbconn = pool_get()) == NULL)
00341       return -EMFILE;
00342 
00343     inode = query_inode(dbconn, path);
00344     if (inode < 0) {
00345         pool_put(dbconn);
00346         return inode;
00347     }
00348 
00349     ret = query_utime(dbconn, inode, time);
00350     if (ret < 0) {
00351         log_printf(LOG_ERROR, "Error: query_utime()\n");
00352         pool_put(dbconn);
00353         return -EIO;
00354     }
00355 
00356     pool_put(dbconn);
00357 
00358     return 0;
00359 }
00360 
00361 static int mysqlfs_open(const char *path, struct fuse_file_info *fi)
00362 {
00363     MYSQL *dbconn;
00364     long inode;
00365     int ret;
00366 
00367     log_printf(LOG_D_CALL, "mysqlfs_open(\"%s\")\n", path);
00368 
00369     if ((dbconn = pool_get()) == NULL)
00370       return -EMFILE;
00371 
00372     inode = query_inode(dbconn, path);
00373     if(inode < 0){
00374         pool_put(dbconn);
00375         return -ENOENT;
00376     }
00377 
00378     /* Save inode for future use. Lets us skip path->inode translation.  */
00379     fi->fh = inode;
00380 
00381     log_printf(LOG_D_OTHER, "inode(\"%s\") = %d\n", path, fi->fh);
00382 
00383     ret = query_inuse_inc(dbconn, inode, 1);
00384     if (ret < 0) {
00385         pool_put(dbconn);
00386         return ret;
00387     }
00388 
00389     pool_put(dbconn);
00390 
00391     return 0;
00392 }
00393 
00394 static int mysqlfs_read(const char *path, char *buf, size_t size, off_t offset,
00395                         struct fuse_file_info *fi)
00396 {
00397     int ret;
00398     MYSQL *dbconn;
00399 
00400     log_printf(LOG_D_CALL, "mysqlfs_read(\"%s\" %zu@%llu)\n", path, size, offset);
00401 
00402     if ((dbconn = pool_get()) == NULL)
00403       return -EMFILE;
00404 
00405     ret = query_read(dbconn, fi->fh, buf, size, offset);
00406     pool_put(dbconn);
00407 
00408     return ret;
00409 }
00410 
00411 static int mysqlfs_write(const char *path, const char *buf, size_t size,
00412                          off_t offset, struct fuse_file_info *fi)
00413 {
00414     int ret;
00415     MYSQL *dbconn;
00416 
00417     log_printf(LOG_D_CALL, "mysqlfs_write(\"%s\" %zu@%lld)\n", path, size, offset);
00418 
00419     if ((dbconn = pool_get()) == NULL)
00420       return -EMFILE;
00421 
00422     ret = query_write(dbconn, fi->fh, buf, size, offset);
00423     pool_put(dbconn);
00424 
00425     return ret;
00426 }
00427 
00428 static int mysqlfs_release(const char *path, struct fuse_file_info *fi)
00429 {
00430     int ret;
00431     MYSQL *dbconn;
00432 
00433     log_printf(LOG_D_CALL, "mysqlfs_release(\"%s\")\n", path);
00434 
00435     if ((dbconn = pool_get()) == NULL)
00436       return -EMFILE;
00437 
00438     ret = query_inuse_inc(dbconn, fi->fh, -1);
00439     if (ret < 0) {
00440         pool_put(dbconn);
00441         return ret;
00442     }
00443 
00444     ret = query_purge_deleted(dbconn, fi->fh);
00445     if (ret < 0) {
00446         pool_put(dbconn);
00447         return ret;
00448     }
00449 
00450     pool_put(dbconn);
00451 
00452     return 0;
00453 }
00454 
00455 static int mysqlfs_link(const char *from, const char *to)
00456 {
00457     int ret;
00458     long inode, new_parent;
00459     MYSQL *dbconn;
00460     char *tmp, *name, esc_name[PATH_MAX * 2];
00461 
00462     log_printf(LOG_D_CALL, "link(%s, %s)\n", from, to);
00463 
00464     if ((dbconn = pool_get()) == NULL)
00465       return -EMFILE;
00466 
00467     inode = query_inode(dbconn, from);
00468     if(inode < 0){
00469         pool_put(dbconn);
00470         return inode;
00471     }
00472 
00473     tmp = strdup(to);
00474     name = dirname(tmp);
00475     new_parent = query_inode(dbconn, name);
00476     free(tmp);
00477     if (new_parent < 0) {
00478         pool_put(dbconn);
00479         return new_parent;
00480     }
00481 
00482     tmp = strdup(to);
00483     name = basename(tmp);
00484     mysql_real_escape_string(dbconn, esc_name, name, strlen(name));
00485     free(tmp);
00486 
00487     ret = query_mkdirentry(dbconn, inode, esc_name, new_parent);
00488     if(ret < 0){
00489         pool_put(dbconn);
00490         return ret;
00491     }
00492 
00493     pool_put(dbconn);
00494 
00495     return 0;
00496 }
00497 
00498 static int mysqlfs_symlink(const char *from, const char *to)
00499 {
00500     int ret;
00501     int inode;
00502     MYSQL *dbconn;
00503 
00504     log_printf(LOG_D_CALL, "%s(\"%s\" -> \"%s\")\n", __func__, from, to);
00505 
00506     ret = mysqlfs_mknod(to, S_IFLNK | 0755, 0);
00507     if (ret < 0)
00508       return ret;
00509 
00510     if ((dbconn = pool_get()) == NULL)
00511       return -EMFILE;
00512 
00513     inode = query_inode(dbconn, to);
00514     if(inode < 0){
00515         pool_put(dbconn);
00516         return -ENOENT;
00517     }
00518 
00519     ret = query_write(dbconn, inode, from, strlen(from), 0);
00520     if (ret > 0) ret = 0;
00521 
00522     pool_put(dbconn);
00523 
00524     return ret;
00525 }
00526 
00527 static int mysqlfs_readlink(const char *path, char *buf, size_t size)
00528 {
00529     int ret;
00530     long inode;
00531     MYSQL *dbconn;
00532 
00533     log_printf(LOG_D_CALL, "%s(\"%s\")\n", __func__, path);
00534 
00535     if ((dbconn = pool_get()) == NULL)
00536       return -EMFILE;
00537 
00538     inode = query_inode(dbconn, path);
00539     if(inode < 0){
00540         pool_put(dbconn);
00541         return -ENOENT;
00542     }
00543 
00544     memset (buf, 0, size);
00545     ret = query_read(dbconn, inode, buf, size, 0);
00546     log_printf(LOG_DEBUG, "readlink(%s): %s [%zd -> %d]\n", path, buf, size, ret);
00547     pool_put(dbconn);
00548 
00549     if (ret > 0) ret = 0;
00550     return ret;
00551 }
00552 
00553 static int mysqlfs_rename(const char *from, const char *to)
00554 {
00555     int ret;
00556     MYSQL *dbconn;
00557 
00558     log_printf(LOG_D_CALL, "%s(%s -> %s)\n", __func__, from, to);
00559 
00560     // FIXME: This should be wrapped in a transaction!!!
00561     mysqlfs_unlink(to);
00562 
00563     if ((dbconn = pool_get()) == NULL)
00564       return -EMFILE;
00565 
00566     ret = query_rename(dbconn, from, to);
00567 
00568     pool_put(dbconn);
00569 
00570     return ret;
00571 }
00572 
00574 static struct fuse_operations mysqlfs_oper = {
00575     .getattr    = mysqlfs_getattr,
00576     .readdir    = mysqlfs_readdir,
00577     .mknod      = mysqlfs_mknod,
00578     .mkdir      = mysqlfs_mkdir,
00579     .unlink     = mysqlfs_unlink,
00580     .rmdir      = mysqlfs_unlink,
00581     .chmod      = mysqlfs_chmod,
00582     .chown      = mysqlfs_chown,
00583     .truncate   = mysqlfs_truncate,
00584     .utime      = mysqlfs_utime,
00585     .open       = mysqlfs_open,
00586     .read       = mysqlfs_read,
00587     .write      = mysqlfs_write,
00588     .release    = mysqlfs_release,
00589     .link       = mysqlfs_link,
00590     .symlink    = mysqlfs_symlink,
00591     .readlink   = mysqlfs_readlink,
00592     .rename     = mysqlfs_rename,
00593 };
00594 
00596 void usage(){
00597     fprintf(stderr,
00598             "usage: mysqlfs [opts] <mountpoint>\n\n");
00599     fprintf(stderr,
00600             "       mysqlfs [-osocket=/tmp/mysql.sock] [-oport=####] -ohost=host -ouser=user -opassword=password "
00601             "-odatabase=database ./mountpoint\n");
00602     fprintf(stderr,
00603             "       mysqlfs [-d] [-ologfile=filename] -ohost=host -ouser=user -opassword=password "
00604             "-odatabase=database ./mountpoint\n");
00605     fprintf(stderr,
00606             "       mysqlfs [-mycnf_group=group_name] -ohost=host -ouser=user -opassword=password "
00607             "-odatabase=database ./mountpoint\n");
00608     fprintf(stderr, "\n(mimick mysql options)\n");
00609     fprintf(stderr,
00610             "       mysqlfs --host=host --user=user --password=password --database=database ./mountpoint\n");
00611     fprintf(stderr,
00612             "       mysqlfs -h host -u user --password=password -D database ./mountpoint\n");
00613 }
00614 
00616 #define MYSQLFS_OPT_KEY(t, p, v) { t, offsetof(struct mysqlfs_opt, p), v }
00617 
00619 enum
00620   {
00621     KEY_BACKGROUND,     
00622     KEY_DEBUG_DNQ,      
00623     KEY_HELP,
00624     KEY_VERSION,
00625   };
00626 
00628 static struct fuse_opt mysqlfs_opts[] =
00629   {
00630     MYSQLFS_OPT_KEY(  "background",     bg,     1),
00631     MYSQLFS_OPT_KEY(  "database=%s",    db,     1),
00632     MYSQLFS_OPT_KEY("--database=%s",    db,     1),
00633     MYSQLFS_OPT_KEY( "-D %s",           db,     1),
00634     MYSQLFS_OPT_KEY(  "fsck",           fsck,   1),
00635     MYSQLFS_OPT_KEY(  "fsck=%d",        fsck,   1),
00636     MYSQLFS_OPT_KEY("--fsck=%d",        fsck,   1),
00637     MYSQLFS_OPT_KEY("nofsck",           fsck,   0),
00638     MYSQLFS_OPT_KEY(  "host=%s",        host,   0),
00639     MYSQLFS_OPT_KEY("--host=%s",        host,   0),
00640     MYSQLFS_OPT_KEY( "-h %s",           host,   0),
00641     MYSQLFS_OPT_KEY(  "logfile=%s",     logfile,        0),
00642     MYSQLFS_OPT_KEY("--logfile=%s",     logfile,        0),
00643     MYSQLFS_OPT_KEY(  "mycnf_group=%s", mycnf_group,    0), /* Read defaults from specified group in my.cnf  -- Command line options still have precedence.  */
00644     MYSQLFS_OPT_KEY("--mycnf_group=%s", mycnf_group,    0),
00645     MYSQLFS_OPT_KEY(  "password=%s",    passwd, 0),
00646     MYSQLFS_OPT_KEY("--password=%s",    passwd, 0),
00647     MYSQLFS_OPT_KEY(  "port=%d",        port,   0),
00648     MYSQLFS_OPT_KEY("--port=%d",        port,   0),
00649     MYSQLFS_OPT_KEY( "-P %d",           port,   0),
00650     MYSQLFS_OPT_KEY(  "socket=%s",      socket, 0),
00651     MYSQLFS_OPT_KEY("--socket=%s",      socket, 0),
00652     MYSQLFS_OPT_KEY( "-S %s",           socket, 0),
00653     MYSQLFS_OPT_KEY(  "user=%s",        user,   0),
00654     MYSQLFS_OPT_KEY("--user=%s",        user,   0),
00655     MYSQLFS_OPT_KEY( "-u %s",           user,   0),
00656 
00657     FUSE_OPT_KEY("debug-dnq",   KEY_DEBUG_DNQ),
00658     FUSE_OPT_KEY("-v",          KEY_VERSION),
00659     FUSE_OPT_KEY("--version",   KEY_VERSION),
00660     FUSE_OPT_KEY("--help",      KEY_HELP),
00661     FUSE_OPT_END
00662   };
00663 
00664 
00665 
00666 static int mysqlfs_opt_proc(void *data, const char *arg, int key,
00667                             struct fuse_args *outargs){
00668     struct mysqlfs_opt *opt = (struct mysqlfs_opt *) data;
00669 
00670     switch (key)
00671     {
00672         case FUSE_OPT_KEY_OPT: /* dig through the list for matches */
00673     /*
00674      * There are primitives for this in FUSE, but no need to change at this point
00675      */
00676             break;
00677 
00678         case KEY_DEBUG_DNQ:
00679         /*
00680          * Debug: Dump Config and Quit -- used to debug options-handling changes
00681          */
00682 
00683             fprintf (stderr, "DEBUG: Dump and Quit\n\n");
00684             fprintf (stderr, "connect: mysql://%s:%s@%s:%d/%s\n", opt->user, opt->passwd, opt->host, opt->port, opt->db);
00685             fprintf (stderr, "connect: sock://%s\n", opt->socket);
00686             fprintf (stderr, "fsck? %s\n", (opt->fsck ? "yes" : "no"));
00687             fprintf (stderr, "group: %s\n", opt->mycnf_group);
00688             fprintf (stderr, "pool: %d initial connections\n", opt->init_conns);
00689             fprintf (stderr, "pool: %d idling connections\n", opt->max_idling_conns);
00690             fprintf (stderr, "logfile: file://%s\n", opt->logfile);
00691             fprintf (stderr, "bg? %s (debug)\n\n", (opt->bg ? "yes" : "no"));
00692 
00693             exit (2);
00694 
00695         case KEY_HELP: /* trigger usage call */
00696             usage ();
00697             exit (0);
00698 
00699         case KEY_VERSION: /* show version and quit */
00700             fprintf (stderr, "%s-%s fuse-%2.1f\n\n", PACKAGE_TARNAME, PACKAGE_VERSION, ((double) FUSE_USE_VERSION)/10.0);
00701             exit (0);
00702 
00703         default: /* key != FUSE_OPT_KEY_OPT */
00704             fuse_opt_add_arg(outargs, arg);
00705             return 0;
00706     }
00707 
00708     fuse_opt_add_arg(outargs, arg);
00709     return 0;
00710 }
00711 
00715 int main(int argc, char *argv[])
00716 {
00717     struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
00718     struct mysqlfs_opt opt = {
00719         .init_conns     = 1,
00720         .max_idling_conns = 5,
00721         .mycnf_group    = "mysqlfs",
00722         .logfile        = "mysqlfs.log",
00723     };
00724 
00725     log_file = stderr;
00726 
00727     fuse_opt_parse(&args, &opt, mysqlfs_opts, mysqlfs_opt_proc);
00728 
00729     if (pool_init(&opt) < 0) {
00730         log_printf(LOG_ERROR, "Error: pool_init() failed\n");
00731         fuse_opt_free_args(&args);
00732         return EXIT_FAILURE;        
00733     }
00734 
00735     /*
00736      * I found that -- running from a script (ie no term?) -- the MySQLfs would not background, so the terminal is held; this makes automated testing difficult.
00737      *
00738      * I (allanc) put this into here to allow for AUTOTEST, but then autotest has to seek-and-destroy the app.  This isn't quite perfect yet, I get some flakiness here, othertines the pid is 4 more than the parent, which is odd.
00739      */
00740     if (0 < opt.bg)
00741     {
00742         if (0 < fork())
00743             return EXIT_SUCCESS;
00744         //else
00745         //    fprintf (stderr, "forked %d\n", getpid());
00746     }
00747 
00748     log_file = log_init(opt.logfile, 1);
00749 
00750     fuse_main(args.argc, args.argv, &mysqlfs_oper);
00751     fuse_opt_free_args(&args);
00752 
00753     pool_cleanup();
00754 
00755     return EXIT_SUCCESS;
00756 }

Generated on Sun Jul 12 20:25:26 2009 for mysqlfs by  doxygen 1.4.7