diff options
Diffstat (limited to 'uisimulator/common/io.c')
-rw-r--r-- | uisimulator/common/io.c | 729 |
1 files changed, 0 insertions, 729 deletions
diff --git a/uisimulator/common/io.c b/uisimulator/common/io.c deleted file mode 100644 index 6662e9ffda..0000000000 --- a/uisimulator/common/io.c +++ /dev/null | |||
@@ -1,729 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 Daniel Stenberg | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <stdio.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <string.h> | ||
25 | #include <stdarg.h> | ||
26 | #include <sys/stat.h> | ||
27 | #include <time.h> | ||
28 | #include <errno.h> | ||
29 | #include "config.h" | ||
30 | #include "system.h" | ||
31 | #include "ata_idle_notify.h" | ||
32 | #include "mv.h" | ||
33 | |||
34 | #define HAVE_STATVFS (!defined(WIN32)) | ||
35 | #define HAVE_LSTAT (!defined(WIN32)) | ||
36 | |||
37 | #if HAVE_STATVFS | ||
38 | #include <sys/statvfs.h> | ||
39 | #endif | ||
40 | |||
41 | #ifdef WIN32 | ||
42 | #include <windows.h> | ||
43 | #endif | ||
44 | |||
45 | #ifndef _MSC_VER | ||
46 | #include <dirent.h> | ||
47 | #include <unistd.h> | ||
48 | #else | ||
49 | #include "dir-win32.h" | ||
50 | #endif | ||
51 | |||
52 | #include <fcntl.h> | ||
53 | #ifdef HAVE_SDL_THREADS | ||
54 | #include "thread-sdl.h" | ||
55 | #else | ||
56 | #define sim_thread_unlock() NULL | ||
57 | #define sim_thread_lock(a) | ||
58 | #endif | ||
59 | #include "thread.h" | ||
60 | #include "kernel.h" | ||
61 | #include "debug.h" | ||
62 | #include "ata.h" /* for IF_MV et al. */ | ||
63 | #include "rbpaths.h" | ||
64 | #include "load_code.h" | ||
65 | |||
66 | /* keep this in sync with file.h! */ | ||
67 | #undef MAX_PATH /* this avoids problems when building simulator */ | ||
68 | #define MAX_PATH 260 | ||
69 | #define MAX_OPEN_FILES 11 | ||
70 | |||
71 | /* Windows (and potentially other OSes) distinguish binary and text files. | ||
72 | * Define a dummy for the others. */ | ||
73 | #ifndef O_BINARY | ||
74 | #define O_BINARY 0 | ||
75 | #endif | ||
76 | |||
77 | /* Unicode compatibility for win32 */ | ||
78 | #if defined __MINGW32__ | ||
79 | /* Rockbox unicode functions */ | ||
80 | extern const unsigned char* utf8decode(const unsigned char *utf8, | ||
81 | unsigned short *ucs); | ||
82 | extern unsigned char* utf8encode(unsigned long ucs, unsigned char *utf8); | ||
83 | |||
84 | /* Static buffers for the conversion results. This isn't thread safe, | ||
85 | * but it's sufficient for rockbox. */ | ||
86 | static unsigned char convbuf1[3*MAX_PATH]; | ||
87 | static unsigned char convbuf2[3*MAX_PATH]; | ||
88 | |||
89 | static wchar_t* utf8_to_ucs2(const unsigned char *utf8, void *buffer) | ||
90 | { | ||
91 | wchar_t *ucs = buffer; | ||
92 | |||
93 | while (*utf8) | ||
94 | utf8 = utf8decode(utf8, ucs++); | ||
95 | |||
96 | *ucs = 0; | ||
97 | return buffer; | ||
98 | } | ||
99 | static unsigned char *ucs2_to_utf8(const wchar_t *ucs, unsigned char *buffer) | ||
100 | { | ||
101 | unsigned char *utf8 = buffer; | ||
102 | |||
103 | while (*ucs) | ||
104 | utf8 = utf8encode(*ucs++, utf8); | ||
105 | |||
106 | *utf8 = 0; | ||
107 | return buffer; | ||
108 | } | ||
109 | |||
110 | #define UTF8_TO_OS(a) utf8_to_ucs2(a,convbuf1) | ||
111 | #define OS_TO_UTF8(a) ucs2_to_utf8(a,convbuf1) | ||
112 | #define DIR_T _WDIR | ||
113 | #define DIRENT_T struct _wdirent | ||
114 | #define STAT_T struct _stat | ||
115 | extern int _wmkdir(const wchar_t*); | ||
116 | extern int _wrmdir(const wchar_t*); | ||
117 | #define MKDIR(a,b) (_wmkdir)(UTF8_TO_OS(a)) | ||
118 | #define RMDIR(a) (_wrmdir)(UTF8_TO_OS(a)) | ||
119 | #define OPENDIR(a) (_wopendir)(UTF8_TO_OS(a)) | ||
120 | #define READDIR(a) (_wreaddir)(a) | ||
121 | #define CLOSEDIR(a) (_wclosedir)(a) | ||
122 | #define STAT(a,b) (_wstat)(UTF8_TO_OS(a),b) | ||
123 | /* empty variable parameter list doesn't work for variadic macros, | ||
124 | * so pretend the second parameter is variable too */ | ||
125 | #define OPEN(a,...) (_wopen)(UTF8_TO_OS(a), __VA_ARGS__) | ||
126 | #define CLOSE(a) (close)(a) | ||
127 | #define REMOVE(a) (_wremove)(UTF8_TO_OS(a)) | ||
128 | #define RENAME(a,b) (_wrename)(UTF8_TO_OS(a),utf8_to_ucs2(b,convbuf2)) | ||
129 | /* readlink isn't used in the sim yet (FIXME) */ | ||
130 | #define READLINK(a,b,c) ({ fprintf(stderr, "no readlink on windows yet"); abort(); }) | ||
131 | #else /* !__MINGW32__ */ | ||
132 | |||
133 | #define UTF8_TO_OS(a) (a) | ||
134 | #define OS_TO_UTF8(a) (a) | ||
135 | #define DIR_T DIR | ||
136 | #define DIRENT_T struct dirent | ||
137 | #define STAT_T struct stat | ||
138 | #define MKDIR(a,b) (mkdir)(a,b) | ||
139 | #define RMDIR(a) (rmdir)(a) | ||
140 | #define OPENDIR(a) (opendir)(a) | ||
141 | #define READDIR(a) (readdir)(a) | ||
142 | #define CLOSEDIR(a) (closedir)(a) | ||
143 | #define STAT(a,b) (stat)(a,b) | ||
144 | /* empty variable parameter list doesn't work for variadic macros, | ||
145 | * so pretend the second parameter is variable too */ | ||
146 | #define OPEN(a, ...) (open)(a, __VA_ARGS__) | ||
147 | #define CLOSE(x) (close)(x) | ||
148 | #define REMOVE(a) (remove)(a) | ||
149 | #define RENAME(a,b) (rename)(a,b) | ||
150 | #define READLINK(a,b,c) (readlink)(a,b,c) | ||
151 | |||
152 | #endif /* !__MINGW32__ */ | ||
153 | |||
154 | |||
155 | #ifdef HAVE_DIRCACHE | ||
156 | int dircache_get_entry_id(const char *filename); | ||
157 | void dircache_add_file(const char *name, long startcluster); | ||
158 | void dircache_remove(const char *name); | ||
159 | void dircache_rename(const char *oldname, const char *newname); | ||
160 | #endif | ||
161 | |||
162 | #ifndef APPLICATION | ||
163 | |||
164 | #define SIMULATOR_DEFAULT_ROOT "simdisk" | ||
165 | extern const char *sim_root_dir; | ||
166 | |||
167 | static int num_openfiles = 0; | ||
168 | |||
169 | /* from dir.h */ | ||
170 | struct dirinfo { | ||
171 | int attribute; | ||
172 | long size; | ||
173 | unsigned short wrtdate; | ||
174 | unsigned short wrttime; | ||
175 | }; | ||
176 | |||
177 | struct sim_dirent { | ||
178 | unsigned char d_name[MAX_PATH]; | ||
179 | struct dirinfo info; | ||
180 | long startcluster; | ||
181 | }; | ||
182 | |||
183 | struct dirstruct { | ||
184 | void *dir; /* actually a DIR* dir */ | ||
185 | char *name; | ||
186 | } SIM_DIR; | ||
187 | |||
188 | struct mydir { | ||
189 | DIR_T *dir; | ||
190 | IF_MV(int volumes_returned); | ||
191 | char *name; | ||
192 | }; | ||
193 | |||
194 | typedef struct mydir MYDIR; | ||
195 | |||
196 | static unsigned int rockbox2sim(int opt) | ||
197 | { | ||
198 | #if 0 | ||
199 | /* this shouldn't be needed since we use the host's versions */ | ||
200 | int newopt = O_BINARY; | ||
201 | |||
202 | if(opt & 1) | ||
203 | newopt |= O_WRONLY; | ||
204 | if(opt & 2) | ||
205 | newopt |= O_RDWR; | ||
206 | if(opt & 4) | ||
207 | newopt |= O_CREAT; | ||
208 | if(opt & 8) | ||
209 | newopt |= O_APPEND; | ||
210 | if(opt & 0x10) | ||
211 | newopt |= O_TRUNC; | ||
212 | |||
213 | return newopt; | ||
214 | #else | ||
215 | return opt|O_BINARY; | ||
216 | #endif | ||
217 | } | ||
218 | |||
219 | #endif /* APPLICATION */ | ||
220 | |||
221 | /** Simulator I/O engine routines **/ | ||
222 | #define IO_YIELD_THRESHOLD 512 | ||
223 | |||
224 | enum io_dir | ||
225 | { | ||
226 | IO_READ, | ||
227 | IO_WRITE, | ||
228 | }; | ||
229 | |||
230 | struct sim_io | ||
231 | { | ||
232 | struct mutex sim_mutex; /* Rockbox mutex */ | ||
233 | int cmd; /* The command to perform */ | ||
234 | int ready; /* I/O ready flag - 1= ready */ | ||
235 | int fd; /* The file to read/write */ | ||
236 | void *buf; /* The buffer to read/write */ | ||
237 | size_t count; /* Number of bytes to read/write */ | ||
238 | size_t accum; /* Acculated bytes transferred */ | ||
239 | }; | ||
240 | |||
241 | static struct sim_io io; | ||
242 | |||
243 | int ata_init(void) | ||
244 | { | ||
245 | /* Initialize the rockbox kernel objects on a rockbox thread */ | ||
246 | mutex_init(&io.sim_mutex); | ||
247 | io.accum = 0; | ||
248 | return 1; | ||
249 | } | ||
250 | |||
251 | int ata_spinup_time(void) | ||
252 | { | ||
253 | return HZ; | ||
254 | } | ||
255 | |||
256 | static ssize_t io_trigger_and_wait(enum io_dir cmd) | ||
257 | { | ||
258 | void *mythread = NULL; | ||
259 | ssize_t result; | ||
260 | |||
261 | if (io.count > IO_YIELD_THRESHOLD || | ||
262 | (io.accum += io.count) >= IO_YIELD_THRESHOLD) | ||
263 | { | ||
264 | /* Allow other rockbox threads to run */ | ||
265 | io.accum = 0; | ||
266 | mythread = sim_thread_unlock(); | ||
267 | } | ||
268 | |||
269 | switch (cmd) | ||
270 | { | ||
271 | case IO_READ: | ||
272 | result = read(io.fd, io.buf, io.count); | ||
273 | break; | ||
274 | case IO_WRITE: | ||
275 | result = write(io.fd, io.buf, io.count); | ||
276 | break; | ||
277 | /* shut up gcc */ | ||
278 | default: | ||
279 | result = -1; | ||
280 | } | ||
281 | |||
282 | call_storage_idle_notifys(false); | ||
283 | |||
284 | /* Regain our status as current */ | ||
285 | if (mythread != NULL) | ||
286 | { | ||
287 | sim_thread_lock(mythread); | ||
288 | } | ||
289 | |||
290 | return result; | ||
291 | } | ||
292 | |||
293 | |||
294 | ssize_t sim_read(int fd, void *buf, size_t count) | ||
295 | { | ||
296 | ssize_t result; | ||
297 | |||
298 | mutex_lock(&io.sim_mutex); | ||
299 | |||
300 | /* Setup parameters */ | ||
301 | io.fd = fd; | ||
302 | io.buf = buf; | ||
303 | io.count = count; | ||
304 | |||
305 | result = io_trigger_and_wait(IO_READ); | ||
306 | |||
307 | mutex_unlock(&io.sim_mutex); | ||
308 | |||
309 | return result; | ||
310 | } | ||
311 | |||
312 | |||
313 | ssize_t sim_write(int fd, const void *buf, size_t count) | ||
314 | { | ||
315 | ssize_t result; | ||
316 | |||
317 | mutex_lock(&io.sim_mutex); | ||
318 | |||
319 | io.fd = fd; | ||
320 | io.buf = (void*)buf; | ||
321 | io.count = count; | ||
322 | |||
323 | result = io_trigger_and_wait(IO_WRITE); | ||
324 | |||
325 | mutex_unlock(&io.sim_mutex); | ||
326 | |||
327 | return result; | ||
328 | } | ||
329 | |||
330 | #if !defined(APPLICATION) | ||
331 | |||
332 | static const char *handle_special_links(const char* link) | ||
333 | { | ||
334 | #ifdef HAVE_MULTIDRIVE | ||
335 | static char buffer[MAX_PATH]; /* sufficiently big */ | ||
336 | char vol_string[VOL_ENUM_POS + 8]; | ||
337 | int len = sprintf(vol_string, VOL_NAMES, 1); | ||
338 | |||
339 | /* link might be passed with or without HOME_DIR expanded. To handle | ||
340 | * both perform substring matching (VOL_NAMES is unique enough) */ | ||
341 | const char *begin = strstr(link, vol_string); | ||
342 | if (begin) | ||
343 | { | ||
344 | /* begin now points to the start of vol_string within link, | ||
345 | * we want to copy the remainder of the paths, prefixed by | ||
346 | * the actual mount point (the remainder might be "") */ | ||
347 | snprintf(buffer, sizeof(buffer), "%s/../simext/%s", | ||
348 | sim_root_dir ?: SIMULATOR_DEFAULT_ROOT, begin + len); | ||
349 | return buffer; | ||
350 | } | ||
351 | else | ||
352 | #endif | ||
353 | return link; | ||
354 | } | ||
355 | |||
356 | |||
357 | static const char *get_sim_pathname(const char *name) | ||
358 | { | ||
359 | static char buffer[MAX_PATH]; /* sufficiently big */ | ||
360 | |||
361 | if(name[0] == '/') | ||
362 | { | ||
363 | snprintf(buffer, sizeof(buffer), "%s%s", | ||
364 | sim_root_dir ?: SIMULATOR_DEFAULT_ROOT, name); | ||
365 | return handle_special_links(buffer); | ||
366 | } | ||
367 | fprintf(stderr, "WARNING, bad file name lacks slash: %s\n", name); | ||
368 | return name; | ||
369 | } | ||
370 | |||
371 | |||
372 | MYDIR *sim_opendir(const char *name) | ||
373 | { | ||
374 | DIR_T *dir; | ||
375 | dir = (DIR_T *) OPENDIR(get_sim_pathname(name)); | ||
376 | |||
377 | if (dir) | ||
378 | { | ||
379 | MYDIR *my = (MYDIR *)malloc(sizeof(MYDIR)); | ||
380 | my->dir = dir; | ||
381 | my->name = (char *)malloc(strlen(name)+1); | ||
382 | strcpy(my->name, name); | ||
383 | IF_MV(my->volumes_returned = 0); | ||
384 | |||
385 | return my; | ||
386 | } | ||
387 | /* failed open, return NULL */ | ||
388 | return (MYDIR *)0; | ||
389 | } | ||
390 | |||
391 | #if defined(WIN32) | ||
392 | static inline struct tm* localtime_r (const time_t *clock, struct tm *result) { | ||
393 | if (!clock || !result) return NULL; | ||
394 | memcpy(result,localtime(clock),sizeof(*result)); | ||
395 | return result; | ||
396 | } | ||
397 | #endif | ||
398 | |||
399 | struct sim_dirent *sim_readdir(MYDIR *dir) | ||
400 | { | ||
401 | char buffer[MAX_PATH]; /* sufficiently big */ | ||
402 | static struct sim_dirent secret; | ||
403 | STAT_T s; | ||
404 | struct tm tm; | ||
405 | DIRENT_T *x11; | ||
406 | |||
407 | #ifdef EOVERFLOW | ||
408 | read_next: | ||
409 | #endif | ||
410 | |||
411 | #define ATTR_LINK 0x80 /* see dir.h */ | ||
412 | |||
413 | secret.info.attribute = 0; | ||
414 | #ifdef HAVE_MULTIVOLUME | ||
415 | if (dir->name[0] == '/' && dir->name[1] == '\0' | ||
416 | && dir->volumes_returned++ < (NUM_VOLUMES-1) | ||
417 | && volume_present(dir->volumes_returned)) | ||
418 | { | ||
419 | sprintf((char *)secret.d_name, VOL_NAMES, dir->volumes_returned); | ||
420 | secret.info.attribute = ATTR_LINK; | ||
421 | /* build file name for stat() which is the actual mount point */ | ||
422 | snprintf(buffer, sizeof(buffer), "%s/../simext", | ||
423 | sim_root_dir ?: SIMULATOR_DEFAULT_ROOT); | ||
424 | } | ||
425 | else | ||
426 | #endif | ||
427 | { | ||
428 | x11 = READDIR(dir->dir); | ||
429 | |||
430 | if(!x11) | ||
431 | return (struct sim_dirent *)0; | ||
432 | |||
433 | strcpy((char *)secret.d_name, OS_TO_UTF8(x11->d_name)); | ||
434 | /* build file name for stat() */ | ||
435 | snprintf(buffer, sizeof(buffer), "%s/%s", | ||
436 | get_sim_pathname(dir->name), secret.d_name); | ||
437 | } | ||
438 | |||
439 | if (STAT(buffer, &s)) /* get info */ | ||
440 | { | ||
441 | #ifdef EOVERFLOW | ||
442 | /* File size larger than 2 GB? */ | ||
443 | if (errno == EOVERFLOW) | ||
444 | { | ||
445 | DEBUGF("stat() overflow for %s. Skipping\n", buffer); | ||
446 | goto read_next; | ||
447 | } | ||
448 | #endif | ||
449 | |||
450 | return NULL; | ||
451 | } | ||
452 | |||
453 | #define ATTR_DIRECTORY 0x10 | ||
454 | |||
455 | if (S_ISDIR(s.st_mode)) | ||
456 | secret.info.attribute = ATTR_DIRECTORY; | ||
457 | |||
458 | secret.info.size = s.st_size; | ||
459 | |||
460 | if (localtime_r(&(s.st_mtime), &tm) == NULL) | ||
461 | return NULL; | ||
462 | secret.info.wrtdate = ((tm.tm_year - 80) << 9) | | ||
463 | ((tm.tm_mon + 1) << 5) | | ||
464 | tm.tm_mday; | ||
465 | secret.info.wrttime = (tm.tm_hour << 11) | | ||
466 | (tm.tm_min << 5) | | ||
467 | (tm.tm_sec >> 1); | ||
468 | |||
469 | #if HAVE_LSTAT | ||
470 | if (!lstat(buffer, &s) && S_ISLNK(s.st_mode)) | ||
471 | { | ||
472 | secret.info.attribute |= ATTR_LINK; | ||
473 | } | ||
474 | #endif | ||
475 | |||
476 | return &secret; | ||
477 | } | ||
478 | |||
479 | void sim_closedir(MYDIR *dir) | ||
480 | { | ||
481 | free(dir->name); | ||
482 | CLOSEDIR(dir->dir); | ||
483 | |||
484 | free(dir); | ||
485 | } | ||
486 | |||
487 | int sim_open(const char *name, int o, ...) | ||
488 | { | ||
489 | int opts = rockbox2sim(o); | ||
490 | int ret; | ||
491 | if (num_openfiles >= MAX_OPEN_FILES) | ||
492 | return -2; | ||
493 | |||
494 | if (opts & O_CREAT) | ||
495 | { | ||
496 | va_list ap; | ||
497 | va_start(ap, o); | ||
498 | mode_t mode = va_arg(ap, unsigned int); | ||
499 | ret = OPEN(get_sim_pathname(name), opts, mode); | ||
500 | #ifdef HAVE_DIRCACHE | ||
501 | if (ret >= 0 && (dircache_get_entry_id(name) < 0)) | ||
502 | dircache_add_file(name, 0); | ||
503 | #endif | ||
504 | va_end(ap); | ||
505 | } | ||
506 | else | ||
507 | ret = OPEN(get_sim_pathname(name), opts); | ||
508 | |||
509 | if (ret >= 0) | ||
510 | num_openfiles++; | ||
511 | return ret; | ||
512 | } | ||
513 | |||
514 | int sim_close(int fd) | ||
515 | { | ||
516 | int ret; | ||
517 | ret = CLOSE(fd); | ||
518 | if (ret == 0) | ||
519 | num_openfiles--; | ||
520 | return ret; | ||
521 | } | ||
522 | |||
523 | int sim_creat(const char *name, mode_t mode) | ||
524 | { | ||
525 | int ret = OPEN(get_sim_pathname(name), | ||
526 | O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, mode); | ||
527 | #ifdef HAVE_DIRCACHE | ||
528 | if (ret >= 0 && (dircache_get_entry_id(name) < 0)) | ||
529 | dircache_add_file(name, 0); | ||
530 | #endif | ||
531 | return ret; | ||
532 | } | ||
533 | |||
534 | int sim_mkdir(const char *name) | ||
535 | { | ||
536 | return MKDIR(get_sim_pathname(name), 0777); | ||
537 | } | ||
538 | |||
539 | int sim_rmdir(const char *name) | ||
540 | { | ||
541 | return RMDIR(get_sim_pathname(name)); | ||
542 | } | ||
543 | |||
544 | int sim_remove(const char *name) | ||
545 | { | ||
546 | int ret = REMOVE(get_sim_pathname(name)); | ||
547 | #ifdef HAVE_DIRCACHE | ||
548 | if (ret >= 0) | ||
549 | dircache_remove(name); | ||
550 | #endif | ||
551 | return ret; | ||
552 | } | ||
553 | |||
554 | int sim_rename(const char *oldname, const char *newname) | ||
555 | { | ||
556 | char sim_old[MAX_PATH]; | ||
557 | char sim_new[MAX_PATH]; | ||
558 | #ifdef HAVE_DIRCACHE | ||
559 | dircache_rename(oldname, newname); | ||
560 | #endif | ||
561 | // This is needed as get_sim_pathname() has a static buffer | ||
562 | strncpy(sim_old, get_sim_pathname(oldname), MAX_PATH); | ||
563 | strncpy(sim_new, get_sim_pathname(newname), MAX_PATH); | ||
564 | return RENAME(sim_old, sim_new); | ||
565 | } | ||
566 | |||
567 | /* rockbox off_t may be different from system off_t */ | ||
568 | long sim_lseek(int fildes, long offset, int whence) | ||
569 | { | ||
570 | return lseek(fildes, offset, whence); | ||
571 | } | ||
572 | |||
573 | #else | ||
574 | #define get_sim_pathname(x) x | ||
575 | #endif | ||
576 | |||
577 | long filesize(int fd) | ||
578 | { | ||
579 | #ifdef WIN32 | ||
580 | return _filelength(fd); | ||
581 | #else | ||
582 | struct stat buf; | ||
583 | |||
584 | if (!fstat(fd, &buf)) | ||
585 | return buf.st_size; | ||
586 | else | ||
587 | return -1; | ||
588 | #endif | ||
589 | } | ||
590 | |||
591 | void fat_size(IF_MV(int volume,) unsigned long* size, unsigned long* free) | ||
592 | { | ||
593 | #ifdef HAVE_MULTIVOLUME | ||
594 | if (volume != 0) { | ||
595 | /* debugf("io.c: fat_size(volume=%d); simulator only supports volume 0\n",volume); */ | ||
596 | |||
597 | if (size) *size = 0; | ||
598 | if (free) *free = 0; | ||
599 | return; | ||
600 | } | ||
601 | #endif | ||
602 | |||
603 | #ifdef WIN32 | ||
604 | long secperclus, bytespersec, free_clusters, num_clusters; | ||
605 | |||
606 | if (GetDiskFreeSpace(NULL, &secperclus, &bytespersec, &free_clusters, | ||
607 | &num_clusters)) { | ||
608 | if (size) | ||
609 | *size = num_clusters * secperclus / 2 * (bytespersec / 512); | ||
610 | if (free) | ||
611 | *free = free_clusters * secperclus / 2 * (bytespersec / 512); | ||
612 | } else | ||
613 | #elif HAVE_STATVFS | ||
614 | struct statvfs vfs; | ||
615 | |||
616 | if (!statvfs(".", &vfs)) { | ||
617 | DEBUGF("statvfs: frsize=%d blocks=%ld free=%ld\n", | ||
618 | (int)vfs.f_frsize, (long)vfs.f_blocks, (long)vfs.f_bfree); | ||
619 | if (size) | ||
620 | *size = vfs.f_blocks / 2 * (vfs.f_frsize / 512); | ||
621 | if (free) | ||
622 | *free = vfs.f_bfree / 2 * (vfs.f_frsize / 512); | ||
623 | } else | ||
624 | #endif | ||
625 | { | ||
626 | if (size) | ||
627 | *size = 0; | ||
628 | if (free) | ||
629 | *free = 0; | ||
630 | } | ||
631 | } | ||
632 | |||
633 | int sim_fsync(int fd) | ||
634 | { | ||
635 | #ifdef WIN32 | ||
636 | return _commit(fd); | ||
637 | #else | ||
638 | return fsync(fd); | ||
639 | #endif | ||
640 | } | ||
641 | |||
642 | #ifndef __PCTOOL__ | ||
643 | |||
644 | #include <SDL_loadso.h> | ||
645 | void *lc_open(const char *filename, unsigned char *buf, size_t buf_size) | ||
646 | { | ||
647 | (void)buf; | ||
648 | (void)buf_size; | ||
649 | void *handle = SDL_LoadObject(get_sim_pathname(filename)); | ||
650 | if (handle == NULL) | ||
651 | { | ||
652 | DEBUGF("failed to load %s\n", filename); | ||
653 | DEBUGF("lc_open(%s): %s\n", filename, SDL_GetError()); | ||
654 | } | ||
655 | return handle; | ||
656 | } | ||
657 | |||
658 | void *lc_get_header(void *handle) | ||
659 | { | ||
660 | char *ret = SDL_LoadFunction(handle, "__header"); | ||
661 | if (ret == NULL) | ||
662 | ret = SDL_LoadFunction(handle, "___header"); | ||
663 | |||
664 | return ret; | ||
665 | } | ||
666 | |||
667 | void lc_close(void *handle) | ||
668 | { | ||
669 | SDL_UnloadObject(handle); | ||
670 | } | ||
671 | |||
672 | void *lc_open_from_mem(void *addr, size_t blob_size) | ||
673 | { | ||
674 | #ifndef SIMULATOR | ||
675 | (void)addr; | ||
676 | (void)blob_size; | ||
677 | /* we don't support loading code from memory on application builds, | ||
678 | * it doesn't make sense (since it means writing the blob to disk again and | ||
679 | * then falling back to load from disk) and requires the ability to write | ||
680 | * to an executable directory */ | ||
681 | return NULL; | ||
682 | #else | ||
683 | /* support it in the sim for the sake of simulating */ | ||
684 | int fd, i; | ||
685 | char temp_filename[MAX_PATH]; | ||
686 | |||
687 | /* We have to create the dynamic link library file from ram so we | ||
688 | can simulate the codec loading. With voice and crossfade, | ||
689 | multiple codecs may be loaded at the same time, so we need | ||
690 | to find an unused filename */ | ||
691 | for (i = 0; i < 10; i++) | ||
692 | { | ||
693 | snprintf(temp_filename, sizeof(temp_filename), | ||
694 | ROCKBOX_DIR "/libtemp_binary_%d.dll", i); | ||
695 | fd = open(temp_filename, O_WRONLY|O_CREAT|O_TRUNC, 0700); | ||
696 | if (fd >= 0) | ||
697 | break; /* Created a file ok */ | ||
698 | } | ||
699 | |||
700 | if (fd < 0) | ||
701 | { | ||
702 | DEBUGF("open failed\n"); | ||
703 | return NULL; | ||
704 | } | ||
705 | |||
706 | if (write(fd, addr, blob_size) < (ssize_t)blob_size) | ||
707 | { | ||
708 | DEBUGF("Write failed\n"); | ||
709 | close(fd); | ||
710 | remove(temp_filename); | ||
711 | return NULL; | ||
712 | } | ||
713 | |||
714 | close(fd); | ||
715 | return lc_open(temp_filename, NULL, 0); | ||
716 | #endif | ||
717 | } | ||
718 | |||
719 | #endif /* __PCTOOL__ */ | ||
720 | |||
721 | /* rockbox off_t may be different from system off_t */ | ||
722 | int sim_ftruncate(int fd, long length) | ||
723 | { | ||
724 | #ifdef WIN32 | ||
725 | return _chsize(fd, length); | ||
726 | #else | ||
727 | return ftruncate(fd, length); | ||
728 | #endif | ||
729 | } | ||