OLD | NEW |
| (Empty) |
1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 * Use of this source code is governed by a BSD-style license that can be | |
3 * found in the LICENSE file. | |
4 */ | |
5 | |
6 #include "handlers.h" | |
7 | |
8 #include <assert.h> | |
9 #include <stdio.h> | |
10 #include <stdlib.h> | |
11 #include <string.h> | |
12 | |
13 #include "hello_nacl_mounts.h" | |
14 | |
15 #define MAX_OPEN_FILES 10 | |
16 | |
17 /** | |
18 * A mapping from int -> FILE*, so the JavaScript messages can refer to an open | |
19 * File. */ | |
20 static FILE* g_OpenFiles[MAX_OPEN_FILES]; | |
21 | |
22 | |
23 /** | |
24 * Add the file to the g_OpenFiles map. | |
25 * @param[in] file The file to add to g_OpenFiles. | |
26 * @return int The index of the FILE in g_OpenFiles, or -1 if there are too many | |
27 * open files. */ | |
28 static int AddFileToMap(FILE* file) { | |
29 int i; | |
30 assert(file != NULL); | |
31 for (i = 0; i < MAX_OPEN_FILES; ++i) { | |
32 if (g_OpenFiles[i] == NULL) { | |
33 g_OpenFiles[i] = file; | |
34 return i; | |
35 } | |
36 } | |
37 | |
38 return -1; | |
39 } | |
40 | |
41 /** | |
42 * Remove the file from the g_OpenFiles map. | |
43 * @param[in] i The index of the file handle to remove. */ | |
44 static void RemoveFileFromMap(int i) { | |
45 assert(i >= 0 && i < MAX_OPEN_FILES); | |
46 g_OpenFiles[i] = NULL; | |
47 } | |
48 | |
49 /** | |
50 * Get a file handle from the g_OpenFiles map. | |
51 * @param[in] i The index of the file handle to get. | |
52 * @return the FILE*, or NULL of there is no open file with that handle. | |
53 */ | |
54 static FILE* GetFileFromMap(int i) { | |
55 assert(i >= 0 && i < MAX_OPEN_FILES); | |
56 return g_OpenFiles[i]; | |
57 } | |
58 | |
59 /** | |
60 * Get a file, given a string containing the index. | |
61 * @param[in] s The string containing the file index. | |
62 * @param[out] file_index The file index of this file. | |
63 * @return The FILE* for this file, or NULL if the index is invalid. */ | |
64 static FILE* GetFileFromIndexString(const char* s, int* file_index) { | |
65 char* endptr; | |
66 int result = strtol(s, &endptr, 10); | |
67 if (endptr != s + strlen(s)) { | |
68 /* Garbage at the end of the number...? */ | |
69 return NULL; | |
70 } | |
71 | |
72 if (file_index) | |
73 *file_index = result; | |
74 | |
75 return GetFileFromMap(result); | |
76 } | |
77 | |
78 | |
79 /** | |
80 * Handle a call to fopen() made by JavaScript. | |
81 * | |
82 * fopen expects 2 parameters: | |
83 * 0: the path of the file to open | |
84 * 1: the mode string | |
85 * on success, fopen returns a result in |output| separated by \1: | |
86 * 0: "fopen" | |
87 * 1: the filename opened | |
88 * 2: the file index | |
89 * on failure, fopen returns an error string in |output|. | |
90 * | |
91 * @param[in] num_params The number of params in |params|. | |
92 * @param[in] params An array of strings, parameters to this function. | |
93 * @param[out] output A string to write informational function output to. | |
94 * @return An errorcode; 0 means success, anything else is a failure. */ | |
95 int HandleFopen(int num_params, char** params, char** output) { | |
96 FILE* file; | |
97 int file_index; | |
98 const char* filename; | |
99 const char* mode; | |
100 | |
101 if (num_params != 2) { | |
102 *output = PrintfToNewString("Error: fopen takes 2 parameters."); | |
103 return 1; | |
104 } | |
105 | |
106 filename = params[0]; | |
107 mode = params[1]; | |
108 | |
109 file = fopen(filename, mode); | |
110 if (!file) { | |
111 *output = PrintfToNewString("Error: fopen returned a NULL FILE*."); | |
112 return 2; | |
113 } | |
114 | |
115 file_index = AddFileToMap(file); | |
116 if (file_index == -1) { | |
117 *output = PrintfToNewString( | |
118 "Error: Example only allows %d open file handles.", MAX_OPEN_FILES); | |
119 return 3; | |
120 } | |
121 | |
122 *output = PrintfToNewString("fopen\1%s\1%d", filename, file_index); | |
123 return 0; | |
124 } | |
125 | |
126 /** | |
127 * Handle a call to fwrite() made by JavaScript. | |
128 * | |
129 * fwrite expects 2 parameters: | |
130 * 0: The index of the file (which is mapped to a FILE*) | |
131 * 1: A string to write to the file | |
132 * on success, fwrite returns a result in |output| separated by \1: | |
133 * 0: "fwrite" | |
134 * 1: the file index | |
135 * 2: the number of bytes written | |
136 * on failure, fwrite returns an error string in |output|. | |
137 * | |
138 * @param[in] num_params The number of params in |params|. | |
139 * @param[in] params An array of strings, parameters to this function. | |
140 * @param[out] output A string to write informational function output to. | |
141 * @return An errorcode; 0 means success, anything else is a failure. */ | |
142 int HandleFwrite(int num_params, char** params, char** output) { | |
143 FILE* file; | |
144 const char* file_index_string; | |
145 const char* data; | |
146 size_t data_len; | |
147 size_t bytes_written; | |
148 | |
149 if (num_params != 2) { | |
150 *output = PrintfToNewString("Error: fwrite takes 2 parameters."); | |
151 return 1; | |
152 } | |
153 | |
154 file_index_string = params[0]; | |
155 file = GetFileFromIndexString(file_index_string, NULL); | |
156 data = params[1]; | |
157 data_len = strlen(data); | |
158 | |
159 if (!file) { | |
160 *output = PrintfToNewString("Error: Unknown file handle %s.", | |
161 file_index_string); | |
162 return 2; | |
163 } | |
164 | |
165 bytes_written = fwrite(data, 1, data_len, file); | |
166 | |
167 *output = PrintfToNewString("fwrite\1%s\1%d", file_index_string, | |
168 bytes_written); | |
169 return 0; | |
170 } | |
171 | |
172 /** | |
173 * Handle a call to fread() made by JavaScript. | |
174 * | |
175 * fread expects 2 parameters: | |
176 * 0: The index of the file (which is mapped to a FILE*) | |
177 * 1: The number of bytes to read from the file. | |
178 * on success, fread returns a result in |output| separated by \1: | |
179 * 0: "fread" | |
180 * 1: the file index | |
181 * 2: the data read from the file | |
182 * on failure, fread returns an error string in |output|. | |
183 * | |
184 * @param[in] num_params The number of params in |params|. | |
185 * @param[in] params An array of strings, parameters to this function. | |
186 * @param[out] output A string to write informational function output to. | |
187 * @return An errorcode; 0 means success, anything else is a failure. */ | |
188 int HandleFread(int num_params, char** params, char** output) { | |
189 FILE* file; | |
190 const char* file_index_string; | |
191 char* buffer; | |
192 size_t data_len; | |
193 size_t bytes_read; | |
194 | |
195 if (num_params != 2) { | |
196 *output = PrintfToNewString("Error: fread takes 2 parameters."); | |
197 return 1; | |
198 } | |
199 | |
200 file_index_string = params[0]; | |
201 file = GetFileFromIndexString(file_index_string, NULL); | |
202 data_len = strtol(params[1], NULL, 10); | |
203 | |
204 if (!file) { | |
205 *output = PrintfToNewString("Error: Unknown file handle %s.", | |
206 file_index_string); | |
207 return 2; | |
208 } | |
209 | |
210 buffer = (char*)malloc(data_len + 1); | |
211 bytes_read = fread(buffer, 1, data_len, file); | |
212 buffer[bytes_read] = 0; | |
213 | |
214 *output = PrintfToNewString("fread\1%s\1%s", file_index_string, buffer); | |
215 free(buffer); | |
216 return 0; | |
217 } | |
218 | |
219 /** | |
220 * Handle a call to fseek() made by JavaScript. | |
221 * | |
222 * fseek expects 3 parameters: | |
223 * 0: The index of the file (which is mapped to a FILE*) | |
224 * 1: The offset to seek to | |
225 * 2: An integer representing the whence parameter of standard fseek. | |
226 * whence = 0: seek from the beginning of the file | |
227 * whence = 1: seek from the current file position | |
228 * whence = 2: seek from the end of the file | |
229 * on success, fseek returns a result in |output| separated by \1: | |
230 * 0: "fseek" | |
231 * 1: the file index | |
232 * 2: The new file position | |
233 * on failure, fseek returns an error string in |output|. | |
234 * | |
235 * @param[in] num_params The number of params in |params|. | |
236 * @param[in] params An array of strings, parameters to this function. | |
237 * @param[out] output A string to write informational function output to. | |
238 * @return An errorcode; 0 means success, anything else is a failure. */ | |
239 int HandleFseek(int num_params, char** params, char** output) { | |
240 FILE* file; | |
241 const char* file_index_string; | |
242 long offset; | |
243 int whence; | |
244 int result; | |
245 | |
246 if (num_params != 3) { | |
247 *output = PrintfToNewString("Error: fseek takes 3 parameters."); | |
248 return 1; | |
249 } | |
250 | |
251 file_index_string = params[0]; | |
252 file = GetFileFromIndexString(file_index_string, NULL); | |
253 offset = strtol(params[1], NULL, 10); | |
254 whence = strtol(params[2], NULL, 10); | |
255 | |
256 if (!file) { | |
257 *output = PrintfToNewString("Error: Unknown file handle %s.", | |
258 file_index_string); | |
259 return 2; | |
260 } | |
261 | |
262 result = fseek(file, offset, whence); | |
263 if (result) { | |
264 *output = PrintfToNewString("Error: fseek returned error %d.", result); | |
265 return 3; | |
266 } | |
267 | |
268 offset = ftell(file); | |
269 if (offset < 0) { | |
270 *output = PrintfToNewString( | |
271 "Error: fseek succeeded, but ftell returned error %d.", offset); | |
272 return 4; | |
273 } | |
274 | |
275 *output = PrintfToNewString("fseek\1%s\1%d", file_index_string, offset); | |
276 return 0; | |
277 } | |
278 | |
279 /** | |
280 * Handle a call to fclose() made by JavaScript. | |
281 * | |
282 * fclose expects 1 parameter: | |
283 * 0: The index of the file (which is mapped to a FILE*) | |
284 * on success, fclose returns a result in |output| separated by \1: | |
285 * 0: "fclose" | |
286 * 1: the file index | |
287 * on failure, fclose returns an error string in |output|. | |
288 * | |
289 * @param[in] num_params The number of params in |params|. | |
290 * @param[in] params An array of strings, parameters to this function. | |
291 * @param[out] output A string to write informational function output to. | |
292 * @return An errorcode; 0 means success, anything else is a failure. */ | |
293 int HandleFclose(int num_params, char** params, char** output) { | |
294 FILE* file; | |
295 int file_index; | |
296 const char* file_index_string; | |
297 int result; | |
298 | |
299 if (num_params != 1) { | |
300 *output = PrintfToNewString("Error: fclose takes 1 parameters."); | |
301 return 1; | |
302 } | |
303 | |
304 file_index_string = params[0]; | |
305 file = GetFileFromIndexString(file_index_string, &file_index); | |
306 if (!file) { | |
307 *output = PrintfToNewString("Error: Unknown file handle %s.", | |
308 file_index_string); | |
309 return 2; | |
310 } | |
311 | |
312 result = fclose(file); | |
313 if (result) { | |
314 *output = PrintfToNewString("Error: fclose returned error %d.", result); | |
315 return 3; | |
316 } | |
317 | |
318 RemoveFileFromMap(file_index); | |
319 | |
320 *output = PrintfToNewString("fclose\1%s", file_index_string); | |
321 return 0; | |
322 } | |
OLD | NEW |