gopherfs

A FUSE gopher file system.
git clone git://r-36.net/gopherfs
Log | Files | Refs | README | LICENSE

gopherfs.c (3330B)


      1 /*
      2  * Copy me if you can.
      3  * by 20h
      4  */
      5 
      6 #define FUSE_USE_VERSION 26
      7 
      8 #include <fuse.h>
      9 #include <unistd.h>
     10 #include <stdio.h>
     11 #include <string.h>
     12 #include <stdlib.h>
     13 #include <errno.h>
     14 #include <fcntl.h>
     15 #include <time.h>
     16 #include "ind.h"
     17 #include "arg.h"
     18 #include "sdb.h"
     19 #include "proto.h"
     20 #include "download.h"
     21 
     22 sdb *db;
     23 char *argv0;
     24 
     25 static int
     26 gopendir(const char *path, struct fuse_file_info *fi)
     27 {
     28 	sdbe *e;
     29 
     30 	e = getelem(db, (char *)path, nil);
     31 	if(e == nil)
     32 		return ~ENOENT;
     33 
     34 	return 0;
     35 }
     36 
     37 
     38 static int
     39 ggetattr(const char *path, struct stat *stbuf)
     40 {
     41 	int res;
     42 	sdbe *e;
     43 
     44 	res = 0;
     45 
     46 	memset(stbuf, 0, sizeof(struct stat));
     47 	if(!strcmp(path, "/")) {
     48 		stbuf->st_mode = S_IFDIR | 0755;
     49 		stbuf->st_nlink = 1;
     50 		stbuf->st_size = 1;
     51 	} else {
     52 		e = getelem(db, (char *)path, nil);
     53 		if(e == nil)
     54 			return ~ENOENT;
     55 		if(e->v[0] == '1') {
     56 			stbuf->st_mode = S_IFDIR | 0444;
     57 			stbuf->st_nlink = 2;
     58 		} else {
     59 			stbuf->st_mode = S_IFREG | 0444;
     60 			stbuf->st_nlink = 1;
     61 			stbuf->st_size = 1;
     62 		}
     63 	}
     64 
     65 	return res;
     66 }
     67 
     68 static int
     69 greaddir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
     70 			struct fuse_file_info *fi)
     71 {
     72 	sdbe *e;
     73 	char *v, *d;
     74 
     75 	e = nil;
     76 
     77 	filler(buf, ".", 0, 0);
     78 	filler(buf, "..", 0, 0);
     79 
     80 	e = getelem(db, (char *)path, e);
     81 	if(e == nil)
     82 		return 0;
     83 
     84         if(checkcache(db, e->k) == 1)
     85                 if(rnpggopher(e->v + sizeof(char) + sizeof(time_t), db, e->k,
     86                                 -1) < 0)
     87                         return 0;
     88 
     89 	for(; e != nil; e = getelem(db, (char *)path, e)) {
     90 		if(!strcmp(e->k, (char *)path))
     91 			continue;
     92 		if(strchr(e->k + strlen(path) + 1, '/'))
     93 			continue;
     94 		v = gmemdup(e->k, strlen(e->k) + 1);
     95 		d = strrchr(v, '/');
     96 		if(d == nil)
     97 			continue;
     98 		*d++ = '\0';
     99 		filler(buf, d, 0, 0);
    100 		free(v);
    101 	}
    102 
    103 	return 0;
    104 }
    105 
    106 static int
    107 gopen(const char *path, struct fuse_file_info *fi)
    108 {
    109 
    110         if(checkqueue(db, (char *)path) < 0)
    111                 if(downloadfile(db, (char *)path) < 0)
    112                         return ~ENOENT;
    113 
    114 	fi->direct_io = 1;
    115 
    116 	return 0;
    117 }
    118 
    119 static int
    120 gread(const char *path, char *buf, size_t size, off_t offset,
    121 		struct fuse_file_info *fi)
    122 {
    123 
    124 	return getbytes(db, (char *)path, buf, size, offset);
    125 }
    126 
    127 static struct fuse_operations goper = {
    128 	.getattr = ggetattr,
    129 	.readdir = greaddir,
    130 	.opendir = gopendir,
    131 	.open = gopen,
    132 	.read = gread,
    133 };
    134 
    135 void
    136 usage(void)
    137 {
    138 
    139 	tprintf(2, "usage: %s [-h] URI mntpnt [-o option[,...]]\n", argv0);
    140 	exit(1);
    141 }
    142 
    143 int
    144 main(int argc, char *argv[])
    145 {
    146 	char *server, *port, *path, type;
    147 	char *p, *b, *c, *d;
    148 	int res;
    149 
    150 	db = createdb();
    151 	path = "";
    152 	type = '1';
    153 	c = nil;
    154 	res = 1;
    155 
    156 	ARGBEGIN {
    157 	case 'h':
    158 	default:
    159 		usage();
    160 	} ARGEND;
    161 
    162 	if(argc == 0)
    163 		usage();
    164 
    165 	if(argc > 0 && argv[0] != nil) {
    166 		c = gmemdup(argv[0], strlen(argv[0]) + 1);
    167 		p = strstr(c, "gopher://");
    168 		if(p == nil) {
    169 			tprintf(2, "Wrong URI Syntax\n");
    170 			goto badending;
    171 		}
    172 		p += 9;
    173 		server = p;
    174 
    175 		b = strchr(p, ':');
    176 		d = strchr(p, '/');
    177 		if(b > d)
    178 			b = nil;
    179 		if(b != nil) {
    180 			*b++ = '\0';
    181 			port = b;
    182 		} else
    183 			port = "70";
    184 		if(d != nil) {
    185 			*d++ = '\0';
    186 			type = *d;
    187 			p = strchr(d, '/');
    188 			if(p != nil) {
    189 				*p++ = '\0';
    190 				path = p;
    191 			}
    192 		}
    193 
    194 		adddbentry(db, type, "", path, "", server, port);
    195 		free(c);
    196 	}
    197 
    198 	res = fuse_main(argc, argv, &goper, nil);
    199 
    200 badending:
    201 	destroydb(db);
    202 
    203 	return res;
    204 }
    205