gopherfs

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

download.c (3857B)


      1 /*
      2  * Copy me if you can.
      3  * by 20h
      4  */
      5 
      6 #include <unistd.h>
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <string.h>
     10 #include <pthread.h>
     11 #include <time.h>
     12 #include <sys/types.h>
     13 #include <sys/stat.h>
     14 #include <fcntl.h>
     15 #include "ind.h"
     16 #include "sdb.h"
     17 #include "proto.h"
     18 
     19 void
     20 mkrecpathfile(char *path)
     21 {
     22 	struct stat st;
     23 	char *cpath, *c, *n;
     24 	int fd;
     25 
     26 	cpath = gmemdup(path, strlen(path) + 1);
     27 
     28 	c = n = strchr(cpath + 1, '/');
     29 	for(;c != nil; n = strchr(c, '/')) {
     30 		if(n == nil) {
     31 			fd = creat(cpath, 0755);
     32 			if(fd < 0) {
     33 				perror("creat");
     34 				exit(1);
     35 			}
     36 			close(fd);
     37 
     38 			return;
     39 		}
     40 
     41 		c = n;
     42 		*c = '\0';
     43 		if(stat(cpath, &st) < 0)
     44 			mkdir(cpath, S_IRWXU);
     45 		if(!S_ISDIR(st.st_mode)) {
     46 			perror("mkrecpathfile");
     47 			exit(1);
     48 		}
     49 
     50 		*c++ = '/';
     51 	}
     52 
     53 	return;
     54 }
     55 
     56 void
     57 clearpath(char *str)
     58 {
     59 	char *b, *c;
     60 
     61 	c = strchr(str, '/');
     62 	for(; c != nil; c = strchr(b, '/')) {
     63 		*c++ = '_';
     64 		b = c;
     65 	}
     66 
     67 	return;
     68 }
     69 
     70 char *
     71 mkcachestr(sdb *db, char *path)
     72 {
     73 	char *home, *fpath, *d, *c, *a, *b;
     74 	sdbe *e, *r;
     75 
     76 	a = nil;
     77 	c = nil;
     78 	fpath = nil;
     79 
     80 	home = getenv("HOME");
     81 	if(home == nil)
     82 		home = "/tmp";
     83 
     84 	e = getelem(db, path, nil);
     85 	if(e == nil)
     86 		goto badend;
     87 	a = gmemdup(path, strlen(path) + 1);
     88 	b = strrchr(a, '/');
     89 	if(b == nil)
     90 		goto badend;
     91 	*b = '\0';
     92 
     93 	r = getelem(db, a, nil);
     94 	if(r == nil)
     95 		goto badend;
     96 	free(a);
     97 	a = gmemdup(r->v + sizeof(char) + sizeof(time_t), strlen(r->v +
     98 			sizeof(char) + sizeof(time_t)) + 1);
     99 	b = strchr(a, '/');
    100 	if(b == nil)
    101 		goto badend;
    102 	*b = '\0';
    103 
    104 	c = gmemdup(e->v + sizeof(char) + sizeof(time_t), strlen(e->v +
    105 			sizeof(char) + sizeof(time_t)) + 1);
    106 	d = strchr(c, '/');
    107 	if(d == nil)
    108 		goto badend;
    109 	*d++ = '\0';
    110 	clearpath(d);
    111 	fpath = greallocz(nil, strlen(home) + strlen(a) + strlen(d) +
    112 			strlen(GOPHERPATH) + strlen(path) + 3, 2);
    113 	sprintf(fpath, "%s%s%s/%s", home, GOPHERPATH, a, d);
    114 
    115 badend:
    116 	if(a != nil)
    117 		free(a);
    118 	if(c != nil)
    119 		free(c);
    120 
    121 	return fpath;
    122 }
    123 
    124 int
    125 checkqueue(sdb *db, char *path)
    126 {
    127 	char *fpath;
    128 	sdbe *e;
    129 	struct stat st;
    130 	int res;
    131 
    132 	res = 0;
    133 
    134 	e = getelem(db, path, nil);
    135 	if(e == nil)
    136 		return -1;
    137 
    138 	fpath = mkcachestr(db, path);
    139 	if(fpath == nil)
    140 		return -1;
    141 	if(stat(fpath, &st) < 0) {
    142 		res = -1;
    143 		goto badend;
    144 	}
    145 
    146 	if(time(nil) - st.st_mtime > FCACHE) {
    147 		res = -1;
    148 		goto badend;
    149 	}
    150 
    151 badend:
    152 	free(fpath);
    153 
    154 	return res;
    155 }
    156 
    157 int
    158 downloadfile(sdb *db, char *path)
    159 {
    160         char *fpath;
    161         sdbe *e;
    162         struct stat st;
    163         int fd, res;
    164 
    165         res = 0;
    166 
    167         e = getelem(db, path, nil);
    168         if(e == nil)
    169                 return -1;
    170 
    171         fpath = mkcachestr(db, path);
    172         if(fpath == nil)
    173                 return -1;
    174         if(stat(fpath, &st) < 0)
    175 		mkrecpathfile(fpath);
    176 
    177 	fd = open(fpath, O_WRONLY);
    178 	if(fd < 0) {
    179 		res = -1;
    180 		goto badend;
    181 	}
    182 
    183 	if(rnpggopher(e->v + sizeof(char) + sizeof(time_t), db, e->k, fd) < 0) {
    184 		close(fd);
    185 		res = -1;
    186 		goto badend;
    187 	}
    188 	close(fd);
    189 
    190 badend:
    191 	free(fpath);
    192 
    193 	return res;
    194 }
    195 
    196 int
    197 getbytes(sdb *db, char *path, char *buf, int size, int offset)
    198 {
    199         char *fpath;
    200         sdbe *e;
    201         struct stat st;
    202         int fd, res;
    203 
    204         res = 0;
    205 
    206         e = getelem(db, path, nil);
    207         if(e == nil)
    208                 return -1;
    209 
    210         fpath = mkcachestr(db, path);
    211         if(fpath == nil)
    212                 return -1;
    213         if(stat(fpath, &st) < 0) {
    214                 res = -1;
    215                 goto badend;
    216         }
    217 
    218         if(st.st_size <= offset) {
    219                 res = 0;
    220                 goto badend;
    221         }
    222 
    223 	fd = open(fpath, O_RDONLY);
    224 	if(fd < 0) {
    225 		res = -1;
    226 		goto badend;
    227 	}
    228 
    229 	if(lseek(fd, offset, SEEK_SET) < offset) {
    230 		close(fd);
    231 		res = -1;
    232 		goto badend;
    233 	}
    234 
    235 	res = (offset + size > st.st_size) ? size - (offset + size -
    236 		st.st_size) : size;
    237 	if(read(fd, buf, res) < 0) {
    238 		close(fd);
    239 		res = -1;
    240 		goto badend;
    241 	}
    242 	close(fd);
    243 
    244 badend:
    245 	free(fpath);
    246 
    247 	return res;
    248 }
    249