/filesys.cpp
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
- /*
- * UAE - The Un*x Amiga Emulator
- *
- * Unix file system handler for AmigaDOS
- *
- * Copyright 1996 Ed Hanway
- * Copyright 1996, 1997 Bernd Schmidt
- *
- * Version 0.4: 970308
- *
- * Based on example code (c) 1988 The Software Distillery
- * and published in Transactor for the Amiga, Volume 2, Issues 2-5.
- * (May - August 1989)
- *
- * Known limitations:
- * Does not support several (useless) 2.0+ packet types.
- * May not return the correct error code in some cases.
- * Does not check for sane values passed by AmigaDOS. May crash the emulation
- * if passed garbage values.
- * Could do tighter checks on malloc return values.
- * Will probably fail spectacularly in some cases if the filesystem is
- * modified at the same time by another process while UAE is running.
- */
- #include "sysconfig.h"
- #include "sysdeps.h"
- #include "threaddep/thread.h"
- #include "options.h"
- #include "traps.h"
- #include "uae.h"
- #include "memory.h"
- #include "custom.h"
- #include "events.h"
- #include "newcpu.h"
- #include "filesys.h"
- #include "autoconf.h"
- #include "fsusage.h"
- #include "native2amiga.h"
- #include "scsidev.h"
- #include "uaeserial.h"
- #include "fsdb.h"
- #include "zfile.h"
- #include "zarchive.h"
- #include "gui.h"
- #include "gayle.h"
- #include "idecontrollers.h"
- #include "savestate.h"
- #include "a2091.h"
- #include "ncr_scsi.h"
- #include "cdtv.h"
- #include "sana2.h"
- #include "bsdsocket.h"
- #include "uaeresource.h"
- #include "inputdevice.h"
- #include "clipboard.h"
- #include "consolehook.h"
- #include "blkdev.h"
- #include "isofs_api.h"
- #include "scsi.h"
- #include "uaenative.h"
- #include "tabletlibrary.h"
- #include "cia.h"
- #include "picasso96.h"
- #include "cpuboard.h"
- #include "rommgr.h"
- #include "debug.h"
- #include "debugmem.h"
- #ifdef RETROPLATFORM
- #include "rp.h"
- #endif
- #define TRACING_ENABLED 1
- int log_filesys = 0;
- #define TRAPMD 1
- #if TRACING_ENABLED
- #if 0
- #define TRACE(x) if (log_filesys > 0 && (unit->volflags & MYVOLUMEINFO_CDFS)) { write_log x; }
- #else
- #define TRACE(x) if (log_filesys > 0) { write_log x; }
- #endif
- #define TRACEI(x) if (log_filesys > 0) { write_log x; }
- #define TRACE2(x) if (log_filesys >= 2) { write_log x; }
- #define TRACE3(x) if (log_filesys >= 3) { write_log x; }
- #define DUMPLOCK(c,u,x) dumplock(c,u,x)
- #else
- #define TRACE(x)
- #define DUMPLOCK(c,u,x)
- #define TRACE2(x)
- #define TRACE3(x)
- #endif
- #define KS12_BOOT_HACK 1
- #define UNIT_LED(unit) ((unit)->ui.unit_type == UNIT_CDFS ? LED_CD : LED_HD)
- static int bootrom_header;
- static uae_u32 dlg (uae_u32 a)
- {
- return (dbg (a + 0) << 24) | (dbg (a + 1) << 16) | (dbg (a + 2) << 8) | (dbg (a + 3) << 0);
- }
- static void aino_test (a_inode *aino)
- {
- #ifdef AINO_DEBUG
- a_inode *aino2 = aino, *aino3;
- for (;;) {
- if (!aino || !aino->next)
- return;
- if ((aino->checksum1 ^ aino->checksum2) != 0xaaaa5555) {
- write_log (_T("PANIC: corrupted or freed but used aino detected!"), aino);
- }
- aino3 = aino;
- aino = aino->next;
- if (aino->prev != aino3) {
- write_log (_T("PANIC: corrupted aino linking!\n"));
- break;
- }
- if (aino == aino2) break;
- }
- #endif
- }
- static void aino_test_init (a_inode *aino)
- {
- #ifdef AINO_DEBUG
- aino->checksum1 = (uae_u32)aino;
- aino->checksum2 = aino->checksum1 ^ 0xaaaa5555;
- #endif
- }
- #define UAEFS_VERSION "UAE fs 0.6"
- uaecptr filesys_initcode, filesys_initcode_ptr, filesys_initcode_real;
- static uaecptr bootrom_start;
- static uae_u32 fsdevname, fshandlername, filesys_configdev;
- static uae_u32 cdfs_devname, cdfs_handlername;
- static uaecptr afterdos_name, afterdos_id, afterdos_initcode;
- static uaecptr keymaphook_name, keymaphook_id, keymaphook_initcode;
- static uaecptr shell_execute_data, shell_execute_process;
- static int filesys_in_interrupt;
- static uae_u32 mountertask;
- static int automountunit = -1;
- static int autocreatedunit;
- static int cd_unit_offset, cd_unit_number;
- static uaecptr ROM_filesys_doio, ROM_filesys_doio_original;
- static uaecptr ROM_filesys_putmsg, ROM_filesys_putmsg_original;
- static uaecptr ROM_filesys_putmsg_return;
- static uaecptr ROM_filesys_hack_remove;
- static smp_comm_pipe shellexecute_pipe;
- static uae_u32 segtrack_mode = 0;
- #define FS_STARTUP 0
- #define FS_GO_DOWN 1
- #define DEVNAMES_PER_HDF 32
- #define UNIT_FILESYSTEM 0
- #define UNIT_CDFS 1
- typedef struct {
- int unit_type;
- int open; // >0 start as filesystem, <0 = allocated but do not start
- TCHAR *devname; /* device name, e.g. UAE0: */
- uaecptr devname_amiga;
- uaecptr startup;
- uaecptr devicenode;
- uaecptr parmpacket;
- TCHAR *volname; /* volume name, e.g. CDROM, WORK, etc. */
- int volflags; /* volume flags, readonly, stream uaefsdb support */
- TCHAR *rootdir; /* root native directory/hdf. empty drive if invalid path */
- TCHAR *rootdirdiff; /* "diff" file/directory */
- bool readonly; /* disallow write access? */
- bool locked; /* action write protect */
- bool unknown_media; /* ID_UNREADABLE_DISK */
- int bootpri; /* boot priority. -128 = no autoboot, -129 = no mount */
- int devno;
- bool wasisempty; /* if true, this unit was created empty */
- int canremove; /* if >0, this unit can be safely ejected and remounted */
- bool configureddrive; /* if true, this is drive that was manually configured */
- bool inject_icons; /* inject icons if directory filesystem */
- struct hardfiledata hf;
- struct zvolume *zarchive;
- /* Threading stuff */
- smp_comm_pipe *volatile unit_pipe, *volatile back_pipe;
- uae_thread_id tid;
- struct _unit *self;
- /* Reset handling */
- uae_sem_t reset_sync_sem;
- volatile int reset_state;
- /* RDB stuff */
- uaecptr rdb_devname_amiga[DEVNAMES_PER_HDF];
- int rdb_lowcyl;
- int rdb_highcyl;
- int rdb_cylblocks;
- uae_u8 *rdb_filesysstore;
- int rdb_filesyssize;
- TCHAR *filesysdir;
- /* filesystem seglist */
- uaecptr filesysseg;
- uae_u32 rdb_dostype;
- /* CDFS */
- bool cd_open;
- int cddevno;
- void *cdfs_superblock;
- } UnitInfo;
- struct uaedev_mount_info {
- UnitInfo ui[MAX_FILESYSTEM_UNITS];
- };
- static struct uaedev_mount_info mountinfo;
- /* minimal AmigaDOS definitions */
- /* field offsets in DosPacket */
- #define dp_Type 8
- #define dp_Res1 12
- #define dp_Res2 16
- #define dp_Arg1 20
- #define dp_Arg2 24
- #define dp_Arg3 28
- #define dp_Arg4 32
- #define dp_Arg5 36
- #define DP64_INIT -3L
- #define dp64_Type 8
- #define dp64_Res0 12
- #define dp64_Res2 16
- #define dp64_Res1 24
- #define dp64_Arg1 32
- #define dp64_Arg2 40
- #define dp64_Arg3 48
- #define dp64_Arg4 52
- #define dp64_Arg5 56
- #define dp_Max 60
- /* result codes */
- #define DOS_TRUE ((uae_u32)-1L)
- #define DOS_FALSE (0L)
- /* DirEntryTypes */
- #define ST_PIPEFILE -5
- #define ST_LINKFILE -4
- #define ST_FILE -3
- #define ST_ROOT 1
- #define ST_USERDIR 2
- #define ST_SOFTLINK 3
- #define ST_LINKDIR 4
- #if 1
- #define MAXFILESIZE32 (0xffffffff)
- #else
- /* technically correct but most native
- * filesystems don't enforce it
- */
- #define MAXFILESIZE32 (0x7fffffff)
- #endif
- #define MAXFILESIZE32_2G (0x7fffffff)
- /* Passed as type to Lock() */
- #define SHARED_LOCK -2 /* File is readable by others */
- #define ACCESS_READ -2 /* Synonym */
- #define EXCLUSIVE_LOCK -1 /* No other access allowed */
- #define ACCESS_WRITE -1 /* Synonym */
- /* packet types */
- #define ACTION_CURRENT_VOLUME 7
- #define ACTION_LOCATE_OBJECT 8
- #define ACTION_RENAME_DISK 9
- #define ACTION_FREE_LOCK 15
- #define ACTION_DELETE_OBJECT 16
- #define ACTION_RENAME_OBJECT 17
- #define ACTION_MORE_CACHE 18
- #define ACTION_COPY_DIR 19
- #define ACTION_SET_PROTECT 21
- #define ACTION_CREATE_DIR 22
- #define ACTION_EXAMINE_OBJECT 23
- #define ACTION_EXAMINE_NEXT 24
- #define ACTION_DISK_INFO 25
- #define ACTION_INFO 26
- #define ACTION_FLUSH 27
- #define ACTION_SET_COMMENT 28
- #define ACTION_PARENT 29
- #define ACTION_SET_DATE 34
- #define ACTION_FIND_WRITE 1004
- #define ACTION_FIND_INPUT 1005
- #define ACTION_FIND_OUTPUT 1006
- #define ACTION_END 1007
- #define ACTION_SEEK 1008
- #define ACTION_WRITE_PROTECT 1023
- #define ACTION_IS_FILESYSTEM 1027
- #define ACTION_READ 'R'
- #define ACTION_WRITE 'W'
- /* 2.0+ packet types */
- #define ACTION_INHIBIT 31
- #define ACTION_SET_FILE_SIZE 1022
- #define ACTION_LOCK_RECORD 2008
- #define ACTION_FREE_RECORD 2009
- #define ACTION_SAME_LOCK 40
- #define ACTION_CHANGE_MODE 1028
- #define ACTION_FH_FROM_LOCK 1026
- #define ACTION_COPY_DIR_FH 1030
- #define ACTION_PARENT_FH 1031
- #define ACTION_EXAMINE_ALL 1033
- #define ACTION_EXAMINE_FH 1034
- #define ACTION_EXAMINE_ALL_END 1035
- #define ACTION_FORMAT 1020
- #define ACTION_IS_FILESYSTEM 1027
- #define ACTION_ADD_NOTIFY 4097
- #define ACTION_REMOVE_NOTIFY 4098
- #define ACTION_READ_LINK 1024
- /* OS4 64-bit filesize packets */
- #define ACTION_FILESYSTEM_ATTR 3005
- #define ACTION_CHANGE_FILE_POSITION64 8001
- #define ACTION_GET_FILE_POSITION64 8002
- #define ACTION_CHANGE_FILE_SIZE64 8003
- #define ACTION_GET_FILE_SIZE64 8004
- /* MOS 64-bit filesize packets */
- #define ACTION_SEEK64 26400
- #define ACTION_SET_FILE_SIZE64 26401
- #define ACTION_LOCK_RECORD64 26402
- #define ACTION_FREE_RECORD64 26403
- #define ACTION_QUERY_ATTR 26407
- #define ACTION_EXAMINE_OBJECT64 26408
- #define ACTION_EXAMINE_NEXT64 26409
- #define ACTION_EXAMINE_FH64 26410
- /* not supported */
- #define ACTION_MAKE_LINK 1021
- #define DISK_TYPE_DOS 0x444f5300 /* DOS\0 */
- #define DISK_TYPE_DOS_FFS 0x444f5301 /* DOS\1 */
- #define CDFS_DOSTYPE 0x43440000 /* CDxx */
- typedef struct _dpacket {
- uaecptr packet_addr;
- uae_u8 *packet_data;
- uae_u8 packet_array[dp_Max];
- bool need_flush;
- } dpacket;
- typedef struct {
- uae_u32 uniq;
- /* The directory we're going through. */
- a_inode *aino;
- /* The file we're going to look up next. */
- a_inode *curr_file;
- } ExamineKey;
- struct lockrecord
- {
- struct lockrecord *next;
- dpacket *packet;
- uae_u64 pos;
- uae_u64 len;
- uae_u32 mode;
- uae_u32 timeout;
- uae_u32 msg;
- };
- typedef struct key {
- struct key *next;
- a_inode *aino;
- uae_u32 uniq;
- struct fs_filehandle *fd;
- uae_u64 file_pos;
- int dosmode;
- int createmode;
- int notifyactive;
- struct lockrecord *record;
- } Key;
- typedef struct notify {
- struct notify *next;
- uaecptr notifyrequest;
- TCHAR *fullname;
- TCHAR *partname;
- } Notify;
- typedef struct exallkey {
- uae_u32 id;
- struct fs_dirhandle *dirhandle;
- TCHAR *fn;
- uaecptr control;
- } ExAllKey;
- /* Since ACTION_EXAMINE_NEXT is so braindamaged, we have to keep
- * some of these around
- */
- #define EXKEYS 128
- #define EXALLKEYS 100
- #define MAX_AINO_HASH 128
- #define NOTIFY_HASH_SIZE 127
- /* handler state info */
- typedef struct _unit {
- struct _unit *next;
- /* Amiga stuff */
- uaecptr dosbase;
- /* volume points to our IO board, always 1:1 mapping */
- uaecptr volume;
- uaecptr port; /* Our port */
- uaecptr locklist;
- /* Native stuff */
- uae_s32 unit; /* unit number */
- UnitInfo ui; /* unit startup info */
- TCHAR tmpbuf3[256];
- /* Dummy message processing */
- uaecptr dummy_message;
- volatile unsigned int cmds_sent;
- volatile unsigned int cmds_complete;
- volatile unsigned int cmds_acked;
- /* ExKeys */
- ExamineKey examine_keys[EXKEYS];
- int next_exkey;
- unsigned int total_locked_ainos;
- /* ExAll */
- ExAllKey exalls[EXALLKEYS];
- int exallid;
- /* Keys */
- struct key *keys;
- struct lockrecord *waitingrecords;
- a_inode rootnode;
- unsigned int aino_cache_size;
- a_inode *aino_hash[MAX_AINO_HASH];
- unsigned int nr_cache_hits;
- unsigned int nr_cache_lookups;
- struct notify *notifyhash[NOTIFY_HASH_SIZE];
- int volflags;
- uae_u32 lockkey;
- bool inhibited;
- bool canremovable;
- /* increase when media is changed.
- * used to detect if cached aino is valid
- */
- int mountcount;
- int mount_changed;
- void *cdfs_superblock;
- TCHAR *mount_volume;
- TCHAR *mount_rootdir;
- bool mount_readonly;
- int mount_flags;
- int reinsertdelay;
- TCHAR *newvolume;
- TCHAR *newrootdir;
- bool newreadonly;
- int newflags;
- } Unit;
- int nr_units (void)
- {
- int cnt = 0;
- for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
- if (mountinfo.ui[i].open > 0)
- cnt++;
- }
- return cnt;
- }
- int nr_directory_units (struct uae_prefs *p)
- {
- int cnt = 0;
- if (p) {
- for (int i = 0; i < p->mountitems; i++) {
- if (p->mountconfig[i].ci.controller_type == HD_CONTROLLER_TYPE_UAE)
- cnt++;
- }
- } else {
- for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
- if (mountinfo.ui[i].open > 0 && mountinfo.ui[i].hf.ci.controller_type == HD_CONTROLLER_TYPE_UAE)
- cnt++;
- }
- }
- return cnt;
- }
- static int is_virtual (int unit_no)
- {
- int t = is_hardfile (unit_no);
- return t == FILESYS_VIRTUAL || t == FILESYS_CD;
- }
- int is_hardfile (int unit_no)
- {
- if (mountinfo.ui[unit_no].volname || mountinfo.ui[unit_no].wasisempty || mountinfo.ui[unit_no].unknown_media) {
- if (unit_no >= cd_unit_offset && unit_no < cd_unit_offset + cd_unit_number)
- return FILESYS_CD;
- return FILESYS_VIRTUAL;
- }
- if (mountinfo.ui[unit_no].hf.ci.sectors == 0) {
- if (mountinfo.ui[unit_no].hf.flags & 1)
- return FILESYS_HARDDRIVE;
- return FILESYS_HARDFILE_RDB;
- }
- return FILESYS_HARDFILE;
- }
- static void close_filesys_unit (UnitInfo *uip)
- {
- if (!uip->open)
- return;
- if (uip->hf.handle_valid)
- hdf_close (&uip->hf);
- if (uip->volname != 0)
- xfree (uip->volname);
- if (uip->devname != 0)
- xfree (uip->devname);
- if (uip->rootdir != 0)
- xfree (uip->rootdir);
- if (uip->unit_pipe)
- xfree (uip->unit_pipe);
- if (uip->back_pipe)
- xfree (uip->back_pipe);
- if (uip->cd_open) {
- sys_command_close (uip->cddevno);
- isofs_unmount (uip->cdfs_superblock);
- }
- uip->unit_pipe = 0;
- uip->back_pipe = 0;
- uip->hf.handle_valid = 0;
- uip->volname = 0;
- uip->devname = 0;
- uip->rootdir = 0;
- uip->open = 0;
- uip->cd_open = 0;
- }
- static uaedev_config_data *getuci (struct uaedev_config_data *uci, int nr)
- {
- return &uci[nr];
- }
- static UnitInfo *getuip (struct uae_prefs *p, int index)
- {
- if (index < 0)
- return NULL;
- index = p->mountconfig[index].configoffset;
- if (index < 0)
- return NULL;
- return &mountinfo.ui[index];
- }
- static int getuindex (struct uae_prefs *p, int index)
- {
- if (index < 0)
- return -1;
- return p->mountconfig[index].unitnum;
- }
- int get_filesys_unitconfig (struct uae_prefs *p, int index, struct mountedinfo *mi)
- {
- UnitInfo *ui = getuip (p, index);
- struct uaedev_config_data *uci = &p->mountconfig[index];
- UnitInfo uitmp;
- TCHAR filepath[MAX_DPATH];
- memset (mi, 0, sizeof (struct mountedinfo));
- memset (&uitmp, 0, sizeof uitmp);
- _tcscpy(mi->rootdir, uci->ci.rootdir);
- if (!ui) {
- ui = &uitmp;
- if (uci->ci.type == UAEDEV_DIR) {
- cfgfile_resolve_path_out_load(uci->ci.rootdir, filepath, MAX_DPATH, PATH_DIR);
- _tcscpy(mi->rootdir, filepath);
- mi->ismounted = 1;
- if (filepath[0] == 0)
- return FILESYS_VIRTUAL;
- if (my_existsfile (filepath)) {
- mi->ismedia = 1;
- return FILESYS_VIRTUAL;
- }
- if (my_getvolumeinfo (filepath) < 0)
- return -1;
- mi->ismedia = true;
- return FILESYS_VIRTUAL;
- } else if (uci->ci.type == UAEDEV_HDF) {
- cfgfile_resolve_path_out_load(uci->ci.rootdir, filepath, MAX_DPATH, PATH_HDF);
- _tcscpy(mi->rootdir, filepath);
- ui->hf.ci.readonly = true;
- ui->hf.ci.blocksize = uci->ci.blocksize;
- int err = hdf_open (&ui->hf, filepath);
- if (err <= 0) {
- mi->ismedia = false;
- mi->ismounted = true;
- mi->error = err;
- if (uci->ci.reserved == 0 && uci->ci.sectors == 0 && uci->ci.surfaces == 0) {
- if (ui->hf.flags & 1)
- return FILESYS_HARDDRIVE;
- return FILESYS_HARDFILE_RDB;
- }
- return -1;
- }
- mi->ismedia = true;
- if (ui->hf.drive_empty)
- mi->ismedia = 0;
- hdf_close (&ui->hf);
- } else if (uci->ci.type == UAEDEV_CD) {
- cfgfile_resolve_path_out_load(uci->ci.rootdir, filepath, MAX_DPATH, PATH_CD);
- _tcscpy(mi->rootdir, filepath);
- struct device_info di;
- ui->hf.ci.readonly = true;
- ui->hf.ci.blocksize = uci->ci.blocksize;
- mi->size = -1;
- mi->ismounted = true;
- if (blkdev_get_info (p, ui->hf.ci.device_emu_unit, &di)) {
- mi->ismedia = di.media_inserted != 0;
- _tcscpy (mi->rootdir, di.label);
- }
- #if 0
- if (ui->hf.ci.cd_emu_unit == 0)
- _tcscpy (mi->rootdir, _T("CD"));
- else
- _stprintf (mi->rootdir, _T("CD %d"), ui->hf.ci.cd_emu_unit);
- #endif
- }
- } else if (uci->ci.type != UAEDEV_TAPE) {
- if (ui->hf.ci.controller_type == HD_CONTROLLER_TYPE_UAE) { // what is this? || (ui->controller && p->cs_ide)) {
- mi->ismounted = 1;
- if (uci->ci.type == UAEDEV_HDF)
- mi->ismedia = ui->hf.drive_empty ? false : true;
- else
- mi->ismedia = true;
- }
- }
- if (uci->ci.type == UAEDEV_TAPE) {
- cfgfile_resolve_path_out_load(uci->ci.rootdir, filepath, MAX_DPATH, PATH_TAPE);
- _tcscpy(mi->rootdir, filepath);
- struct device_info di;
- int unitnum = getuindex (p, index);
- mi->size = -1;
- mi->ismounted = false;
- if (unitnum >= 0) {
- mi->ismounted = true;
- if (tape_get_info (unitnum, &di)) {
- mi->ismedia = di.media_inserted != 0;
- _tcscpy (mi->rootdir, di.label);
- }
- } else {
- struct scsi_data_tape *tape;
- unitnum = 0;
- tape = tape_alloc (unitnum, filepath, uci->ci.readonly);
- if (tape) {
- if (tape_get_info (unitnum, &di)) {
- mi->ismedia = di.media_inserted != 0;
- _tcscpy (mi->rootdir, di.label);
- }
- tape_free (tape);
- }
- }
- return FILESYS_TAPE;
- }
- if (mi->size < 0)
- return -1;
- mi->size = ui->hf.virtsize;
- if (uci->ci.highcyl) {
- uci->ci.cyls = mi->nrcyls = uci->ci.highcyl;
- } else {
- 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);
- }
- if (uci->ci.type == UAEDEV_DIR)
- return FILESYS_VIRTUAL;
- if (uci->ci.reserved == 0 && uci->ci.sectors == 0 && uci->ci.surfaces == 0) {
- if (ui->hf.flags & 1)
- return FILESYS_HARDDRIVE;
- return FILESYS_HARDFILE_RDB;
- }
- return FILESYS_HARDFILE;
- }
- static void stripsemicolon (TCHAR *s)
- {
- if (!s)
- return;
- while (_tcslen(s) > 0 && s[_tcslen(s) - 1] == ':')
- s[_tcslen(s) - 1] = 0;
- }
- static void stripspace (TCHAR *s)
- {
- if (!s)
- return;
- for (int i = 0; i < _tcslen (s); i++) {
- if (s[i] == ' ')
- s[i] = '_';
- }
- }
- static void striplength (TCHAR *s, int len)
- {
- if (!s)
- return;
- if (_tcslen (s) <= len)
- return;
- s[len] = 0;
- }
- static void fixcharset (TCHAR *s)
- {
- char tmp[MAX_DPATH];
- if (!s)
- return;
- ua_fs_copy (tmp, MAX_DPATH, s, '_');
- au_fs_copy (s, strlen (tmp) + 1, tmp);
- }
- TCHAR *validatevolumename (TCHAR *s, const TCHAR *def)
- {
- stripsemicolon (s);
- fixcharset (s);
- striplength (s, 30);
- if (_tcslen(s) == 0 && def) {
- xfree(s);
- s = my_strdup(def);
- }
- return s;
- }
- TCHAR *validatedevicename (TCHAR *s, const TCHAR *def)
- {
- stripsemicolon (s);
- stripspace (s);
- fixcharset (s);
- striplength (s, 30);
- if (_tcslen(s) == 0 && def) {
- xfree(s);
- s = my_strdup(def);
- }
- return s;
- }
- TCHAR *filesys_createvolname (const TCHAR *volname, const TCHAR *rootdir, struct zvolume *zv, const TCHAR *def)
- {
- TCHAR *nvol = NULL;
- int i, archivehd;
- TCHAR *p = NULL;
- TCHAR path[MAX_DPATH];
- cfgfile_resolve_path_out_load(rootdir, path, MAX_DPATH, PATH_DIR);
- archivehd = -1;
- if (my_existsfile (path))
- archivehd = 1;
- else if (my_existsdir (path))
- archivehd = 0;
- if (zv && zv->volumename && _tcslen(zv->volumename) > 0) {
- nvol = my_strdup(zv->volumename);
- nvol = validatevolumename (nvol, def);
- return nvol;
- }
- if ((!volname || _tcslen (volname) == 0) && path && archivehd >= 0) {
- p = my_strdup (path);
- for (i = _tcslen (p) - 1; i >= 0; i--) {
- TCHAR c = p[i];
- if (c == ':' || c == '/' || c == '\\') {
- if (i == _tcslen (p) - 1)
- continue;
- if (!_tcscmp (p + i, _T(":\\"))) {
- xfree (p);
- p = xmalloc (TCHAR, 10);
- p[0] = path[0];
- p[1] = 0;
- i = 0;
- } else {
- i++;
- }
- break;
- }
- }
- if (i >= 0)
- nvol = my_strdup (p + i);
- }
- if (!nvol && archivehd >= 0) {
- if (volname && _tcslen (volname) > 0)
- nvol = my_strdup (volname);
- else
- nvol = my_strdup (def);
- }
- if (!nvol) {
- if (volname && _tcslen (volname))
- nvol = my_strdup (volname);
- else
- nvol = my_strdup (_T(""));
- }
- nvol = validatevolumename (nvol, def);
- xfree (p);
- return nvol;
- }
- static int set_filesys_volume (const TCHAR *rootdir, int *flags, bool *readonly, bool *emptydrive, struct zvolume **zvp)
- {
- *emptydrive = 0;
- if (my_existsfile (rootdir)) {
- struct zvolume *zv;
- zv = zfile_fopen_archive (rootdir);
- if (!zv) {
- error_log (_T("'%s' is not a supported archive file."), rootdir);
- return -1;
- }
- *zvp = zv;
- *flags = MYVOLUMEINFO_ARCHIVE;
- *readonly = 1;
- } else {
- *flags = my_getvolumeinfo (rootdir);
- if (*flags < 0) {
- if (rootdir && rootdir[0])
- error_log (_T("directory '%s' not found, mounting as empty drive."), rootdir);
- *emptydrive = 1;
- *flags = 0;
- } else if ((*flags) & MYVOLUMEINFO_READONLY) {
- error_log (_T("'%s' set to read-only."), rootdir);
- *readonly = 1;
- }
- }
- return 1;
- }
- void uci_set_defaults (struct uaedev_config_info *uci, bool rdb)
- {
- memset (uci, 0, sizeof (struct uaedev_config_info));
- if (!rdb) {
- uci->sectors = 32;
- uci->reserved = 2;
- uci->surfaces = 1;
- }
- uci->blocksize = 512;
- uci->maxtransfer = 0x7fffffff;
- uci->mask = 0xffffffff;
- uci->bufmemtype = 1;
- uci->buffers = 50;
- uci->stacksize = 4000;
- uci->bootpri = 0;
- uci->priority = 10;
- uci->sectorsperblock = 1;
- uci->device_emu_unit = -1;
- }
- static void get_usedblocks(struct fs_usage *fsu, bool fs, int *pblocksize, uae_s64 *pnumblocks, uae_s64 *pinuse, bool reduce)
- {
- uae_s64 numblocks = 0, inuse;
- int blocksize = *pblocksize;
- if (fs && currprefs.filesys_limit) {
- if (fsu->total > (uae_s64)currprefs.filesys_limit * 1024) {
- uae_s64 oldtotal = fsu->total;
- fsu->total = currprefs.filesys_limit * 1024;
- fsu->avail = ((fsu->avail / 1024) * (fsu->total / 1024)) / (oldtotal / 1024);
- fsu->avail *= 1024;
- }
- }
- if (reduce) {
- while (blocksize < 32768 || numblocks == 0) {
- numblocks = fsu->total / blocksize;
- if (numblocks <= 10)
- numblocks = 10;
- // Value that does not overflow when multiplied by 100 (uses 128 to keep it simple)
- if (numblocks < 0x02000000)
- break;
- blocksize *= 2;
- }
- }
- numblocks = fsu->total / blocksize;
- inuse = (numblocks * blocksize - fsu->avail) / blocksize;
- if (inuse > numblocks)
- inuse = numblocks;
- if (pnumblocks)
- *pnumblocks = numblocks;
- if (pinuse)
- *pinuse = inuse;
- if (pblocksize)
- *pblocksize = blocksize;
- }
- static bool get_blocks(const TCHAR *rootdir, int unit, int flags, int *pblocksize, uae_s64 *pnumblocks, uae_s64 *pinuse, bool reduce)
- {
- struct fs_usage fsu;
- int ret;
- bool fs = false;
- int blocksize;
- blocksize = 512;
- if (flags & MYVOLUMEINFO_ARCHIVE) {
- ret = zfile_fs_usage_archive(rootdir, 0, &fsu);
- fs = true;
- } else {
- ret = get_fs_usage(rootdir, 0, &fsu);
- fs = true;
- }
- if (ret)
- return false;
- get_usedblocks(&fsu, fs, &blocksize, pnumblocks, pinuse, reduce);
- if (pblocksize)
- *pblocksize = blocksize;
- return ret == 0;
- }
- static int set_filesys_unit_1 (int nr, struct uaedev_config_info *ci, bool custom)
- {
- UnitInfo *ui;
- int i;
- bool emptydrive = false;
- bool iscd;
- struct uaedev_config_info c;
- memcpy (&c, ci, sizeof (struct uaedev_config_info));
- if (nr < 0) {
- for (nr = 0; nr < MAX_FILESYSTEM_UNITS; nr++) {
- if (!mountinfo.ui[nr].open)
- break;
- }
- if (nr == MAX_FILESYSTEM_UNITS) {
- error_log (_T("No slot allocated for this unit"));
- return -1;
- }
- }
- if (ci->controller_type != HD_CONTROLLER_TYPE_UAE || ci->type == UAEDEV_TAPE) {
- ui = &mountinfo.ui[nr];
- memset (ui, 0, sizeof (UnitInfo));
- memcpy (&ui->hf.ci, &c, sizeof (struct uaedev_config_info));
- ui->readonly = c.readonly;
- ui->unit_type = -1;
- ui->open = -1;
- return nr;
- }
- iscd = nr >= cd_unit_offset && nr < cd_unit_offset + cd_unit_number;
- if (!custom)
- cfgfile_resolve_path_load(c.rootdir, MAX_DPATH, iscd ? PATH_CD : (ci->volname[0] ? PATH_DIR : PATH_HDF));
- for (i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
- if (nr == i || !mountinfo.ui[i].open || mountinfo.ui[i].rootdir == NULL || is_hardfile (i) == FILESYS_CD)
- continue;
- if (_tcslen(c.rootdir) > 0 && samepath(mountinfo.ui[i].rootdir, c.rootdir)) {
- error_log (_T("directory/hardfile '%s' already added."), c.rootdir);
- return -1;
- }
- }
- for (;;) {
- bool retry = false;
- for (i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
- int hf = is_hardfile(i);
- if (nr == i || !mountinfo.ui[i].open || mountinfo.ui[i].rootdir == NULL)
- continue;
- if (hf != FILESYS_HARDDRIVE && hf != FILESYS_HARDFILE && hf != FILESYS_HARDFILE_RDB)
- continue;
- if (mountinfo.ui[i].hf.ci.controller_unit == c.controller_unit) {
- c.controller_unit++;
- if (c.controller_unit >= MAX_FILESYSTEM_UNITS) {
- error_log (_T("directory/hardfile '%s' invalid unit number."), c.rootdir);
- return -1;
- }
- retry = true;
- }
- }
- if (!retry)
- break;
- }
- ui = &mountinfo.ui[nr];
- memset (ui, 0, sizeof (UnitInfo));
- memcpy(&ui->hf.ci, &c, sizeof c);
- if (iscd) {
- ui->unit_type = UNIT_CDFS;
- emptydrive = 1;
- ui->volflags = MYVOLUMEINFO_CDFS | MYVOLUMEINFO_READONLY;
- c.readonly = true;
- } else if (c.volname[0]) {
- int flags = 0;
- uae_s64 numblocks;
- emptydrive = 1;
- if (c.rootdir[0]) {
- if (set_filesys_volume (c.rootdir, &flags, &c.readonly, &emptydrive, &ui->zarchive) < 0)
- return -1;
- }
- ui->volname = filesys_createvolname (c.volname, c.rootdir, ui->zarchive, _T("harddrive"));
- ui->volflags = flags;
- TCHAR *vs = au(UAEFS_VERSION);
- TCHAR *vsp = vs + _tcslen(vs) - 1;
- while (vsp != vs) {
- if (*vsp == ' ') {
- *vsp++ = 0;
- break;
- }
- vsp--;
- }
- _tcscpy(ui->hf.vendor_id, _T("UAE"));
- _tcscpy(ui->hf.product_id, vs);
- _tcscpy(ui->hf.product_rev, vsp);
- xfree(vs);
- ui->hf.ci.unit_feature_level = HD_LEVEL_SCSI_2;
- if (get_blocks(c.rootdir, nr, flags, &ui->hf.ci.blocksize, &numblocks, NULL, false))
- ui->hf.ci.max_lba = numblocks > 0xffffffff ? 0xffffffff : numblocks;
- else
- ui->hf.ci.max_lba = 0x00ffffff;
- } else {
- ui->unit_type = UNIT_FILESYSTEM;
- ui->hf.unitnum = nr;
- ui->volname = 0;
- if (ui->hf.ci.rootdir[0]) {
- if (hdf_open (&ui->hf) <= 0 && !c.readonly) {
- write_log (_T("Attempting to open '%s' in read-only mode.\n"), ui->hf.ci.rootdir);
- ui->hf.ci.readonly = c.readonly = true;
- if (hdf_open (&ui->hf) > 0) {
- error_log (_T("'%s' opened in read-only mode.\n"), ui->hf.ci.rootdir);
- }
- }
- } else {
- // empty drive?
- ui->hf.drive_empty = 1;
- }
- if (!ui->hf.drive_empty) {
- if (ui->hf.handle_valid == 0) {
- error_log (_T("Hardfile '%s' not found."), ui->hf.ci.rootdir);
- goto err;
- }
- if (ui->hf.ci.blocksize > ui->hf.virtsize || ui->hf.virtsize == 0) {
- error_log (_T("Hardfile '%s' too small."), ui->hf.ci.rootdir);
- goto err;
- }
- }
- if ((ui->hf.ci.blocksize & (ui->hf.ci.blocksize - 1)) != 0 || ui->hf.ci.blocksize == 0) {
- error_log (_T("Hardfile '%s' bad blocksize %d."), ui->hf.ci.rootdir, ui->hf.ci.blocksize);
- goto err;
- }
- if ((ui->hf.ci.sectors || ui->hf.ci.surfaces || ui->hf.ci.reserved) &&
- (ui->hf.ci.sectors < 1 || ui->hf.ci.surfaces < 1 || ui->hf.ci.surfaces > 1023 ||
- ui->hf.ci.reserved < 0 || ui->hf.ci.reserved > 1023) != 0) {
- error_log (_T("Hardfile '%s' bad hardfile geometry."), ui->hf.ci.rootdir);
- goto err;
- }
- if (!ui->hf.ci.highcyl) {
- 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);
- }
- if (!ui->hf.ci.cyls)
- ui->hf.ci.cyls = ui->hf.ci.highcyl;
- if (!ui->hf.ci.cyls)
- ui->hf.ci.cyls = 1;
- }
- ui->self = 0;
- ui->reset_state = FS_STARTUP;
- ui->wasisempty = emptydrive;
- ui->canremove = emptydrive && (ci->flags & MYVOLUMEINFO_REUSABLE);
- ui->rootdir = my_strdup (c.rootdir);
- ui->devname = my_strdup (c.devname);
- stripsemicolon(ui->devname);
- if (c.filesys[0])
- ui->filesysdir = my_strdup (c.filesys);
- ui->readonly = c.readonly;
- if (c.bootpri < -129)
- c.bootpri = -129;
- if (c.bootpri > 127)
- c.bootpri = 127;
- ui->bootpri = c.bootpri;
- ui->inject_icons = c.inject_icons;
- ui->open = 1;
- return nr;
- err:
- if (ui->hf.handle_valid)
- hdf_close (&ui->hf);
- return -1;
- }
- static int set_filesys_unit (int nr, struct uaedev_config_info *ci, bool custom)
- {
- int ret;
- ret = set_filesys_unit_1 (nr, ci, custom);
- return ret;
- }
- static int add_filesys_unit (struct uaedev_config_info *ci, bool custom)
- {
- int nr;
- if (nr_units () >= MAX_FILESYSTEM_UNITS)
- return -1;
- nr = set_filesys_unit_1 (-1, ci, custom);
- #ifdef RETROPLATFORM
- if (nr >= 0) {
- UnitInfo *ui = &mountinfo.ui[nr];
- rp_hd_device_enable (nr, true);
- if (ui->unit_type == UNIT_CDFS)
- rp_cd_image_change(nr, ci->rootdir);
- else
- rp_harddrive_image_change(nr, ci->readonly, ci->rootdir);
- }
- #endif
- return nr;
- }
- int kill_filesys_unitconfig (struct uae_prefs *p, int nr)
- {
- struct uaedev_config_data *uci;
- if (nr < 0)
- return 0;
- uci = getuci (p->mountconfig, nr);
- hardfile_do_disk_change (uci, 0);
- if (uci->configoffset >= 0 && uci->ci.controller_type == HD_CONTROLLER_TYPE_UAE) {
- filesys_media_change(uci->ci.rootdir, 0, uci);
- } else {
- pcmcia_disk_reinsert(p, &uci->ci, true);
- }
- while (nr < MOUNT_CONFIG_SIZE) {
- memmove (&p->mountconfig[nr], &p->mountconfig[nr + 1], sizeof (struct uaedev_config_data));
- nr++;
- }
- p->mountitems--;
- memset (&p->mountconfig[MOUNT_CONFIG_SIZE - 1], 0, sizeof (struct uaedev_config_data));
- return 1;
- }
- int move_filesys_unitconfig (struct uae_prefs *p, int nr, int to)
- {
- struct uaedev_config_data *uci1, *uci2, tmpuci;
- uci1 = getuci (p->mountconfig, nr);
- uci2 = getuci (p->mountconfig, to);
- if (nr == to)
- return 0;
- memcpy (&tmpuci, uci1, sizeof (struct uaedev_config_data));
- memcpy (uci1, uci2, sizeof (struct uaedev_config_data));
- memcpy (uci2, &tmpuci, sizeof (struct uaedev_config_data));
- return 1;
- }
- static void allocuci (struct uae_prefs *p, int nr, int idx, int unitnum)
- {
- struct uaedev_config_data *uci = &p->mountconfig[nr];
- if (idx >= 0) {
- UnitInfo *ui;
- uci->configoffset = idx;
- ui = &mountinfo.ui[idx];
- ui->configureddrive = 1;
- uci->unitnum = unitnum;
- } else {
- uci->configoffset = -1;
- uci->unitnum = -1;
- }
- }
- static void allocuci (struct uae_prefs *p, int nr, int idx)
- {
- allocuci (p, nr, idx, -1);
- }
- static const TCHAR *getunittype(struct uaedev_config_info *uci)
- {
- return uci->type == UAEDEV_CD ? _T("CD") : (uci->type == UAEDEV_TAPE ? _T("TAPE") : _T("HD"));
- }
- static int cpuboard_hd;
- static romconfig cpuboard_dummy;
- void add_cpuboard_unit(int unit, struct uaedev_config_info *uci, struct romconfig *rc)
- {
- int flags = (uci->controller_type >= HD_CONTROLLER_TYPE_IDE_FIRST && uci->controller_type <= HD_CONTROLLER_TYPE_IDE_LAST) ? EXPANSIONTYPE_IDE : EXPANSIONTYPE_SCSI;
- const struct cpuboardtype *cbt = &cpuboards[currprefs.cpuboard_type];
- cpuboard_hd = 0;
- if (cbt->subtypes) {
- if (cbt->subtypes[currprefs.cpuboard_subtype].add && (cbt->subtypes[currprefs.cpuboard_subtype].deviceflags & flags)) {
- if (unit >= 0) {
- write_log(_T("Adding CPUBoard '%s' %s unit %d ('%s')\n"),
- cbt->subtypes[currprefs.cpuboard_subtype].name,
- getunittype(uci), unit, uci->rootdir);
- }
- cbt->subtypes[currprefs.cpuboard_subtype].add(unit, uci, rc);
- cpuboard_hd = 1;
- }
- }
- }
- static void add_cpuboard_unit_init(void)
- {
- memset(&cpuboard_dummy, 0, sizeof cpuboard_dummy);
- cpuboard_dummy.device_id = 7;
- if (currprefs.cpuboard_type) {
- struct romconfig *rc = get_device_romconfig(&currprefs, ROMTYPE_CPUBOARD, 0);
- if (!rc)
- rc = &cpuboard_dummy;
- const struct cpuboardtype *cbt = &cpuboards[currprefs.cpuboard_type];
- if (cbt->subtypes) {
- if (cbt->subtypes[currprefs.cpuboard_subtype].add) {
- const struct cpuboardsubtype *cst = &cbt->subtypes[currprefs.cpuboard_subtype];
- struct uaedev_config_info ci = { 0 };
- write_log(_T("Initializing CPUBoard '%s' %s controller\n"),
- cst->name, (cst->deviceflags & EXPANSIONTYPE_SCSI) ? _T("SCSI") : _T("IDE"));
- cst->add(-1, &ci, rc);
- }
- }
- }
- }
- static bool add_ide_unit(int type, int unit, struct uaedev_config_info *uci)
- {
- bool added = false;
- if (type >= HD_CONTROLLER_TYPE_IDE_EXPANSION_FIRST && type <= HD_CONTROLLER_TYPE_IDE_LAST) {
- for (int i = 0; expansionroms[i].name; i++) {
- if (i == type - HD_CONTROLLER_TYPE_IDE_EXPANSION_FIRST) {
- const struct expansionromtype *ert = &expansionroms[i];
- if ((ert->deviceflags & 2) && is_board_enabled(&currprefs, ert->romtype, uci->controller_type_unit)) {
- cpuboard_hd = 1;
- if (ert->add) {
- struct romconfig *rc = get_device_romconfig(&currprefs, ert->romtype, uci->controller_type_unit);
- write_log(_T("Adding IDE %s '%s' unit %d ('%s')\n"), getunittype(uci),
- ert->name, unit, uci->rootdir);
- ert->add(unit, uci, rc);
- }
- if (cpuboard_hd)
- added = true;
- }
- }
- }
- }
- return added;
- }
- static bool add_scsi_unit(int type, int unit, struct uaedev_config_info *uci)
- {
- bool added = false;
- if (type >= HD_CONTROLLER_TYPE_SCSI_EXPANSION_FIRST && type <= HD_CONTROLLER_TYPE_SCSI_LAST) {
- for (int i = 0; expansionroms[i].name; i++) {
- if (i == type - HD_CONTROLLER_TYPE_SCSI_EXPANSION_FIRST) {
- const struct expansionromtype *ert = &expansionroms[i];
- if ((ert->deviceflags & 1) && is_board_enabled(&currprefs, ert->romtype, uci->controller_type_unit)) {
- cpuboard_hd = 1;
- if (ert->add) {
- struct romconfig *rc = get_device_romconfig(&currprefs, ert->romtype, uci->controller_type_unit);
- write_log(_T("Adding SCSI %s '%s' unit %d ('%s')\n"), getunittype(uci),
- ert->name, unit, uci->rootdir);
- ert->add(unit, uci, rc);
- }
- if (cpuboard_hd)
- added = true;
- }
- }
- }
- }
- return added;
- }
- static void initialize_mountinfo (void)
- {
- int nr;
- UnitInfo *uip = &mountinfo.ui[0];
- cd_unit_offset = MAX_FILESYSTEM_UNITS;
- autocreatedunit = 0;
- for (nr = 0; nr < currprefs.mountitems; nr++) {
- struct uaedev_config_data *uci = &currprefs.mountconfig[nr];
- if (uci->ci.controller_type == HD_CONTROLLER_TYPE_UAE && (uci->ci.type == UAEDEV_DIR || uci->ci.type == UAEDEV_HDF)) {
- struct uaedev_config_info ci;
- memcpy (&ci, &uci->ci, sizeof (struct uaedev_config_info));
- ci.flags = MYVOLUMEINFO_REUSABLE;
- int idx = set_filesys_unit_1 (-1, &ci, false);
- allocuci (&currprefs, nr, idx);
- }
- }
- filesys_addexternals ();
- nr = nr_units ();
- cd_unit_offset = nr;
- cd_unit_number = 0;
- if (currprefs.scsi && currprefs.win32_automount_cddrives) {
- uae_u32 mask = scsi_get_cd_drive_mask ();
- for (int i = 0; i < 32; i++) {
- if (mask & (1 << i)) {
- struct uaedev_config_info ci = { 0 };
- _stprintf (ci.devname, _T("CD%d"), i);
- cd_unit_number++;
- _tcscpy (ci.rootdir, _T("/"));
- ci.readonly = true;
- ci.sectors = 1;
- ci.surfaces = 1;
- ci.blocksize = 2048;
- int idx = set_filesys_unit_1 (i + cd_unit_offset, &ci, true);
- allocuci (&currprefs, nr, idx);
- nr++;
- }
- }
- }
- for (nr = 0; nr < currprefs.mountitems; nr++) {
- struct uaedev_config_data *uci = &currprefs.mountconfig[nr];
- if (uci->ci.controller_type == HD_CONTROLLER_TYPE_UAE) {
- if (uci->ci.type == UAEDEV_TAPE) {
- struct uaedev_config_info ci;
- memcpy (&ci, &uci->ci, sizeof (struct uaedev_config_info));
- int unitnum = scsi_add_tape (&uci->ci);
- if (unitnum >= 0) {
- int idx = set_filesys_unit_1 (-1, &ci, false);
- allocuci (&currprefs, nr, idx, unitnum);
- }
- }
- }
- }
- // init all controllers first
- add_cpuboard_unit_init();
- for (int i = 0; expansionroms[i].name; i++) {
- const struct expansionromtype *ert = &expansionroms[i];
- for (int j = 0; j < MAX_DUPLICATE_EXPANSION_BOARDS; j++) {
- struct romconfig *rc = get_device_romconfig(&currprefs, ert->romtype, j);
- if ((ert->deviceflags & 3) && rc) {
- if (ert->add) {
- struct uaedev_config_info ci = { 0 };
- ci.controller_type_unit = j;
- ert->add(-1, &ci, rc);
- }
- }
- }
- }
- for (nr = 0; nr < currprefs.mountitems; nr++) {
- struct uaedev_config_info *uci = &currprefs.mountconfig[nr].ci;
- int type = uci->controller_type;
- int unit = uci->controller_unit;
- bool added = false;
- uci->uae_unitnum = nr;
- if (type == HD_CONTROLLER_TYPE_UAE) {
- continue;
- } else if (type != HD_CONTROLLER_TYPE_IDE_AUTO && type >= HD_CONTROLLER_TYPE_IDE_FIRST && type <= HD_CONTROLLER_TYPE_IDE_LAST) {
- added = add_ide_unit(type, unit, uci);
- } else if (type == HD_CONTROLLER_TYPE_IDE_AUTO) {
- for (int st = HD_CONTROLLER_TYPE_IDE_FIRST; st <= HD_CONTROLLER_TYPE_IDE_LAST; st++) {
- added = add_ide_unit(st, unit, uci);
- if (added)
- break;
- }
- } else if (type != HD_CONTROLLER_TYPE_SCSI_AUTO && type >= HD_CONTROLLER_TYPE_SCSI_FIRST && type <= HD_CONTROLLER_TYPE_SCSI_LAST) {
- added = add_scsi_unit(type, unit, uci);
- } else if (type == HD_CONTROLLER_TYPE_SCSI_AUTO) {
- for (int st = HD_CONTROLLER_TYPE_SCSI_FIRST; st <= HD_CONTROLLER_TYPE_SCSI_LAST; st++) {
- added = add_scsi_unit(st, unit, uci);
- if (added)
- break;
- }
- #if 0
- } else if (type == HD_CONTROLLER_TYPE_PCMCIA) {
- if (uci->controller_type_unit == 0) {
- gayle_add_pcmcia_sram_unit (uci);
- added = true;
- } else {
- gayle_add_pcmcia_ide_unit (uci);
- added = true;
- }
- #endif
- }
- if (added)
- allocuci (&currprefs, nr, -1);
- }
-
- }
- int sprintf_filesys_unit (TCHAR *buffer, int num)
- {
- UnitInfo *uip = mountinfo.ui;
- if (uip[num].volname != 0)
- _stprintf (buffer, _T("(DH%d:) Filesystem, %s: %s %s"), num, uip[num].volname,
- uip[num].rootdir, uip[num].readonly ? _T("ro") : _T(""));
- else
- _stprintf (buffer, _T("(DH%d:) Hardfile, \"%s\", size %d Mbytes"), num,
- uip[num].rootdir, (int)(uip[num].hf.virtsize / (1024 * 1024)));
- return 0;
- }
- static void free_mountinfo (void)
- {
- int i;
- for (i = 0; i < MAX_FILESYSTEM_UNITS; i++)
- close_filesys_unit (mountinfo.ui + i);
- gayle_free_units ();
- }
- struct hardfiledata *get_hardfile_data_controller(int nr)
- {
- UnitInfo *uip = mountinfo.ui;
- for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
- if (uip[i].open == 0)
- continue;
- if (uip[i].hf.ci.controller_unit == nr && uip[i].hf.ci.type != UAEDEV_DIR)
- return &uip[i].hf;
- }
- for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
- if (uip[i].open == 0)
- continue;
- if (uip[i].hf.ci.controller_unit == nr && uip[i].hf.ci.type == UAEDEV_DIR)
- return &uip[i].hf;
- }
- return NULL;
- }
- struct hardfiledata *get_hardfile_data (int nr)
- {
- UnitInfo *uip = mountinfo.ui;
- if (nr < 0 || nr >= MAX_FILESYSTEM_UNITS || uip[nr].open == 0 || is_virtual (nr))
- return NULL;
- return &uip[nr].hf;
- }
- static uae_u32 a_uniq, key_uniq;
- #define PUT_PCK_RES1(p,v) do { put_long_host((p)->packet_data + dp_Res1, (v)); } while (0)
- #define PUT_PCK_RES2(p,v) do { put_long_host((p)->packet_data + dp_Res2, (v)); } while (0)
- #define GET_PCK_TYPE(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Type)))
- #define GET_PCK_RES1(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Res1)))
- #define GET_PCK_RES2(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Res2)))
- #define GET_PCK_ARG1(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Arg1)))
- #define GET_PCK_ARG2(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Arg2)))
- #define GET_PCK_ARG3(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Arg3)))
- #define GET_PCK_ARG4(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Arg4)))
- #define GET_PCK_ARG5(p) ((uae_s32)(get_long_host((p)->packet_data + dp_Arg5)))
- #define PUT_PCK64_RES0(p,v) do { put_long_host((p)->packet_data + dp64_Res0, (v)); } while (0)
- #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)
- #define PUT_PCK64_RES2(p,v) do { put_long_host((p)->packet_data + dp64_Res2, (v)); } while (0)
- #define GET_PCK64_TYPE(p) ((uae_s32)(get_long_host((p)->packet_data + dp64_Type)))
- #define GET_PCK64_RES0(p) ((uae_s32)(get_long_host((p)->packet_data + dp64_Res0)))
- #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) )
- #define GET_PCK64_ARG1(p) ((uae_s32)(get_long_host((p)->packet_data + dp64_Arg1)))
- #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) )
- #define GET_PCK64_ARG3(p) ((uae_s32)(get_long_host((p)->packet_data + dp64_Arg3)))
- #define GET_PCK64_ARG4(p) ((uae_s32)(get_long_host((p)->packet_data + dp64_Arg4)))
- #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) )
- static void readdpacket(TrapContext *ctx, dpacket *packet, uaecptr pck)
- {
- // Read enough to get also all 64-bit fields
- packet->packet_addr = pck;
- if (trap_is_indirect() || !valid_address(pck, dp_Max)) {
- trap_get_bytes(ctx, packet->packet_array, pck, dp_Max);
- packet->packet_data = packet->packet_array;
- packet->need_flush = true;
- } else {
- packet->packet_data = get_real_address(pck);
- packet->need_flush = false;
- }
- }
- static void writedpacket(TrapContext *ctx, dpacket *packet)
- {
- if (!packet->need_flush)
- return;
- int type = GET_PCK_TYPE(packet);
- if (type >= 8000 && type < 9000 && GET_PCK64_RES0(packet) == DP64_INIT) {
- // 64-bit RESx fields
- trap_put_bytes(ctx, packet->packet_data + 12, packet->packet_addr + 12, 32 - 12);
- } else {
- // dp_Res1 and dp_Res2
- trap_put_bytes(ctx, packet->packet_data + 12, packet->packet_addr + 12, 20 - 12);
- }
- }
- static void set_quadp(TrapContext *ctx, uaecptr p, uae_s64 v)
- {
- if (!trap_valid_address(ctx, p, 8))
- return;
- trap_put_quad(ctx, p, v);
- }
- static uae_u64 get_quadp(TrapContext *ctx, uaecptr p)
- {
- if (!trap_valid_address(ctx, p, 8))
- return 0;
- return trap_get_quad(ctx, p);
- }
- static int flush_cache (Unit *unit, int num);
- static TCHAR *char1(TrapContext *ctx, uaecptr addr)
- {
- uae_char buf[1024];
- #if TRAPMD
- trap_get_string(ctx, (uae_u8*)buf, addr, sizeof(buf));
- #else
- unsigned int i = 0;
- do {
- buf[i] = trap_get_byte(ctx, addr);
- addr++;
- } while (buf[i++] && i < sizeof (buf));
- #endif
- return au_fs(buf);
- }
- static TCHAR *bstr1(TrapContext *ctx, uaecptr addr)
- {
- uae_char buf[257];
- int n = trap_get_byte(ctx, addr);
- addr++;
- #if TRAPMD
- trap_get_bytes(ctx, (uae_u8*)buf, addr, n);
- #else
- for (int i = 0; i < n; i++, addr++)
- buf[i] = trap_get_byte(ctx, addr);
- #endif
- buf[n] = 0;
- return au_fs(buf);
- }
- static TCHAR *bstr(TrapContext *ctx, Unit *unit, uaecptr addr)
- {
- int n = trap_get_byte(ctx, addr);
- uae_char buf[257];
- addr++;
- #if TRAPMD
- trap_get_bytes(ctx, (uae_u8*)buf, addr, n);
- #else
- for (int i = 0; i < n; i++, addr++)
- buf[i] = trap_get_byte(ctx, addr);
- #endif
- buf[n] = 0;
- au_fs_copy (unit->tmpbuf3, sizeof (unit->tmpbuf3) / sizeof (TCHAR), buf);
- return unit->tmpbuf3;
- }
- static TCHAR *cstr(TrapContext *ctx, Unit *unit, uaecptr addr)
- {
- uae_char buf[257];
- trap_get_string(ctx, buf, addr, sizeof buf);
- au_fs_copy (unit->tmpbuf3, sizeof (unit->tmpbuf3) / sizeof (TCHAR), buf);
- return unit->tmpbuf3;
- }
- static TCHAR *bstr_cut(TrapContext *ctx, Unit *unit, uaecptr addr)
- {
- TCHAR *p = unit->tmpbuf3;
- int i, colon_seen = 0, off;
- int n = trap_get_byte(ctx, addr);
- uae_char buf[257];
- off = 0;
- addr++;
- for (i = 0; i < n; i++, addr++) {
- uae_u8 c = trap_get_byte(ctx, addr);
- buf[i] = c;
- if (c == '/' || (c == ':' && colon_seen++ == 0))
- off = i + 1;
- }
- buf[i] = 0;
- au_fs_copy (unit->tmpbuf3, sizeof (unit->tmpbuf3) / sizeof (TCHAR), buf);
- return &p[off];
- }
- /* convert time_t to/from AmigaDOS time */
- static const uae_s64 msecs_per_day = 24 * 60 * 60 * 1000;
- static const uae_s64 diff = ((8 * 365 + 2) * (24 * 60 * 60)) * (uae_u64)1000;
- void timeval_to_amiga (struct mytimeval *tv, int *days, int *mins, int *ticks, int tickcount)
- {
- /* tv.tv_sec is secs since 1-1-1970 */
- /* days since 1-1-1978 */
- /* mins since midnight */
- /* ticks past minute @ 50Hz */
- uae_s64 t = tv->tv_sec * 1000 + tv->tv_usec / 1000;
- t -= diff;
- if (t < 0)
- t = 0;
- *days = t / msecs_per_day;
- t -= *days * msecs_per_day;
- *mins = t / (60 * 1000);
- t -= *mins * (60 * 1000);
- *ticks = t / (1000 / tickcount);
- }
- void amiga_to_timeval (struct mytimeval *tv, int days, int mins, int ticks, int tickcount)
- {
- uae_s64 t;
- if (days < 0)
- days = 0;
- if (days > 9900 * 365)
- days = 9900 * 365; // in future far enough?
- if (mins < 0 || mins >= 24 * 60)
- mins = 0;
- if (ticks < 0 || ticks >= 60 * tickcount)
- ticks = 0;
- t = ticks * 20;
- t += mins * (60 * 1000);
- t += ((uae_u64)days) * msecs_per_day;
- t += diff;
- tv->tv_sec = t / 1000;
- tv->tv_usec = (t % 1000) * 1000;
- }
- static Unit *units = 0;
- static Unit *find_unit (uaecptr port)
- {
- Unit* u;
- for (u = units; u; u = u->next)
- if (u->port == port)
- break;
- return u;
- }
- static struct fs_dirhandle *fs_opendir (Unit *u, a_inode *aino)
- {
- struct fs_dirhandle *fsd = xmalloc (struct fs_dirhandle, 1);
- fsd->fstype = (u->volflags & MYVOLUMEINFO_ARCHIVE) ? FS_ARCHIVE : ((u->volflags & MYVOLUMEINFO_CDFS) ? FS_CDFS : FS_DIRECTORY);
- if (fsd->fstype == FS_ARCHIVE) {
- fsd->zd = zfile_opendir_archive (aino->nname);
- if (fsd->zd)
- return fsd;
- } else if (fsd->fstype == FS_DIRECTORY) {
- fsd->od = my_opendir (aino->nname);
- if (fsd->od)
- return fsd;
- } else if (fsd->fstype == FS_CDFS) {
- fsd->isod = isofs_opendir (u->ui.cdfs_superblock, aino->uniq_external);
- if (fsd->isod)
- return fsd;
- }
- xfree (fsd);
- return NULL;
- }
- static void fs_closedir (struct fs_dirhandle *fsd)
- {
- if (!fsd)
- return;
- if (fsd->fstype == FS_ARCHIVE)
- zfile_closedir_archive (fsd->zd);
- else if (fsd->fstype == FS_DIRECTORY)
- my_closedir (fsd->od);
- else if (fsd->fstype == FS_CDFS)
- isofs_closedir (fsd->isod);
- xfree (fsd);
- }
- static struct fs_filehandle *fs_openfile (Unit *u, a_inode *aino, int flags)
- {
- struct fs_filehandle *fsf = xmalloc (struct fs_filehandle, 1);
- fsf->fstype = (u->volflags & MYVOLUMEINFO_ARCHIVE) ? FS_ARCHIVE : ((u->volflags & MYVOLUMEINFO_CDFS) ? FS_CDFS : FS_DIRECTORY);
- if (fsf->fstype == FS_ARCHIVE) {
- fsf->zf = zfile_open_archive (aino->nname, flags);
- if (fsf->zf)
- return fsf;
- } else if (fsf->fstype == FS_DIRECTORY) {
- fsf->of = my_open (aino->nname, flags);
- if (fsf->of)
- return fsf;
- } else if (fsf->fstype == FS_CDFS) {
- fsf->isof = isofs_openfile (u->ui.cdfs_superblock, aino->uniq_external, flags);
- if (fsf->isof)
- return fsf;
- }
- xfree (fsf);
- return NULL;
- }
- static void fs_closefile (struct fs_filehandle *fsf)
- {
- if (!fsf)
- return;
- if (fsf->fstype == FS_ARCHIVE) {
- zfile_close_archive (fsf->zf);
- } else if (fsf->fstype == FS_DIRECTORY) {
- my_close (fsf->of);
- } else if (fsf->fstype == FS_CDFS) {
- isofs_closefile (fsf->isof);
- }
- xfree (fsf);
- }
- static unsigned int fs_read (struct fs_filehandle *fsf, void *b, unsigned int size)
- {
- if (fsf->fstype == FS_ARCHIVE)
- return zfile_read_archive (fsf->zf, b, size);
- else if (fsf->fstype == FS_DIRECTORY)
- return my_read (fsf->of, b, size);
- else if (fsf->fstype == FS_CDFS)
- return isofs_read (fsf->isof, b, size);
- return 0;
- }
- static unsigned int fs_write (struct fs_filehandle *fsf, void *b, unsigned int size)
- {
- if (fsf->fstype == FS_DIRECTORY)
- return my_write (fsf->of, b, size);
- return 0;
- }
- /* return value = old position. -1 = error. */
- static uae_s64 fs_lseek64 (struct fs_filehandle *fsf, uae_s64 offset, int whence)
- {
- if (fsf->fstype == FS_ARCHIVE)
- return zfile_lseek_archive (fsf->zf, offset, whence);
- else if (fsf->fstype == FS_DIRECTORY)
- return my_lseek (fsf->of, offset, whence);
- else if (fsf->fstype == FS_CDFS)
- return isofs_lseek (fsf->isof, offset, whence);
- return -1;
- }
- static uae_s32 fs_lseek (struct fs_filehandle *fsf, uae_s32 offset, int whence)
- {
- uae_s64 v = fs_lseek64 (fsf, offset, whence);
- if (v < 0 || v > 0x7fffffff)
- return -1;
- return (uae_s32)v;
- }
- static uae_s64 fs_fsize64 (struct fs_filehandle *fsf)
- {
- if (fsf->fstype == FS_ARCHIVE)
- return zfile_fsize_archive (fsf->zf);
- else if (fsf->fstype == FS_DIRECTORY)
- return my_fsize (fsf->of);
- else if (fsf->fstype == FS_CDFS)
- return isofs_fsize (fsf->isof);
- return -1;
- }
- static uae_u32 fs_fsize (struct fs_filehandle *fsf)
- {
- return (uae_u32)fs_fsize64 (fsf);
- }
- static uae_s64 key_filesize(Key *k)
- {
- if (k->aino->vfso)
- return k->aino->vfso->size;
- return fs_fsize64 (k->fd);
- }
- static uae_s64 key_seek(Key *k, uae_s64 offset, int whence)
- {
- if (k->aino->vfso)
- return k->file_pos;
- return fs_lseek64 (k->fd, offset, whence);
- }
- static void set_highcyl(uaecptr volume, uae_u32 blocks)
- {
- put_long(volume + 184 - 32, blocks);
- }
- static void set_volume_name(Unit *unit, struct mytimeval *tv)
- {
- int namelen;
- int i;
- char *s;
- s = ua_fs (unit->ui.volname, -1);
- namelen = strlen (s);
- if (namelen >= 58)
- namelen = 58;
- put_byte(unit->volume + 64, namelen);
- for (i = 0; i < namelen; i++)
- put_byte(unit->volume + 64 + 1 + i, s[i]);
- put_byte(unit->volume + 64 + 1 + namelen, 0);
- if (tv && (tv->tv_sec || tv->tv_usec)) {
- int days, mins, ticks;
- timeval_to_amiga (tv, &days, &mins, &ticks, 50);
- put_long(unit->volume + 16, days);
- put_long(unit->volume + 20, mins);
- put_long(unit->volume + 24, ticks);
- }
- xfree (s);
- unit->rootnode.aname = unit->ui.volname;
- unit->rootnode.nname = unit->ui.rootdir;
- unit->rootnode.mountcount = unit->mountcount;
- }
- static int filesys_isvolume(Unit *unit)
- {
- if (!unit->volume)
- return 0;
- return get_byte(unit->volume + 64) || unit->ui.unknown_media;
- }
- static void clear_exkeys (Unit *unit)
- {
- int i;
- a_inode *a;
- for (i = 0; i < EXKEYS; i++) {
- unit->examine_keys[i].aino = 0;
- unit->examine_keys[i].curr_file = 0;
- unit->examine_keys[i].uniq = 0;
- }
- for (i = 0; i < EXALLKEYS; i++) {
- fs_closedir (unit->exalls[i].dirhandle);
- unit->exalls[i].dirhandle = NULL;
- xfree (unit->exalls[i].fn);
- unit->exalls[i].fn = NULL;
- unit->exalls[i].id = 0;
- }
- unit->exallid = 0;
- unit->next_exkey = 1;
- a = &unit->rootnode;
- while (a) {
- a->exnext_count = 0;
- if (a->locked_children) {
- a->locked_children = 0;
- unit->total_locked_ainos--;
- }
- a = a->next;
- if (a == &unit->rootnode)
- break;
- }
- }
- static void filesys_delayed_eject(Unit *u)
- {
- if (u->reinsertdelay)
- return;
- u->reinsertdelay = 50;
- u->newreadonly = false;
- xfree(u->newrootdir);
- u->newrootdir = NULL;
- write_log(_T("FILESYS: delayed eject %d\n"), u->unit);
- }
- static void filesys_delayed_change (Unit *u, int frames, const TCHAR *rootdir, const TCHAR *volume, bool readonly, int flags)
- {
- if (u->reinsertdelay)
- return;
- u->reinsertdelay = frames;
- u->newflags = flags;
- u->newr…
Large files files are truncated, but you can click here to view the full file