- filled in group field, previously missing.
[npfs.git] / fs / gphotofs.c
blob2a4e32f29ec825fb194c483dfd23921d26287836
1 /*
2 * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * LATCHESAR IONKOV AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
23 #define _XOPEN_SOURCE 600
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <pthread.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <assert.h>
32 #include <gphoto2/gphoto2.h>
33 #include "npfs.h"
35 #define ROOTPERM 0755
36 #define NELEM(x) (sizeof(x)/sizeof((x)[0]))
38 typedef struct File File;
40 struct File {
41 char* path;
42 CameraFile* camfile;
43 const char* data;
44 int nopen;
47 static u32 gpfs_read(Npfilefid *, u64, u32, u8 *, Npreq *);
48 static u32 gpfs_write(Npfilefid *, u64, u32, u8 *, Npreq *);
49 static int gpfs_wstat(Npfile *, Npstat *);
50 static void gpfs_destroy(Npfile *);
51 static Npfile* gpfs_create(Npfile *, char *, u32, Npuser *, Npgroup *);
52 static Npfile* gpfs_first(Npfile *);
53 static Npfile* gpfs_next(Npfile *, Npfile *);
54 static int gpfs_wstat(Npfile *, Npstat *);
55 static int gpfs_remove(Npfile *, Npfile *);
56 static int gpfs_openfid(Npfilefid *);
57 static void gpfs_closefid(Npfilefid *);
59 static Npuser *user;
60 static Npsrv *srv;
61 static Npfile *root;
62 static u64 qidpath;
63 static Camera *cam;
64 static GPContext *ctx;
66 Npfileops fileops = {
67 .read = gpfs_read,
68 .write = gpfs_write,
69 .wstat = gpfs_wstat,
70 .destroy = gpfs_destroy,
71 .openfid = gpfs_openfid,
72 .closefid = gpfs_closefid,
75 Npdirops dirops = {
76 .create = gpfs_create,
77 .first = gpfs_first,
78 .next = gpfs_next,
79 .wstat = gpfs_wstat,
80 .remove = gpfs_remove,
81 .destroy = gpfs_destroy,
84 static File* file_alloc(char *);
86 void
87 usage()
89 fprintf(stderr, "gphotofs: -d -u user -w nthreads "
90 "-o mount-options mount-point\n");
91 exit(-1);
94 int
95 main(int argc, char **argv)
97 int err, c, debuglevel, nwthreads;
98 char *opts, *s;
100 debuglevel = 0;
101 nwthreads = 1;
102 opts = "";
103 user = np_uid2user(getuid());
104 while ((c = getopt(argc, argv, "du:w:o:")) != -1) {
105 switch (c) {
106 case 'd':
107 debuglevel = 1;
108 break;
110 case 'u':
111 user = np_uname2user(optarg);
112 break;
114 case 'w':
115 nwthreads = strtol(optarg, &s, 10);
116 if (*s != '\0')
117 usage();
118 break;
120 case 'o':
121 opts = optarg;
122 break;
124 default:
125 fprintf(stderr, "invalid option\n");
129 if (!user) {
130 fprintf(stderr, "invalid user\n");
131 return -1;
134 ctx = gp_context_new();
135 gp_camera_new(&cam);
137 err = gp_camera_init(cam, ctx);
138 if (err) {
139 fprintf(stderr, "cannot initialize the camera: %d\n", err);
140 return -1;
143 root = npfile_alloc(NULL, strdup(""), ROOTPERM|Dmdir, qidpath++,
144 &dirops, file_alloc(""));
146 root->parent = root;
147 npfile_incref(root);
148 root->atime = time(NULL);
149 root->mtime = root->atime;
150 root->uid = user;
151 root->gid = user->dfltgroup;
152 root->muid = user;
154 srv = np_pipesrv_create(nwthreads);
155 if (!srv)
156 return -1;
158 npfile_init_srv(srv, root);
159 if (optind >= argc)
160 usage();
162 srv->debuglevel = debuglevel;
163 np_pipesrv_mount(srv, argv[optind], user->uname, 0, opts);
165 while (1) {
166 sleep(100);
169 return 0;
172 static File*
173 file_alloc(char *path)
175 File *f;
177 f = malloc(sizeof(*f));
178 f->path = strdup(path);
179 f->camfile = NULL;
180 f->data = NULL;
181 f->nopen = 0;
183 return f;
186 static u32
187 gpfs_read(Npfilefid *fid, u64 offset, u32 count, u8 *data, Npreq *req)
189 int n;
190 Npfile *file;
191 File *f;
193 file = fid->file;
194 f = file->aux;
195 n = count;
196 if (file->length < offset+count)
197 n = file->length - offset;
199 if (n < 0)
200 n = 0;
202 memmove(data, f->data + offset, n);
203 return n;
206 static u32
207 gpfs_write(Npfilefid *fid, u64 offset, u32 count, u8 *data, Npreq *req)
209 np_werror("permission denied", EPERM);
210 return 0;
213 static int
214 gpfs_wstat(Npfile *file, Npstat *stat)
216 np_werror("permission denied", EPERM);
217 return 0;
220 static void
221 gpfs_destroy(Npfile* file)
223 File *f;
225 fprintf(stderr, "destroy file: %s\n", file->name);
226 f = file->aux;
227 gp_file_unref(f->camfile);
228 free(f->path);
229 free(f);
232 static Npfile*
233 gpfs_create(Npfile *dir, char *name, u32 perm, Npuser *uid, Npgroup *gid)
235 np_werror("permission denied", EPERM);
236 return NULL;
239 static void
240 read_files(Npfile *dir)
242 int i, n;
243 int plen, nlen;
244 char *folder, *p;
245 Npfile *nf;
246 File *d;
247 CameraList *cl;
248 const char *fname;
249 CameraFileInfo finfo;
251 d = dir->aux;
252 /* if (dir == root)
253 folder = strdup("/");
254 else {
256 p = d->path;
257 if (strcmp(p, "/") == 0)
258 p = "";
260 plen = strlen(p);
261 nlen = strlen(dir->name);
262 folder = malloc(plen + nlen + 2);
263 memcpy(folder, p, plen);
264 folder[plen] = '/';
265 strcpy(folder + plen + 1, dir->name);
266 // }
268 gp_list_new(&cl);
269 gp_camera_folder_list_files(cam, folder, cl, ctx);
270 n = gp_list_count(cl);
271 for(i = 0; i < n; i++) {
272 gp_list_get_name(cl, i, &fname);
273 gp_camera_file_get_info(cam, folder, fname, &finfo, ctx);
275 nf = npfile_alloc(dir, (char *) fname, 0500, qidpath++,
276 &fileops, file_alloc(folder));
277 nf->mtime = finfo.file.mtime;
278 nf->atime = nf->mtime;
279 nf->uid = user;
280 nf->gid = user->dfltgroup;
281 nf->muid = user;
282 nf->length = finfo.file.size;
283 if (dir->dirlast) {
284 dir->dirlast->next = nf;
285 nf->prev = dir->dirlast;
286 } else
287 dir->dirfirst = nf;
289 dir->dirlast = nf;
290 npfile_incref(nf);
293 gp_camera_folder_list_folders(cam, folder, cl, ctx);
294 n = gp_list_count(cl);
295 for(i = 0; i < n; i++) {
296 gp_list_get_name(cl, i, &fname);
298 nf = npfile_alloc(dir, (char *) fname, 0500|Dmdir, qidpath++,
299 &dirops, file_alloc(folder));
300 nf->uid = user;
301 nf->gid = user->dfltgroup;
302 nf->muid = user;
303 if (dir->dirlast) {
304 dir->dirlast->next = nf;
305 nf->prev = dir->dirlast;
306 } else
307 dir->dirfirst = nf;
309 dir->dirlast = nf;
310 npfile_incref(nf);
314 static Npfile*
315 gpfs_first(Npfile *dir)
317 if (!dir->dirfirst)
318 read_files(dir);
320 npfile_incref(dir->dirfirst);
321 return dir->dirfirst;
324 static Npfile*
325 gpfs_next(Npfile *dir, Npfile *prevchild)
327 npfile_incref(prevchild->next);
328 return prevchild->next;
331 static int
332 gpfs_remove(Npfile *dir, Npfile *file)
334 np_werror("permission denied", EPERM);
335 return 0;
338 static int
339 gpfs_openfid(Npfilefid *fid)
341 int n;
342 Npfile *file;
343 File *f;
344 unsigned long len;
346 file = fid->file;
347 f = file->aux;
349 if (!f->nopen) {
350 gp_file_new(&f->camfile);
351 n = gp_camera_file_get(cam, f->path, file->name,
352 GP_FILE_TYPE_RAW, f->camfile, ctx);
353 if (n) {
354 fprintf(stderr, "error getting file: %d\n", n);
355 np_werror("error getting file", EIO);
356 return 0;
359 gp_file_get_data_and_size(f->camfile, &f->data, &len);
362 f->nopen++;
363 return 1;
367 static void
368 gpfs_closefid(Npfilefid *fid)
370 Npfile *file;
371 File *f;
373 file = fid->file;
374 f = file->aux;
375 f->nopen--;
376 if (!f->nopen) {
377 gp_file_unref(f->camfile);
378 f->camfile = NULL;