Line data Source code
1 : #include "../../burp.h"
2 : #include "../../alloc.h"
3 : #include "../../cmd.h"
4 : #include "../../log.h"
5 : #include "../../sbuf.h"
6 : #include "../manio.h"
7 : #include "json_output.h"
8 :
9 : typedef struct ent ent_t;
10 :
11 : struct ent
12 : {
13 : char *name;
14 : int count;
15 : struct stat statp;
16 : struct ent **ents;
17 : };
18 :
19 62 : static void ent_free(struct ent **ent)
20 : {
21 124 : if(!ent || !*ent) return;
22 62 : free_w(&(*ent)->name);
23 62 : free_v((void **)&(*ent)->ents);
24 62 : free_v((void **)ent);
25 : }
26 :
27 62 : static struct ent *ent_alloc(const char *name)
28 : {
29 : struct ent *ent;
30 124 : if(!(ent=(struct ent *)calloc_w(1, sizeof(struct ent), __func__))
31 62 : || !(ent->name=strdup_w(name, __func__)))
32 : goto error;
33 62 : return ent;
34 : error:
35 0 : ent_free(&ent);
36 0 : return NULL;
37 : }
38 :
39 : // FIX THIS:
40 : // For extra kicks, could make the config option allow multiple caches -
41 : // eg, 'monitor_browse_cache=5', then rotate out the oldest one.
42 :
43 : static struct ent *root=NULL;
44 : static char *cached_client=NULL;
45 : static unsigned long cached_bno=0;
46 :
47 61 : static int ent_add_to_list(struct ent *ent,
48 : struct sbuf *sb, const char *ent_name)
49 : {
50 61 : struct ent *enew=NULL;
51 61 : if(!(ent->ents=(struct ent **)realloc_w(ent->ents,
52 61 : (ent->count+1)*sizeof(struct ent *), __func__))
53 61 : || !(enew=ent_alloc(ent_name)))
54 : {
55 0 : log_out_of_memory(__func__);
56 : return -1;
57 : }
58 61 : memcpy(&enew->statp, &sb->statp, sizeof(struct stat));
59 61 : ent->ents[ent->count]=enew;
60 61 : ent->count++;
61 : return 0;
62 : }
63 :
64 63 : static void ents_free(struct ent *ent)
65 : {
66 63 : int i=0;
67 126 : if(!ent) return;
68 61 : for(i=0; i<ent->count; i++)
69 61 : ents_free(ent->ents[i]);
70 62 : ent_free(&ent);
71 : }
72 :
73 2 : void cache_free(void)
74 : {
75 2 : free_w(&cached_client);
76 2 : ents_free(root);
77 2 : }
78 :
79 : /*
80 : static void cache_dump(struct ent *e, int *depth)
81 : {
82 : int count;
83 : for(count=0; count<*depth; count++)
84 : printf(" ");
85 : printf("'%s'\n", e->name);
86 : for(count=0; count<e->count; count++)
87 : {
88 : (*depth)++;
89 : cache_dump(e->ents[count], depth);
90 : (*depth)--;
91 : }
92 : }
93 : */
94 :
95 1 : int cache_load(struct manio *manio, struct sbuf *sb,
96 : const char *cname, unsigned long bno)
97 : {
98 1 : int ret=-1;
99 1 : int ars=0;
100 : // int depth=0;
101 1 : char *tok=NULL;
102 1 : struct ent *point=NULL;
103 1 : struct ent *p=NULL;
104 :
105 : //printf("in cache load\n");
106 1 : cache_free();
107 :
108 1 : if(!(root=ent_alloc(""))) goto end;
109 :
110 : while(1)
111 : {
112 32 : sbuf_free_content(sb);
113 32 : if((ars=manio_read(manio, sb)))
114 : {
115 1 : if(ars<0) goto end;
116 : // ars==1 means it ended ok.
117 : break;
118 : }
119 :
120 31 : if(manio->protocol==PROTO_2 && sb->endfile.buf)
121 : continue;
122 :
123 20 : if(sb->path.cmd!=CMD_DIRECTORY
124 20 : && sb->path.cmd!=CMD_FILE
125 6 : && sb->path.cmd!=CMD_ENC_FILE
126 6 : && sb->path.cmd!=CMD_EFS_FILE
127 6 : && sb->path.cmd!=CMD_SPECIAL
128 22 : && !cmd_is_link(sb->path.cmd))
129 : continue;
130 :
131 : // Some messing around so that we can list '/'.
132 20 : if(!*(root->name) && !strncmp(sb->path.buf, "/", 1))
133 : {
134 1 : memcpy(&root->statp, &sb->statp, sizeof(struct stat));
135 1 : free_w(&root->name);
136 1 : if(!(root->name=strdup_w("/", __func__)))
137 : goto end;
138 : }
139 :
140 20 : point=root;
141 89 : if((tok=strtok(sb->path.buf, "/"))) do
142 : {
143 69 : if(point->count>0)
144 : {
145 27 : p=point->ents[point->count-1];
146 27 : if(!strcmp(tok, p->name))
147 : {
148 : point=p;
149 : continue;
150 : }
151 : }
152 :
153 61 : if(sb->path.buf+sb->path.len!=tok+strlen(tok))
154 : {
155 : // There is an entry in a directory where the
156 : // directory itself was not backed up.
157 : // We will make a fake entry for the directory,
158 : // and use the same stat data.
159 : // Make sure that we set the directory flag.
160 41 : sb->statp.st_mode&=S_IFDIR;
161 : }
162 61 : if(ent_add_to_list(point, sb, tok)) goto end;
163 61 : point=point->ents[point->count-1];
164 : } while((tok=strtok(NULL, "/")));
165 : }
166 :
167 1 : if(!(cached_client=strdup_w(cname, __func__)))
168 : goto end;
169 1 : cached_bno=bno;
170 1 : ret=0;
171 : // cache_dump(root, &depth);
172 : end:
173 1 : return ret;
174 : }
175 :
176 4 : int cache_loaded(const char *cname, unsigned long bno)
177 : {
178 4 : if(cached_client
179 2 : && !strcmp(cname, cached_client)
180 2 : && cached_bno==bno)
181 : return 1;
182 3 : return 0;
183 : }
184 :
185 : static int result_single(struct ent *ent)
186 : {
187 : // printf("result: %s\n", ent->name);
188 0 : return json_from_statp(ent->name, &ent->statp);
189 : }
190 :
191 0 : static int result_list(struct ent *ent)
192 : {
193 0 : int i=0;
194 : // printf("in results\n");
195 0 : for(i=0; i<ent->count; i++)
196 0 : result_single(ent->ents[i]);
197 0 : return 0;
198 : }
199 :
200 0 : int cache_lookup(const char *browse)
201 : {
202 0 : int i=0;
203 0 : int ret=-1;
204 0 : char *tok=NULL;
205 0 : char *copy=NULL;
206 0 : struct ent *point=root;
207 :
208 0 : if(!browse || !*browse)
209 : {
210 : // The difference between the top level for Windows and the
211 : // top level for non-Windows.
212 0 : if(*(point->name)) ret=result_single(point);
213 0 : else ret=result_list(point);
214 : goto end;
215 : }
216 :
217 0 : if(!(copy=strdup_w(browse, __func__)))
218 : goto end;
219 0 : if((tok=strtok(copy, "/"))) do
220 : {
221 : // FIX THIS: Should do a binary search here, for monster speed
222 : // increases when there are lots of files in a directory.
223 0 : for(i=0; i<point->count; i++)
224 : {
225 0 : if(strcmp(tok, point->ents[i]->name)) continue;
226 : point=point->ents[i];
227 : break;
228 : }
229 : } while((tok=strtok(NULL, "/")));
230 :
231 0 : ret=result_list(point);
232 : end:
233 0 : free_w(©);
234 0 : return ret;
235 : }
|