Hook version command-line option
[rarfs.git] / src / main.cc
blob2ca0c49fc7565551bad53d127e701219958baa79
1 /***************************************************************************
2 * Copyright (C) 2006 Kent Gustavsson <nedo80@gmail.com>
3 ****************************************************************************/
4 /*
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Library General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #define FUSE_USE_VERSION 25
21 #include <fuse.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <fuse_opt.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <cstdlib>
31 #include <iostream>
32 #include <fstream>
33 #include "rarblock.h"
34 #include "rararchive.h"
35 #include "config.h"
37 RARArchive arc;
39 static int rarfs_getattr(const char *p, struct stat *stbuf)
41 int res = 0;
43 std::string path = p + 1;
44 int pos;
45 while ( (pos = path.find("/")) != std::string::npos )
46 path.replace(pos,1,"\\");
48 memset(stbuf, 0, sizeof(struct stat));
49 if(strcmp(p, "/") == 0)
51 stbuf->st_mode = S_IFDIR | 0755;
52 stbuf->st_nlink = 2;
54 arc.GetDate(path, &stbuf->st_atim);
55 arc.GetDate(path, &stbuf->st_mtim);
57 else if(arc.HasFolder(path))
59 stbuf->st_mode = S_IFDIR | 0755;
60 stbuf->st_nlink = 2;
61 arc.GetDate(path, &stbuf->st_atim);
62 arc.GetDate(path, &stbuf->st_mtim);
64 else if(arc.HasFile(path))
66 stbuf->st_mode = S_IFREG | 0444;
67 stbuf->st_nlink = 1;
68 stbuf->st_size = arc.GetFileSize(path);
69 arc.GetDate(path, &stbuf->st_atim);
70 arc.GetDate(path, &stbuf->st_mtim);
72 else
73 res = -ENOENT;
75 return res;
78 static int rarfs_readdir(const char *p, void *buf, fuse_fill_dir_t filler,
79 off_t offset, struct fuse_file_info *fi)
81 std::vector<std::string> list = arc.GetFiles();
82 std::vector<std::string>::iterator iter;
83 std::map < std::string, int > ugly;
85 std::string path = p + 1;
86 int pos;
87 while ( (pos = path.find("/")) != std::string::npos )
88 path.replace(pos,1,"\\");
90 if(strcmp(p, "/") != 0)
92 if (!arc.HasFolder(path))
93 return -ENOENT;
96 filler(buf, ".", NULL, 0);
97 filler(buf, "..", NULL, 0);
99 for(iter = list.begin() ; iter != list.end() ; iter++)
101 if( iter->size() > path.size() )
103 if ( iter->substr(0, path.size()) == path )
105 std::string file = iter->substr(path.size());
106 if ( file[0] == '\\' )
107 file = file.substr(1);
109 if( file.find("\\") == std::string::npos )
111 filler(buf, file.c_str(), NULL, 0);
117 list = arc.GetFolders();
118 for(iter = list.begin() ; iter != list.end() ; iter++)
120 if( iter->size() > path.size() )
122 if ( iter->substr(0, path.size()) == path )
124 std::string folder = iter->substr(path.size());
125 if ( folder[0] == '\\' )
126 folder = folder.substr(1);
127 folder = folder.substr(0, folder.find("\\"));
128 ugly[folder] = 1;
133 std::map <std::string, int>::iterator ui;
134 for( ui = ugly.begin() ; ui != ugly.end() ; ui++)
135 filler(buf, ui->first.c_str(), NULL, 0);
137 return 0;
140 static int rarfs_open(const char *p, fuse_file_info *fi)
142 std::string path = p + 1;
143 int pos;
144 while ( (pos = path.find("/")) != std::string::npos )
145 path.replace(pos,1,"\\");
148 if(!arc.HasFile(path))
149 return -ENOENT;
152 if((fi->flags & 3) != O_RDONLY)
153 return -EACCES;
155 return 0;
158 static int rarfs_read(const char *p, char *buf, size_t size, off_t offset, fuse_file_info *fi)
160 std::string path = p + 1;
161 int pos;
162 while ( (pos = path.find("/")) != std::string::npos )
163 path.replace(pos,1,"\\");
165 size_t len;
166 if(!arc.HasFile(path))
167 return -ENOENT;
169 return arc.Read(path.c_str(), buf, size, offset) ;
172 static struct fuse_operations rarfs_oper;
174 struct Opt
176 Opt();
177 static void usage(char const* arg0);
179 char rarfile[512];
180 bool mount_expected;
182 /* "Key" values for command-line options */
183 static const int KEY_HELP = 0;
184 static const int KEY_VERSION = 1;
186 static const int KEEP = 1;
187 static const int DISCARD = 0;
190 Opt::Opt() :
191 mount_expected(true)
193 rarfile[0] = 0;
196 static struct fuse_opt rarfs_opts[] = {
197 FUSE_OPT_KEY("-h", Opt::KEY_HELP),
198 FUSE_OPT_KEY("--help", Opt::KEY_HELP),
199 FUSE_OPT_KEY("-V", Opt::KEY_VERSION),
200 FUSE_OPT_KEY("--version", Opt::KEY_VERSION),
201 FUSE_OPT_END
204 static int rarfs_opt_proc(void *data, const char *arg, int key,
205 struct fuse_args *outargs)
207 Opt *param = static_cast<Opt*>(data);
209 switch (key) {
210 case FUSE_OPT_KEY_NONOPT:
211 if( param->rarfile[0] == 0 )
213 strcpy(param->rarfile, arg);
214 return Opt::DISCARD;
216 break;
218 case Opt::KEY_HELP:
219 Opt::usage(outargs->argv[0]);
220 putc('\n', stderr);
222 /* Copied from usage() in helper.c in Fuse 2.9.0 */
223 fprintf(stderr,
224 "general options:\n"
225 " -o opt,[opt...] mount options\n"
226 " -h --help print help\n"
227 " -V --version print version\n"
228 "\n");
230 /* Substitute "help without header" option for fuse_
231 parse_cmdline() */
232 int ret;
233 ret = fuse_opt_add_arg(outargs, "-ho");
234 if( ret < 0 )
236 return ret;
239 param->mount_expected = false;
240 return Opt::DISCARD;
242 case Opt::KEY_VERSION:
243 fputs(PACKAGE " " VERSION "\n", stderr);
244 param->mount_expected = false;
245 break;
248 return Opt::KEEP;
251 void Opt::usage(char const* arg0)
253 fprintf(stderr, "USAGE: %s <file> <dir>\n", arg0);
256 int main( int argc, char ** argv)
259 struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
260 Opt param;
262 if (fuse_opt_parse(&args, &param, rarfs_opts, rarfs_opt_proc) == -1)
263 exit(1);
265 if ( param.mount_expected )
267 if ( ! arc.Init(param.rarfile) )
269 Opt::usage(argv[0]);
270 return -1;
273 rarfs_oper.getattr = rarfs_getattr;
274 rarfs_oper.readdir = rarfs_readdir;
275 rarfs_oper.open = rarfs_open;
276 rarfs_oper.read = rarfs_read;
278 arc.Parse(false);
281 return fuse_main(args.argc, args.argv, &rarfs_oper);