mpw/toolbox/os_volume.cpp

430 lines
12 KiB
C++
Raw Normal View History

/*
* 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
* directorys 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 theyve 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 volumes 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 volumes 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;
}
}