blob: d87e331970a5fcd7d866accf72212a1eccf68532 [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 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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.
Björn Stenberg32125d42002-05-13 15:23:30 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +000021
Daniel Stenberged6c7e42002-06-14 11:00:13 +000022#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
Daniel Stenberg22b77012005-02-22 12:19:12 +000025#include <stdarg.h>
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +000026#include <sys/stat.h>
Peter D'Hoyef0ed5942007-04-06 23:54:21 +000027#include <time.h>
Björn Stenbergf6ed9702003-07-04 08:30:01 +000028#ifdef __FreeBSD__
29#include <sys/param.h>
30#include <sys/mount.h>
Barry Wardell64f949f2006-09-29 16:15:11 +000031#elif defined(__APPLE__)
32#include <sys/param.h>
33#include <sys/mount.h>
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +000034#elif !defined(WIN32)
Björn Stenberg6fb512a2002-11-12 11:32:26 +000035#include <sys/vfs.h>
Björn Stenbergf6ed9702003-07-04 08:30:01 +000036#endif
Hardeep Sidhufb26bfb2004-06-14 07:00:50 +000037
Daniel Stenberg22b77012005-02-22 12:19:12 +000038#ifdef WIN32
39#include <windows.h>
40#endif
41
Hardeep Sidhufb26bfb2004-06-14 07:00:50 +000042#ifndef _MSC_VER
Daniel Stenberge3a12d32002-05-07 12:25:30 +000043#include <dirent.h>
Björn Stenberg2ba4fed2003-01-28 23:14:41 +000044#include <unistd.h>
Hardeep Sidhufb26bfb2004-06-14 07:00:50 +000045#else
46#include "dir-win32.h"
47#endif
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +000048
Daniel Stenberg22b77012005-02-22 12:19:12 +000049#define MAX_PATH 260
Nicolas Pennequinef9abe42007-10-09 15:15:00 +000050#define MAX_OPEN_FILES 11
Daniel Stenberg22b77012005-02-22 12:19:12 +000051
Daniel Stenberged6c7e42002-06-14 11:00:13 +000052#include <fcntl.h>
Michael Sevakisf64ebb12007-09-08 12:20:53 +000053#include <SDL.h>
54#include <SDL_thread.h>
55#include "thread.h"
56#include "kernel.h"
Daniel Stenberged6c7e42002-06-14 11:00:13 +000057#include "debug.h"
Miika Pekkarinend70bd0e2006-08-26 14:19:18 +000058#include "config.h"
Jens Arnold51280802007-09-13 20:53:32 +000059#include "ata.h" /* for IF_MV2 et al. */
Michael Sevakisa4d19b72007-12-03 14:01:12 +000060#include "thread-sdl.h"
61
Miika Pekkarinend70bd0e2006-08-26 14:19:18 +000062
Jens Arnold67eb1542007-02-01 23:08:15 +000063/* Windows (and potentially other OSes) distinguish binary and text files.
64 * Define a dummy for the others. */
65#ifndef O_BINARY
66#define O_BINARY 0
67#endif
68
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000069/* Unicode compatibility for win32 */
70#if defined __MINGW32__
71/* Rockbox unicode functions */
72extern const unsigned char* utf8decode(const unsigned char *utf8,
73 unsigned short *ucs);
74extern unsigned char* utf8encode(unsigned long ucs, unsigned char *utf8);
75
Jens Arnold49be3fa2007-04-20 17:35:05 +000076/* Static buffers for the conversion results. This isn't thread safe,
77 * but it's sufficient for rockbox. */
78static unsigned char convbuf1[3*MAX_PATH];
79static unsigned char convbuf2[3*MAX_PATH];
80
81static wchar_t* utf8_to_ucs2(const unsigned char *utf8, void *buffer)
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000082{
Jens Arnold49be3fa2007-04-20 17:35:05 +000083 wchar_t *ucs = buffer;
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000084
85 while (*utf8)
86 utf8 = utf8decode(utf8, ucs++);
Steve Bavinf87eb602007-11-08 12:11:34 +000087
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000088 *ucs = 0;
Jens Arnold49be3fa2007-04-20 17:35:05 +000089 return buffer;
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000090}
Jens Arnold49be3fa2007-04-20 17:35:05 +000091static unsigned char *ucs2_to_utf8(const wchar_t *ucs, unsigned char *buffer)
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000092{
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000093 unsigned char *utf8 = buffer;
Jens Arnold49be3fa2007-04-20 17:35:05 +000094
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000095 while (*ucs)
96 utf8 = utf8encode(*ucs++, utf8);
Steve Bavinf87eb602007-11-08 12:11:34 +000097
Jens Arnold2fd7c3c2007-04-19 20:17:24 +000098 *utf8 = 0;
99 return buffer;
100}
101
Jens Arnold49be3fa2007-04-20 17:35:05 +0000102#define UTF8_TO_OS(a) utf8_to_ucs2(a,convbuf1)
103#define OS_TO_UTF8(a) ucs2_to_utf8(a,convbuf1)
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000104#define DIR_T _WDIR
105#define DIRENT_T struct _wdirent
106#define STAT_T struct _stat
107extern int _wmkdir(const wchar_t*);
108extern int _wrmdir(const wchar_t*);
109#define MKDIR(a,b) (_wmkdir)(UTF8_TO_OS(a))
110#define RMDIR(a) (_wrmdir)(UTF8_TO_OS(a))
111#define OPENDIR(a) (_wopendir)(UTF8_TO_OS(a))
112#define READDIR(a) (_wreaddir)(a)
113#define CLOSEDIR(a) (_wclosedir)(a)
114#define STAT(a,b) (_wstat)(UTF8_TO_OS(a),b)
115#define OPEN(a,b,c) (_wopen)(UTF8_TO_OS(a),b,c)
Jonas Häggqvistb24631c2007-10-09 17:51:02 +0000116#define CLOSE(a) (close)(a)
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000117#define REMOVE(a) (_wremove)(UTF8_TO_OS(a))
Jens Arnold49be3fa2007-04-20 17:35:05 +0000118#define RENAME(a,b) (_wrename)(UTF8_TO_OS(a),utf8_to_ucs2(b,convbuf2))
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000119
120#else /* !__MINGW32__ */
121
122#define UTF8_TO_OS(a) (a)
123#define OS_TO_UTF8(a) (a)
124#define DIR_T DIR
125#define DIRENT_T struct dirent
126#define STAT_T struct stat
127#define MKDIR(a,b) (mkdir)(a,b)
128#define RMDIR(a) (rmdir)(a)
129#define OPENDIR(a) (opendir)(a)
130#define READDIR(a) (readdir)(a)
131#define CLOSEDIR(a) (closedir)(a)
132#define STAT(a,b) (stat)(a,b)
133#define OPEN(a,b,c) (open)(a,b,c)
Nicolas Pennequinef9abe42007-10-09 15:15:00 +0000134#define CLOSE(x) (close)(x)
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000135#define REMOVE(a) (remove)(a)
136#define RENAME(a,b) (rename)(a,b)
137
138#endif /* !__MINGW32__ */
139
140
Miika Pekkarinend70bd0e2006-08-26 14:19:18 +0000141#ifdef HAVE_DIRCACHE
142void dircache_remove(const char *name);
Steve Bavinb61f0c62009-02-27 21:25:17 +0000143void dircache_rename(const char *oldname, const char *newname);
Miika Pekkarinend70bd0e2006-08-26 14:19:18 +0000144#endif
Daniel Stenberged6c7e42002-06-14 11:00:13 +0000145
Steve Bavin9e05cc52007-11-08 10:15:44 +0000146
Björn Stenberg819378b2008-11-24 20:32:57 +0000147#define SIMULATOR_DEFAULT_ROOT "simdisk"
Steve Bavin9e05cc52007-11-08 10:15:44 +0000148extern const char *sim_root_dir;
Daniel Stenberge3a12d32002-05-07 12:25:30 +0000149
Nicolas Pennequinef9abe42007-10-09 15:15:00 +0000150static int num_openfiles = 0;
151
Daniel Stenberg22b77012005-02-22 12:19:12 +0000152struct sim_dirent {
153 unsigned char d_name[MAX_PATH];
154 int attribute;
Jens Arnoldd6cb7162007-04-07 00:14:16 +0000155 long size;
156 long startcluster;
Steve Bavinf87eb602007-11-08 12:11:34 +0000157 unsigned short wrtdate; /* Last write date */
Daniel Stenberg22b77012005-02-22 12:19:12 +0000158 unsigned short wrttime; /* Last write time */
159};
160
161struct dirstruct {
162 void *dir; /* actually a DIR* dir */
Steve Bavinf87eb602007-11-08 12:11:34 +0000163 char *name;
Daniel Stenberg22b77012005-02-22 12:19:12 +0000164} SIM_DIR;
165
Daniel Stenberge3a12d32002-05-07 12:25:30 +0000166struct mydir {
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000167 DIR_T *dir;
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000168 char *name;
Daniel Stenberge3a12d32002-05-07 12:25:30 +0000169};
170
171typedef struct mydir MYDIR;
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +0000172
Jens Arnold527e1212005-02-24 23:11:21 +0000173#if 1 /* maybe this needs disabling for MSVC... */
Daniel Stenberg36c9a952004-06-14 22:22:49 +0000174static unsigned int rockbox2sim(int opt)
175{
Linus Nielsen Feltzingfc72c532006-02-03 15:19:58 +0000176 int newopt = O_BINARY;
Jens Arnold67eb1542007-02-01 23:08:15 +0000177
Daniel Stenberg36c9a952004-06-14 22:22:49 +0000178 if(opt & 1)
179 newopt |= O_WRONLY;
180 if(opt & 2)
181 newopt |= O_RDWR;
182 if(opt & 4)
183 newopt |= O_CREAT;
184 if(opt & 8)
185 newopt |= O_APPEND;
186 if(opt & 0x10)
187 newopt |= O_TRUNC;
188
189 return newopt;
190}
Linus Nielsen Feltzingb6f67a82004-07-08 05:50:20 +0000191#endif
Daniel Stenberg36c9a952004-06-14 22:22:49 +0000192
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000193/** Simulator I/O engine routines **/
Michael Sevakis6a058832007-12-03 15:33:12 +0000194#define IO_YIELD_THRESHOLD 512
195
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000196enum
197{
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000198 IO_READ,
199 IO_WRITE,
200};
201
202struct sim_io
203{
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000204 struct mutex sim_mutex; /* Rockbox mutex */
Michael Sevakis6a058832007-12-03 15:33:12 +0000205 int cmd; /* The command to perform */
206 int ready; /* I/O ready flag - 1= ready */
207 int fd; /* The file to read/write */
208 void *buf; /* The buffer to read/write */
209 size_t count; /* Number of bytes to read/write */
210 size_t accum; /* Acculated bytes transferred */
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000211};
212
213static struct sim_io io;
214
Michael Sevakisc4a76312007-09-10 03:49:12 +0000215int ata_init(void)
216{
217 /* Initialize the rockbox kernel objects on a rockbox thread */
218 mutex_init(&io.sim_mutex);
Michael Sevakis6a058832007-12-03 15:33:12 +0000219 io.accum = 0;
Michael Sevakisc4a76312007-09-10 03:49:12 +0000220 return 1;
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000221}
222
Björn Stenbergff498512009-01-10 21:38:56 +0000223int ata_spinup_time(void)
224{
225 return HZ;
226}
227
Michael Sevakisa4d19b72007-12-03 14:01:12 +0000228static ssize_t io_trigger_and_wait(int cmd)
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000229{
Michael Sevakis6a058832007-12-03 15:33:12 +0000230 void *mythread = NULL;
Michael Sevakisa4d19b72007-12-03 14:01:12 +0000231 ssize_t result;
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000232
Michael Sevakis6a058832007-12-03 15:33:12 +0000233 if (io.count > IO_YIELD_THRESHOLD ||
234 (io.accum += io.count) >= IO_YIELD_THRESHOLD)
235 {
236 /* Allow other rockbox threads to run */
237 io.accum = 0;
238 mythread = thread_sdl_thread_unlock();
239 }
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000240
Michael Sevakisa4d19b72007-12-03 14:01:12 +0000241 switch (cmd)
242 {
243 case IO_READ:
244 result = read(io.fd, io.buf, io.count);
245 break;
246 case IO_WRITE:
247 result = write(io.fd, io.buf, io.count);
248 break;
249 }
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000250
Michael Sevakisa4d19b72007-12-03 14:01:12 +0000251 /* Regain our status as current */
Michael Sevakis6a058832007-12-03 15:33:12 +0000252 if (mythread != NULL)
253 {
254 thread_sdl_thread_lock(mythread);
255 }
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000256
Michael Sevakisa4d19b72007-12-03 14:01:12 +0000257 return result;
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000258}
259
Björn Stenbergee46a3d2008-12-15 23:42:19 +0000260#ifndef __PCTOOL__
Steve Bavin6eea66f2009-02-27 21:15:52 +0000261static const char *get_sim_pathname(const char *name)
Steve Bavin9e05cc52007-11-08 10:15:44 +0000262{
Steve Bavin6eea66f2009-02-27 21:15:52 +0000263 static char buffer[MAX_PATH]; /* sufficiently big */
264
265 if(name[0] == '/')
266 {
Steve Bavinb61f0c62009-02-27 21:25:17 +0000267 snprintf(buffer, sizeof(buffer), "%s%s",
Steve Bavin6eea66f2009-02-27 21:15:52 +0000268 sim_root_dir != NULL ? sim_root_dir : SIMULATOR_DEFAULT_ROOT, name);
269 return buffer;
270 }
Steve Bavinb61f0c62009-02-27 21:25:17 +0000271 fprintf(stderr, "WARNING, bad file name lacks slash: %s\n", name);
Steve Bavin6eea66f2009-02-27 21:15:52 +0000272 return name;
Steve Bavin9e05cc52007-11-08 10:15:44 +0000273}
Steve Bavin6eea66f2009-02-27 21:15:52 +0000274#else
275#define get_sim_pathname(name) name
Björn Stenbergee46a3d2008-12-15 23:42:19 +0000276#endif
Steve Bavin9e05cc52007-11-08 10:15:44 +0000277
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000278MYDIR *sim_opendir(const char *name)
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +0000279{
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000280 DIR_T *dir;
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +0000281
Steve Bavin6eea66f2009-02-27 21:15:52 +0000282 dir = (DIR_T *) OPENDIR(get_sim_pathname(name));
Björn Stenbergee46a3d2008-12-15 23:42:19 +0000283
Steve Bavin6eea66f2009-02-27 21:15:52 +0000284 if (dir)
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000285 {
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000286 MYDIR *my = (MYDIR *)malloc(sizeof(MYDIR));
287 my->dir = dir;
Björn Stenbergee46a3d2008-12-15 23:42:19 +0000288 my->name = (char *)malloc(strlen(name)+1);
289 strcpy(my->name, name);
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000290
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000291 return my;
292 }
293 /* failed open, return NULL */
294 return (MYDIR *)0;
Daniel Stenberg7b3abdc2002-04-30 13:14:59 +0000295}
Daniel Stenberg91f165e2002-05-05 10:28:23 +0000296
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000297struct sim_dirent *sim_readdir(MYDIR *dir)
Daniel Stenberg159d4482002-05-07 11:35:03 +0000298{
Steve Bavinf87eb602007-11-08 12:11:34 +0000299 char buffer[MAX_PATH]; /* sufficiently big */
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000300 static struct sim_dirent secret;
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000301 STAT_T s;
302 DIRENT_T *x11 = READDIR(dir->dir);
Peter D'Hoye832e0df2007-04-06 23:33:33 +0000303 struct tm* tm;
Daniel Stenberg159d4482002-05-07 11:35:03 +0000304
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000305 if(!x11)
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000306 return (struct sim_dirent *)0;
Daniel Stenberg159d4482002-05-07 11:35:03 +0000307
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000308 strcpy((char *)secret.d_name, OS_TO_UTF8(x11->d_name));
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000309
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000310 /* build file name */
Steve Bavinb61f0c62009-02-27 21:25:17 +0000311 snprintf(buffer, sizeof(buffer), "%s/%s",
Steve Bavin6eea66f2009-02-27 21:15:52 +0000312 get_sim_pathname(dir->name), secret.d_name);
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000313 STAT(buffer, &s); /* get info */
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000314
Daniel Stenberg22b77012005-02-22 12:19:12 +0000315#define ATTR_DIRECTORY 0x10
Steve Bavinf87eb602007-11-08 12:11:34 +0000316
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000317 secret.attribute = S_ISDIR(s.st_mode)?ATTR_DIRECTORY:0;
318 secret.size = s.st_size;
Daniel Stenberg159d4482002-05-07 11:35:03 +0000319
Peter D'Hoye832e0df2007-04-06 23:33:33 +0000320 tm = localtime(&(s.st_mtime));
321 secret.wrtdate = ((tm->tm_year - 80) << 9) |
322 ((tm->tm_mon + 1) << 5) |
323 tm->tm_mday;
324 secret.wrttime = (tm->tm_hour << 11) |
325 (tm->tm_min << 5) |
326 (tm->tm_sec >> 1);
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000327 return &secret;
Daniel Stenberg159d4482002-05-07 11:35:03 +0000328}
329
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000330void sim_closedir(MYDIR *dir)
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000331{
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000332 free(dir->name);
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000333 CLOSEDIR(dir->dir);
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000334
Daniel Stenberg11d9ecb2003-03-05 22:59:36 +0000335 free(dir);
Daniel Stenberg27dfc7c2002-05-07 12:06:32 +0000336}
337
Daniel Stenberg36c9a952004-06-14 22:22:49 +0000338int sim_open(const char *name, int o)
Daniel Stenberg91f165e2002-05-05 10:28:23 +0000339{
Daniel Stenberg36c9a952004-06-14 22:22:49 +0000340 int opts = rockbox2sim(o);
Nicolas Pennequinef9abe42007-10-09 15:15:00 +0000341 int ret;
342
343 if (num_openfiles >= MAX_OPEN_FILES)
344 return -2;
Daniel Stenberg91f165e2002-05-05 10:28:23 +0000345
Steve Bavinb61f0c62009-02-27 21:25:17 +0000346 ret = OPEN(get_sim_pathname(name), opts, 0666);
Björn Stenbergee46a3d2008-12-15 23:42:19 +0000347 if (ret >= 0)
348 num_openfiles++;
349 return ret;
Nicolas Pennequinef9abe42007-10-09 15:15:00 +0000350}
351
352int sim_close(int fd)
353{
354 int ret;
355 ret = CLOSE(fd);
Steve Bavinb61f0c62009-02-27 21:25:17 +0000356 if (ret == 0)
357 num_openfiles--;
Nicolas Pennequinef9abe42007-10-09 15:15:00 +0000358 return ret;
Daniel Stenberg91f165e2002-05-05 10:28:23 +0000359}
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000360
Jens Arnold67eb1542007-02-01 23:08:15 +0000361int sim_creat(const char *name)
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000362{
Steve Bavinb61f0c62009-02-27 21:25:17 +0000363 return OPEN(get_sim_pathname(name), O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, 0666);
Steve Bavinf87eb602007-11-08 12:11:34 +0000364}
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000365
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000366ssize_t sim_read(int fd, void *buf, size_t count)
367{
368 ssize_t result;
369
370 mutex_lock(&io.sim_mutex);
371
372 /* Setup parameters */
373 io.fd = fd;
374 io.buf = buf;
375 io.count = count;
376
Michael Sevakisa4d19b72007-12-03 14:01:12 +0000377 result = io_trigger_and_wait(IO_READ);
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000378
379 mutex_unlock(&io.sim_mutex);
380
381 return result;
382}
383
384ssize_t sim_write(int fd, const void *buf, size_t count)
385{
386 ssize_t result;
387
388 mutex_lock(&io.sim_mutex);
389
390 io.fd = fd;
391 io.buf = (void*)buf;
392 io.count = count;
393
Michael Sevakisa4d19b72007-12-03 14:01:12 +0000394 result = io_trigger_and_wait(IO_WRITE);
Michael Sevakisf64ebb12007-09-08 12:20:53 +0000395
396 mutex_unlock(&io.sim_mutex);
397
398 return result;
399}
400
Jens Arnold6b0fdae2007-02-03 10:28:55 +0000401int sim_mkdir(const char *name)
Linus Nielsen Feltzingef7293f2004-01-21 14:58:40 +0000402{
Steve Bavinb61f0c62009-02-27 21:25:17 +0000403 return MKDIR(get_sim_pathname(name), 0777);
Linus Nielsen Feltzingef7293f2004-01-21 14:58:40 +0000404}
405
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000406int sim_rmdir(const char *name)
Linus Nielsen Feltzing8fa821d2004-04-16 09:24:38 +0000407{
Steve Bavinb61f0c62009-02-27 21:25:17 +0000408 return RMDIR(get_sim_pathname(name));
Linus Nielsen Feltzing8fa821d2004-04-16 09:24:38 +0000409}
410
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000411int sim_remove(const char *name)
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000412{
Miika Pekkarinend70bd0e2006-08-26 14:19:18 +0000413#ifdef HAVE_DIRCACHE
414 dircache_remove(name);
415#endif
Steve Bavinb61f0c62009-02-27 21:25:17 +0000416 return REMOVE(get_sim_pathname(name));
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000417}
418
Steve Bavinb61f0c62009-02-27 21:25:17 +0000419int sim_rename(const char *oldname, const char *newname)
Björn Stenberg7d80ba02003-01-15 11:38:03 +0000420{
Miika Pekkarinend70bd0e2006-08-26 14:19:18 +0000421#ifdef HAVE_DIRCACHE
Steve Bavinb61f0c62009-02-27 21:25:17 +0000422 dircache_rename(oldname, newname);
Miika Pekkarinend70bd0e2006-08-26 14:19:18 +0000423#endif
Steve Bavinb61f0c62009-02-27 21:25:17 +0000424 return RENAME(get_sim_pathname(oldname), get_sim_pathname(newname));
Björn Stenberg7d80ba02003-01-15 11:38:03 +0000425}
426
Jens Arnold399c0812005-02-28 18:32:57 +0000427/* rockbox off_t may be different from system off_t */
428long sim_lseek(int fildes, long offset, int whence)
Linus Nielsen Feltzinge98bad52003-03-18 00:39:57 +0000429{
Jens Arnold399c0812005-02-28 18:32:57 +0000430 return lseek(fildes, offset, whence);
431}
432
433long sim_filesize(int fd)
434{
Jens Arnoldbb9dfa02005-03-09 19:26:59 +0000435#ifdef WIN32
436 return _filelength(fd);
437#else
438 struct stat buf;
Steve Bavinf87eb602007-11-08 12:11:34 +0000439
Jens Arnoldbb9dfa02005-03-09 19:26:59 +0000440 if (!fstat(fd, &buf))
441 return buf.st_size;
442 else
443 return -1;
444#endif
Linus Nielsen Feltzinge98bad52003-03-18 00:39:57 +0000445}
446
Jens Arnold51280802007-09-13 20:53:32 +0000447void fat_size(IF_MV2(int volume,) unsigned long* size, unsigned long* free)
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000448{
Jens Arnold51280802007-09-13 20:53:32 +0000449#ifdef HAVE_MULTIVOLUME
450 if (volume != 0) {
Steve Bavinac313ab2008-04-07 17:27:56 +0000451 /* debugf("io.c: fat_size(volume=%d); simulator only supports volume 0\n",volume); */
Steve Bavinf87eb602007-11-08 12:11:34 +0000452
Jens Arnold51280802007-09-13 20:53:32 +0000453 if (size) *size = 0;
454 if (free) *free = 0;
455 return;
456 }
457#endif
458
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000459#ifdef WIN32
Jens Arnold78724262005-02-22 21:55:48 +0000460 long secperclus, bytespersec, free_clusters, num_clusters;
461
462 if (GetDiskFreeSpace(NULL, &secperclus, &bytespersec, &free_clusters,
463 &num_clusters)) {
464 if (size)
465 *size = num_clusters * secperclus / 2 * (bytespersec / 512);
466 if (free)
467 *free = free_clusters * secperclus / 2 * (bytespersec / 512);
468 }
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000469#else
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000470 struct statfs fs;
471
472 if (!statfs(".", &fs)) {
Jens Arnoldbd5c0ad2007-03-17 10:50:58 +0000473 DEBUGF("statfs: bsize=%d blocks=%ld free=%ld\n",
474 (int)fs.f_bsize, fs.f_blocks, fs.f_bfree);
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000475 if (size)
476 *size = fs.f_blocks * (fs.f_bsize / 1024);
477 if (free)
478 *free = fs.f_bfree * (fs.f_bsize / 1024);
479 }
Jens Arnold78724262005-02-22 21:55:48 +0000480#endif
Björn Stenberg6fb512a2002-11-12 11:32:26 +0000481 else {
482 if (size)
483 *size = 0;
484 if (free)
485 *free = 0;
486 }
487}
Daniel Stenberg22b77012005-02-22 12:19:12 +0000488
489int sim_fsync(int fd)
490{
491#ifdef WIN32
492 return _commit(fd);
493#else
494 return fsync(fd);
495#endif
496}
497
498#ifdef WIN32
499/* sim-win32 */
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000500#define dlopen(_x_, _y_) LoadLibraryW(UTF8_TO_OS(_x_))
Jens Arnoldcf208c52005-02-22 18:21:16 +0000501#define dlsym(_x_, _y_) (void *)GetProcAddress(_x_, _y_)
Daniel Stenberg22b77012005-02-22 12:19:12 +0000502#define dlclose(_x_) FreeLibrary(_x_)
Daniel Stenberg22b77012005-02-22 12:19:12 +0000503#else
504/* sim-x11 */
505#include <dlfcn.h>
506#endif
507
Nicolas Pennequinc70671b2007-11-02 17:43:37 +0000508void *sim_codec_load_ram(char* codecptr, int size, void **pd)
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000509{
Jens Arnold38b75472006-03-02 01:08:38 +0000510 void *hdr;
Steve Bavinb61f0c62009-02-27 21:25:17 +0000511 char name[MAX_PATH];
Hardeep Sidhu25377db2006-06-17 09:42:16 +0000512 char path[MAX_PATH];
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000513 int fd;
Steve Bavin8c9d5f32006-09-28 08:46:28 +0000514 int codec_count;
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000515#ifdef WIN32
Peter D'Hoye6be61562007-04-12 22:38:54 +0000516 char buf[MAX_PATH];
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000517#endif
518
Jens Arnold38b75472006-03-02 01:08:38 +0000519 *pd = NULL;
Jens Arnoldb8749fd2006-01-18 00:05:14 +0000520
Steve Bavinf87eb602007-11-08 12:11:34 +0000521 /* We have to create the dynamic link library file from ram so we
Steve Bavin8c9d5f32006-09-28 08:46:28 +0000522 can simulate the codec loading. With voice and crossfade,
Steve Bavinf87eb602007-11-08 12:11:34 +0000523 multiple codecs may be loaded at the same time, so we need
Steve Bavin8c9d5f32006-09-28 08:46:28 +0000524 to find an unused filename */
525 for (codec_count = 0; codec_count < 10; codec_count++)
526 {
Steve Bavinb61f0c62009-02-27 21:25:17 +0000527 snprintf(name, sizeof(name), "/_temp_codec%d.dll", codec_count);
528 snprintf(path, sizeof(path), "%s", get_sim_pathname(name));
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000529 fd = OPEN(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRWXU);
Steve Bavin8c9d5f32006-09-28 08:46:28 +0000530 if (fd >= 0)
531 break; /* Created a file ok */
532 }
Jens Arnold67eb1542007-02-01 23:08:15 +0000533 if (fd < 0)
Steve Bavin8c9d5f32006-09-28 08:46:28 +0000534 {
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000535 DEBUGF("failed to open for write: %s\n", path);
536 return NULL;
537 }
538
Steve Bavinb61f0c62009-02-27 21:25:17 +0000539 if (write(fd, codecptr, size) != size)
540 {
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000541 DEBUGF("write failed");
542 return NULL;
543 }
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000544 close(fd);
Jens Arnoldb8749fd2006-01-18 00:05:14 +0000545
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000546 /* Now load the library. */
Jens Arnold38b75472006-03-02 01:08:38 +0000547 *pd = dlopen(path, RTLD_NOW);
Steve Bavinb61f0c62009-02-27 21:25:17 +0000548 if (*pd == NULL)
Steve Bavin6eea66f2009-02-27 21:15:52 +0000549 {
Steve Bavinf87eb602007-11-08 12:11:34 +0000550 DEBUGF("failed to load %s\n", path);
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000551#ifdef WIN32
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000552 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
553 buf, sizeof buf, NULL);
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000554 DEBUGF("dlopen(%s): %s\n", path, buf);
555#else
556 DEBUGF("dlopen(%s): %s\n", path, dlerror());
557#endif
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000558 return NULL;
559 }
560
Jens Arnold38b75472006-03-02 01:08:38 +0000561 hdr = dlsym(*pd, "__header");
Jens Arnoldb8749fd2006-01-18 00:05:14 +0000562 if (!hdr)
Jens Arnold38b75472006-03-02 01:08:38 +0000563 hdr = dlsym(*pd, "___header");
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000564
Jens Arnoldb8749fd2006-01-18 00:05:14 +0000565 return hdr; /* maybe NULL if symbol not present */
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000566}
567
Jens Arnold38b75472006-03-02 01:08:38 +0000568void sim_codec_close(void *pd)
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000569{
Jens Arnold38b75472006-03-02 01:08:38 +0000570 dlclose(pd);
Miika Pekkarinen645a2e12005-07-10 16:33:03 +0000571}
572
Jens Arnold38b75472006-03-02 01:08:38 +0000573void *sim_plugin_load(char *plugin, void **pd)
Daniel Stenberg22b77012005-02-22 12:19:12 +0000574{
Jens Arnold38b75472006-03-02 01:08:38 +0000575 void *hdr;
Peter D'Hoye6be61562007-04-12 22:38:54 +0000576 char path[MAX_PATH];
Jens Arnoldcf208c52005-02-22 18:21:16 +0000577#ifdef WIN32
Peter D'Hoye6be61562007-04-12 22:38:54 +0000578 char buf[MAX_PATH];
Jens Arnoldcf208c52005-02-22 18:21:16 +0000579#endif
580
Steve Bavinb61f0c62009-02-27 21:25:17 +0000581 snprintf(path, sizeof(path), "%s", get_sim_pathname(plugin));
Peter D'Hoye6be61562007-04-12 22:38:54 +0000582
Jens Arnold38b75472006-03-02 01:08:38 +0000583 *pd = NULL;
Jens Arnolda7902772006-01-16 23:20:58 +0000584
Jens Arnold38b75472006-03-02 01:08:38 +0000585 *pd = dlopen(path, RTLD_NOW);
586 if (*pd == NULL) {
Jens Arnoldcf208c52005-02-22 18:21:16 +0000587 DEBUGF("failed to load %s\n", plugin);
588#ifdef WIN32
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000589 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
590 buf, sizeof(buf), NULL);
Jens Arnoldcf208c52005-02-22 18:21:16 +0000591 DEBUGF("dlopen(%s): %s\n", path, buf);
592#else
593 DEBUGF("dlopen(%s): %s\n", path, dlerror());
594#endif
Daniel Stenberg22b77012005-02-22 12:19:12 +0000595 return NULL;
596 }
597
Jens Arnold38b75472006-03-02 01:08:38 +0000598 hdr = dlsym(*pd, "__header");
Jens Arnolda7902772006-01-16 23:20:58 +0000599 if (!hdr)
Jens Arnold38b75472006-03-02 01:08:38 +0000600 hdr = dlsym(*pd, "___header");
Jens Arnolda7902772006-01-16 23:20:58 +0000601
Jens Arnolda7902772006-01-16 23:20:58 +0000602 return hdr; /* maybe NULL if symbol not present */
Daniel Stenberg22b77012005-02-22 12:19:12 +0000603}
604
Jens Arnold38b75472006-03-02 01:08:38 +0000605void sim_plugin_close(void *pd)
Daniel Stenberg22b77012005-02-22 12:19:12 +0000606{
Jens Arnold38b75472006-03-02 01:08:38 +0000607 dlclose(pd);
Daniel Stenberg22b77012005-02-22 12:19:12 +0000608}
609
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000610#ifdef WIN32
611static unsigned old_cp;
Daniel Stenberg22b77012005-02-22 12:19:12 +0000612
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000613void debug_exit(void)
614{
615 /* Reset console output codepage */
616 SetConsoleOutputCP(old_cp);
617}
618
619void debug_init(void)
620{
621 old_cp = GetConsoleOutputCP();
622 /* Set console output codepage to UTF8. Only works
623 * correctly when the console uses a truetype font. */
624 SetConsoleOutputCP(65001);
625 atexit(debug_exit);
626}
627#else
Daniel Stenberg22b77012005-02-22 12:19:12 +0000628void debug_init(void)
629{
630 /* nothing to be done */
631}
Jens Arnold2fd7c3c2007-04-19 20:17:24 +0000632#endif
Daniel Stenberg22b77012005-02-22 12:19:12 +0000633
634void debugf(const char *fmt, ...)
635{
636 va_list ap;
637 va_start( ap, fmt );
638 vfprintf( stderr, fmt, ap );
639 va_end( ap );
640}
641
642void ldebugf(const char* file, int line, const char *fmt, ...)
643{
644 va_list ap;
645 va_start( ap, fmt );
646 fprintf( stderr, "%s:%d ", file, line );
647 vfprintf( stderr, fmt, ap );
648 va_end( ap );
649}
650
Jens Arnold576d0292005-03-05 21:48:58 +0000651/* rockbox off_t may be different from system off_t */
652int sim_ftruncate(int fd, long length)
Daniel Stenberg22b77012005-02-22 12:19:12 +0000653{
654#ifdef WIN32
655 return _chsize(fd, length);
656#else
657 return ftruncate(fd, length);
658#endif
659}