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