mpw/toolbox/os_volume.cpp

430 lines
12 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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 = 0; // MacOS::nsvErr;
memoryWriteWord(d0, parm + _ioResult);
return d0;
}
}