blob: 1871b29395961e443612aaa6d9d480356688e984 [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>
Björn Stenbergf6ed9702003-07-04 08:30:01 +000025#ifdef __FreeBSD__
26#include <sys/param.h>
27#include <sys/mount.h>
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +000028#elif !defined(WIN32)
Björn Stenberg6fb512a2002-11-12 11:32:26 +000029#include <sys/vfs.h>
Björn Stenbergf6ed9702003-07-04 08:30:01 +000030#endif
Hardeep Sidhufb26bfb2004-06-14 07:00:50 +000031
Daniel Stenberg22b77012005-02-22 12:19:12 +000032#ifdef WIN32
33#include <windows.h>
34#endif
35
Hardeep Sidhufb26bfb2004-06-14 07:00:50 +000036#ifndef _MSC_VER
Daniel Stenberge3a12d32002-05-07 12:25:30 +000037#include <dirent.h>
Björn Stenberg2ba4fed2003-01-28 23:14:41 +000038#include <unistd.h>
Hardeep Sidhufb26bfb2004-06-14 07:00:50 +000039#else
40#include "dir-win32.h"
41#endif
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +000042
Daniel Stenberg22b77012005-02-22 12:19:12 +000043#define MAX_PATH 260
44
Daniel Stenberged6c7e42002-06-14 11:00:13 +000045#include <fcntl.h>
46#include "debug.h"
47
Daniel Stenberge3a12d32002-05-07 12:25:30 +000048#define SIMULATOR_ARCHOS_ROOT "archos"
49
Daniel Stenberg22b77012005-02-22 12:19:12 +000050struct sim_dirent {
51 unsigned char d_name[MAX_PATH];
52 int attribute;
53 int size;
54 int startcluster;
55 unsigned short wrtdate; /* Last write date */
56 unsigned short wrttime; /* Last write time */
57};
58
59struct dirstruct {
60 void *dir; /* actually a DIR* dir */
61 char *name;
62} SIM_DIR;
63
Daniel Stenberge3a12d32002-05-07 12:25:30 +000064struct mydir {
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +000065 DIR *dir;
66 char *name;
Daniel Stenberge3a12d32002-05-07 12:25:30 +000067};
68
69typedef struct mydir MYDIR;
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +000070
Jens Arnold527e1212005-02-24 23:11:21 +000071#if 1 /* maybe this needs disabling for MSVC... */
Daniel Stenberg36c9a952004-06-14 22:22:49 +000072static unsigned int rockbox2sim(int opt)
73{
74 int newopt = 0;
75 if(opt & 1)
76 newopt |= O_WRONLY;
77 if(opt & 2)
78 newopt |= O_RDWR;
79 if(opt & 4)
80 newopt |= O_CREAT;
81 if(opt & 8)
82 newopt |= O_APPEND;
83 if(opt & 0x10)
84 newopt |= O_TRUNC;
85
86 return newopt;
87}
Linus Nielsen Feltzingb6f67a82004-07-08 05:50:20 +000088#endif
Daniel Stenberg36c9a952004-06-14 22:22:49 +000089
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +000090MYDIR *sim_opendir(const char *name)
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +000091{
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +000092 char buffer[256]; /* sufficiently big */
93 DIR *dir;
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +000094
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +000095 if(name[0] == '/') {
96 sprintf(buffer, "%s%s", SIMULATOR_ARCHOS_ROOT, name);
97 dir=(DIR *)opendir(buffer);
98 }
99 else
100 dir=(DIR *)opendir(name);
101
102 if(dir) {
103 MYDIR *my = (MYDIR *)malloc(sizeof(MYDIR));
104 my->dir = dir;
105 my->name = (char *)strdup(name);
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000106
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000107 return my;
108 }
109 /* failed open, return NULL */
110 return (MYDIR *)0;
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +0000111}
Daniel Stenberg91f165e2002-05-05 10:28:23 +0000112
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000113struct sim_dirent *sim_readdir(MYDIR *dir)
Daniel Stenberg159d4482002-05-07 11:35:03 +0000114{
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000115 char buffer[512]; /* sufficiently big */
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000116 static struct sim_dirent secret;
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000117 struct stat s;
118 struct dirent *x11 = (readdir)(dir->dir);
Daniel Stenberg159d4482002-05-07 11:35:03 +0000119
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000120 if(!x11)
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000121 return (struct sim_dirent *)0;
Daniel Stenberg159d4482002-05-07 11:35:03 +0000122
Daniel Stenbergee76cc32005-11-28 09:36:26 +0000123 strcpy((char *)secret.d_name, x11->d_name);
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000124
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000125 /* build file name */
126 sprintf(buffer, SIMULATOR_ARCHOS_ROOT "%s/%s",
127 dir->name, x11->d_name);
128 stat(buffer, &s); /* get info */
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000129
Daniel Stenberg22b77012005-02-22 12:19:12 +0000130#define ATTR_DIRECTORY 0x10
131
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000132 secret.attribute = S_ISDIR(s.st_mode)?ATTR_DIRECTORY:0;
133 secret.size = s.st_size;
Jörg Hohensohn74eb6422004-06-20 16:34:29 +0000134 secret.wrtdate = (unsigned short)(s.st_mtime >> 16);
135 secret.wrttime = (unsigned short)(s.st_mtime & 0xFFFF);
Daniel Stenberg159d4482002-05-07 11:35:03 +0000136
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000137 return &secret;
Daniel Stenberg159d4482002-05-07 11:35:03 +0000138}
139
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000140void sim_closedir(MYDIR *dir)
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000141{
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000142 free(dir->name);
Jens Arnold576d0292005-03-05 21:48:58 +0000143 closedir(dir->dir);
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000144
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000145 free(dir);
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000146}
147
Daniel Stenberg36c9a952004-06-14 22:22:49 +0000148int sim_open(const char *name, int o)
Daniel Stenberg91f165e2002-05-05 10:28:23 +0000149{
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000150 char buffer[256]; /* sufficiently big */
Daniel Stenberg36c9a952004-06-14 22:22:49 +0000151 int opts = rockbox2sim(o);
Daniel Stenberg91f165e2002-05-05 10:28:23 +0000152
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000153 if(name[0] == '/') {
154 sprintf(buffer, "%s%s", SIMULATOR_ARCHOS_ROOT, name);
Jens Arnold399c0812005-02-28 18:32:57 +0000155
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000156 debugf("We open the real file '%s'\n", buffer);
Jens Arnold576d0292005-03-05 21:48:58 +0000157 return open(buffer, opts, 0666);
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000158 }
Daniel Stenberg56e63352004-06-14 22:32:13 +0000159 fprintf(stderr, "WARNING, bad file name lacks slash: %s\n",
160 name);
161 return -1;
Daniel Stenberg91f165e2002-05-05 10:28:23 +0000162}
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000163
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000164int sim_creat(const char *name, mode_t mode)
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000165{
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000166 char buffer[256]; /* sufficiently big */
167 (void)mode;
168 if(name[0] == '/') {
169 sprintf(buffer, "%s%s", SIMULATOR_ARCHOS_ROOT, name);
170
171 debugf("We create the real file '%s'\n", buffer);
Jens Arnold576d0292005-03-05 21:48:58 +0000172 return creat(buffer, 0666);
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000173 }
Daniel Stenberg56e63352004-06-14 22:32:13 +0000174 fprintf(stderr, "WARNING, bad file name lacks slash: %s\n",
175 name);
176 return -1;
Jens Arnold399c0812005-02-28 18:32:57 +0000177}
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000178
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000179int sim_mkdir(const char *name, mode_t mode)
Linus Nielsen Feltzingef7293f2004-01-21 14:58:40 +0000180{
181 char buffer[256]; /* sufficiently big */
182 (void)mode;
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000183
184 sprintf(buffer, "%s%s", SIMULATOR_ARCHOS_ROOT, name);
Linus Nielsen Feltzingef7293f2004-01-21 14:58:40 +0000185
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000186 debugf("We create the real directory '%s'\n", buffer);
187#ifdef WIN32
Daniel Stenberg22b77012005-02-22 12:19:12 +0000188 /* since we build with -DNOCYGWIN we have the plain win32 version */
Jens Arnold576d0292005-03-05 21:48:58 +0000189 return mkdir(buffer);
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000190#else
Jens Arnold576d0292005-03-05 21:48:58 +0000191 return mkdir(buffer, 0666);
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000192#endif
Linus Nielsen Feltzingef7293f2004-01-21 14:58:40 +0000193}
194
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000195int sim_rmdir(const char *name)
Linus Nielsen Feltzing8fa821d2004-04-16 09:24:38 +0000196{
197 char buffer[256]; /* sufficiently big */
198 if(name[0] == '/') {
199 sprintf(buffer, "%s%s", SIMULATOR_ARCHOS_ROOT, name);
200
201 debugf("We remove the real directory '%s'\n", buffer);
Jens Arnold576d0292005-03-05 21:48:58 +0000202 return rmdir(buffer);
Linus Nielsen Feltzing8fa821d2004-04-16 09:24:38 +0000203 }
Jens Arnold576d0292005-03-05 21:48:58 +0000204 return rmdir(name);
Linus Nielsen Feltzing8fa821d2004-04-16 09:24:38 +0000205}
206
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000207int sim_remove(const char *name)
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000208{
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000209 char buffer[256]; /* sufficiently big */
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000210
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000211 if(name[0] == '/') {
212 sprintf(buffer, "%s%s", SIMULATOR_ARCHOS_ROOT, name);
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000213
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000214 debugf("We remove the real file '%s'\n", buffer);
Jens Arnold576d0292005-03-05 21:48:58 +0000215 return remove(buffer);
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000216 }
Jens Arnold576d0292005-03-05 21:48:58 +0000217 return remove(name);
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000218}
219
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000220int sim_rename(const char *oldpath, const char* newpath)
Björn Stenberg7d80ba02003-01-15 11:38:03 +0000221{
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000222 char buffer1[256];
223 char buffer2[256];
Björn Stenberg7d80ba02003-01-15 11:38:03 +0000224
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000225 if(oldpath[0] == '/') {
226 sprintf(buffer1, "%s%s", SIMULATOR_ARCHOS_ROOT, oldpath);
227 sprintf(buffer2, "%s%s", SIMULATOR_ARCHOS_ROOT, newpath);
Björn Stenberg7d80ba02003-01-15 11:38:03 +0000228
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000229 debugf("We rename the real file '%s' to '%s'\n", buffer1, buffer2);
Jens Arnold576d0292005-03-05 21:48:58 +0000230 return rename(buffer1, buffer2);
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000231 }
232 return -1;
Björn Stenberg7d80ba02003-01-15 11:38:03 +0000233}
234
Jens Arnold399c0812005-02-28 18:32:57 +0000235/* rockbox off_t may be different from system off_t */
236long sim_lseek(int fildes, long offset, int whence)
Linus Nielsen Feltzinge98bad52003-03-18 00:39:57 +0000237{
Jens Arnold399c0812005-02-28 18:32:57 +0000238 return lseek(fildes, offset, whence);
239}
240
241long sim_filesize(int fd)
242{
Jens Arnoldbb9dfa02005-03-09 19:26:59 +0000243#ifdef WIN32
244 return _filelength(fd);
245#else
246 struct stat buf;
247
248 if (!fstat(fd, &buf))
249 return buf.st_size;
250 else
251 return -1;
252#endif
Linus Nielsen Feltzinge98bad52003-03-18 00:39:57 +0000253}
254
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000255void fat_size(unsigned int* size, unsigned int* free)
256{
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000257#ifdef WIN32
Jens Arnold78724262005-02-22 21:55:48 +0000258 long secperclus, bytespersec, free_clusters, num_clusters;
259
260 if (GetDiskFreeSpace(NULL, &secperclus, &bytespersec, &free_clusters,
261 &num_clusters)) {
262 if (size)
263 *size = num_clusters * secperclus / 2 * (bytespersec / 512);
264 if (free)
265 *free = free_clusters * secperclus / 2 * (bytespersec / 512);
266 }
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000267#else
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000268 struct statfs fs;
269
270 if (!statfs(".", &fs)) {
271 DEBUGF("statfs: bsize=%d blocks=%d free=%d\n",
272 fs.f_bsize, fs.f_blocks, fs.f_bfree);
273 if (size)
274 *size = fs.f_blocks * (fs.f_bsize / 1024);
275 if (free)
276 *free = fs.f_bfree * (fs.f_bsize / 1024);
277 }
Jens Arnold78724262005-02-22 21:55:48 +0000278#endif
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000279 else {
280 if (size)
281 *size = 0;
282 if (free)
283 *free = 0;
284 }
285}
Daniel Stenberg22b77012005-02-22 12:19:12 +0000286
287int sim_fsync(int fd)
288{
289#ifdef WIN32
290 return _commit(fd);
291#else
292 return fsync(fd);
293#endif
294}
295
296#ifdef WIN32
297/* sim-win32 */
Daniel Stenberg22b77012005-02-22 12:19:12 +0000298#define dlopen(_x_, _y_) LoadLibrary(_x_)
Jens Arnoldcf208c52005-02-22 18:21:16 +0000299#define dlsym(_x_, _y_) (void *)GetProcAddress(_x_, _y_)
Daniel Stenberg22b77012005-02-22 12:19:12 +0000300#define dlclose(_x_) FreeLibrary(_x_)
Daniel Stenberg22b77012005-02-22 12:19:12 +0000301#else
302/* sim-x11 */
303#include <dlfcn.h>
304#endif
305
Jens Arnolda7902772006-01-16 23:20:58 +0000306void *sim_codec_load_ram(char* codecptr, int size,
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000307 void* ptr2, int bufwrap, int *pd_fd)
308{
309 void *pd;
310 char *path = "archos/_temp_codec.dll";
311 int (*codec_start)(void * api);
312 int fd;
313 int copy_n;
314#ifdef WIN32
315 char buf[256];
316#endif
317
318 /* We have to create the dynamic link library file from ram
319 * so we could simulate the codec loading.
320 */
321 *pd_fd = -1;
322 fd = open(path, O_WRONLY | O_CREAT, S_IRWXU);
323 if (fd < 0) {
324 DEBUGF("failed to open for write: %s\n", path);
325 return NULL;
326 }
327
328 if (bufwrap == 0)
329 bufwrap = size;
330
331 copy_n = bufwrap < size ? bufwrap : size;
332 if (write(fd, codecptr, copy_n) != copy_n) {
333 DEBUGF("write failed");
334 return NULL;
335 }
336 size -= copy_n;
337 if (size > 0) {
338 if (write(fd, ptr2, size) != size) {
339 DEBUGF("write failed [2]");
340 return NULL;
341 }
342 }
343 close(fd);
344
345 /* Now load the library. */
346 pd = dlopen(path, RTLD_NOW);
347 if (!pd) {
348 DEBUGF("failed to load %s\n", path);
349#ifdef WIN32
350 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
351 buf, sizeof buf, NULL);
352 DEBUGF("dlopen(%s): %s\n", path, buf);
353#else
354 DEBUGF("dlopen(%s): %s\n", path, dlerror());
355#endif
356 dlclose(pd);
357 return NULL;
358 }
359
360 codec_start = dlsym(pd, "codec_start");
361 if (!codec_start) {
362 codec_start = dlsym(pd, "_codec_start");
363 if (!codec_start) {
364 dlclose(pd);
365 return NULL;
366 }
367 }
368
369 *pd_fd = (int)pd;
370 return codec_start;
371}
372
373void sim_codec_close(int pd)
374{
Jens Arnolda7902772006-01-16 23:20:58 +0000375 dlclose((void *)pd);
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000376}
377
Daniel Stenberg22b77012005-02-22 12:19:12 +0000378void *sim_plugin_load(char *plugin, int *fd)
379{
Jens Arnolda7902772006-01-16 23:20:58 +0000380 void *pd, *hdr;
Daniel Stenberg22b77012005-02-22 12:19:12 +0000381 char path[256];
Jens Arnoldcf208c52005-02-22 18:21:16 +0000382#ifdef WIN32
383 char buf[256];
384#endif
385
Daniel Stenberg22b77012005-02-22 12:19:12 +0000386 snprintf(path, sizeof path, "archos%s", plugin);
Daniel Stenberg22b77012005-02-22 12:19:12 +0000387
Jens Arnolda7902772006-01-16 23:20:58 +0000388 *fd = 0;
389
Daniel Stenberg22b77012005-02-22 12:19:12 +0000390 pd = dlopen(path, RTLD_NOW);
391 if (!pd) {
Jens Arnoldcf208c52005-02-22 18:21:16 +0000392 DEBUGF("failed to load %s\n", plugin);
393#ifdef WIN32
394 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
395 buf, sizeof buf, NULL);
396 DEBUGF("dlopen(%s): %s\n", path, buf);
397#else
398 DEBUGF("dlopen(%s): %s\n", path, dlerror());
399#endif
Daniel Stenberg22b77012005-02-22 12:19:12 +0000400 dlclose(pd);
401 return NULL;
402 }
403
Jens Arnolda7902772006-01-16 23:20:58 +0000404 hdr = dlsym(pd, "__header");
405 if (!hdr)
406 hdr = dlsym(pd, "___header");
407
Jens Arnoldcf208c52005-02-22 18:21:16 +0000408 *fd = (int)pd; /* success */
Jens Arnolda7902772006-01-16 23:20:58 +0000409 return hdr; /* maybe NULL if symbol not present */
Daniel Stenberg22b77012005-02-22 12:19:12 +0000410}
411
412void sim_plugin_close(int pd)
413{
Jens Arnoldcf208c52005-02-22 18:21:16 +0000414 dlclose((void *)pd);
Daniel Stenberg22b77012005-02-22 12:19:12 +0000415}
416
417#ifndef WIN32
418/* the win32 version is in debug-win32.c */
419
420void debug_init(void)
421{
422 /* nothing to be done */
423}
424
425void debugf(const char *fmt, ...)
426{
427 va_list ap;
428 va_start( ap, fmt );
429 vfprintf( stderr, fmt, ap );
430 va_end( ap );
431}
432
433void ldebugf(const char* file, int line, const char *fmt, ...)
434{
435 va_list ap;
436 va_start( ap, fmt );
437 fprintf( stderr, "%s:%d ", file, line );
438 vfprintf( stderr, fmt, ap );
439 va_end( ap );
440}
441
442#endif
443
Jens Arnold576d0292005-03-05 21:48:58 +0000444/* rockbox off_t may be different from system off_t */
445int sim_ftruncate(int fd, long length)
Daniel Stenberg22b77012005-02-22 12:19:12 +0000446{
447#ifdef WIN32
448 return _chsize(fd, length);
449#else
450 return ftruncate(fd, length);
451#endif
452}