PageRenderTime 75ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/filesys.cpp

https://github.com/tonioni/WinUAE
C++ | 10368 lines | 10225 code | 86 blank | 57 comment | 152 complexity | ec14108ce989ddb29ad600a1052dc3f7 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * UAE - The Un*x Amiga Emulator
  3. *
  4. * Unix file system handler for AmigaDOS
  5. *
  6. * Copyright 1996 Ed Hanway
  7. * Copyright 1996, 1997 Bernd Schmidt
  8. *
  9. * Version 0.4: 970308
  10. *
  11. * Based on example code (c) 1988 The Software Distillery
  12. * and published in Transactor for the Amiga, Volume 2, Issues 2-5.
  13. * (May - August 1989)
  14. *
  15. * Known limitations:
  16. * Does not support several (useless) 2.0+ packet types.
  17. * May not return the correct error code in some cases.
  18. * Does not check for sane values passed by AmigaDOS. May crash the emulation
  19. * if passed garbage values.
  20. * Could do tighter checks on malloc return values.
  21. * Will probably fail spectacularly in some cases if the filesystem is
  22. * modified at the same time by another process while UAE is running.
  23. */
  24. #include "sysconfig.h"
  25. #include "sysdeps.h"
  26. #include "threaddep/thread.h"
  27. #include "options.h"
  28. #include "traps.h"
  29. #include "uae.h"
  30. #include "memory.h"
  31. #include "custom.h"
  32. #include "events.h"
  33. #include "newcpu.h"
  34. #include "filesys.h"
  35. #include "autoconf.h"
  36. #include "fsusage.h"
  37. #include "native2amiga.h"
  38. #include "scsidev.h"
  39. #include "uaeserial.h"
  40. #include "fsdb.h"
  41. #include "zfile.h"
  42. #include "zarchive.h"
  43. #include "gui.h"
  44. #include "gayle.h"
  45. #include "idecontrollers.h"
  46. #include "savestate.h"
  47. #include "a2091.h"
  48. #include "ncr_scsi.h"
  49. #include "cdtv.h"
  50. #include "sana2.h"
  51. #include "bsdsocket.h"
  52. #include "uaeresource.h"
  53. #include "inputdevice.h"
  54. #include "clipboard.h"
  55. #include "consolehook.h"
  56. #include "blkdev.h"
  57. #include "isofs_api.h"
  58. #include "scsi.h"
  59. #include "uaenative.h"
  60. #include "tabletlibrary.h"
  61. #include "cia.h"
  62. #include "picasso96.h"
  63. #include "cpuboard.h"
  64. #include "rommgr.h"
  65. #include "debug.h"
  66. #include "debugmem.h"
  67. #ifdef RETROPLATFORM
  68. #include "rp.h"
  69. #endif
  70. #define TRACING_ENABLED 1
  71. int log_filesys = 0;
  72. #define TRAPMD 1
  73. #if TRACING_ENABLED
  74. #if 0
  75. #define TRACE(x) if (log_filesys > 0 && (unit->volflags & MYVOLUMEINFO_CDFS)) { write_log x; }
  76. #else
  77. #define TRACE(x) if (log_filesys > 0) { write_log x; }
  78. #endif
  79. #define TRACEI(x) if (log_filesys > 0) { write_log x; }
  80. #define TRACE2(x) if (log_filesys >= 2) { write_log x; }
  81. #define TRACE3(x) if (log_filesys >= 3) { write_log x; }
  82. #define DUMPLOCK(c,u,x) dumplock(c,u,x)
  83. #else
  84. #define TRACE(x)
  85. #define DUMPLOCK(c,u,x)
  86. #define TRACE2(x)
  87. #define TRACE3(x)
  88. #endif
  89. #define KS12_BOOT_HACK 1
  90. #define UNIT_LED(unit) ((unit)->ui.unit_type == UNIT_CDFS ? LED_CD : LED_HD)
  91. static int bootrom_header;
  92. static uae_u32 dlg (uae_u32 a)
  93. {
  94. return (dbg (a + 0) << 24) | (dbg (a + 1) << 16) | (dbg (a + 2) << 8) | (dbg (a + 3) << 0);
  95. }
  96. static void aino_test (a_inode *aino)
  97. {
  98. #ifdef AINO_DEBUG
  99. a_inode *aino2 = aino, *aino3;
  100. for (;;) {
  101. if (!aino || !aino->next)
  102. return;
  103. if ((aino->checksum1 ^ aino->checksum2) != 0xaaaa5555) {
  104. write_log (_T("PANIC: corrupted or freed but used aino detected!"), aino);
  105. }
  106. aino3 = aino;
  107. aino = aino->next;
  108. if (aino->prev != aino3) {
  109. write_log (_T("PANIC: corrupted aino linking!\n"));
  110. break;
  111. }
  112. if (aino == aino2) break;
  113. }
  114. #endif
  115. }
  116. static void aino_test_init (a_inode *aino)
  117. {
  118. #ifdef AINO_DEBUG
  119. aino->checksum1 = (uae_u32)aino;
  120. aino->checksum2 = aino->checksum1 ^ 0xaaaa5555;
  121. #endif
  122. }
  123. #define UAEFS_VERSION "UAE fs 0.6"
  124. uaecptr filesys_initcode, filesys_initcode_ptr, filesys_initcode_real;
  125. static uaecptr bootrom_start;
  126. static uae_u32 fsdevname, fshandlername, filesys_configdev;
  127. static uae_u32 cdfs_devname, cdfs_handlername;
  128. static uaecptr afterdos_name, afterdos_id, afterdos_initcode;
  129. static uaecptr keymaphook_name, keymaphook_id, keymaphook_initcode;
  130. static uaecptr shell_execute_data, shell_execute_process;
  131. static int filesys_in_interrupt;
  132. static uae_u32 mountertask;
  133. static int automountunit = -1;
  134. static int autocreatedunit;
  135. static int cd_unit_offset, cd_unit_number;
  136. static uaecptr ROM_filesys_doio, ROM_filesys_doio_original;
  137. static uaecptr ROM_filesys_putmsg, ROM_filesys_putmsg_original;
  138. static uaecptr ROM_filesys_putmsg_return;
  139. static uaecptr ROM_filesys_hack_remove;
  140. static smp_comm_pipe shellexecute_pipe;
  141. static uae_u32 segtrack_mode = 0;
  142. #define FS_STARTUP 0
  143. #define FS_GO_DOWN 1
  144. #define DEVNAMES_PER_HDF 32
  145. #define UNIT_FILESYSTEM 0
  146. #define UNIT_CDFS 1
  147. typedef struct {
  148. int unit_type;
  149. int open; // >0 start as filesystem, <0 = allocated but do not start
  150. TCHAR *devname; /* device name, e.g. UAE0: */
  151. uaecptr devname_amiga;
  152. uaecptr startup;
  153. uaecptr devicenode;
  154. uaecptr parmpacket;
  155. TCHAR *volname; /* volume name, e.g. CDROM, WORK, etc. */
  156. int volflags; /* volume flags, readonly, stream uaefsdb support */
  157. TCHAR *rootdir; /* root native directory/hdf. empty drive if invalid path */
  158. TCHAR *rootdirdiff; /* "diff" file/directory */
  159. bool readonly; /* disallow write access? */
  160. bool locked; /* action write protect */
  161. bool unknown_media; /* ID_UNREADABLE_DISK */
  162. int bootpri; /* boot priority. -128 = no autoboot, -129 = no mount */
  163. int devno;
  164. bool wasisempty; /* if true, this unit was created empty */
  165. int canremove; /* if >0, this unit can be safely ejected and remounted */
  166. bool configureddrive; /* if true, this is drive that was manually configured */
  167. bool inject_icons; /* inject icons if directory filesystem */
  168. struct hardfiledata hf;
  169. struct zvolume *zarchive;
  170. /* Threading stuff */
  171. smp_comm_pipe *volatile unit_pipe, *volatile back_pipe;
  172. uae_thread_id tid;
  173. struct _unit *self;
  174. /* Reset handling */
  175. uae_sem_t reset_sync_sem;
  176. volatile int reset_state;
  177. /* RDB stuff */
  178. uaecptr rdb_devname_amiga[DEVNAMES_PER_HDF];
  179. int rdb_lowcyl;
  180. int rdb_highcyl;
  181. int rdb_cylblocks;
  182. uae_u8 *rdb_filesysstore;
  183. int rdb_filesyssize;
  184. TCHAR *filesysdir;
  185. /* filesystem seglist */
  186. uaecptr filesysseg;
  187. uae_u32 rdb_dostype;
  188. /* CDFS */
  189. bool cd_open;
  190. int cddevno;
  191. void *cdfs_superblock;
  192. } UnitInfo;
  193. struct uaedev_mount_info {
  194. UnitInfo ui[MAX_FILESYSTEM_UNITS];
  195. };
  196. static struct uaedev_mount_info mountinfo;
  197. /* minimal AmigaDOS definitions */
  198. /* field offsets in DosPacket */
  199. #define dp_Type 8
  200. #define dp_Res1 12
  201. #define dp_Res2 16
  202. #define dp_Arg1 20
  203. #define dp_Arg2 24
  204. #define dp_Arg3 28
  205. #define dp_Arg4 32
  206. #define dp_Arg5 36
  207. #define DP64_INIT -3L
  208. #define dp64_Type 8
  209. #define dp64_Res0 12
  210. #define dp64_Res2 16
  211. #define dp64_Res1 24
  212. #define dp64_Arg1 32
  213. #define dp64_Arg2 40
  214. #define dp64_Arg3 48
  215. #define dp64_Arg4 52
  216. #define dp64_Arg5 56
  217. #define dp_Max 60
  218. /* result codes */
  219. #define DOS_TRUE ((uae_u32)-1L)
  220. #define DOS_FALSE (0L)
  221. /* DirEntryTypes */
  222. #define ST_PIPEFILE -5
  223. #define ST_LINKFILE -4
  224. #define ST_FILE -3
  225. #define ST_ROOT 1
  226. #define ST_USERDIR 2
  227. #define ST_SOFTLINK 3
  228. #define ST_LINKDIR 4
  229. #if 1
  230. #define MAXFILESIZE32 (0xffffffff)
  231. #else
  232. /* technically correct but most native
  233. * filesystems don't enforce it
  234. */
  235. #define MAXFILESIZE32 (0x7fffffff)
  236. #endif
  237. #define MAXFILESIZE32_2G (0x7fffffff)
  238. /* Passed as type to Lock() */
  239. #define SHARED_LOCK -2 /* File is readable by others */
  240. #define ACCESS_READ -2 /* Synonym */
  241. #define EXCLUSIVE_LOCK -1 /* No other access allowed */
  242. #define ACCESS_WRITE -1 /* Synonym */
  243. /* packet types */
  244. #define ACTION_CURRENT_VOLUME 7
  245. #define ACTION_LOCATE_OBJECT 8
  246. #define ACTION_RENAME_DISK 9
  247. #define ACTION_FREE_LOCK 15
  248. #define ACTION_DELETE_OBJECT 16
  249. #define ACTION_RENAME_OBJECT 17
  250. #define ACTION_MORE_CACHE 18
  251. #define ACTION_COPY_DIR 19
  252. #define ACTION_SET_PROTECT 21
  253. #define ACTION_CREATE_DIR 22
  254. #define ACTION_EXAMINE_OBJECT 23
  255. #define ACTION_EXAMINE_NEXT 24
  256. #define ACTION_DISK_INFO 25
  257. #define ACTION_INFO 26
  258. #define ACTION_FLUSH 27
  259. #define ACTION_SET_COMMENT 28
  260. #define ACTION_PARENT 29
  261. #define ACTION_SET_DATE 34
  262. #define ACTION_FIND_WRITE 1004
  263. #define ACTION_FIND_INPUT 1005
  264. #define ACTION_FIND_OUTPUT 1006
  265. #define ACTION_END 1007
  266. #define ACTION_SEEK 1008
  267. #define ACTION_WRITE_PROTECT 1023
  268. #define ACTION_IS_FILESYSTEM 1027
  269. #define ACTION_READ 'R'
  270. #define ACTION_WRITE 'W'
  271. /* 2.0+ packet types */
  272. #define ACTION_INHIBIT 31
  273. #define ACTION_SET_FILE_SIZE 1022
  274. #define ACTION_LOCK_RECORD 2008
  275. #define ACTION_FREE_RECORD 2009
  276. #define ACTION_SAME_LOCK 40
  277. #define ACTION_CHANGE_MODE 1028
  278. #define ACTION_FH_FROM_LOCK 1026
  279. #define ACTION_COPY_DIR_FH 1030
  280. #define ACTION_PARENT_FH 1031
  281. #define ACTION_EXAMINE_ALL 1033
  282. #define ACTION_EXAMINE_FH 1034
  283. #define ACTION_EXAMINE_ALL_END 1035
  284. #define ACTION_FORMAT 1020
  285. #define ACTION_IS_FILESYSTEM 1027
  286. #define ACTION_ADD_NOTIFY 4097
  287. #define ACTION_REMOVE_NOTIFY 4098
  288. #define ACTION_READ_LINK 1024
  289. /* OS4 64-bit filesize packets */
  290. #define ACTION_FILESYSTEM_ATTR 3005
  291. #define ACTION_CHANGE_FILE_POSITION64 8001
  292. #define ACTION_GET_FILE_POSITION64 8002
  293. #define ACTION_CHANGE_FILE_SIZE64 8003
  294. #define ACTION_GET_FILE_SIZE64 8004
  295. /* MOS 64-bit filesize packets */
  296. #define ACTION_SEEK64 26400
  297. #define ACTION_SET_FILE_SIZE64 26401
  298. #define ACTION_LOCK_RECORD64 26402
  299. #define ACTION_FREE_RECORD64 26403
  300. #define ACTION_QUERY_ATTR 26407
  301. #define ACTION_EXAMINE_OBJECT64 26408
  302. #define ACTION_EXAMINE_NEXT64 26409
  303. #define ACTION_EXAMINE_FH64 26410
  304. /* not supported */
  305. #define ACTION_MAKE_LINK 1021
  306. #define DISK_TYPE_DOS 0x444f5300 /* DOS\0 */
  307. #define DISK_TYPE_DOS_FFS 0x444f5301 /* DOS\1 */
  308. #define CDFS_DOSTYPE 0x43440000 /* CDxx */
  309. typedef struct _dpacket {
  310. uaecptr packet_addr;
  311. uae_u8 *packet_data;
  312. uae_u8 packet_array[dp_Max];
  313. bool need_flush;
  314. } dpacket;
  315. typedef struct {
  316. uae_u32 uniq;
  317. /* The directory we're going through. */
  318. a_inode *aino;
  319. /* The file we're going to look up next. */
  320. a_inode *curr_file;
  321. } ExamineKey;
  322. struct lockrecord
  323. {
  324. struct lockrecord *next;
  325. dpacket *packet;
  326. uae_u64 pos;
  327. uae_u64 len;
  328. uae_u32 mode;
  329. uae_u32 timeout;
  330. uae_u32 msg;
  331. };
  332. typedef struct key {
  333. struct key *next;
  334. a_inode *aino;
  335. uae_u32 uniq;
  336. struct fs_filehandle *fd;
  337. uae_u64 file_pos;
  338. int dosmode;
  339. int createmode;
  340. int notifyactive;
  341. struct lockrecord *record;
  342. } Key;
  343. typedef struct notify {
  344. struct notify *next;
  345. uaecptr notifyrequest;
  346. TCHAR *fullname;
  347. TCHAR *partname;
  348. } Notify;
  349. typedef struct exallkey {
  350. uae_u32 id;
  351. struct fs_dirhandle *dirhandle;
  352. TCHAR *fn;
  353. uaecptr control;
  354. } ExAllKey;
  355. /* Since ACTION_EXAMINE_NEXT is so braindamaged, we have to keep
  356. * some of these around
  357. */
  358. #define EXKEYS 128
  359. #define EXALLKEYS 100
  360. #define MAX_AINO_HASH 128
  361. #define NOTIFY_HASH_SIZE 127
  362. /* handler state info */
  363. typedef struct _unit {
  364. struct _unit *next;
  365. /* Amiga stuff */
  366. uaecptr dosbase;
  367. /* volume points to our IO board, always 1:1 mapping */
  368. uaecptr volume;
  369. uaecptr port; /* Our port */
  370. uaecptr locklist;
  371. /* Native stuff */
  372. uae_s32 unit; /* unit number */
  373. UnitInfo ui; /* unit startup info */
  374. TCHAR tmpbuf3[256];
  375. /* Dummy message processing */
  376. uaecptr dummy_message;
  377. volatile unsigned int cmds_sent;
  378. volatile unsigned int cmds_complete;
  379. volatile unsigned int cmds_acked;
  380. /* ExKeys */
  381. ExamineKey examine_keys[EXKEYS];
  382. int next_exkey;
  383. unsigned int total_locked_ainos;
  384. /* ExAll */
  385. ExAllKey exalls[EXALLKEYS];
  386. int exallid;
  387. /* Keys */
  388. struct key *keys;
  389. struct lockrecord *waitingrecords;
  390. a_inode rootnode;
  391. unsigned int aino_cache_size;
  392. a_inode *aino_hash[MAX_AINO_HASH];
  393. unsigned int nr_cache_hits;
  394. unsigned int nr_cache_lookups;
  395. struct notify *notifyhash[NOTIFY_HASH_SIZE];
  396. int volflags;
  397. uae_u32 lockkey;
  398. bool inhibited;
  399. bool canremovable;
  400. /* increase when media is changed.
  401. * used to detect if cached aino is valid
  402. */
  403. int mountcount;
  404. int mount_changed;
  405. void *cdfs_superblock;
  406. TCHAR *mount_volume;
  407. TCHAR *mount_rootdir;
  408. bool mount_readonly;
  409. int mount_flags;
  410. int reinsertdelay;
  411. TCHAR *newvolume;
  412. TCHAR *newrootdir;
  413. bool newreadonly;
  414. int newflags;
  415. } Unit;
  416. int nr_units (void)
  417. {
  418. int cnt = 0;
  419. for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
  420. if (mountinfo.ui[i].open > 0)
  421. cnt++;
  422. }
  423. return cnt;
  424. }
  425. int nr_directory_units (struct uae_prefs *p)
  426. {
  427. int cnt = 0;
  428. if (p) {
  429. for (int i = 0; i < p->mountitems; i++) {
  430. if (p->mountconfig[i].ci.controller_type == HD_CONTROLLER_TYPE_UAE)
  431. cnt++;
  432. }
  433. } else {
  434. for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
  435. if (mountinfo.ui[i].open > 0 && mountinfo.ui[i].hf.ci.controller_type == HD_CONTROLLER_TYPE_UAE)
  436. cnt++;
  437. }
  438. }
  439. return cnt;
  440. }
  441. static int is_virtual (int unit_no)
  442. {
  443. int t = is_hardfile (unit_no);
  444. return t == FILESYS_VIRTUAL || t == FILESYS_CD;
  445. }
  446. int is_hardfile (int unit_no)
  447. {
  448. if (mountinfo.ui[unit_no].volname || mountinfo.ui[unit_no].wasisempty || mountinfo.ui[unit_no].unknown_media) {
  449. if (unit_no >= cd_unit_offset && unit_no < cd_unit_offset + cd_unit_number)
  450. return FILESYS_CD;
  451. return FILESYS_VIRTUAL;
  452. }
  453. if (mountinfo.ui[unit_no].hf.ci.sectors == 0) {
  454. if (mountinfo.ui[unit_no].hf.flags & 1)
  455. return FILESYS_HARDDRIVE;
  456. return FILESYS_HARDFILE_RDB;
  457. }
  458. return FILESYS_HARDFILE;
  459. }
  460. static void close_filesys_unit (UnitInfo *uip)
  461. {
  462. if (!uip->open)
  463. return;
  464. if (uip->hf.handle_valid)
  465. hdf_close (&uip->hf);
  466. if (uip->volname != 0)
  467. xfree (uip->volname);
  468. if (uip->devname != 0)
  469. xfree (uip->devname);
  470. if (uip->rootdir != 0)
  471. xfree (uip->rootdir);
  472. if (uip->unit_pipe)
  473. xfree (uip->unit_pipe);
  474. if (uip->back_pipe)
  475. xfree (uip->back_pipe);
  476. if (uip->cd_open) {
  477. sys_command_close (uip->cddevno);
  478. isofs_unmount (uip->cdfs_superblock);
  479. }
  480. uip->unit_pipe = 0;
  481. uip->back_pipe = 0;
  482. uip->hf.handle_valid = 0;
  483. uip->volname = 0;
  484. uip->devname = 0;
  485. uip->rootdir = 0;
  486. uip->open = 0;
  487. uip->cd_open = 0;
  488. }
  489. static uaedev_config_data *getuci (struct uaedev_config_data *uci, int nr)
  490. {
  491. return &uci[nr];
  492. }
  493. static UnitInfo *getuip (struct uae_prefs *p, int index)
  494. {
  495. if (index < 0)
  496. return NULL;
  497. index = p->mountconfig[index].configoffset;
  498. if (index < 0)
  499. return NULL;
  500. return &mountinfo.ui[index];
  501. }
  502. static int getuindex (struct uae_prefs *p, int index)
  503. {
  504. if (index < 0)
  505. return -1;
  506. return p->mountconfig[index].unitnum;
  507. }
  508. int get_filesys_unitconfig (struct uae_prefs *p, int index, struct mountedinfo *mi)
  509. {
  510. UnitInfo *ui = getuip (p, index);
  511. struct uaedev_config_data *uci = &p->mountconfig[index];
  512. UnitInfo uitmp;
  513. TCHAR filepath[MAX_DPATH];
  514. memset (mi, 0, sizeof (struct mountedinfo));
  515. memset (&uitmp, 0, sizeof uitmp);
  516. _tcscpy(mi->rootdir, uci->ci.rootdir);
  517. if (!ui) {
  518. ui = &uitmp;
  519. if (uci->ci.type == UAEDEV_DIR) {
  520. cfgfile_resolve_path_out_load(uci->ci.rootdir, filepath, MAX_DPATH, PATH_DIR);
  521. _tcscpy(mi->rootdir, filepath);
  522. mi->ismounted = 1;
  523. if (filepath[0] == 0)
  524. return FILESYS_VIRTUAL;
  525. if (my_existsfile (filepath)) {
  526. mi->ismedia = 1;
  527. return FILESYS_VIRTUAL;
  528. }
  529. if (my_getvolumeinfo (filepath) < 0)
  530. return -1;
  531. mi->ismedia = true;
  532. return FILESYS_VIRTUAL;
  533. } else if (uci->ci.type == UAEDEV_HDF) {
  534. cfgfile_resolve_path_out_load(uci->ci.rootdir, filepath, MAX_DPATH, PATH_HDF);
  535. _tcscpy(mi->rootdir, filepath);
  536. ui->hf.ci.readonly = true;
  537. ui->hf.ci.blocksize = uci->ci.blocksize;
  538. int err = hdf_open (&ui->hf, filepath);
  539. if (err <= 0) {
  540. mi->ismedia = false;
  541. mi->ismounted = true;
  542. mi->error = err;
  543. if (uci->ci.reserved == 0 && uci->ci.sectors == 0 && uci->ci.surfaces == 0) {
  544. if (ui->hf.flags & 1)
  545. return FILESYS_HARDDRIVE;
  546. return FILESYS_HARDFILE_RDB;
  547. }
  548. return -1;
  549. }
  550. mi->ismedia = true;
  551. if (ui->hf.drive_empty)
  552. mi->ismedia = 0;
  553. hdf_close (&ui->hf);
  554. } else if (uci->ci.type == UAEDEV_CD) {
  555. cfgfile_resolve_path_out_load(uci->ci.rootdir, filepath, MAX_DPATH, PATH_CD);
  556. _tcscpy(mi->rootdir, filepath);
  557. struct device_info di;
  558. ui->hf.ci.readonly = true;
  559. ui->hf.ci.blocksize = uci->ci.blocksize;
  560. mi->size = -1;
  561. mi->ismounted = true;
  562. if (blkdev_get_info (p, ui->hf.ci.device_emu_unit, &di)) {
  563. mi->ismedia = di.media_inserted != 0;
  564. _tcscpy (mi->rootdir, di.label);
  565. }
  566. #if 0
  567. if (ui->hf.ci.cd_emu_unit == 0)
  568. _tcscpy (mi->rootdir, _T("CD"));
  569. else
  570. _stprintf (mi->rootdir, _T("CD %d"), ui->hf.ci.cd_emu_unit);
  571. #endif
  572. }
  573. } else if (uci->ci.type != UAEDEV_TAPE) {
  574. if (ui->hf.ci.controller_type == HD_CONTROLLER_TYPE_UAE) { // what is this? || (ui->controller && p->cs_ide)) {
  575. mi->ismounted = 1;
  576. if (uci->ci.type == UAEDEV_HDF)
  577. mi->ismedia = ui->hf.drive_empty ? false : true;
  578. else
  579. mi->ismedia = true;
  580. }
  581. }
  582. if (uci->ci.type == UAEDEV_TAPE) {
  583. cfgfile_resolve_path_out_load(uci->ci.rootdir, filepath, MAX_DPATH, PATH_TAPE);
  584. _tcscpy(mi->rootdir, filepath);
  585. struct device_info di;
  586. int unitnum = getuindex (p, index);
  587. mi->size = -1;
  588. mi->ismounted = false;
  589. if (unitnum >= 0) {
  590. mi->ismounted = true;
  591. if (tape_get_info (unitnum, &di)) {
  592. mi->ismedia = di.media_inserted != 0;
  593. _tcscpy (mi->rootdir, di.label);
  594. }
  595. } else {
  596. struct scsi_data_tape *tape;
  597. unitnum = 0;
  598. tape = tape_alloc (unitnum, filepath, uci->ci.readonly);
  599. if (tape) {
  600. if (tape_get_info (unitnum, &di)) {
  601. mi->ismedia = di.media_inserted != 0;
  602. _tcscpy (mi->rootdir, di.label);
  603. }
  604. tape_free (tape);
  605. }
  606. }
  607. return FILESYS_TAPE;
  608. }
  609. if (mi->size < 0)
  610. return -1;
  611. mi->size = ui->hf.virtsize;
  612. if (uci->ci.highcyl) {
  613. uci->ci.cyls = mi->nrcyls = uci->ci.highcyl;
  614. } else {
  615. uci->ci.cyls = mi->nrcyls = (int)(uci->ci.sectors * uci->ci.surfaces ? (ui->hf.virtsize / uci->ci.blocksize) / (uci->ci.sectors * uci->ci.surfaces) : 0);
  616. }
  617. if (uci->ci.type == UAEDEV_DIR)
  618. return FILESYS_VIRTUAL;
  619. if (uci->ci.reserved == 0 && uci->ci.sectors == 0 && uci->ci.surfaces == 0) {
  620. if (ui->hf.flags & 1)
  621. return FILESYS_HARDDRIVE;
  622. return FILESYS_HARDFILE_RDB;
  623. }
  624. return FILESYS_HARDFILE;
  625. }
  626. static void stripsemicolon (TCHAR *s)
  627. {
  628. if (!s)
  629. return;
  630. while (_tcslen(s) > 0 && s[_tcslen(s) - 1] == ':')
  631. s[_tcslen(s) - 1] = 0;
  632. }
  633. static void stripspace (TCHAR *s)
  634. {
  635. if (!s)
  636. return;
  637. for (int i = 0; i < _tcslen (s); i++) {
  638. if (s[i] == ' ')
  639. s[i] = '_';
  640. }
  641. }
  642. static void striplength (TCHAR *s, int len)
  643. {
  644. if (!s)
  645. return;
  646. if (_tcslen (s) <= len)
  647. return;
  648. s[len] = 0;
  649. }
  650. static void fixcharset (TCHAR *s)
  651. {
  652. char tmp[MAX_DPATH];
  653. if (!s)
  654. return;
  655. ua_fs_copy (tmp, MAX_DPATH, s, '_');
  656. au_fs_copy (s, strlen (tmp) + 1, tmp);
  657. }
  658. TCHAR *validatevolumename (TCHAR *s, const TCHAR *def)
  659. {
  660. stripsemicolon (s);
  661. fixcharset (s);
  662. striplength (s, 30);
  663. if (_tcslen(s) == 0 && def) {
  664. xfree(s);
  665. s = my_strdup(def);
  666. }
  667. return s;
  668. }
  669. TCHAR *validatedevicename (TCHAR *s, const TCHAR *def)
  670. {
  671. stripsemicolon (s);
  672. stripspace (s);
  673. fixcharset (s);
  674. striplength (s, 30);
  675. if (_tcslen(s) == 0 && def) {
  676. xfree(s);
  677. s = my_strdup(def);
  678. }
  679. return s;
  680. }
  681. TCHAR *filesys_createvolname (const TCHAR *volname, const TCHAR *rootdir, struct zvolume *zv, const TCHAR *def)
  682. {
  683. TCHAR *nvol = NULL;
  684. int i, archivehd;
  685. TCHAR *p = NULL;
  686. TCHAR path[MAX_DPATH];
  687. cfgfile_resolve_path_out_load(rootdir, path, MAX_DPATH, PATH_DIR);
  688. archivehd = -1;
  689. if (my_existsfile (path))
  690. archivehd = 1;
  691. else if (my_existsdir (path))
  692. archivehd = 0;
  693. if (zv && zv->volumename && _tcslen(zv->volumename) > 0) {
  694. nvol = my_strdup(zv->volumename);
  695. nvol = validatevolumename (nvol, def);
  696. return nvol;
  697. }
  698. if ((!volname || _tcslen (volname) == 0) && path && archivehd >= 0) {
  699. p = my_strdup (path);
  700. for (i = _tcslen (p) - 1; i >= 0; i--) {
  701. TCHAR c = p[i];
  702. if (c == ':' || c == '/' || c == '\\') {
  703. if (i == _tcslen (p) - 1)
  704. continue;
  705. if (!_tcscmp (p + i, _T(":\\"))) {
  706. xfree (p);
  707. p = xmalloc (TCHAR, 10);
  708. p[0] = path[0];
  709. p[1] = 0;
  710. i = 0;
  711. } else {
  712. i++;
  713. }
  714. break;
  715. }
  716. }
  717. if (i >= 0)
  718. nvol = my_strdup (p + i);
  719. }
  720. if (!nvol && archivehd >= 0) {
  721. if (volname && _tcslen (volname) > 0)
  722. nvol = my_strdup (volname);
  723. else
  724. nvol = my_strdup (def);
  725. }
  726. if (!nvol) {
  727. if (volname && _tcslen (volname))
  728. nvol = my_strdup (volname);
  729. else
  730. nvol = my_strdup (_T(""));
  731. }
  732. nvol = validatevolumename (nvol, def);
  733. xfree (p);
  734. return nvol;
  735. }
  736. static int set_filesys_volume (const TCHAR *rootdir, int *flags, bool *readonly, bool *emptydrive, struct zvolume **zvp)
  737. {
  738. *emptydrive = 0;
  739. if (my_existsfile (rootdir)) {
  740. struct zvolume *zv;
  741. zv = zfile_fopen_archive (rootdir);
  742. if (!zv) {
  743. error_log (_T("'%s' is not a supported archive file."), rootdir);
  744. return -1;
  745. }
  746. *zvp = zv;
  747. *flags = MYVOLUMEINFO_ARCHIVE;
  748. *readonly = 1;
  749. } else {
  750. *flags = my_getvolumeinfo (rootdir);
  751. if (*flags < 0) {
  752. if (rootdir && rootdir[0])
  753. error_log (_T("directory '%s' not found, mounting as empty drive."), rootdir);
  754. *emptydrive = 1;
  755. *flags = 0;
  756. } else if ((*flags) & MYVOLUMEINFO_READONLY) {
  757. error_log (_T("'%s' set to read-only."), rootdir);
  758. *readonly = 1;
  759. }
  760. }
  761. return 1;
  762. }
  763. void uci_set_defaults (struct uaedev_config_info *uci, bool rdb)
  764. {
  765. memset (uci, 0, sizeof (struct uaedev_config_info));
  766. if (!rdb) {
  767. uci->sectors = 32;
  768. uci->reserved = 2;
  769. uci->surfaces = 1;
  770. }
  771. uci->blocksize = 512;
  772. uci->maxtransfer = 0x7fffffff;
  773. uci->mask = 0xffffffff;
  774. uci->bufmemtype = 1;
  775. uci->buffers = 50;
  776. uci->stacksize = 4000;
  777. uci->bootpri = 0;
  778. uci->priority = 10;
  779. uci->sectorsperblock = 1;
  780. uci->device_emu_unit = -1;
  781. }
  782. static void get_usedblocks(struct fs_usage *fsu, bool fs, int *pblocksize, uae_s64 *pnumblocks, uae_s64 *pinuse, bool reduce)
  783. {
  784. uae_s64 numblocks = 0, inuse;
  785. int blocksize = *pblocksize;
  786. if (fs && currprefs.filesys_limit) {
  787. if (fsu->total > (uae_s64)currprefs.filesys_limit * 1024) {
  788. uae_s64 oldtotal = fsu->total;
  789. fsu->total = currprefs.filesys_limit * 1024;
  790. fsu->avail = ((fsu->avail / 1024) * (fsu->total / 1024)) / (oldtotal / 1024);
  791. fsu->avail *= 1024;
  792. }
  793. }
  794. if (reduce) {
  795. while (blocksize < 32768 || numblocks == 0) {
  796. numblocks = fsu->total / blocksize;
  797. if (numblocks <= 10)
  798. numblocks = 10;
  799. // Value that does not overflow when multiplied by 100 (uses 128 to keep it simple)
  800. if (numblocks < 0x02000000)
  801. break;
  802. blocksize *= 2;
  803. }
  804. }
  805. numblocks = fsu->total / blocksize;
  806. inuse = (numblocks * blocksize - fsu->avail) / blocksize;
  807. if (inuse > numblocks)
  808. inuse = numblocks;
  809. if (pnumblocks)
  810. *pnumblocks = numblocks;
  811. if (pinuse)
  812. *pinuse = inuse;
  813. if (pblocksize)
  814. *pblocksize = blocksize;
  815. }
  816. static bool get_blocks(const TCHAR *rootdir, int unit, int flags, int *pblocksize, uae_s64 *pnumblocks, uae_s64 *pinuse, bool reduce)
  817. {
  818. struct fs_usage fsu;
  819. int ret;
  820. bool fs = false;
  821. int blocksize;
  822. blocksize = 512;
  823. if (flags & MYVOLUMEINFO_ARCHIVE) {
  824. ret = zfile_fs_usage_archive(rootdir, 0, &fsu);
  825. fs = true;
  826. } else {
  827. ret = get_fs_usage(rootdir, 0, &fsu);
  828. fs = true;
  829. }
  830. if (ret)
  831. return false;
  832. get_usedblocks(&fsu, fs, &blocksize, pnumblocks, pinuse, reduce);
  833. if (pblocksize)
  834. *pblocksize = blocksize;
  835. return ret == 0;
  836. }
  837. static int set_filesys_unit_1 (int nr, struct uaedev_config_info *ci, bool custom)
  838. {
  839. UnitInfo *ui;
  840. int i;
  841. bool emptydrive = false;
  842. bool iscd;
  843. struct uaedev_config_info c;
  844. memcpy (&c, ci, sizeof (struct uaedev_config_info));
  845. if (nr < 0) {
  846. for (nr = 0; nr < MAX_FILESYSTEM_UNITS; nr++) {
  847. if (!mountinfo.ui[nr].open)
  848. break;
  849. }
  850. if (nr == MAX_FILESYSTEM_UNITS) {
  851. error_log (_T("No slot allocated for this unit"));
  852. return -1;
  853. }
  854. }
  855. if (ci->controller_type != HD_CONTROLLER_TYPE_UAE || ci->type == UAEDEV_TAPE) {
  856. ui = &mountinfo.ui[nr];
  857. memset (ui, 0, sizeof (UnitInfo));
  858. memcpy (&ui->hf.ci, &c, sizeof (struct uaedev_config_info));
  859. ui->readonly = c.readonly;
  860. ui->unit_type = -1;
  861. ui->open = -1;
  862. return nr;
  863. }
  864. iscd = nr >= cd_unit_offset && nr < cd_unit_offset + cd_unit_number;
  865. if (!custom)
  866. cfgfile_resolve_path_load(c.rootdir, MAX_DPATH, iscd ? PATH_CD : (ci->volname[0] ? PATH_DIR : PATH_HDF));
  867. for (i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
  868. if (nr == i || !mountinfo.ui[i].open || mountinfo.ui[i].rootdir == NULL || is_hardfile (i) == FILESYS_CD)
  869. continue;
  870. if (_tcslen(c.rootdir) > 0 && samepath(mountinfo.ui[i].rootdir, c.rootdir)) {
  871. error_log (_T("directory/hardfile '%s' already added."), c.rootdir);
  872. return -1;
  873. }
  874. }
  875. for (;;) {
  876. bool retry = false;
  877. for (i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
  878. int hf = is_hardfile(i);
  879. if (nr == i || !mountinfo.ui[i].open || mountinfo.ui[i].rootdir == NULL)
  880. continue;
  881. if (hf != FILESYS_HARDDRIVE && hf != FILESYS_HARDFILE && hf != FILESYS_HARDFILE_RDB)
  882. continue;
  883. if (mountinfo.ui[i].hf.ci.controller_unit == c.controller_unit) {
  884. c.controller_unit++;
  885. if (c.controller_unit >= MAX_FILESYSTEM_UNITS) {
  886. error_log (_T("directory/hardfile '%s' invalid unit number."), c.rootdir);
  887. return -1;
  888. }
  889. retry = true;
  890. }
  891. }
  892. if (!retry)
  893. break;
  894. }
  895. ui = &mountinfo.ui[nr];
  896. memset (ui, 0, sizeof (UnitInfo));
  897. memcpy(&ui->hf.ci, &c, sizeof c);
  898. if (iscd) {
  899. ui->unit_type = UNIT_CDFS;
  900. emptydrive = 1;
  901. ui->volflags = MYVOLUMEINFO_CDFS | MYVOLUMEINFO_READONLY;
  902. c.readonly = true;
  903. } else if (c.volname[0]) {
  904. int flags = 0;
  905. uae_s64 numblocks;
  906. emptydrive = 1;
  907. if (c.rootdir[0]) {
  908. if (set_filesys_volume (c.rootdir, &flags, &c.readonly, &emptydrive, &ui->zarchive) < 0)
  909. return -1;
  910. }
  911. ui->volname = filesys_createvolname (c.volname, c.rootdir, ui->zarchive, _T("harddrive"));
  912. ui->volflags = flags;
  913. TCHAR *vs = au(UAEFS_VERSION);
  914. TCHAR *vsp = vs + _tcslen(vs) - 1;
  915. while (vsp != vs) {
  916. if (*vsp == ' ') {
  917. *vsp++ = 0;
  918. break;
  919. }
  920. vsp--;
  921. }
  922. _tcscpy(ui->hf.vendor_id, _T("UAE"));
  923. _tcscpy(ui->hf.product_id, vs);
  924. _tcscpy(ui->hf.product_rev, vsp);
  925. xfree(vs);
  926. ui->hf.ci.unit_feature_level = HD_LEVEL_SCSI_2;
  927. if (get_blocks(c.rootdir, nr, flags, &ui->hf.ci.blocksize, &numblocks, NULL, false))
  928. ui->hf.ci.max_lba = numblocks > 0xffffffff ? 0xffffffff : numblocks;
  929. else
  930. ui->hf.ci.max_lba = 0x00ffffff;
  931. } else {
  932. ui->unit_type = UNIT_FILESYSTEM;
  933. ui->hf.unitnum = nr;
  934. ui->volname = 0;
  935. if (ui->hf.ci.rootdir[0]) {
  936. if (hdf_open (&ui->hf) <= 0 && !c.readonly) {
  937. write_log (_T("Attempting to open '%s' in read-only mode.\n"), ui->hf.ci.rootdir);
  938. ui->hf.ci.readonly = c.readonly = true;
  939. if (hdf_open (&ui->hf) > 0) {
  940. error_log (_T("'%s' opened in read-only mode.\n"), ui->hf.ci.rootdir);
  941. }
  942. }
  943. } else {
  944. // empty drive?
  945. ui->hf.drive_empty = 1;
  946. }
  947. if (!ui->hf.drive_empty) {
  948. if (ui->hf.handle_valid == 0) {
  949. error_log (_T("Hardfile '%s' not found."), ui->hf.ci.rootdir);
  950. goto err;
  951. }
  952. if (ui->hf.ci.blocksize > ui->hf.virtsize || ui->hf.virtsize == 0) {
  953. error_log (_T("Hardfile '%s' too small."), ui->hf.ci.rootdir);
  954. goto err;
  955. }
  956. }
  957. if ((ui->hf.ci.blocksize & (ui->hf.ci.blocksize - 1)) != 0 || ui->hf.ci.blocksize == 0) {
  958. error_log (_T("Hardfile '%s' bad blocksize %d."), ui->hf.ci.rootdir, ui->hf.ci.blocksize);
  959. goto err;
  960. }
  961. if ((ui->hf.ci.sectors || ui->hf.ci.surfaces || ui->hf.ci.reserved) &&
  962. (ui->hf.ci.sectors < 1 || ui->hf.ci.surfaces < 1 || ui->hf.ci.surfaces > 1023 ||
  963. ui->hf.ci.reserved < 0 || ui->hf.ci.reserved > 1023) != 0) {
  964. error_log (_T("Hardfile '%s' bad hardfile geometry."), ui->hf.ci.rootdir);
  965. goto err;
  966. }
  967. if (!ui->hf.ci.highcyl) {
  968. ui->hf.ci.cyls = (int)(ui->hf.ci.sectors * ui->hf.ci.surfaces ? (ui->hf.virtsize / ui->hf.ci.blocksize) / (ui->hf.ci.sectors * ui->hf.ci.surfaces) : 0);
  969. }
  970. if (!ui->hf.ci.cyls)
  971. ui->hf.ci.cyls = ui->hf.ci.highcyl;
  972. if (!ui->hf.ci.cyls)
  973. ui->hf.ci.cyls = 1;
  974. }
  975. ui->self = 0;
  976. ui->reset_state = FS_STARTUP;
  977. ui->wasisempty = emptydrive;
  978. ui->canremove = emptydrive && (ci->flags & MYVOLUMEINFO_REUSABLE);
  979. ui->rootdir = my_strdup (c.rootdir);
  980. ui->devname = my_strdup (c.devname);
  981. stripsemicolon(ui->devname);
  982. if (c.filesys[0])
  983. ui->filesysdir = my_strdup (c.filesys);
  984. ui->readonly = c.readonly;
  985. if (c.bootpri < -129)
  986. c.bootpri = -129;
  987. if (c.bootpri > 127)
  988. c.bootpri = 127;
  989. ui->bootpri = c.bootpri;
  990. ui->inject_icons = c.inject_icons;
  991. ui->open = 1;
  992. return nr;
  993. err:
  994. if (ui->hf.handle_valid)
  995. hdf_close (&ui->hf);
  996. return -1;
  997. }
  998. static int set_filesys_unit (int nr, struct uaedev_config_info *ci, bool custom)
  999. {
  1000. int ret;
  1001. ret = set_filesys_unit_1 (nr, ci, custom);
  1002. return ret;
  1003. }
  1004. static int add_filesys_unit (struct uaedev_config_info *ci, bool custom)
  1005. {
  1006. int nr;
  1007. if (nr_units () >= MAX_FILESYSTEM_UNITS)
  1008. return -1;
  1009. nr = set_filesys_unit_1 (-1, ci, custom);
  1010. #ifdef RETROPLATFORM
  1011. if (nr >= 0) {
  1012. UnitInfo *ui = &mountinfo.ui[nr];
  1013. rp_hd_device_enable (nr, true);
  1014. if (ui->unit_type == UNIT_CDFS)
  1015. rp_cd_image_change(nr, ci->rootdir);
  1016. else
  1017. rp_harddrive_image_change(nr, ci->readonly, ci->rootdir);
  1018. }
  1019. #endif
  1020. return nr;
  1021. }
  1022. int kill_filesys_unitconfig (struct uae_prefs *p, int nr)
  1023. {
  1024. struct uaedev_config_data *uci;
  1025. if (nr < 0)
  1026. return 0;
  1027. uci = getuci (p->mountconfig, nr);
  1028. hardfile_do_disk_change (uci, 0);
  1029. if (uci->configoffset >= 0 && uci->ci.controller_type == HD_CONTROLLER_TYPE_UAE) {
  1030. filesys_media_change(uci->ci.rootdir, 0, uci);
  1031. } else {
  1032. pcmcia_disk_reinsert(p, &uci->ci, true);
  1033. }
  1034. while (nr < MOUNT_CONFIG_SIZE) {
  1035. memmove (&p->mountconfig[nr], &p->mountconfig[nr + 1], sizeof (struct uaedev_config_data));
  1036. nr++;
  1037. }
  1038. p->mountitems--;
  1039. memset (&p->mountconfig[MOUNT_CONFIG_SIZE - 1], 0, sizeof (struct uaedev_config_data));
  1040. return 1;
  1041. }
  1042. int move_filesys_unitconfig (struct uae_prefs *p, int nr, int to)
  1043. {
  1044. struct uaedev_config_data *uci1, *uci2, tmpuci;
  1045. uci1 = getuci (p->mountconfig, nr);
  1046. uci2 = getuci (p->mountconfig, to);
  1047. if (nr == to)
  1048. return 0;
  1049. memcpy (&tmpuci, uci1, sizeof (struct uaedev_config_data));
  1050. memcpy (uci1, uci2, sizeof (struct uaedev_config_data));
  1051. memcpy (uci2, &tmpuci, sizeof (struct uaedev_config_data));
  1052. return 1;
  1053. }
  1054. static void allocuci (struct uae_prefs *p, int nr, int idx, int unitnum)
  1055. {
  1056. struct uaedev_config_data *uci = &p->mountconfig[nr];
  1057. if (idx >= 0) {
  1058. UnitInfo *ui;
  1059. uci->configoffset = idx;
  1060. ui = &mountinfo.ui[idx];
  1061. ui->configureddrive = 1;
  1062. uci->unitnum = unitnum;
  1063. } else {
  1064. uci->configoffset = -1;
  1065. uci->unitnum = -1;
  1066. }
  1067. }
  1068. static void allocuci (struct uae_prefs *p, int nr, int idx)
  1069. {
  1070. allocuci (p, nr, idx, -1);
  1071. }
  1072. static const TCHAR *getunittype(struct uaedev_config_info *uci)
  1073. {
  1074. return uci->type == UAEDEV_CD ? _T("CD") : (uci->type == UAEDEV_TAPE ? _T("TAPE") : _T("HD"));
  1075. }
  1076. static int cpuboard_hd;
  1077. static romconfig cpuboard_dummy;
  1078. void add_cpuboard_unit(int unit, struct uaedev_config_info *uci, struct romconfig *rc)
  1079. {
  1080. int flags = (uci->controller_type >= HD_CONTROLLER_TYPE_IDE_FIRST && uci->controller_type <= HD_CONTROLLER_TYPE_IDE_LAST) ? EXPANSIONTYPE_IDE : EXPANSIONTYPE_SCSI;
  1081. const struct cpuboardtype *cbt = &cpuboards[currprefs.cpuboard_type];
  1082. cpuboard_hd = 0;
  1083. if (cbt->subtypes) {
  1084. if (cbt->subtypes[currprefs.cpuboard_subtype].add && (cbt->subtypes[currprefs.cpuboard_subtype].deviceflags & flags)) {
  1085. if (unit >= 0) {
  1086. write_log(_T("Adding CPUBoard '%s' %s unit %d ('%s')\n"),
  1087. cbt->subtypes[currprefs.cpuboard_subtype].name,
  1088. getunittype(uci), unit, uci->rootdir);
  1089. }
  1090. cbt->subtypes[currprefs.cpuboard_subtype].add(unit, uci, rc);
  1091. cpuboard_hd = 1;
  1092. }
  1093. }
  1094. }
  1095. static void add_cpuboard_unit_init(void)
  1096. {
  1097. memset(&cpuboard_dummy, 0, sizeof cpuboard_dummy);
  1098. cpuboard_dummy.device_id = 7;
  1099. if (currprefs.cpuboard_type) {
  1100. struct romconfig *rc = get_device_romconfig(&currprefs, ROMTYPE_CPUBOARD, 0);
  1101. if (!rc)
  1102. rc = &cpuboard_dummy;
  1103. const struct cpuboardtype *cbt = &cpuboards[currprefs.cpuboard_type];
  1104. if (cbt->subtypes) {
  1105. if (cbt->subtypes[currprefs.cpuboard_subtype].add) {
  1106. const struct cpuboardsubtype *cst = &cbt->subtypes[currprefs.cpuboard_subtype];
  1107. struct uaedev_config_info ci = { 0 };
  1108. write_log(_T("Initializing CPUBoard '%s' %s controller\n"),
  1109. cst->name, (cst->deviceflags & EXPANSIONTYPE_SCSI) ? _T("SCSI") : _T("IDE"));
  1110. cst->add(-1, &ci, rc);
  1111. }
  1112. }
  1113. }
  1114. }
  1115. static bool add_ide_unit(int type, int unit, struct uaedev_config_info *uci)
  1116. {
  1117. bool added = false;
  1118. if (type >= HD_CONTROLLER_TYPE_IDE_EXPANSION_FIRST && type <= HD_CONTROLLER_TYPE_IDE_LAST) {
  1119. for (int i = 0; expansionroms[i].name; i++) {
  1120. if (i == type - HD_CONTROLLER_TYPE_IDE_EXPANSION_FIRST) {
  1121. const struct expansionromtype *ert = &expansionroms[i];
  1122. if ((ert->deviceflags & 2) && is_board_enabled(&currprefs, ert->romtype, uci->controller_type_unit)) {
  1123. cpuboard_hd = 1;
  1124. if (ert->add) {
  1125. struct romconfig *rc = get_device_romconfig(&currprefs, ert->romtype, uci->controller_type_unit);
  1126. write_log(_T("Adding IDE %s '%s' unit %d ('%s')\n"), getunittype(uci),
  1127. ert->name, unit, uci->rootdir);
  1128. ert->add(unit, uci, rc);
  1129. }
  1130. if (cpuboard_hd)
  1131. added = true;
  1132. }
  1133. }
  1134. }
  1135. }
  1136. return added;
  1137. }
  1138. static bool add_scsi_unit(int type, int unit, struct uaedev_config_info *uci)
  1139. {
  1140. bool added = false;
  1141. if (type >= HD_CONTROLLER_TYPE_SCSI_EXPANSION_FIRST && type <= HD_CONTROLLER_TYPE_SCSI_LAST) {
  1142. for (int i = 0; expansionroms[i].name; i++) {
  1143. if (i == type - HD_CONTROLLER_TYPE_SCSI_EXPANSION_FIRST) {
  1144. const struct expansionromtype *ert = &expansionroms[i];
  1145. if ((ert->deviceflags & 1) && is_board_enabled(&currprefs, ert->romtype, uci->controller_type_unit)) {
  1146. cpuboard_hd = 1;
  1147. if (ert->add) {
  1148. struct romconfig *rc = get_device_romconfig(&currprefs, ert->romtype, uci->controller_type_unit);
  1149. write_log(_T("Adding SCSI %s '%s' unit %d ('%s')\n"), getunittype(uci),
  1150. ert->name, unit, uci->rootdir);
  1151. ert->add(unit, uci, rc);
  1152. }
  1153. if (cpuboard_hd)
  1154. added = true;
  1155. }
  1156. }
  1157. }
  1158. }
  1159. return added;
  1160. }
  1161. static void initialize_mountinfo (void)
  1162. {
  1163. int nr;
  1164. UnitInfo *uip = &mountinfo.ui[0];
  1165. cd_unit_offset = MAX_FILESYSTEM_UNITS;
  1166. autocreatedunit = 0;
  1167. for (nr = 0; nr < currprefs.mountitems; nr++) {
  1168. struct uaedev_config_data *uci = &currprefs.mountconfig[nr];
  1169. if (uci->ci.controller_type == HD_CONTROLLER_TYPE_UAE && (uci->ci.type == UAEDEV_DIR || uci->ci.type == UAEDEV_HDF)) {
  1170. struct uaedev_config_info ci;
  1171. memcpy (&ci, &uci->ci, sizeof (struct uaedev_config_info));
  1172. ci.flags = MYVOLUMEINFO_REUSABLE;
  1173. int idx = set_filesys_unit_1 (-1, &ci, false);
  1174. allocuci (&currprefs, nr, idx);
  1175. }
  1176. }
  1177. filesys_addexternals ();
  1178. nr = nr_units ();
  1179. cd_unit_offset = nr;
  1180. cd_unit_number = 0;
  1181. if (currprefs.scsi && currprefs.win32_automount_cddrives) {
  1182. uae_u32 mask = scsi_get_cd_drive_mask ();
  1183. for (int i = 0; i < 32; i++) {
  1184. if (mask & (1 << i)) {
  1185. struct uaedev_config_info ci = { 0 };
  1186. _stprintf (ci.devname, _T("CD%d"), i);
  1187. cd_unit_number++;
  1188. _tcscpy (ci.rootdir, _T("/"));
  1189. ci.readonly = true;
  1190. ci.sectors = 1;
  1191. ci.surfaces = 1;
  1192. ci.blocksize = 2048;
  1193. int idx = set_filesys_unit_1 (i + cd_unit_offset, &ci, true);
  1194. allocuci (&currprefs, nr, idx);
  1195. nr++;
  1196. }
  1197. }
  1198. }
  1199. for (nr = 0; nr < currprefs.mountitems; nr++) {
  1200. struct uaedev_config_data *uci = &currprefs.mountconfig[nr];
  1201. if (uci->ci.controller_type == HD_CONTROLLER_TYPE_UAE) {
  1202. if (uci->ci.type == UAEDEV_TAPE) {
  1203. struct uaedev_config_info ci;
  1204. memcpy (&ci, &uci->ci, sizeof (struct uaedev_config_info));
  1205. int unitnum = scsi_add_tape (&uci->ci);
  1206. if (unitnum >= 0) {
  1207. int idx = set_filesys_unit_1 (-1, &ci, false);
  1208. allocuci (&currprefs, nr, idx, unitnum);
  1209. }
  1210. }
  1211. }
  1212. }
  1213. // init all controllers first
  1214. add_cpuboard_unit_init();
  1215. for (int i = 0; expansionroms[i].name; i++) {
  1216. const struct expansionromtype *ert = &expansionroms[i];
  1217. for (int j = 0; j < MAX_DUPLICATE_EXPANSION_BOARDS; j++) {
  1218. struct romconfig *rc = get_device_romconfig(&currprefs, ert->romtype, j);
  1219. if ((ert->deviceflags & 3) && rc) {
  1220. if (ert->add) {
  1221. struct uaedev_config_info ci = { 0 };
  1222. ci.controller_type_unit = j;
  1223. ert->add(-1, &ci, rc);
  1224. }
  1225. }
  1226. }
  1227. }
  1228. for (nr = 0; nr < currprefs.mountitems; nr++) {
  1229. struct uaedev_config_info *uci = &currprefs.mountconfig[nr].ci;
  1230. int type = uci->controller_type;
  1231. int unit = uci->controller_unit;
  1232. bool added = false;
  1233. uci->uae_unitnum = nr;
  1234. if (type == HD_CONTROLLER_TYPE_UAE) {
  1235. continue;
  1236. } else if (type != HD_CONTROLLER_TYPE_IDE_AUTO && type >= HD_CONTROLLER_TYPE_IDE_FIRST && type <= HD_CONTROLLER_TYPE_IDE_LAST) {
  1237. added = add_ide_unit(type, unit, uci);
  1238. } else if (type == HD_CONTROLLER_TYPE_IDE_AUTO) {
  1239. for (int st = HD_CONTROLLER_TYPE_IDE_FIRST; st <= HD_CONTROLLER_TYPE_IDE_LAST; st++) {
  1240. added = add_ide_unit(st, unit, uci);
  1241. if (added)
  1242. break;
  1243. }
  1244. } else if (type != HD_CONTROLLER_TYPE_SCSI_AUTO && type >= HD_CONTROLLER_TYPE_SCSI_FIRST && type <= HD_CONTROLLER_TYPE_SCSI_LAST) {
  1245. added = add_scsi_unit(type, unit, uci);
  1246. } else if (type == HD_CONTROLLER_TYPE_SCSI_AUTO) {
  1247. for (int st = HD_CONTROLLER_TYPE_SCSI_FIRST; st <= HD_CONTROLLER_TYPE_SCSI_LAST; st++) {
  1248. added = add_scsi_unit(st, unit, uci);
  1249. if (added)
  1250. break;
  1251. }
  1252. #if 0
  1253. } else if (type == HD_CONTROLLER_TYPE_PCMCIA) {
  1254. if (uci->controller_type_unit == 0) {
  1255. gayle_add_pcmcia_sram_unit (uci);
  1256. added = true;
  1257. } else {
  1258. gayle_add_pcmcia_ide_unit (uci);
  1259. added = true;
  1260. }
  1261. #endif
  1262. }
  1263. if (added)
  1264. allocuci (&currprefs, nr, -1);
  1265. }
  1266. }
  1267. int sprintf_filesys_unit (TCHAR *buffer, int num)
  1268. {
  1269. UnitInfo *uip = mountinfo.ui;
  1270. if (uip[num].volname != 0)
  1271. _stprintf (buffer, _T("(DH%d:) Filesystem, %s: %s %s"), num, uip[num].volname,
  1272. uip[num].rootdir, uip[num].readonly ? _T("ro") : _T(""));
  1273. else
  1274. _stprintf (buffer, _T("(DH%d:) Hardfile, \"%s\", size %d Mbytes"), num,
  1275. uip[num].rootdir, (int)(uip[num].hf.virtsize / (1024 * 1024)));
  1276. return 0;
  1277. }
  1278. static void free_mountinfo (void)
  1279. {
  1280. int i;
  1281. for (i = 0; i < MAX_FILESYSTEM_UNITS; i++)
  1282. close_filesys_unit (mountinfo.ui + i);
  1283. gayle_free_units ();
  1284. }
  1285. struct hardfiledata *get_hardfile_data_controller(int nr)
  1286. {
  1287. UnitInfo *uip = mountinfo.ui;
  1288. for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
  1289. if (uip[i].open == 0)
  1290. continue;
  1291. if (uip[i].hf.ci.controller_unit == nr && uip[i].hf.ci.type != UAEDEV_DIR)
  1292. return &uip[i].hf;
  1293. }
  1294. for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
  1295. if (uip[i].open == 0)
  1296. continue;
  1297. if (uip[i].hf.ci.controller_unit == nr && uip[i].hf.ci.type == UAEDEV_DIR)
  1298. return &uip[i].hf;
  1299. }
  1300. return NULL;
  1301. }
  1302. struct hardfiledata *get_hardfile_data (int nr)
  1303. {
  1304. UnitInfo *uip = mountinfo.ui;
  1305. if (nr < 0 || nr >= MAX_FILESYSTEM_UNITS || uip[nr].open == 0 || is_virtual (nr))
  1306. return NULL;
  1307. return &uip[nr].hf;
  1308. }
  1309. static uae_u32 a_uniq, key_uniq;
  1310. #define PUT_PCK_RES1(p,v) do { put_long_host((p)->packet_data + dp_Res1, (v)); } while (0)
  1311. #define PUT_PCK_RES2(p,v) do { put_long_host((p)->packet_data + dp_Res2, (v)); } while (0)
  1312. #define GET_PCK_TYPE(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Type)))
  1313. #define GET_PCK_RES1(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Res1)))
  1314. #define GET_PCK_RES2(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Res2)))
  1315. #define GET_PCK_ARG1(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Arg1)))
  1316. #define GET_PCK_ARG2(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Arg2)))
  1317. #define GET_PCK_ARG3(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Arg3)))
  1318. #define GET_PCK_ARG4(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Arg4)))
  1319. #define GET_PCK_ARG5(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Arg5)))
  1320. #define PUT_PCK64_RES0(p,v) do { put_long_host((p)->packet_data + dp64_Res0, (v)); } while (0)
  1321. #define PUT_PCK64_RES1(p,v) do { put_long_host((p)->packet_data + dp64_Res1, (((uae_u64)v) >> 32)); put_long_host((p)->packet_data + dp64_Res1 + 4, ((uae_u32)v)); } while (0)
  1322. #define PUT_PCK64_RES2(p,v) do { put_long_host((p)->packet_data + dp64_Res2, (v)); } while (0)
  1323. #define GET_PCK64_TYPE(p) ((uae_s32)(get_long_host((p)->packet_data + dp64_Type)))
  1324. #define GET_PCK64_RES0(p) ((uae_s32)(get_long_host((p)->packet_data + dp64_Res0)))
  1325. #define GET_PCK64_RES1(p) ( (((uae_s64)(get_long_host((p)->packet_data + dp64_Res1))) << 32) | (((uae_s64)(get_long_host((p)->packet_data + dp64_Res1 + 4))) << 0) )
  1326. #define GET_PCK64_ARG1(p) ((uae_s32)(get_long_host((p)->packet_data + dp64_Arg1)))
  1327. #define GET_PCK64_ARG2(p) ( (((uae_s64)(get_long_host((p)->packet_data + dp64_Arg2))) << 32) | (((uae_s64)(get_long_host((p)->packet_data + dp64_Arg2 + 4))) << 0) )
  1328. #define GET_PCK64_ARG3(p) ((uae_s32)(get_long_host((p)->packet_data + dp64_Arg3)))
  1329. #define GET_PCK64_ARG4(p) ((uae_s32)(get_long_host((p)->packet_data + dp64_Arg4)))
  1330. #define GET_PCK64_ARG5(p) ( (((uae_s64)(get_long_host((p)->packet_data + dp64_Arg5))) << 32) | (((uae_s64)(get_long_host((p)->packet_data + dp64_Arg5 + 4))) << 0) )
  1331. static void readdpacket(TrapContext *ctx, dpacket *packet, uaecptr pck)
  1332. {
  1333. // Read enough to get also all 64-bit fields
  1334. packet->packet_addr = pck;
  1335. if (trap_is_indirect() || !valid_address(pck, dp_Max)) {
  1336. trap_get_bytes(ctx, packet->packet_array, pck, dp_Max);
  1337. packet->packet_data = packet->packet_array;
  1338. packet->need_flush = true;
  1339. } else {
  1340. packet->packet_data = get_real_address(pck);
  1341. packet->need_flush = false;
  1342. }
  1343. }
  1344. static void writedpacket(TrapContext *ctx, dpacket *packet)
  1345. {
  1346. if (!packet->need_flush)
  1347. return;
  1348. int type = GET_PCK_TYPE(packet);
  1349. if (type >= 8000 && type < 9000 && GET_PCK64_RES0(packet) == DP64_INIT) {
  1350. // 64-bit RESx fields
  1351. trap_put_bytes(ctx, packet->packet_data + 12, packet->packet_addr + 12, 32 - 12);
  1352. } else {
  1353. // dp_Res1 and dp_Res2
  1354. trap_put_bytes(ctx, packet->packet_data + 12, packet->packet_addr + 12, 20 - 12);
  1355. }
  1356. }
  1357. static void set_quadp(TrapContext *ctx, uaecptr p, uae_s64 v)
  1358. {
  1359. if (!trap_valid_address(ctx, p, 8))
  1360. return;
  1361. trap_put_quad(ctx, p, v);
  1362. }
  1363. static uae_u64 get_quadp(TrapContext *ctx, uaecptr p)
  1364. {
  1365. if (!trap_valid_address(ctx, p, 8))
  1366. return 0;
  1367. return trap_get_quad(ctx, p);
  1368. }
  1369. static int flush_cache (Unit *unit, int num);
  1370. static TCHAR *char1(TrapContext *ctx, uaecptr addr)
  1371. {
  1372. uae_char buf[1024];
  1373. #if TRAPMD
  1374. trap_get_string(ctx, (uae_u8*)buf, addr, sizeof(buf));
  1375. #else
  1376. unsigned int i = 0;
  1377. do {
  1378. buf[i] = trap_get_byte(ctx, addr);
  1379. addr++;
  1380. } while (buf[i++] && i < sizeof (buf));
  1381. #endif
  1382. return au_fs(buf);
  1383. }
  1384. static TCHAR *bstr1(TrapContext *ctx, uaecptr addr)
  1385. {
  1386. uae_char buf[257];
  1387. int n = trap_get_byte(ctx, addr);
  1388. addr++;
  1389. #if TRAPMD
  1390. trap_get_bytes(ctx, (uae_u8*)buf, addr, n);
  1391. #else
  1392. for (int i = 0; i < n; i++, addr++)
  1393. buf[i] = trap_get_byte(ctx, addr);
  1394. #endif
  1395. buf[n] = 0;
  1396. return au_fs(buf);
  1397. }
  1398. static TCHAR *bstr(TrapContext *ctx, Unit *unit, uaecptr addr)
  1399. {
  1400. int n = trap_get_byte(ctx, addr);
  1401. uae_char buf[257];
  1402. addr++;
  1403. #if TRAPMD
  1404. trap_get_bytes(ctx, (uae_u8*)buf, addr, n);
  1405. #else
  1406. for (int i = 0; i < n; i++, addr++)
  1407. buf[i] = trap_get_byte(ctx, addr);
  1408. #endif
  1409. buf[n] = 0;
  1410. au_fs_copy (unit->tmpbuf3, sizeof (unit->tmpbuf3) / sizeof (TCHAR), buf);
  1411. return unit->tmpbuf3;
  1412. }
  1413. static TCHAR *cstr(TrapContext *ctx, Unit *unit, uaecptr addr)
  1414. {
  1415. uae_char buf[257];
  1416. trap_get_string(ctx, buf, addr, sizeof buf);
  1417. au_fs_copy (unit->tmpbuf3, sizeof (unit->tmpbuf3) / sizeof (TCHAR), buf);
  1418. return unit->tmpbuf3;
  1419. }
  1420. static TCHAR *bstr_cut(TrapContext *ctx, Unit *unit, uaecptr addr)
  1421. {
  1422. TCHAR *p = unit->tmpbuf3;
  1423. int i, colon_seen = 0, off;
  1424. int n = trap_get_byte(ctx, addr);
  1425. uae_char buf[257];
  1426. off = 0;
  1427. addr++;
  1428. for (i = 0; i < n; i++, addr++) {
  1429. uae_u8 c = trap_get_byte(ctx, addr);
  1430. buf[i] = c;
  1431. if (c == '/' || (c == ':' && colon_seen++ == 0))
  1432. off = i + 1;
  1433. }
  1434. buf[i] = 0;
  1435. au_fs_copy (unit->tmpbuf3, sizeof (unit->tmpbuf3) / sizeof (TCHAR), buf);
  1436. return &p[off];
  1437. }
  1438. /* convert time_t to/from AmigaDOS time */
  1439. static const uae_s64 msecs_per_day = 24 * 60 * 60 * 1000;
  1440. static const uae_s64 diff = ((8 * 365 + 2) * (24 * 60 * 60)) * (uae_u64)1000;
  1441. void timeval_to_amiga (struct mytimeval *tv, int *days, int *mins, int *ticks, int tickcount)
  1442. {
  1443. /* tv.tv_sec is secs since 1-1-1970 */
  1444. /* days since 1-1-1978 */
  1445. /* mins since midnight */
  1446. /* ticks past minute @ 50Hz */
  1447. uae_s64 t = tv->tv_sec * 1000 + tv->tv_usec / 1000;
  1448. t -= diff;
  1449. if (t < 0)
  1450. t = 0;
  1451. *days = t / msecs_per_day;
  1452. t -= *days * msecs_per_day;
  1453. *mins = t / (60 * 1000);
  1454. t -= *mins * (60 * 1000);
  1455. *ticks = t / (1000 / tickcount);
  1456. }
  1457. void amiga_to_timeval (struct mytimeval *tv, int days, int mins, int ticks, int tickcount)
  1458. {
  1459. uae_s64 t;
  1460. if (days < 0)
  1461. days = 0;
  1462. if (days > 9900 * 365)
  1463. days = 9900 * 365; // in future far enough?
  1464. if (mins < 0 || mins >= 24 * 60)
  1465. mins = 0;
  1466. if (ticks < 0 || ticks >= 60 * tickcount)
  1467. ticks = 0;
  1468. t = ticks * 20;
  1469. t += mins * (60 * 1000);
  1470. t += ((uae_u64)days) * msecs_per_day;
  1471. t += diff;
  1472. tv->tv_sec = t / 1000;
  1473. tv->tv_usec = (t % 1000) * 1000;
  1474. }
  1475. static Unit *units = 0;
  1476. static Unit *find_unit (uaecptr port)
  1477. {
  1478. Unit* u;
  1479. for (u = units; u; u = u->next)
  1480. if (u->port == port)
  1481. break;
  1482. return u;
  1483. }
  1484. static struct fs_dirhandle *fs_opendir (Unit *u, a_inode *aino)
  1485. {
  1486. struct fs_dirhandle *fsd = xmalloc (struct fs_dirhandle, 1);
  1487. fsd->fstype = (u->volflags & MYVOLUMEINFO_ARCHIVE) ? FS_ARCHIVE : ((u->volflags & MYVOLUMEINFO_CDFS) ? FS_CDFS : FS_DIRECTORY);
  1488. if (fsd->fstype == FS_ARCHIVE) {
  1489. fsd->zd = zfile_opendir_archive (aino->nname);
  1490. if (fsd->zd)
  1491. return fsd;
  1492. } else if (fsd->fstype == FS_DIRECTORY) {
  1493. fsd->od = my_opendir (aino->nname);
  1494. if (fsd->od)
  1495. return fsd;
  1496. } else if (fsd->fstype == FS_CDFS) {
  1497. fsd->isod = isofs_opendir (u->ui.cdfs_superblock, aino->uniq_external);
  1498. if (fsd->isod)
  1499. return fsd;
  1500. }
  1501. xfree (fsd);
  1502. return NULL;
  1503. }
  1504. static void fs_closedir (struct fs_dirhandle *fsd)
  1505. {
  1506. if (!fsd)
  1507. return;
  1508. if (fsd->fstype == FS_ARCHIVE)
  1509. zfile_closedir_archive (fsd->zd);
  1510. else if (fsd->fstype == FS_DIRECTORY)
  1511. my_closedir (fsd->od);
  1512. else if (fsd->fstype == FS_CDFS)
  1513. isofs_closedir (fsd->isod);
  1514. xfree (fsd);
  1515. }
  1516. static struct fs_filehandle *fs_openfile (Unit *u, a_inode *aino, int flags)
  1517. {
  1518. struct fs_filehandle *fsf = xmalloc (struct fs_filehandle, 1);
  1519. fsf->fstype = (u->volflags & MYVOLUMEINFO_ARCHIVE) ? FS_ARCHIVE : ((u->volflags & MYVOLUMEINFO_CDFS) ? FS_CDFS : FS_DIRECTORY);
  1520. if (fsf->fstype == FS_ARCHIVE) {
  1521. fsf->zf = zfile_open_archive (aino->nname, flags);
  1522. if (fsf->zf)
  1523. return fsf;
  1524. } else if (fsf->fstype == FS_DIRECTORY) {
  1525. fsf->of = my_open (aino->nname, flags);
  1526. if (fsf->of)
  1527. return fsf;
  1528. } else if (fsf->fstype == FS_CDFS) {
  1529. fsf->isof = isofs_openfile (u->ui.cdfs_superblock, aino->uniq_external, flags);
  1530. if (fsf->isof)
  1531. return fsf;
  1532. }
  1533. xfree (fsf);
  1534. return NULL;
  1535. }
  1536. static void fs_closefile (struct fs_filehandle *fsf)
  1537. {
  1538. if (!fsf)
  1539. return;
  1540. if (fsf->fstype == FS_ARCHIVE) {
  1541. zfile_close_archive (fsf->zf);
  1542. } else if (fsf->fstype == FS_DIRECTORY) {
  1543. my_close (fsf->of);
  1544. } else if (fsf->fstype == FS_CDFS) {
  1545. isofs_closefile (fsf->isof);
  1546. }
  1547. xfree (fsf);
  1548. }
  1549. static unsigned int fs_read (struct fs_filehandle *fsf, void *b, unsigned int size)
  1550. {
  1551. if (fsf->fstype == FS_ARCHIVE)
  1552. return zfile_read_archive (fsf->zf, b, size);
  1553. else if (fsf->fstype == FS_DIRECTORY)
  1554. return my_read (fsf->of, b, size);
  1555. else if (fsf->fstype == FS_CDFS)
  1556. return isofs_read (fsf->isof, b, size);
  1557. return 0;
  1558. }
  1559. static unsigned int fs_write (struct fs_filehandle *fsf, void *b, unsigned int size)
  1560. {
  1561. if (fsf->fstype == FS_DIRECTORY)
  1562. return my_write (fsf->of, b, size);
  1563. return 0;
  1564. }
  1565. /* return value = old position. -1 = error. */
  1566. static uae_s64 fs_lseek64 (struct fs_filehandle *fsf, uae_s64 offset, int whence)
  1567. {
  1568. if (fsf->fstype == FS_ARCHIVE)
  1569. return zfile_lseek_archive (fsf->zf, offset, whence);
  1570. else if (fsf->fstype == FS_DIRECTORY)
  1571. return my_lseek (fsf->of, offset, whence);
  1572. else if (fsf->fstype == FS_CDFS)
  1573. return isofs_lseek (fsf->isof, offset, whence);
  1574. return -1;
  1575. }
  1576. static uae_s32 fs_lseek (struct fs_filehandle *fsf, uae_s32 offset, int whence)
  1577. {
  1578. uae_s64 v = fs_lseek64 (fsf, offset, whence);
  1579. if (v < 0 || v > 0x7fffffff)
  1580. return -1;
  1581. return (uae_s32)v;
  1582. }
  1583. static uae_s64 fs_fsize64 (struct fs_filehandle *fsf)
  1584. {
  1585. if (fsf->fstype == FS_ARCHIVE)
  1586. return zfile_fsize_archive (fsf->zf);
  1587. else if (fsf->fstype == FS_DIRECTORY)
  1588. return my_fsize (fsf->of);
  1589. else if (fsf->fstype == FS_CDFS)
  1590. return isofs_fsize (fsf->isof);
  1591. return -1;
  1592. }
  1593. static uae_u32 fs_fsize (struct fs_filehandle *fsf)
  1594. {
  1595. return (uae_u32)fs_fsize64 (fsf);
  1596. }
  1597. static uae_s64 key_filesize(Key *k)
  1598. {
  1599. if (k->aino->vfso)
  1600. return k->aino->vfso->size;
  1601. return fs_fsize64 (k->fd);
  1602. }
  1603. static uae_s64 key_seek(Key *k, uae_s64 offset, int whence)
  1604. {
  1605. if (k->aino->vfso)
  1606. return k->file_pos;
  1607. return fs_lseek64 (k->fd, offset, whence);
  1608. }
  1609. static void set_highcyl(uaecptr volume, uae_u32 blocks)
  1610. {
  1611. put_long(volume + 184 - 32, blocks);
  1612. }
  1613. static void set_volume_name(Unit *unit, struct mytimeval *tv)
  1614. {
  1615. int namelen;
  1616. int i;
  1617. char *s;
  1618. s = ua_fs (unit->ui.volname, -1);
  1619. namelen = strlen (s);
  1620. if (namelen >= 58)
  1621. namelen = 58;
  1622. put_byte(unit->volume + 64, namelen);
  1623. for (i = 0; i < namelen; i++)
  1624. put_byte(unit->volume + 64 + 1 + i, s[i]);
  1625. put_byte(unit->volume + 64 + 1 + namelen, 0);
  1626. if (tv && (tv->tv_sec || tv->tv_usec)) {
  1627. int days, mins, ticks;
  1628. timeval_to_amiga (tv, &days, &mins, &ticks, 50);
  1629. put_long(unit->volume + 16, days);
  1630. put_long(unit->volume + 20, mins);
  1631. put_long(unit->volume + 24, ticks);
  1632. }
  1633. xfree (s);
  1634. unit->rootnode.aname = unit->ui.volname;
  1635. unit->rootnode.nname = unit->ui.rootdir;
  1636. unit->rootnode.mountcount = unit->mountcount;
  1637. }
  1638. static int filesys_isvolume(Unit *unit)
  1639. {
  1640. if (!unit->volume)
  1641. return 0;
  1642. return get_byte(unit->volume + 64) || unit->ui.unknown_media;
  1643. }
  1644. static void clear_exkeys (Unit *unit)
  1645. {
  1646. int i;
  1647. a_inode *a;
  1648. for (i = 0; i < EXKEYS; i++) {
  1649. unit->examine_keys[i].aino = 0;
  1650. unit->examine_keys[i].curr_file = 0;
  1651. unit->examine_keys[i].uniq = 0;
  1652. }
  1653. for (i = 0; i < EXALLKEYS; i++) {
  1654. fs_closedir (unit->exalls[i].dirhandle);
  1655. unit->exalls[i].dirhandle = NULL;
  1656. xfree (unit->exalls[i].fn);
  1657. unit->exalls[i].fn = NULL;
  1658. unit->exalls[i].id = 0;
  1659. }
  1660. unit->exallid = 0;
  1661. unit->next_exkey = 1;
  1662. a = &unit->rootnode;
  1663. while (a) {
  1664. a->exnext_count = 0;
  1665. if (a->locked_children) {
  1666. a->locked_children = 0;
  1667. unit->total_locked_ainos--;
  1668. }
  1669. a = a->next;
  1670. if (a == &unit->rootnode)
  1671. break;
  1672. }
  1673. }
  1674. static void filesys_delayed_eject(Unit *u)
  1675. {
  1676. if (u->reinsertdelay)
  1677. return;
  1678. u->reinsertdelay = 50;
  1679. u->newreadonly = false;
  1680. xfree(u->newrootdir);
  1681. u->newrootdir = NULL;
  1682. write_log(_T("FILESYS: delayed eject %d\n"), u->unit);
  1683. }
  1684. static void filesys_delayed_change (Unit *u, int frames, const TCHAR *rootdir, const TCHAR *volume, bool readonly, int flags)
  1685. {
  1686. if (u->reinsertdelay)
  1687. return;
  1688. u->reinsertdelay = frames;
  1689. u->newflags = flags;
  1690. u->newr

Large files files are truncated, but you can click here to view the full file