blob: 73eda239ffe6c6b8a78b689b0b0688b28ab06503 [file] [log] [blame]
Björn Stenberg32125d42002-05-13 15:23:30 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Daniel Stenberg
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +000019
Daniel Stenberged6c7e42002-06-14 11:00:13 +000020#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
Daniel Stenberg22b77012005-02-22 12:19:12 +000023#include <stdarg.h>
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +000024#include <sys/stat.h>
Peter D'Hoyef0ed5942007-04-06 23:54:21 +000025#include <time.h>
Björn Stenbergf6ed9702003-07-04 08:30:01 +000026#ifdef __FreeBSD__
27#include <sys/param.h>
28#include <sys/mount.h>
Barry Wardell64f949f2006-09-29 16:15:11 +000029#elif defined(__APPLE__)
30#include <sys/param.h>
31#include <sys/mount.h>
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +000032#elif !defined(WIN32)
Björn Stenberg6fb512a2002-11-12 11:32:26 +000033#include <sys/vfs.h>
Björn Stenbergf6ed9702003-07-04 08:30:01 +000034#endif
Hardeep Sidhufb26bfb2004-06-14 07:00:50 +000035
Daniel Stenberg22b77012005-02-22 12:19:12 +000036#ifdef WIN32
37#include <windows.h>
38#endif
39
Hardeep Sidhufb26bfb2004-06-14 07:00:50 +000040#ifndef _MSC_VER
Daniel Stenberge3a12d32002-05-07 12:25:30 +000041#include <dirent.h>
Björn Stenberg2ba4fed2003-01-28 23:14:41 +000042#include <unistd.h>
Hardeep Sidhufb26bfb2004-06-14 07:00:50 +000043#else
44#include "dir-win32.h"
45#endif
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +000046
Daniel Stenberg22b77012005-02-22 12:19:12 +000047#define MAX_PATH 260
48
Daniel Stenberged6c7e42002-06-14 11:00:13 +000049#include <fcntl.h>
Michael Sevakisf64ebb12007-09-08 12:20:53 +000050#include <SDL.h>
51#include <SDL_thread.h>
52#include "thread.h"
53#include "kernel.h"
Daniel Stenberged6c7e42002-06-14 11:00:13 +000054#include "debug.h"
Miika Pekkarinend70bd0e2006-08-26 14:19:18 +000055#include "config.h"
Jens Arnold51280802007-09-13 20:53:32 +000056#include "ata.h" /* for IF_MV2 et al. */
Miika Pekkarinend70bd0e2006-08-26 14:19:18 +000057
Jens Arnold67eb1542007-02-01 23:08:15 +000058/* Windows (and potentially other OSes) distinguish binary and text files.
59 * Define a dummy for the others. */
60#ifndef O_BINARY
61#define O_BINARY 0
62#endif
63
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000064/* Unicode compatibility for win32 */
65#if defined __MINGW32__
66/* Rockbox unicode functions */
67extern const unsigned char* utf8decode(const unsigned char *utf8,
68 unsigned short *ucs);
69extern unsigned char* utf8encode(unsigned long ucs, unsigned char *utf8);
70
Jens Arnold49be3fa2007-04-20 17:35:05 +000071/* Static buffers for the conversion results. This isn't thread safe,
72 * but it's sufficient for rockbox. */
73static unsigned char convbuf1[3*MAX_PATH];
74static unsigned char convbuf2[3*MAX_PATH];
75
76static wchar_t* utf8_to_ucs2(const unsigned char *utf8, void *buffer)
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000077{
Jens Arnold49be3fa2007-04-20 17:35:05 +000078 wchar_t *ucs = buffer;
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000079
80 while (*utf8)
81 utf8 = utf8decode(utf8, ucs++);
82
83 *ucs = 0;
Jens Arnold49be3fa2007-04-20 17:35:05 +000084 return buffer;
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000085}
Jens Arnold49be3fa2007-04-20 17:35:05 +000086static unsigned char *ucs2_to_utf8(const wchar_t *ucs, unsigned char *buffer)
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000087{
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000088 unsigned char *utf8 = buffer;
Jens Arnold49be3fa2007-04-20 17:35:05 +000089
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000090 while (*ucs)
91 utf8 = utf8encode(*ucs++, utf8);
92
93 *utf8 = 0;
94 return buffer;
95}
96
Jens Arnold49be3fa2007-04-20 17:35:05 +000097#define UTF8_TO_OS(a) utf8_to_ucs2(a,convbuf1)
98#define OS_TO_UTF8(a) ucs2_to_utf8(a,convbuf1)
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000099#define DIR_T _WDIR
100#define DIRENT_T struct _wdirent
101#define STAT_T struct _stat
102extern int _wmkdir(const wchar_t*);
103extern int _wrmdir(const wchar_t*);
104#define MKDIR(a,b) (_wmkdir)(UTF8_TO_OS(a))
105#define RMDIR(a) (_wrmdir)(UTF8_TO_OS(a))
106#define OPENDIR(a) (_wopendir)(UTF8_TO_OS(a))
107#define READDIR(a) (_wreaddir)(a)
108#define CLOSEDIR(a) (_wclosedir)(a)
109#define STAT(a,b) (_wstat)(UTF8_TO_OS(a),b)
110#define OPEN(a,b,c) (_wopen)(UTF8_TO_OS(a),b,c)
111#define REMOVE(a) (_wremove)(UTF8_TO_OS(a))
Jens Arnold49be3fa2007-04-20 17:35:05 +0000112#define RENAME(a,b) (_wrename)(UTF8_TO_OS(a),utf8_to_ucs2(b,convbuf2))
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000113
114#else /* !__MINGW32__ */
115
116#define UTF8_TO_OS(a) (a)
117#define OS_TO_UTF8(a) (a)
118#define DIR_T DIR
119#define DIRENT_T struct dirent
120#define STAT_T struct stat
121#define MKDIR(a,b) (mkdir)(a,b)
122#define RMDIR(a) (rmdir)(a)
123#define OPENDIR(a) (opendir)(a)
124#define READDIR(a) (readdir)(a)
125#define CLOSEDIR(a) (closedir)(a)
126#define STAT(a,b) (stat)(a,b)
127#define OPEN(a,b,c) (open)(a,b,c)
128#define REMOVE(a) (remove)(a)
129#define RENAME(a,b) (rename)(a,b)
130
131#endif /* !__MINGW32__ */
132
133
Miika Pekkarinend70bd0e2006-08-26 14:19:18 +0000134#ifdef HAVE_DIRCACHE
135void dircache_remove(const char *name);
136void dircache_rename(const char *oldpath, const char *newpath);
137#endif
Daniel Stenberged6c7e42002-06-14 11:00:13 +0000138
Daniel Stenberge3a12d32002-05-07 12:25:30 +0000139#define SIMULATOR_ARCHOS_ROOT "archos"
140
Daniel Stenberg22b77012005-02-22 12:19:12 +0000141struct sim_dirent {
142 unsigned char d_name[MAX_PATH];
143 int attribute;
Jens Arnoldd6cb7162007-04-07 00:14:16 +0000144 long size;
145 long startcluster;
Daniel Stenberg22b77012005-02-22 12:19:12 +0000146 unsigned short wrtdate; /* Last write date */
147 unsigned short wrttime; /* Last write time */
148};
149
150struct dirstruct {
151 void *dir; /* actually a DIR* dir */
152 char *name;
153} SIM_DIR;
154
Daniel Stenberge3a12d32002-05-07 12:25:30 +0000155struct mydir {
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000156 DIR_T *dir;
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000157 char *name;
Daniel Stenberge3a12d32002-05-07 12:25:30 +0000158};
159
160typedef struct mydir MYDIR;
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +0000161
Jens Arnold527e1212005-02-24 23:11:21 +0000162#if 1 /* maybe this needs disabling for MSVC... */
Daniel Stenberg36c9a952004-06-14 22:22:49 +0000163static unsigned int rockbox2sim(int opt)
164{
Linus Nielsen Feltzingfc72c532006-02-03 15:19:58 +0000165 int newopt = O_BINARY;
Jens Arnold67eb1542007-02-01 23:08:15 +0000166
Daniel Stenberg36c9a952004-06-14 22:22:49 +0000167 if(opt & 1)
168 newopt |= O_WRONLY;
169 if(opt & 2)
170 newopt |= O_RDWR;
171 if(opt & 4)
172 newopt |= O_CREAT;
173 if(opt & 8)
174 newopt |= O_APPEND;
175 if(opt & 0x10)
176 newopt |= O_TRUNC;
177
178 return newopt;
179}
Linus Nielsen Feltzingb6f67a82004-07-08 05:50:20 +0000180#endif
Daniel Stenberg36c9a952004-06-14 22:22:49 +0000181
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000182/** Simulator I/O engine routines **/
183enum
184{
185 IO_QUIT = -1,
186 IO_OPEN,
187 IO_CLOSE,
188 IO_READ,
189 IO_WRITE,
190};
191
192struct sim_io
193{
194 SDL_mutex *m; /* Mutex for condition */
195 SDL_cond *c; /* Condition for synchronizing threads */
196 SDL_Thread *t; /* The I/O thread */
197 struct mutex sim_mutex; /* Rockbox mutex */
198 volatile int cmd; /* The command to perform */
199 volatile int ready; /* I/O ready flag - 1= ready */
200 volatile int fd; /* The file to read/write */
201 void* volatile buf; /* The buffer to read/write */
202 volatile size_t count; /* Number of bytes to read/write */
203 ssize_t result; /* Result of operation */
204};
205
206static struct sim_io io;
207
208static int io_thread(void *data)
209{
210 SDL_LockMutex(io.m);
211
212 io.ready = 1; /* Indication mutex has been locked */
213
214 for (;;)
215 {
216 SDL_CondWait(io.c, io.m); /* unlock mutex and wait */
217
218 switch (io.cmd)
219 {
220 case IO_READ:
221 io.result = read(io.fd, io.buf, io.count);
222 io.ready = 1;
223 break;
224 case IO_WRITE:
225 io.result = write(io.fd, io.buf, io.count);
226 io.ready = 1;
227 break;
228 case IO_QUIT:
229 SDL_UnlockMutex(io.m);
230 return 0;
231 }
232 }
233
234 (void)data;
235}
236
Michael Sevakisc4a76312007-09-10 03:49:12 +0000237bool sim_io_init(void)
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000238{
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000239 io.ready = 0;
240
241 io.m = SDL_CreateMutex();
242 if (io.m == NULL)
243 {
244 fprintf(stderr, "Failed to create IO mutex\n");
Michael Sevakisc4a76312007-09-10 03:49:12 +0000245 return false;
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000246 }
247
248 io.c = SDL_CreateCond();
249 if (io.c == NULL)
250 {
251 fprintf(stderr, "Failed to create IO cond\n");
Michael Sevakisc4a76312007-09-10 03:49:12 +0000252 return false;
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000253 }
254
255 io.t = SDL_CreateThread(io_thread, NULL);
256 if (io.t == NULL)
257 {
258 fprintf(stderr, "Failed to create IO thread\n");
Michael Sevakisc4a76312007-09-10 03:49:12 +0000259 return false;
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000260 }
261
262 /* Wait for IO thread to lock mutex */
Michael Sevakis0107dfc2007-09-09 01:59:07 +0000263 while (!io.ready)
264 SDL_Delay(0);
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000265
266 /* Wait for it to unlock */
267 SDL_LockMutex(io.m);
268 /* Free it for another thread */
269 SDL_UnlockMutex(io.m);
Michael Sevakisc4a76312007-09-10 03:49:12 +0000270
271 return true;
272}
273
274int ata_init(void)
275{
276 /* Initialize the rockbox kernel objects on a rockbox thread */
277 mutex_init(&io.sim_mutex);
278 return 1;
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000279}
280
281void sim_io_shutdown(void)
282{
283 SDL_LockMutex(io.m);
284
285 io.cmd = IO_QUIT;
286
287 SDL_CondSignal(io.c);
288 SDL_UnlockMutex(io.m);
289
290 SDL_WaitThread(io.t, NULL);
291
292 SDL_DestroyMutex(io.m);
293 SDL_DestroyCond(io.c);
294}
295
296static void io_trigger_and_wait(int cmd)
297{
298 /* Lock mutex before setting up new params and signaling condition */
299 SDL_LockMutex(io.m);
300
301 io.cmd = cmd;
302 io.ready = 0;
303
304 /* Get thread started */
305 SDL_CondSignal(io.c);
306
307 /* Let it run */
308 SDL_UnlockMutex(io.m);
309
310 /* Wait for IO to complete */
311 while (!io.ready)
312 yield();
313}
314
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000315MYDIR *sim_opendir(const char *name)
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +0000316{
Peter D'Hoye6be61562007-04-12 22:38:54 +0000317 char buffer[MAX_PATH]; /* sufficiently big */
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000318 DIR_T *dir;
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +0000319
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000320#ifndef __PCTOOL__
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000321 if(name[0] == '/')
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000322 {
Peter D'Hoye6be61562007-04-12 22:38:54 +0000323 snprintf(buffer, sizeof(buffer), "%s%s", SIMULATOR_ARCHOS_ROOT, name);
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000324 dir=(DIR_T *)OPENDIR(buffer);
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000325 }
326 else
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000327#endif
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000328 dir=(DIR_T *)OPENDIR(name);
329
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000330 if(dir) {
331 MYDIR *my = (MYDIR *)malloc(sizeof(MYDIR));
332 my->dir = dir;
333 my->name = (char *)strdup(name);
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000334
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000335 return my;
336 }
337 /* failed open, return NULL */
338 return (MYDIR *)0;
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +0000339}
Daniel Stenberg91f165e2002-05-05 10:28:23 +0000340
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000341struct sim_dirent *sim_readdir(MYDIR *dir)
Daniel Stenberg159d4482002-05-07 11:35:03 +0000342{
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000343 char buffer[512]; /* sufficiently big */
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000344 static struct sim_dirent secret;
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000345 STAT_T s;
346 DIRENT_T *x11 = READDIR(dir->dir);
Peter D'Hoye832e0df2007-04-06 23:33:33 +0000347 struct tm* tm;
Daniel Stenberg159d4482002-05-07 11:35:03 +0000348
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000349 if(!x11)
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000350 return (struct sim_dirent *)0;
Daniel Stenberg159d4482002-05-07 11:35:03 +0000351
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000352 strcpy((char *)secret.d_name, OS_TO_UTF8(x11->d_name));
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000353
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000354 /* build file name */
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000355#ifdef __PCTOOL__
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000356 snprintf(buffer, sizeof(buffer), "%s/%s", dir->name, secret.d_name);
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000357#else
Peter D'Hoye6be61562007-04-12 22:38:54 +0000358 snprintf(buffer, sizeof(buffer), SIMULATOR_ARCHOS_ROOT "%s/%s",
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000359 dir->name, secret.d_name);
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000360#endif
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000361 STAT(buffer, &s); /* get info */
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000362
Daniel Stenberg22b77012005-02-22 12:19:12 +0000363#define ATTR_DIRECTORY 0x10
364
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000365 secret.attribute = S_ISDIR(s.st_mode)?ATTR_DIRECTORY:0;
366 secret.size = s.st_size;
Daniel Stenberg159d4482002-05-07 11:35:03 +0000367
Peter D'Hoye832e0df2007-04-06 23:33:33 +0000368 tm = localtime(&(s.st_mtime));
369 secret.wrtdate = ((tm->tm_year - 80) << 9) |
370 ((tm->tm_mon + 1) << 5) |
371 tm->tm_mday;
372 secret.wrttime = (tm->tm_hour << 11) |
373 (tm->tm_min << 5) |
374 (tm->tm_sec >> 1);
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000375 return &secret;
Daniel Stenberg159d4482002-05-07 11:35:03 +0000376}
377
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000378void sim_closedir(MYDIR *dir)
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000379{
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000380 free(dir->name);
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000381 CLOSEDIR(dir->dir);
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000382
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000383 free(dir);
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000384}
385
Daniel Stenberg36c9a952004-06-14 22:22:49 +0000386int sim_open(const char *name, int o)
Daniel Stenberg91f165e2002-05-05 10:28:23 +0000387{
Peter D'Hoye6be61562007-04-12 22:38:54 +0000388 char buffer[MAX_PATH]; /* sufficiently big */
Daniel Stenberg36c9a952004-06-14 22:22:49 +0000389 int opts = rockbox2sim(o);
Daniel Stenberg91f165e2002-05-05 10:28:23 +0000390
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000391#ifndef __PCTOOL__
392 if(name[0] == '/')
393 {
Peter D'Hoye6be61562007-04-12 22:38:54 +0000394 snprintf(buffer, sizeof(buffer), "%s%s", SIMULATOR_ARCHOS_ROOT, name);
Jens Arnold399c0812005-02-28 18:32:57 +0000395
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000396 debugf("We open the real file '%s'\n", buffer);
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000397 return OPEN(buffer, opts, 0666);
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000398 }
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000399
Daniel Stenberg56e63352004-06-14 22:32:13 +0000400 fprintf(stderr, "WARNING, bad file name lacks slash: %s\n",
401 name);
402 return -1;
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000403#else
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000404 return OPEN(name, opts, 0666);
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000405#endif
406
Daniel Stenberg91f165e2002-05-05 10:28:23 +0000407}
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000408
Jens Arnold67eb1542007-02-01 23:08:15 +0000409int sim_creat(const char *name)
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000410{
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000411#ifndef __PCTOOL__
Peter D'Hoye6be61562007-04-12 22:38:54 +0000412 char buffer[MAX_PATH]; /* sufficiently big */
Jens Arnold67eb1542007-02-01 23:08:15 +0000413 if(name[0] == '/')
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000414 {
Peter D'Hoye6be61562007-04-12 22:38:54 +0000415 snprintf(buffer, sizeof(buffer), "%s%s", SIMULATOR_ARCHOS_ROOT, name);
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000416
417 debugf("We create the real file '%s'\n", buffer);
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000418 return OPEN(buffer, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, 0666);
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000419 }
Peter D'Hoye6be61562007-04-12 22:38:54 +0000420 fprintf(stderr, "WARNING, bad file name lacks slash: %s\n", name);
Daniel Stenberg56e63352004-06-14 22:32:13 +0000421 return -1;
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000422#else
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000423 return OPEN(name, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, 0666);
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000424#endif
Jens Arnold399c0812005-02-28 18:32:57 +0000425}
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000426
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000427ssize_t sim_read(int fd, void *buf, size_t count)
428{
429 ssize_t result;
430
431 mutex_lock(&io.sim_mutex);
432
433 /* Setup parameters */
434 io.fd = fd;
435 io.buf = buf;
436 io.count = count;
437
438 io_trigger_and_wait(IO_READ);
439
440 result = io.result;
441
442 mutex_unlock(&io.sim_mutex);
443
444 return result;
445}
446
447ssize_t sim_write(int fd, const void *buf, size_t count)
448{
449 ssize_t result;
450
451 mutex_lock(&io.sim_mutex);
452
453 io.fd = fd;
454 io.buf = (void*)buf;
455 io.count = count;
456
457 io_trigger_and_wait(IO_WRITE);
458
459 result = io.result;
460
461 mutex_unlock(&io.sim_mutex);
462
463 return result;
464}
465
Jens Arnold6b0fdae2007-02-03 10:28:55 +0000466int sim_mkdir(const char *name)
Linus Nielsen Feltzingef7293f2004-01-21 14:58:40 +0000467{
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000468#ifdef __PCTOOL__
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000469 return MKDIR(name, 0777);
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000470#else
Peter D'Hoye6be61562007-04-12 22:38:54 +0000471 char buffer[MAX_PATH]; /* sufficiently big */
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000472
Peter D'Hoye6be61562007-04-12 22:38:54 +0000473 snprintf(buffer, sizeof(buffer), "%s%s", SIMULATOR_ARCHOS_ROOT, name);
474
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000475 debugf("We create the real directory '%s'\n", buffer);
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000476 return MKDIR(buffer, 0777);
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000477#endif
Linus Nielsen Feltzingef7293f2004-01-21 14:58:40 +0000478}
479
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000480int sim_rmdir(const char *name)
Linus Nielsen Feltzing8fa821d2004-04-16 09:24:38 +0000481{
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000482#ifdef __PCTOOL__
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000483 return RMDIR(name);
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000484#else
Peter D'Hoye6be61562007-04-12 22:38:54 +0000485 char buffer[MAX_PATH]; /* sufficiently big */
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000486 if(name[0] == '/')
487 {
Peter D'Hoye6be61562007-04-12 22:38:54 +0000488 snprintf(buffer, sizeof(buffer), "%s%s", SIMULATOR_ARCHOS_ROOT, name);
489
Linus Nielsen Feltzing8fa821d2004-04-16 09:24:38 +0000490 debugf("We remove the real directory '%s'\n", buffer);
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000491 return RMDIR(buffer);
Linus Nielsen Feltzing8fa821d2004-04-16 09:24:38 +0000492 }
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000493 return RMDIR(name);
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000494#endif
Linus Nielsen Feltzing8fa821d2004-04-16 09:24:38 +0000495}
496
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000497int sim_remove(const char *name)
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000498{
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000499#ifdef __PCTOOL__
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000500 return REMOVE(name);
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000501#else
Peter D'Hoye6be61562007-04-12 22:38:54 +0000502 char buffer[MAX_PATH]; /* sufficiently big */
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000503
Miika Pekkarinend70bd0e2006-08-26 14:19:18 +0000504#ifdef HAVE_DIRCACHE
505 dircache_remove(name);
506#endif
507
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000508 if(name[0] == '/') {
Peter D'Hoye6be61562007-04-12 22:38:54 +0000509 snprintf(buffer, sizeof(buffer), "%s%s", SIMULATOR_ARCHOS_ROOT, name);
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000510
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000511 debugf("We remove the real file '%s'\n", buffer);
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000512 return REMOVE(buffer);
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000513 }
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000514 return REMOVE(name);
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000515#endif
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000516}
517
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000518int sim_rename(const char *oldpath, const char* newpath)
Björn Stenberg7d80ba02003-01-15 11:38:03 +0000519{
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000520#ifdef __PCTOOL__
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000521 return RENAME(oldpath, newpath);
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000522#else
Peter D'Hoye6be61562007-04-12 22:38:54 +0000523 char buffer1[MAX_PATH];
524 char buffer2[MAX_PATH];
Björn Stenberg7d80ba02003-01-15 11:38:03 +0000525
Miika Pekkarinend70bd0e2006-08-26 14:19:18 +0000526#ifdef HAVE_DIRCACHE
527 dircache_rename(oldpath, newpath);
528#endif
529
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000530 if(oldpath[0] == '/') {
Peter D'Hoye6be61562007-04-12 22:38:54 +0000531 snprintf(buffer1, sizeof(buffer1), "%s%s", SIMULATOR_ARCHOS_ROOT,
532 oldpath);
533 snprintf(buffer2, sizeof(buffer2), "%s%s", SIMULATOR_ARCHOS_ROOT,
534 newpath);
Björn Stenberg7d80ba02003-01-15 11:38:03 +0000535
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000536 debugf("We rename the real file '%s' to '%s'\n", buffer1, buffer2);
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000537 return RENAME(buffer1, buffer2);
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000538 }
539 return -1;
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000540#endif
Björn Stenberg7d80ba02003-01-15 11:38:03 +0000541}
542
Jens Arnold399c0812005-02-28 18:32:57 +0000543/* rockbox off_t may be different from system off_t */
544long sim_lseek(int fildes, long offset, int whence)
Linus Nielsen Feltzinge98bad52003-03-18 00:39:57 +0000545{
Jens Arnold399c0812005-02-28 18:32:57 +0000546 return lseek(fildes, offset, whence);
547}
548
549long sim_filesize(int fd)
550{
Jens Arnoldbb9dfa02005-03-09 19:26:59 +0000551#ifdef WIN32
552 return _filelength(fd);
553#else
554 struct stat buf;
555
556 if (!fstat(fd, &buf))
557 return buf.st_size;
558 else
559 return -1;
560#endif
Linus Nielsen Feltzinge98bad52003-03-18 00:39:57 +0000561}
562
Jens Arnold51280802007-09-13 20:53:32 +0000563void fat_size(IF_MV2(int volume,) unsigned long* size, unsigned long* free)
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000564{
Jens Arnold51280802007-09-13 20:53:32 +0000565#ifdef HAVE_MULTIVOLUME
566 if (volume != 0) {
567 debugf("io.c: fat_size(volume=%d); simulator only supports volume 0\n",
568 volume);
569
570 if (size) *size = 0;
571 if (free) *free = 0;
572 return;
573 }
574#endif
575
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000576#ifdef WIN32
Jens Arnold78724262005-02-22 21:55:48 +0000577 long secperclus, bytespersec, free_clusters, num_clusters;
578
579 if (GetDiskFreeSpace(NULL, &secperclus, &bytespersec, &free_clusters,
580 &num_clusters)) {
581 if (size)
582 *size = num_clusters * secperclus / 2 * (bytespersec / 512);
583 if (free)
584 *free = free_clusters * secperclus / 2 * (bytespersec / 512);
585 }
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000586#else
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000587 struct statfs fs;
588
589 if (!statfs(".", &fs)) {
Jens Arnoldbd5c0ad2007-03-17 10:50:58 +0000590 DEBUGF("statfs: bsize=%d blocks=%ld free=%ld\n",
591 (int)fs.f_bsize, fs.f_blocks, fs.f_bfree);
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000592 if (size)
593 *size = fs.f_blocks * (fs.f_bsize / 1024);
594 if (free)
595 *free = fs.f_bfree * (fs.f_bsize / 1024);
596 }
Jens Arnold78724262005-02-22 21:55:48 +0000597#endif
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000598 else {
599 if (size)
600 *size = 0;
601 if (free)
602 *free = 0;
603 }
604}
Daniel Stenberg22b77012005-02-22 12:19:12 +0000605
606int sim_fsync(int fd)
607{
608#ifdef WIN32
609 return _commit(fd);
610#else
611 return fsync(fd);
612#endif
613}
614
615#ifdef WIN32
616/* sim-win32 */
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000617#define dlopen(_x_, _y_) LoadLibraryW(UTF8_TO_OS(_x_))
Jens Arnoldcf208c52005-02-22 18:21:16 +0000618#define dlsym(_x_, _y_) (void *)GetProcAddress(_x_, _y_)
Daniel Stenberg22b77012005-02-22 12:19:12 +0000619#define dlclose(_x_) FreeLibrary(_x_)
Daniel Stenberg22b77012005-02-22 12:19:12 +0000620#else
621/* sim-x11 */
622#include <dlfcn.h>
623#endif
624
Hardeep Sidhu25377db2006-06-17 09:42:16 +0000625#define TEMP_CODEC_FILE "archos/_temp_codec%d.dll"
626
Jens Arnolda7902772006-01-16 23:20:58 +0000627void *sim_codec_load_ram(char* codecptr, int size,
Jens Arnold38b75472006-03-02 01:08:38 +0000628 void* ptr2, int bufwrap, void **pd)
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000629{
Jens Arnold38b75472006-03-02 01:08:38 +0000630 void *hdr;
Hardeep Sidhu25377db2006-06-17 09:42:16 +0000631 char path[MAX_PATH];
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000632 int fd;
633 int copy_n;
Steve Bavin8c9d5f32006-09-28 08:46:28 +0000634 int codec_count;
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000635#ifdef WIN32
Peter D'Hoye6be61562007-04-12 22:38:54 +0000636 char buf[MAX_PATH];
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000637#endif
638
Jens Arnold38b75472006-03-02 01:08:38 +0000639 *pd = NULL;
Jens Arnoldb8749fd2006-01-18 00:05:14 +0000640
Steve Bavin8c9d5f32006-09-28 08:46:28 +0000641 /* We have to create the dynamic link library file from ram so we
642 can simulate the codec loading. With voice and crossfade,
643 multiple codecs may be loaded at the same time, so we need
644 to find an unused filename */
645 for (codec_count = 0; codec_count < 10; codec_count++)
646 {
Peter D'Hoye6be61562007-04-12 22:38:54 +0000647 snprintf(path, sizeof(path), TEMP_CODEC_FILE, codec_count);
Jens Arnoldb8749fd2006-01-18 00:05:14 +0000648
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000649 fd = OPEN(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRWXU);
Steve Bavin8c9d5f32006-09-28 08:46:28 +0000650 if (fd >= 0)
651 break; /* Created a file ok */
652 }
Jens Arnold67eb1542007-02-01 23:08:15 +0000653 if (fd < 0)
Steve Bavin8c9d5f32006-09-28 08:46:28 +0000654 {
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000655 DEBUGF("failed to open for write: %s\n", path);
656 return NULL;
657 }
658
659 if (bufwrap == 0)
660 bufwrap = size;
661
662 copy_n = bufwrap < size ? bufwrap : size;
663 if (write(fd, codecptr, copy_n) != copy_n) {
664 DEBUGF("write failed");
665 return NULL;
666 }
667 size -= copy_n;
668 if (size > 0) {
669 if (write(fd, ptr2, size) != size) {
670 DEBUGF("write failed [2]");
671 return NULL;
672 }
673 }
674 close(fd);
Jens Arnoldb8749fd2006-01-18 00:05:14 +0000675
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000676 /* Now load the library. */
Jens Arnold38b75472006-03-02 01:08:38 +0000677 *pd = dlopen(path, RTLD_NOW);
678 if (*pd == NULL) {
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000679 DEBUGF("failed to load %s\n", path);
680#ifdef WIN32
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000681 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
682 buf, sizeof buf, NULL);
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000683 DEBUGF("dlopen(%s): %s\n", path, buf);
684#else
685 DEBUGF("dlopen(%s): %s\n", path, dlerror());
686#endif
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000687 return NULL;
688 }
689
Jens Arnold38b75472006-03-02 01:08:38 +0000690 hdr = dlsym(*pd, "__header");
Jens Arnoldb8749fd2006-01-18 00:05:14 +0000691 if (!hdr)
Jens Arnold38b75472006-03-02 01:08:38 +0000692 hdr = dlsym(*pd, "___header");
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000693
Jens Arnoldb8749fd2006-01-18 00:05:14 +0000694 return hdr; /* maybe NULL if symbol not present */
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000695}
696
Jens Arnold38b75472006-03-02 01:08:38 +0000697void sim_codec_close(void *pd)
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000698{
Jens Arnold38b75472006-03-02 01:08:38 +0000699 dlclose(pd);
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000700}
701
Jens Arnold38b75472006-03-02 01:08:38 +0000702void *sim_plugin_load(char *plugin, void **pd)
Daniel Stenberg22b77012005-02-22 12:19:12 +0000703{
Jens Arnold38b75472006-03-02 01:08:38 +0000704 void *hdr;
Peter D'Hoye6be61562007-04-12 22:38:54 +0000705 char path[MAX_PATH];
Jens Arnoldcf208c52005-02-22 18:21:16 +0000706#ifdef WIN32
Peter D'Hoye6be61562007-04-12 22:38:54 +0000707 char buf[MAX_PATH];
Jens Arnoldcf208c52005-02-22 18:21:16 +0000708#endif
709
Peter D'Hoye6be61562007-04-12 22:38:54 +0000710 snprintf(path, sizeof(path), "archos%s", plugin);
711
Jens Arnold38b75472006-03-02 01:08:38 +0000712 *pd = NULL;
Jens Arnolda7902772006-01-16 23:20:58 +0000713
Jens Arnold38b75472006-03-02 01:08:38 +0000714 *pd = dlopen(path, RTLD_NOW);
715 if (*pd == NULL) {
Jens Arnoldcf208c52005-02-22 18:21:16 +0000716 DEBUGF("failed to load %s\n", plugin);
717#ifdef WIN32
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000718 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
719 buf, sizeof(buf), NULL);
Jens Arnoldcf208c52005-02-22 18:21:16 +0000720 DEBUGF("dlopen(%s): %s\n", path, buf);
721#else
722 DEBUGF("dlopen(%s): %s\n", path, dlerror());
723#endif
Daniel Stenberg22b77012005-02-22 12:19:12 +0000724 return NULL;
725 }
726
Jens Arnold38b75472006-03-02 01:08:38 +0000727 hdr = dlsym(*pd, "__header");
Jens Arnolda7902772006-01-16 23:20:58 +0000728 if (!hdr)
Jens Arnold38b75472006-03-02 01:08:38 +0000729 hdr = dlsym(*pd, "___header");
Jens Arnolda7902772006-01-16 23:20:58 +0000730
Jens Arnolda7902772006-01-16 23:20:58 +0000731 return hdr; /* maybe NULL if symbol not present */
Daniel Stenberg22b77012005-02-22 12:19:12 +0000732}
733
Jens Arnold38b75472006-03-02 01:08:38 +0000734void sim_plugin_close(void *pd)
Daniel Stenberg22b77012005-02-22 12:19:12 +0000735{
Jens Arnold38b75472006-03-02 01:08:38 +0000736 dlclose(pd);
Daniel Stenberg22b77012005-02-22 12:19:12 +0000737}
738
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000739#ifdef WIN32
740static unsigned old_cp;
Daniel Stenberg22b77012005-02-22 12:19:12 +0000741
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000742void debug_exit(void)
743{
744 /* Reset console output codepage */
745 SetConsoleOutputCP(old_cp);
746}
747
748void debug_init(void)
749{
750 old_cp = GetConsoleOutputCP();
751 /* Set console output codepage to UTF8. Only works
752 * correctly when the console uses a truetype font. */
753 SetConsoleOutputCP(65001);
754 atexit(debug_exit);
755}
756#else
Daniel Stenberg22b77012005-02-22 12:19:12 +0000757void debug_init(void)
758{
759 /* nothing to be done */
760}
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000761#endif
Daniel Stenberg22b77012005-02-22 12:19:12 +0000762
763void debugf(const char *fmt, ...)
764{
765 va_list ap;
766 va_start( ap, fmt );
767 vfprintf( stderr, fmt, ap );
768 va_end( ap );
769}
770
771void ldebugf(const char* file, int line, const char *fmt, ...)
772{
773 va_list ap;
774 va_start( ap, fmt );
775 fprintf( stderr, "%s:%d ", file, line );
776 vfprintf( stderr, fmt, ap );
777 va_end( ap );
778}
779
Jens Arnold576d0292005-03-05 21:48:58 +0000780/* rockbox off_t may be different from system off_t */
781int sim_ftruncate(int fd, long length)
Daniel Stenberg22b77012005-02-22 12:19:12 +0000782{
783#ifdef WIN32
784 return _chsize(fd, length);
785#else
786 return ftruncate(fd, length);
787#endif
788}