mirror of
https://github.com/ksherlock/mpw.git
synced 2024-11-22 00:32:44 +00:00
430 lines
12 KiB
C++
430 lines
12 KiB
C++
/*
|
||
* Copyright (c) 2015, Kelvin W Sherlock
|
||
* All rights reserved.
|
||
*
|
||
* Redistribution and use in source and binary forms, with or without
|
||
* modification, are permitted provided that the following conditions are met:
|
||
*
|
||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||
* list of conditions and the following disclaimer.
|
||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||
* this list of conditions and the following disclaimer in the documentation
|
||
* and/or other materials provided with the distribution.
|
||
*
|
||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
*
|
||
*/
|
||
|
||
#include <cerrno>
|
||
#include <cctype>
|
||
#include <ctime>
|
||
#include <algorithm>
|
||
#include <chrono>
|
||
#include <deque>
|
||
#include <string>
|
||
|
||
#include <sys/xattr.h>
|
||
#include <sys/stat.h>
|
||
#include <sys/paths.h>
|
||
#include <stdlib.h>
|
||
#include <unistd.h>
|
||
#include <fcntl.h>
|
||
|
||
#include <strings.h>
|
||
|
||
#include <cpu/defs.h>
|
||
#include <cpu/CpuModule.h>
|
||
#include <cpu/fmem.h>
|
||
|
||
#include <macos/sysequ.h>
|
||
#include <macos/errors.h>
|
||
#include <macos/traps.h>
|
||
|
||
#include "os.h"
|
||
#include "os_internal.h"
|
||
#include "toolbox.h"
|
||
#include "fs_spec.h"
|
||
|
||
using ToolBox::Log;
|
||
|
||
using MacOS::macos_error_from_errno;
|
||
|
||
namespace OS {
|
||
|
||
|
||
uint16_t HGetVInfo(uint16_t trap)
|
||
{
|
||
|
||
|
||
/*
|
||
* The PBHGetVInfo function returns information about the specified
|
||
* volume. If the value of ioVolIndex is positive, the File Manager
|
||
* attempts to use it to find the volume; for instance, if the
|
||
* value of ioVolIndex is 2, the File Manager attempts to access
|
||
* the second mounted volume in the VCB queue. If the value of
|
||
* ioVolIndex is negative, the File Manager uses ioNamePtr and
|
||
* ioVRefNum in the standard way to determine the volume. If the
|
||
* value of ioVolIndex is 0, the File Manager attempts to access
|
||
* the volume by using ioVRefNum only. The volume reference number
|
||
* is returned in ioVRefNum, and the volume name is returned in
|
||
* the buffer whose address you passed in ioNamePtr. You should
|
||
* pass a pointer to a Str31 value if you want that name returned.
|
||
* If you pass NIL in the ioNamePtr field, no volume name is
|
||
* returned.
|
||
*
|
||
* If you pass a working directory reference number in ioVRefNum
|
||
* (or if the default directory is a subdirectory), the number
|
||
* of files and directories in the specified directory (the
|
||
* directory’s valence) is returned in ioVNmFls.
|
||
*
|
||
* You can read the ioVDrvInfo and ioVDRefNum fields to determine
|
||
* whether the specified volume is online, offline, or ejected.
|
||
* For online volumes, ioVDrvInfo contains the drive number of
|
||
* the drive containing the specified volume and hence is always
|
||
* greater than 0. If the value returned in ioVDrvInfo is 0, the
|
||
* volume is either offline or ejected. You can determine whether
|
||
* the volume is offline or ejected by inspecting the value of
|
||
* the ioVDRefNum field. For online volumes, ioVDRefNum contains
|
||
* a driver reference number; these numbers are always less than
|
||
* 0. If the volume is not online, the value of ioVDRefNum is
|
||
* either the negative of the drive number (if the volume is
|
||
* offline) or the drive number itself (if the volume is ejected).
|
||
*
|
||
*
|
||
* You can get information about all the online volumes by making
|
||
* repeated calls to PBHGetVInfo, starting with the value of
|
||
* ioVolIndex set to 1 and incrementing that value until PBHGetVInfo
|
||
* returns nsvErr.
|
||
*/
|
||
|
||
|
||
enum {
|
||
/* HVolumeParam */
|
||
_qLink = 0,
|
||
_qType = 4,
|
||
_ioTrap = 6,
|
||
_ioCmdAddr = 8,
|
||
_ioCompletion = 12,
|
||
_ioResult = 16,
|
||
_ioNamePtr = 18,
|
||
_ioVRefNum = 22,
|
||
_filler2 = 24,
|
||
_ioVolIndex = 28,
|
||
_ioVCrDate = 30,
|
||
_ioVLsMod = 34,
|
||
_ioVAtrb = 38,
|
||
_ioVNmFls = 40,
|
||
_ioVBitMap = 42,
|
||
_ioAllocPtr = 44,
|
||
_ioVNmAlBlks = 46,
|
||
_ioVAlBlkSiz = 48,
|
||
_ioVClpSiz = 52,
|
||
_ioAlBlSt = 56,
|
||
_ioVNxtCNID = 58,
|
||
_ioVFrBlk = 62,
|
||
_ioVSigWord = 64,
|
||
_ioVDrvInfo = 66,
|
||
_ioVDRefNum = 68,
|
||
_ioVFSID = 70,
|
||
_ioVBkUp = 72,
|
||
_ioVSeqNum = 76,
|
||
_ioVWrCnt = 78,
|
||
_ioVFilCnt = 82,
|
||
_ioVDirCnt = 86,
|
||
_ioVFndrInfo = 90,
|
||
};
|
||
|
||
|
||
|
||
uint16_t d0;
|
||
|
||
uint32_t parm = cpuGetAReg(0);
|
||
|
||
Log("%04x HGetVInfo(%08x)\n", trap, parm);
|
||
|
||
d0 = MacOS::nsvErr;
|
||
memoryWriteWord(d0, parm + _ioResult);
|
||
|
||
return d0;
|
||
}
|
||
|
||
|
||
|
||
uint16_t FlushVol(uint16_t trap)
|
||
{
|
||
/*
|
||
* On the volume specified by ioNamePtr or ioVRefNum, the PBFlushVol
|
||
* function writes descriptive information about the volume, the
|
||
* contents of the associated volume buffer, and all access path buffers
|
||
* for the volume (if they’ve changed since the last time PBFlushVol
|
||
* was called).
|
||
*/
|
||
|
||
enum {
|
||
_qLink = 0,
|
||
_qType = 4,
|
||
_ioTrap = 6,
|
||
_ioCmdAddr = 8,
|
||
_ioCompletion = 12,
|
||
_ioResult = 16,
|
||
_ioNamePtr = 18,
|
||
_ioVRefNum = 22,
|
||
};
|
||
|
||
uint32_t parm = cpuGetAReg(0);
|
||
|
||
Log("%04x FlushVol(%08x)\n", trap, parm);
|
||
|
||
// volume is specified with ioNamePtr or ioVRefNum.
|
||
// could go through open fds and fsync(fd), fcntl(fd, F_FULLFSYNC) them.
|
||
memoryWriteWord(0, parm + _ioResult);
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
uint16_t GetVol(uint16_t trap)
|
||
{
|
||
|
||
/*
|
||
* The PBGetVol function returns, in ioNamePtr, a pointer to the name
|
||
* of the default volume (unless ioNamePtr is NIL) and, in ioVRefNum,
|
||
* its volume reference number. If a default directory was set with a
|
||
* previous call to PBSetVol, a pointer to its name is returned in
|
||
* ioNamePtr and its working directory reference number is returned
|
||
* in ioVRefNum. However, if, in a previous call to HSetVol (or
|
||
* PBHSetVol), a working directory reference number was passed in,
|
||
* PBGetVol returns a volume reference number in the ioVRefNum field.
|
||
*
|
||
*/
|
||
|
||
enum {
|
||
_qLink = 0,
|
||
_qType = 4,
|
||
_ioTrap = 6,
|
||
_ioCmdAddr = 8,
|
||
_ioCompletion = 12,
|
||
_ioResult = 16,
|
||
_ioNamePtr = 18,
|
||
_ioVRefNum = 22,
|
||
};
|
||
|
||
uint32_t parm = cpuGetAReg(0);
|
||
|
||
Log("%04x GetVol(%08x)\n", trap, parm);
|
||
|
||
|
||
uint32_t namePtr = memoryReadLong(parm + _ioNamePtr);
|
||
|
||
memoryWriteWord(0, parm + _ioResult);
|
||
memoryWriteWord(0, parm + _ioVRefNum);
|
||
|
||
std::string tmp = "MacOS";
|
||
ToolBox::WritePString(namePtr, tmp);
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
uint16_t HGetVol(uint16_t trap)
|
||
{
|
||
|
||
/*
|
||
* The PBHGetVol function returns the default volume and directory last set
|
||
* by a call to either PBSetVol or PBHSetVol. The reference number of the
|
||
* default volume is returned in ioVRefNum. The PBHGetVol function returns
|
||
* a pointer to the volume’s name in the ioNamePtr field. You should pass a
|
||
* pointer to a Str31 value if you want that name returned. If you pass NIL
|
||
* in the ioNamePtr field, no volume name is returned.
|
||
*
|
||
* WARNING
|
||
* On exit, the ioVRefNum field contains a working directory reference
|
||
* number (instead of the volume reference number) if, in the last call to
|
||
* PBSetVol or PBHSetVol, a working directory reference number was passed
|
||
* in this field.
|
||
*
|
||
* The volume reference number of the volume on which the default directory
|
||
* exists is returned in ioWDVRefNum. The directory ID of the default
|
||
* directory is returned in ioWDDirID.
|
||
*/
|
||
|
||
enum {
|
||
/* WDPBRec */
|
||
_qLink = 0,
|
||
_qType = 4,
|
||
_ioTrap = 6,
|
||
_ioCmdAddr = 8,
|
||
_ioCompletion = 12,
|
||
_ioResult = 16,
|
||
_ioNamePtr = 18,
|
||
_ioVRefNum = 22,
|
||
_filler1 = 24,
|
||
_ioWDIndex = 26,
|
||
_ioWDProcID = 28,
|
||
_ioWDVRefNum = 32,
|
||
_filler2 = 34,
|
||
_ioWDDirID = 48,
|
||
};
|
||
|
||
|
||
uint32_t parm = cpuGetAReg(0);
|
||
|
||
Log("%04x HGetVol(%08x)\n", trap, parm);
|
||
|
||
uint32_t namePtr = memoryReadLong(parm + _ioNamePtr);
|
||
|
||
memoryWriteWord(0, parm + _ioResult);
|
||
memoryWriteWord(0, parm + _ioVRefNum);
|
||
memoryWriteLong(0, parm + _ioWDProcID);
|
||
memoryWriteWord(0, parm + _ioWDVRefNum);
|
||
|
||
|
||
// todo -- this should create an FSSpec entry for
|
||
// the current wd and return the id.
|
||
// (FSMakeSpec handles 0 as a dir, so ok for now)
|
||
// ioWDDirID
|
||
memoryWriteLong(0, parm + _ioWDDirID);
|
||
|
||
std::string tmp = "MacOS";
|
||
ToolBox::WritePString(namePtr, tmp);
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
uint16_t SetVol(uint16_t trap)
|
||
{
|
||
|
||
/*
|
||
* If you pass a volume reference number in ioVRefNum, the PBSetVol
|
||
* function makes the specified volume the default volume and the root
|
||
* directory of that volume the default directory. If you pass a working
|
||
* directory reference number, PBSetVol makes the specified directory the
|
||
* default directory, and the volume containing that directory the default
|
||
* volume.
|
||
*/
|
||
|
||
enum {
|
||
_qLink = 0,
|
||
_qType = 4,
|
||
_ioTrap = 6,
|
||
_ioCmdAddr = 8,
|
||
_ioCompletion = 12,
|
||
_ioResult = 16,
|
||
_ioNamePtr = 18,
|
||
_ioVRefNum = 22,
|
||
};
|
||
|
||
uint16_t d0;
|
||
|
||
uint32_t parm = cpuGetAReg(0);
|
||
|
||
Log("%04x SetVol(%08x)\n", trap, parm);
|
||
|
||
|
||
uint32_t ioNamePtr = memoryReadLong(parm + _ioNamePtr);
|
||
uint32_t ioVRefNum = memoryReadWord(parm + _ioVRefNum);
|
||
|
||
|
||
std::string name = ToolBox::ReadPString(ioNamePtr);
|
||
|
||
Log(" SetVol(%s, %d)\n", name.c_str(), ioVRefNum);
|
||
|
||
if (name.length() || ioVRefNum)
|
||
{
|
||
fprintf(stderr, "SetVol(%s, %d) is not supported yet.\n", name.c_str(), ioVRefNum);
|
||
exit(1);
|
||
}
|
||
d0 = 0;
|
||
memoryWriteWord(d0, parm + _ioResult);
|
||
return d0;
|
||
}
|
||
|
||
|
||
uint16_t HSetVol(uint16_t trap)
|
||
{
|
||
/*
|
||
* The PBHSetVol function sets the default volume and directory to the
|
||
* volume and directory specified by the ioNamePtr, ioVRefNum, and
|
||
* ioWDDirID fields.
|
||
*
|
||
* The PBHSetVol function sets the default volume to the volume specified
|
||
* by the ioVRefNum field, which can contain either a volume reference
|
||
* number or a working directory reference number. If the ioNamePtr
|
||
* field specifies a full pathname, however, the default volume is set
|
||
* to the volume whose name is contained in that pathname. (A full
|
||
* pathname overrides the ioVRefNum field.)
|
||
*
|
||
* The PBHSetVol function also sets the default directory. If the
|
||
* ioVRefNum field contains a volume reference number, then the default
|
||
* directory is set to the directory on that volume having the partial
|
||
* pathname specified by ioNamePtr in the directory specified by
|
||
* ioWDDirID. If the value of ioNamePtr is NIL, the default directory
|
||
* is simply the directory whose directory ID is contained in ioWDDirID.
|
||
*
|
||
* If the ioVRefNum field contains a working directory reference number,
|
||
* then ioWDDirID is ignored and the default directory is set to the
|
||
* directory on that volume having the partial pathname specified by
|
||
* ioNamePtr in the directory specified by the working directory
|
||
* reference number. If the value of ioNamePtr is NIL, the default
|
||
* directory is simply the directory specified in ioVRefNum.
|
||
*
|
||
* WARNING
|
||
* Use of the PBHSetVol function is discouraged if your application
|
||
* may execute in system software versions prior to version 7.0. Because
|
||
* the specified directory might not itself be a working directory,
|
||
* PBHSetVol records the default volume and directory separately, using
|
||
* the volume reference number of the volume and the actual directory
|
||
* ID of the specified directory. Subsequent calls to GetVol (or
|
||
* PBGetVol) return only the volume reference number, which will cause
|
||
* that volume’s root directory (rather than the default directory,
|
||
* as expected) to be accessed.
|
||
*
|
||
* NOTE
|
||
* Both the default volume and the default directory are used in calls
|
||
* made with no volume name, a volume reference number of 0, and a
|
||
* directory ID of 0.
|
||
*/
|
||
|
||
enum {
|
||
/* WDPBRec */
|
||
_qLink = 0,
|
||
_qType = 4,
|
||
_ioTrap = 6,
|
||
_ioCmdAddr = 8,
|
||
_ioCompletion = 12,
|
||
_ioResult = 16,
|
||
_ioNamePtr = 18,
|
||
_ioVRefNum = 22,
|
||
_filler1 = 24,
|
||
_ioWDIndex = 26,
|
||
_ioWDProcID = 28,
|
||
_ioWDVRefNum = 32,
|
||
_filler2 = 34,
|
||
_ioWDDirID = 48,
|
||
};
|
||
|
||
uint16_t d0;
|
||
|
||
uint32_t parm = cpuGetAReg(0);
|
||
|
||
Log("%04x HSetVol(%08x)\n", trap, parm);
|
||
|
||
d0 = MacOS::nsvErr;
|
||
memoryWriteWord(d0, parm + _ioResult);
|
||
|
||
return d0;
|
||
}
|
||
|
||
|
||
}
|