mirror of
https://github.com/akuker/RASCSI.git
synced 2024-06-15 21:29:30 +00:00
Issues 245 & 247, improved symlink handling (#252)
* Extensions are case-insensitive * Made options case-sensitive, synchronized rasctl and rascsi options * Manpage and help update * Added comment * Updated log message * Warn about invalid files in image folder * Updated handling of block devices * Updated symlink handling * Fixed wrong handle being closed * Copy links as links * Logging update * Added -D_FILE_OFFSET_BITS=64 for better support of huge files * Logging update * Added comment * Use readdir instead of directory_iterator (issue with outdated C++ libs) * Updated symlink handling * Updated link handling * Updated logging * Updated error logging * Fixed condition * Updated setting default image folder * Comment update
This commit is contained in:
parent
36c614ddc8
commit
fdee57e421
|
@ -3,8 +3,8 @@
|
||||||
rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins
|
rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B rascsi
|
.B rascsi
|
||||||
[\fB\-f\f® \fIFOLDER\fR]
|
[\fB\-F\f® \fIFOLDER\fR]
|
||||||
[\fB\-g\f® \fILOG_LEVEL\fR]
|
[\fB\-L\f® \fILOG_LEVEL\fR]
|
||||||
[\fB\-h\fR]
|
[\fB\-h\fR]
|
||||||
[\fB\-n\fR \fIVENDOR:PRODUCT:REVISION\fR]
|
[\fB\-n\fR \fIVENDOR:PRODUCT:REVISION\fR]
|
||||||
[\fB\-p\f® \fIPORT\fR]
|
[\fB\-p\f® \fIPORT\fR]
|
||||||
|
@ -46,10 +46,10 @@ To quit RaSCSI, press Control + C. If it is running in the background, you can k
|
||||||
.BR \-b\fI " " \fIBLOCK_SIZE
|
.BR \-b\fI " " \fIBLOCK_SIZE
|
||||||
The optional block size. For SCSI drives 512, 1024, 2048 or 4096 bytes, default size is 512 bytes. For SASI drives 256 or 1024 bytes, default is 256 bytes.
|
The optional block size. For SCSI drives 512, 1024, 2048 or 4096 bytes, default size is 512 bytes. For SASI drives 256 or 1024 bytes, default is 256 bytes.
|
||||||
.TP
|
.TP
|
||||||
.BR \-f\fI " " \fIFOLDER
|
.BR \-F\fI " " \fIFOLDER
|
||||||
The default folder for image files. For files in this folder no absolute path needs to be specified. The initial default folder is '~/images'.
|
The default folder for image files. For files in this folder no absolute path needs to be specified. The initial default folder is '~/images'.
|
||||||
.TP
|
.TP
|
||||||
.BR \-g\fI " " \fILOG_LEVEL
|
.BR \-L\fI " " \fILOG_LEVEL
|
||||||
The rascsi log level (trace, debug, info, warn, err, critical, off). The default log level is 'info'.
|
The rascsi log level (trace, debug, info, warn, err, critical, off). The default log level is 'info'.
|
||||||
.TP
|
.TP
|
||||||
.BR \-h\fI " " \fI
|
.BR \-h\fI " " \fI
|
||||||
|
|
|
@ -1,97 +1,129 @@
|
||||||
!! ------ THIS FILE IS AUTO_GENERATED! DO NOT MANUALLY UPDATE!!!
|
!! ------ THIS FILE IS AUTO_GENERATED! DO NOT MANUALLY UPDATE!!!
|
||||||
!! ------ The native file is rascsi.1. Re-run 'make docs' after updating
|
!! ------ The native file is rascsi.1. Re-run 'make docs' after updating\n\n
|
||||||
|
rascsi(1) General Commands Manual rascsi(1)
|
||||||
|
|
||||||
rascsi(1) General Commands Manual rascsi(1)
|
|
||||||
|
|
||||||
NAME
|
NAME
|
||||||
rascsi - Emulates SCSI devices using the Raspberry Pi GPIO pins
|
rascsi - Emulates SCSI devices using the Raspberry Pi GPIO pins
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
rascsi [-f[u00AE] FOLDER] [-g[u00AE] LOG_LEVEL] [-h] [-n VENDOR:PRODUCT:REVISION] [-p[u00AE] PORT] [-r RESERVED_IDS] [-n TYPE] [-v] [-IDn FILE] [-HDn FILE]...
|
rascsi [-F[u00AE] FOLDER] [-L[u00AE] LOG_LEVEL] [-h] [-n VENDOR:PROD‐
|
||||||
|
UCT:REVISION] [-p[u00AE] PORT] [-r RESERVED_IDS] [-n TYPE] [-v] [-IDn
|
||||||
|
FILE] [-HDn FILE]...
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
rascsi Emulates SCSI devices using the Raspberry Pi GPIO pins.
|
rascsi Emulates SCSI devices using the Raspberry Pi GPIO pins.
|
||||||
|
|
||||||
In the arguments to RaSCSI, one or more SCSI (-IDn) or SASI (-HDn) devices can be specified. The number (n) after the ID or HD identifier specifies the ID number for that device.
|
In the arguments to RaSCSI, one or more SCSI (-IDn) or SASI (-HDn) de‐
|
||||||
For SCSI: The ID is limited from 0-7. However, typically SCSI ID 7 is reserved for the "initiator" (the host computer). Note that SASI is considered rare and only used on very
|
vices can be specified. The number (n) after the ID or HD identifier
|
||||||
early Sharp X68000 computers.
|
specifies the ID number for that device. For SCSI: The ID is limited
|
||||||
|
from 0-7. However, typically SCSI ID 7 is reserved for the "initiator"
|
||||||
|
(the host computer). Note that SASI is considered rare and only used on
|
||||||
|
very early Sharp X68000 computers.
|
||||||
|
|
||||||
RaSCSI will determine the type of device based upon the file extension of the FILE argument.
|
RaSCSI will determine the type of device based upon the file extension
|
||||||
hdf: SASI Hard Disk image (XM6 SASI HD image - typically only used with X68000)
|
of the FILE argument.
|
||||||
|
hdf: SASI Hard Disk image (XM6 SASI HD image - typically only used
|
||||||
|
with X68000)
|
||||||
hds: SCSI Hard Disk image (generic, non-removable)
|
hds: SCSI Hard Disk image (generic, non-removable)
|
||||||
hdr: SCSI Hard Disk image (generic, removable)
|
hdr: SCSI Hard Disk image (generic, removable)
|
||||||
hdn: SCSI Hard Disk image (NEC GENUINE)
|
hdn: SCSI Hard Disk image (NEC GENUINE)
|
||||||
hdi: SCSI Hard Disk image (Anex86 HD image)
|
hdi: SCSI Hard Disk image (Anex86 HD image)
|
||||||
nhd: SCSI Hard Disk image (T98Next HD image)
|
nhd: SCSI Hard Disk image (T98Next HD image)
|
||||||
hda: SCSI Hard Disk image (APPLE GENUINE - typically used with Mac SCSI emulation)
|
hda: SCSI Hard Disk image (APPLE GENUINE - typically used with Mac
|
||||||
mos: SCSI Magneto-optical image (XM6 SCSI MO image - typically only used with X68000)
|
SCSI emulation)
|
||||||
|
mos: SCSI Magneto-optical image (XM6 SCSI MO image - typically only
|
||||||
|
used with X68000)
|
||||||
iso: SCSI CD-ROM image (ISO 9660 image)
|
iso: SCSI CD-ROM image (ISO 9660 image)
|
||||||
|
|
||||||
For example, if you want to specify an Apple-compatible HD image on ID 0, you can use the following command:
|
For example, if you want to specify an Apple-compatible HD image on ID
|
||||||
|
0, you can use the following command:
|
||||||
sudo rascsi -ID0 /path/to/drive/hdimage.hda
|
sudo rascsi -ID0 /path/to/drive/hdimage.hda
|
||||||
|
|
||||||
Once RaSCSI starts, it will open a socket (default port is 6868) to allow external management commands. If another process is using the rascsi port, RaSCSI will terminate, since
|
Once RaSCSI starts, it will open a socket (default port is 6868) to al‐
|
||||||
it is likely another instance of RaSCSI. Once RaSCSI has initialized, the rasctl utility can be used to send commands.
|
low external management commands. If another process is using the
|
||||||
|
rascsi port, RaSCSI will terminate, since it is likely another instance
|
||||||
|
of RaSCSI. Once RaSCSI has initialized, the rasctl utility can be used
|
||||||
|
to send commands.
|
||||||
|
|
||||||
To quit RaSCSI, press Control + C. If it is running in the background, you can kill it using an INT signal.
|
To quit RaSCSI, press Control + C. If it is running in the background,
|
||||||
|
you can kill it using an INT signal.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-b BLOCK_SIZE
|
-b BLOCK_SIZE
|
||||||
The optional block size. For SCSI drives 512, 1024, 2048 or 4096 bytes, default size is 512 bytes. For SASI drives 256 or 1024 bytes, default is 256 bytes.
|
The optional block size. For SCSI drives 512, 1024, 2048 or 4096
|
||||||
|
bytes, default size is 512 bytes. For SASI drives 256 or 1024
|
||||||
|
bytes, default is 256 bytes.
|
||||||
|
|
||||||
-f FOLDER
|
-F FOLDER
|
||||||
The default folder for image files. For files in this folder no absolute path needs to be specified. The initial default folder is '~/images'.
|
The default folder for image files. For files in this folder no
|
||||||
|
absolute path needs to be specified. The initial default folder
|
||||||
|
is '~/images'.
|
||||||
|
|
||||||
-g LOG_LEVEL
|
-L LOG_LEVEL
|
||||||
The rascsi log level (trace, debug, info, warn, err, critical, off). The default log level is 'info'.
|
The rascsi log level (trace, debug, info, warn, err, critical,
|
||||||
|
off). The default log level is 'info'.
|
||||||
|
|
||||||
-h Show a help page.
|
-h Show a help page.
|
||||||
|
|
||||||
-n VENDOR:PRODUCT:REVISION
|
-n VENDOR:PRODUCT:REVISION
|
||||||
Set the vendor, product and revision for the device, to be returned with the INQUIRY data. A complete set of name components must be provided. VENDOR may have up to 8,
|
Set the vendor, product and revision for the device, to be re‐
|
||||||
PRODUCT up to 16, REVISION up to 4 characters. Padding with blanks to the maxium length is automatically applied. Once set the name of a device cannot be changed.
|
turned with the INQUIRY data. A complete set of name components
|
||||||
|
must be provided. VENDOR may have up to 8, PRODUCT up to 16, RE‐
|
||||||
|
VISION up to 4 characters. Padding with blanks to the maxium
|
||||||
|
length is automatically applied. Once set the name of a device
|
||||||
|
cannot be changed.
|
||||||
|
|
||||||
-p PORT
|
-p PORT
|
||||||
The rascsi server port, default is 6868.
|
The rascsi server port, default is 6868.
|
||||||
|
|
||||||
-r RESERVED_IDS
|
-r RESERVED_IDS
|
||||||
Comma-separated list of IDs to reserve. -p TYPE The optional case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO, SCBR, SCDP). If no type is specified for devices
|
Comma-separated list of IDs to reserve. -p TYPE The optional
|
||||||
that support an image file, rascsi tries to derive the type from the file extension.
|
case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO,
|
||||||
|
SCBR, SCDP). If no type is specified for devices that support an
|
||||||
|
image file, rascsi tries to derive the type from the file exten‐
|
||||||
|
sion.
|
||||||
|
|
||||||
-v Display the rascsi version.
|
-v Display the rascsi version.
|
||||||
|
|
||||||
-IDn FILE
|
-IDn FILE
|
||||||
n is the SCSI ID number (0-7)
|
n is the SCSI ID number (0-7)
|
||||||
|
|
||||||
FILE is the name of the image file to use for the SCSI device. For devices that do not support an image file (SCBR, SCDP) a dummy name must be provided.
|
FILE is the name of the image file to use for the SCSI device.
|
||||||
|
For devices that do not support an image file (SCBR, SCDP) a
|
||||||
|
dummy name must be provided.
|
||||||
|
|
||||||
-HDn FILE
|
-HDn FILE
|
||||||
n is the SASI ID number (0-15)
|
n is the SASI ID number (0-15)
|
||||||
|
|
||||||
FILE is the name of the image file to use for the SASI device.
|
FILE is the name of the image file to use for the SASI device.
|
||||||
|
|
||||||
Note: SASI usage is rare, and is typically limited to early Unix workstations and Sharp X68000 systems.
|
Note: SASI usage is rare, and is typically limited to early Unix
|
||||||
|
workstations and Sharp X68000 systems.
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
Launch RaSCSI with no emulated drives attached:
|
Launch RaSCSI with no emulated drives attached:
|
||||||
rascsi
|
rascsi
|
||||||
|
|
||||||
Launch RaSCSI with an Apple hard drive image as ID 0 and a CD-ROM as ID 2
|
Launch RaSCSI with an Apple hard drive image as ID 0 and a CD-ROM as ID
|
||||||
|
2
|
||||||
rascsi -ID0 /path/to/harddrive.hda -ID2 /path/to/cdimage.iso
|
rascsi -ID0 /path/to/harddrive.hda -ID2 /path/to/cdimage.iso
|
||||||
|
|
||||||
Launch RaSCSI with a removable SCSI drive image as ID 0 and the raw device file /dev/hdb (e.g. a USB stick) and a DaynaPort network adapter as ID 6:
|
Launch RaSCSI with a removable SCSI drive image as ID 0 and the raw de‐
|
||||||
|
vice file /dev/hdb (e.g. a USB stick) and a DaynaPort network adapter
|
||||||
|
as ID 6:
|
||||||
rascsi -ID0 -t scrm /dev/hdb -ID6 -t scdp DUMMY_FILENAME
|
rascsi -ID0 -t scrm /dev/hdb -ID6 -t scdp DUMMY_FILENAME
|
||||||
|
|
||||||
To create an empty, 100MB HD image, use the following command:
|
To create an empty, 100MB HD image, use the following command:
|
||||||
dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800
|
dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800
|
||||||
|
|
||||||
In case the fallocate command is available a much faster alternative to the dd command is:
|
In case the fallocate command is available a much faster alternative to
|
||||||
|
the dd command is:
|
||||||
fallocate -l 104857600 /path/to/newimage.hda
|
fallocate -l 104857600 /path/to/newimage.hda
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
rasctl(1), scsimon(1)
|
rasctl(1), scsimon(1)
|
||||||
|
|
||||||
Full documentation is available at: <https://www.github.com/akuker/RASCSI/wiki/>
|
Full documentation is available at:
|
||||||
|
<https://www.github.com/akuker/RASCSI/wiki/>
|
||||||
|
|
||||||
rascsi(1)
|
rascsi(1)
|
||||||
|
|
22
doc/rasctl.1
22
doc/rasctl.1
|
@ -3,12 +3,16 @@
|
||||||
rasctl \- Sends management commands to the rascsi process
|
rasctl \- Sends management commands to the rascsi process
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B rasctl
|
.B rasctl
|
||||||
|
\fB\-L\fR |
|
||||||
\fB\-e\fR |
|
\fB\-e\fR |
|
||||||
\fB\-k\fR |
|
\fB\-k\fR |
|
||||||
\fB\-l\fR |
|
\fB\-l\fR |
|
||||||
\fB\-s\fR |
|
\fB\-s\fR |
|
||||||
\fB\-y\fR |
|
\fB\-T\fR |
|
||||||
[\fB\-d\fR \fIIMAGE_FOLDER\fR]
|
[\fB\-F\fR \fIIMAGE_FOLDER\fR]
|
||||||
|
[\fB\-C\fR \fIFILENAME:FILESIZE\fR]
|
||||||
|
[\fB\-x\fR \fICURRENT_NAME:NEW_NAME\fR]
|
||||||
|
[\fB\-R\fR \fICURRENT_NAME:NEW_NAME\fR]
|
||||||
[\fB\-g\fR \fILOG_LEVEL\fR]
|
[\fB\-g\fR \fILOG_LEVEL\fR]
|
||||||
[\fB\-h\fR \fIHOST\fR]
|
[\fB\-h\fR \fIHOST\fR]
|
||||||
[\fB\-p\fR \fIPORT\fR]
|
[\fB\-p\fR \fIPORT\fR]
|
||||||
|
@ -32,13 +36,13 @@ Note: The command and type arguments are case insensitive. Only the first letter
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.BR \-a\fI " "\fIFILENAME:FILESIZE
|
.BR \-C\fI " "\fIFILENAME:FILESIZE
|
||||||
Create an image file in the default image folder with the specified name and size in bytes.
|
Create an image file in the default image folder with the specified name and size in bytes.
|
||||||
.TP
|
.TP
|
||||||
.BR \-d\fI " "\fIIMAGE_FOLDER
|
.BR \-F\fI " "\fIIMAGE_FOLDER
|
||||||
Set the default image folder.
|
Set the default image folder.
|
||||||
.TP
|
.TP
|
||||||
.BR \-g\fI " "\fILOG_LEVEL
|
.BR \-L\fI " "\fILOG_LEVEL
|
||||||
Set the rascsi log level (trace, debug, info, warn, err, critical, off).
|
Set the rascsi log level (trace, debug, info, warn, err, critical, off).
|
||||||
.TP
|
.TP
|
||||||
.BR \-h\fI " " \fIHOST
|
.BR \-h\fI " " \fIHOST
|
||||||
|
@ -47,13 +51,13 @@ The rascsi host to connect to, default is 'localhost'.
|
||||||
.BR \-e\fI
|
.BR \-e\fI
|
||||||
List all images files in the default image folder.
|
List all images files in the default image folder.
|
||||||
.TP
|
.TP
|
||||||
.BR \-k\fI
|
.BR \-N\fI
|
||||||
Lists all available network interfaces provided that they are up.
|
Lists all available network interfaces provided that they are up.
|
||||||
.TP
|
.TP
|
||||||
.BR \-l\fI
|
.BR \-l\fI
|
||||||
List all of the devices that are currently being emulated by RaSCSI, as well as their current status.
|
List all of the devices that are currently being emulated by RaSCSI, as well as their current status.
|
||||||
.TP
|
.TP
|
||||||
.BR \-m\fI " "\fICURRENT_NAME:NEW_NAME
|
.BR \-R\fI " "\fICURRENT_NAME:NEW_NAME
|
||||||
Rename an image file in the default image folder.
|
Rename an image file in the default image folder.
|
||||||
.TP
|
.TP
|
||||||
.BR \-p\fI " " \fIPORT
|
.BR \-p\fI " " \fIPORT
|
||||||
|
@ -65,13 +69,13 @@ Comma-separated list of IDs to reserve.
|
||||||
.BR \-s\fI
|
.BR \-s\fI
|
||||||
Display server-side settings like available images or supported device types.
|
Display server-side settings like available images or supported device types.
|
||||||
.TP
|
.TP
|
||||||
.BR \-y\fI
|
.BR \-T\fI
|
||||||
Display all device types and their properties.
|
Display all device types and their properties.
|
||||||
.TP
|
.TP
|
||||||
.BR \-v\fI " " \fI
|
.BR \-v\fI " " \fI
|
||||||
Display the rascsi version.
|
Display the rascsi version.
|
||||||
.TP
|
.TP
|
||||||
.BR \-w\fI " "\fIFILENAME
|
.BR \-D\fI " "\fIFILENAME
|
||||||
Delete an image file in the default image folder.
|
Delete an image file in the default image folder.
|
||||||
.TP
|
.TP
|
||||||
.BR \-x\fI " "\fICURRENT_NAME:NEW_NAME
|
.BR \-x\fI " "\fICURRENT_NAME:NEW_NAME
|
||||||
|
|
|
@ -6,31 +6,32 @@ NAME
|
||||||
rasctl - Sends management commands to the rascsi process
|
rasctl - Sends management commands to the rascsi process
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
rasctl -e | -k | -l | -s | -y | [-d IMAGE_FOLDER] [-g LOG_LEVEL] [-h
|
rasctl -L | -e | -k | -l | -s | -T | [-F IMAGE_FOLDER] [-C FILE‐
|
||||||
HOST] [-p PORT] [-r RESERVED_IDS] [-v] -i ID [-c CMD] [-f FILE|PARAM]
|
NAME:FILESIZE] [-x CURRENT_NAME:NEW_NAME] [-R CURRENT_NAME:NEW_NAME]
|
||||||
[-n NAME] [-t TYPE] [-u UNIT]
|
[-g LOG_LEVEL] [-h HOST] [-p PORT] [-r RESERVED_IDS] [-v] -i ID [-c
|
||||||
|
CMD] [-f FILE|PARAM] [-n NAME] [-t TYPE] [-u UNIT]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
rasctl Sends commands to the rascsi process to make configuration ad‐
|
rasctl Sends commands to the rascsi process to make configuration ad‐
|
||||||
justments at runtime or to check the status of the devices.
|
justments at runtime or to check the status of the devices.
|
||||||
|
|
||||||
Either the -i or -l option should be specified at one time. Not both.
|
Either the -i or -l option should be specified at one time. Not both.
|
||||||
|
|
||||||
You do NOT need root privileges to use rasctl.
|
You do NOT need root privileges to use rasctl.
|
||||||
|
|
||||||
Note: The command and type arguments are case insensitive. Only the
|
Note: The command and type arguments are case insensitive. Only the
|
||||||
first letter of the command/type is evaluated by the tool.
|
first letter of the command/type is evaluated by the tool.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-a FILENAME:FILESIZE
|
-C FILENAME:FILESIZE
|
||||||
Create an image file in the default image folder with the speci‐
|
Create an image file in the default image folder with the speci‐
|
||||||
fied name and size in bytes.
|
fied name and size in bytes.
|
||||||
|
|
||||||
-d IMAGE_FOLDER
|
-F IMAGE_FOLDER
|
||||||
Set the default image folder.
|
Set the default image folder.
|
||||||
|
|
||||||
-g LOG_LEVEL
|
-L LOG_LEVEL
|
||||||
Set the rascsi log level (trace, debug, info, warn, err, criti‐
|
Set the rascsi log level (trace, debug, info, warn, err, criti‐
|
||||||
cal, off).
|
cal, off).
|
||||||
|
|
||||||
-h HOST
|
-h HOST
|
||||||
|
@ -38,13 +39,13 @@ OPTIONS
|
||||||
|
|
||||||
-e List all images files in the default image folder.
|
-e List all images files in the default image folder.
|
||||||
|
|
||||||
-k Lists all available network interfaces provided that they are
|
-N Lists all available network interfaces provided that they are
|
||||||
up.
|
up.
|
||||||
|
|
||||||
-l List all of the devices that are currently being emulated by
|
-l List all of the devices that are currently being emulated by
|
||||||
RaSCSI, as well as their current status.
|
RaSCSI, as well as their current status.
|
||||||
|
|
||||||
-m CURRENT_NAME:NEW_NAME
|
-R CURRENT_NAME:NEW_NAME
|
||||||
Rename an image file in the default image folder.
|
Rename an image file in the default image folder.
|
||||||
|
|
||||||
-p PORT
|
-p PORT
|
||||||
|
@ -53,14 +54,14 @@ OPTIONS
|
||||||
-r RESERVED_IDS
|
-r RESERVED_IDS
|
||||||
Comma-separated list of IDs to reserve.
|
Comma-separated list of IDs to reserve.
|
||||||
|
|
||||||
-s Display server-side settings like available images or supported
|
-s Display server-side settings like available images or supported
|
||||||
device types.
|
device types.
|
||||||
|
|
||||||
-y Display all device types and their properties.
|
-T Display all device types and their properties.
|
||||||
|
|
||||||
-v Display the rascsi version.
|
-v Display the rascsi version.
|
||||||
|
|
||||||
-w FILENAME
|
-D FILENAME
|
||||||
Delete an image file in the default image folder.
|
Delete an image file in the default image folder.
|
||||||
|
|
||||||
-x CURRENT_NAME:NEW_NAME
|
-x CURRENT_NAME:NEW_NAME
|
||||||
|
@ -73,7 +74,7 @@ OPTIONS
|
||||||
d(etach): Detach disk
|
d(etach): Detach disk
|
||||||
i(nsert): Insert media (removable media devices only)
|
i(nsert): Insert media (removable media devices only)
|
||||||
e(ject): Eject media (removable media devices only)
|
e(ject): Eject media (removable media devices only)
|
||||||
p(rotect): Write protect the medium (not for CD-ROMs, which
|
p(rotect): Write protect the medium (not for CD-ROMs, which
|
||||||
are always read-only)
|
are always read-only)
|
||||||
u(nprotect): Remove write protection from the medium (not for
|
u(nprotect): Remove write protection from the medium (not for
|
||||||
CD-ROMs, which are always read-only)
|
CD-ROMs, which are always read-only)
|
||||||
|
@ -83,18 +84,18 @@ OPTIONS
|
||||||
|
|
||||||
-b BLOCK_SIZE
|
-b BLOCK_SIZE
|
||||||
The optional block size. For SCSI drives 512, 1024, 2048 or 4096
|
The optional block size. For SCSI drives 512, 1024, 2048 or 4096
|
||||||
bytes, default size is 512 bytes. For SASI drives 256 or 1024
|
bytes, default size is 512 bytes. For SASI drives 256 or 1024
|
||||||
bytes, default is 256 bytes.
|
bytes, default is 256 bytes.
|
||||||
|
|
||||||
-f FILE|PARAM
|
-f FILE|PARAM
|
||||||
Device-specific: Either a path to a disk image file, or a param‐
|
Device-specific: Either a path to a disk image file, or a param‐
|
||||||
eter for a non-disk device. See the rascsi(1) man page for per‐
|
eter for a non-disk device. See the rascsi(1) man page for per‐
|
||||||
mitted file types.
|
mitted file types.
|
||||||
|
|
||||||
-t TYPE
|
-t TYPE
|
||||||
Specifies the device type. This type overrides the type derived
|
Specifies the device type. This type overrides the type derived
|
||||||
from the file extension of the specified image. See the
|
from the file extension of the specified image. See the
|
||||||
rascsi(1) man page for the available device types. For some
|
rascsi(1) man page for the available device types. For some
|
||||||
types there are shortcuts (only the first letter is required):
|
types there are shortcuts (only the first letter is required):
|
||||||
hd: SCSI hard disk drive
|
hd: SCSI hard disk drive
|
||||||
rm: SCSI removable media drive
|
rm: SCSI removable media drive
|
||||||
|
@ -104,16 +105,16 @@ OPTIONS
|
||||||
daynaport: DaynaPORT network adapter
|
daynaport: DaynaPORT network adapter
|
||||||
|
|
||||||
-n VENDOR:PRODUCT:REVISION
|
-n VENDOR:PRODUCT:REVISION
|
||||||
The vendor, product and revision for the device, to be returned
|
The vendor, product and revision for the device, to be returned
|
||||||
with the INQUIRY data. A complete set of name components must be
|
with the INQUIRY data. A complete set of name components must be
|
||||||
provided. VENDOR may have up to 8, PRODUCT up to 16, REVISION up
|
provided. VENDOR may have up to 8, PRODUCT up to 16, REVISION up
|
||||||
to 4 characters. Padding with blanks to the maxium length is au‐
|
to 4 characters. Padding with blanks to the maxium length is au‐
|
||||||
tomatically applied. Once set the name of a device cannot be
|
tomatically applied. Once set the name of a device cannot be
|
||||||
changed.
|
changed.
|
||||||
|
|
||||||
-u UNIT
|
-u UNIT
|
||||||
Unit number (0 or 1). This will default to 0. This option is
|
Unit number (0 or 1). This will default to 0. This option is
|
||||||
only used when there are multiple SCSI devices on a shared SCSI
|
only used when there are multiple SCSI devices on a shared SCSI
|
||||||
controller. (This is not common)
|
controller. (This is not common)
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
|
|
|
@ -26,8 +26,8 @@ else
|
||||||
CXXFLAGS += -O3 -Wall -Werror -DNDEBUG
|
CXXFLAGS += -O3 -Wall -Werror -DNDEBUG
|
||||||
BUILD_TYPE = Release
|
BUILD_TYPE = Release
|
||||||
endif
|
endif
|
||||||
CFLAGS += -iquote . -MD -MP
|
CFLAGS += -iquote . -D_FILE_OFFSET_BITS=64 -MD -MP
|
||||||
CXXFLAGS += -std=c++17 -Wno-psabi -iquote . -MD -MP
|
CXXFLAGS += -std=c++17 -Wno-psabi -iquote . -D_FILE_OFFSET_BITS=64 -MD -MP
|
||||||
|
|
||||||
## EXTRA_FLAGS : Can be used to pass special purpose flags
|
## EXTRA_FLAGS : Can be used to pass special purpose flags
|
||||||
CFLAGS += $(EXTRA_FLAGS)
|
CFLAGS += $(EXTRA_FLAGS)
|
||||||
|
|
|
@ -72,8 +72,11 @@ DeviceFactory& DeviceFactory::instance()
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename, const string& ext)
|
Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename, const string& extension)
|
||||||
{
|
{
|
||||||
|
string ext = extension;
|
||||||
|
std::transform(ext.begin(), ext.end(), ext.begin(), [](unsigned char c){ return std::tolower(c); });
|
||||||
|
|
||||||
// If no type was specified try to derive the device type from the filename and extension
|
// If no type was specified try to derive the device type from the filename and extension
|
||||||
if (type == UNDEFINED) {
|
if (type == UNDEFINED) {
|
||||||
if (ext == "hdf") {
|
if (ext == "hdf") {
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "spdlog/sinks/stdout_color_sinks.h"
|
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||||
#include <spdlog/async.h>
|
#include <spdlog/async.h>
|
||||||
#include <sys/sendfile.h>
|
#include <sys/sendfile.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -117,7 +118,6 @@ void Banner(int argc, char* argv[])
|
||||||
FPRT(stdout," hdn : SCSI HD image (NEC GENUINE)\n");
|
FPRT(stdout," hdn : SCSI HD image (NEC GENUINE)\n");
|
||||||
FPRT(stdout," hdi : SCSI HD image (Anex86 HD image)\n");
|
FPRT(stdout," hdi : SCSI HD image (Anex86 HD image)\n");
|
||||||
FPRT(stdout," nhd : SCSI HD image (T98Next HD image)\n");
|
FPRT(stdout," nhd : SCSI HD image (T98Next HD image)\n");
|
||||||
FPRT(stdout," hda : SCSI HD image (APPLE GENUINE)\n");
|
|
||||||
FPRT(stdout," mos : SCSI MO image (MO image)\n");
|
FPRT(stdout," mos : SCSI MO image (MO image)\n");
|
||||||
FPRT(stdout," iso : SCSI CD image (ISO 9660 image)\n");
|
FPRT(stdout," iso : SCSI CD image (ISO 9660 image)\n");
|
||||||
|
|
||||||
|
@ -527,6 +527,45 @@ void GetAllDeviceTypeProperties(PbDeviceTypesInfo& device_types_info)
|
||||||
GetDeviceTypeProperties(device_types_info, SCDP);
|
GetDeviceTypeProperties(device_types_info, SCDP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GetAvailableImages(PbImageFilesInfo& image_files_info)
|
||||||
|
{
|
||||||
|
image_files_info.set_default_image_folder(default_image_folder);
|
||||||
|
|
||||||
|
// filesystem::directory_iterator cannot be used because libstdc++ 8.3.0 does not support big files
|
||||||
|
DIR *d = opendir(default_image_folder.c_str());
|
||||||
|
if (d) {
|
||||||
|
struct dirent *dir;
|
||||||
|
while ((dir = readdir(d))) {
|
||||||
|
if (dir->d_type == DT_REG || dir->d_type == DT_LNK || dir->d_type == DT_BLK) {
|
||||||
|
string filename = default_image_folder + "/" + dir->d_name;
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
if (dir->d_type == DT_REG && !stat(filename.c_str(), &st)) {
|
||||||
|
if (!st.st_size) {
|
||||||
|
LOGTRACE("File '%s' in image folder '%s' has a size of 0 bytes", dir->d_name,
|
||||||
|
default_image_folder.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st.st_size % 512) {
|
||||||
|
LOGTRACE("Size of file '%s' in image folder '%s' is not a multiple of 512", dir->d_name,
|
||||||
|
default_image_folder.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (dir->d_type == DT_LNK && stat(filename.c_str(), &st)) {
|
||||||
|
LOGTRACE("Symlink '%s' in image folder '%s' is broken", dir->d_name,
|
||||||
|
default_image_folder.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetImageFile(image_files_info.add_image_files(), dir->d_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GetAvailableImages(PbServerInfo& server_info)
|
void GetAvailableImages(PbServerInfo& server_info)
|
||||||
{
|
{
|
||||||
PbImageFilesInfo *image_files_info = new PbImageFilesInfo();
|
PbImageFilesInfo *image_files_info = new PbImageFilesInfo();
|
||||||
|
@ -534,26 +573,7 @@ void GetAvailableImages(PbServerInfo& server_info)
|
||||||
|
|
||||||
image_files_info->set_default_image_folder(default_image_folder);
|
image_files_info->set_default_image_folder(default_image_folder);
|
||||||
|
|
||||||
if (!access(default_image_folder.c_str(), F_OK)) {
|
GetAvailableImages(*image_files_info);
|
||||||
for (const auto& entry : filesystem::directory_iterator(default_image_folder, filesystem::directory_options::skip_permission_denied)) {
|
|
||||||
if (entry.is_regular_file() && entry.file_size() && !(entry.file_size() & 0x1ff)) {
|
|
||||||
GetImageFile(image_files_info->add_image_files(), entry.path().filename());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetAvailableImages(PbImageFilesInfo& image_files_info)
|
|
||||||
{
|
|
||||||
image_files_info.set_default_image_folder(default_image_folder);
|
|
||||||
|
|
||||||
if (!access(default_image_folder.c_str(), F_OK)) {
|
|
||||||
for (const auto& entry : filesystem::directory_iterator(default_image_folder, filesystem::directory_options::skip_permission_denied)) {
|
|
||||||
if (entry.is_regular_file() && entry.file_size() && !(entry.file_size() & 0x1ff)) {
|
|
||||||
GetImageFile(image_files_info.add_image_files(), entry.path().filename());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetNetworkInterfacesInfo(PbNetworkInterfacesInfo& network_interfaces_info)
|
void GetNetworkInterfacesInfo(PbNetworkInterfacesInfo& network_interfaces_info)
|
||||||
|
@ -687,7 +707,13 @@ bool SetDefaultImageFolder(const string& f)
|
||||||
|
|
||||||
// If a relative path is specified the path is assumed to be relative to the user's home directory
|
// If a relative path is specified the path is assumed to be relative to the user's home directory
|
||||||
if (folder[0] != '/') {
|
if (folder[0] != '/') {
|
||||||
const passwd *passwd = getpwuid(getuid());
|
int uid = getuid();
|
||||||
|
const char *sudo_user = getenv("SUDO_UID");
|
||||||
|
if (sudo_user) {
|
||||||
|
uid = stoi(sudo_user);
|
||||||
|
}
|
||||||
|
|
||||||
|
const passwd *passwd = getpwuid(uid);
|
||||||
if (passwd) {
|
if (passwd) {
|
||||||
folder = passwd->pw_dir;
|
folder = passwd->pw_dir;
|
||||||
folder += "/";
|
folder += "/";
|
||||||
|
@ -742,7 +768,7 @@ string SetReservedIds(const string& ids)
|
||||||
s << id;
|
s << id;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGINFO("Reserved IDs set to: %s", s.str().c_str());
|
LOGINFO("Reserved ID(s) set to %s", s.str().c_str());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOGINFO("Cleared reserved IDs");
|
LOGINFO("Cleared reserved IDs");
|
||||||
|
@ -864,7 +890,7 @@ bool DeleteImage(int fd, const PbCommand& command)
|
||||||
return ReturnStatus(fd, false, "Can't delete image file '" + filename + "': " + string(strerror(errno)));
|
return ReturnStatus(fd, false, "Can't delete image file '" + filename + "': " + string(strerror(errno)));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGINFO("%s", string("Deleted image file '" + filename + "'").c_str());
|
LOGINFO("Deleted image file '%s'", filename.c_str());
|
||||||
|
|
||||||
return ReturnStatus(fd);
|
return ReturnStatus(fd);
|
||||||
}
|
}
|
||||||
|
@ -908,7 +934,7 @@ bool RenameImage(int fd, const PbCommand& command)
|
||||||
return ReturnStatus(fd, false, "Can't rename image file '" + from + "' to '" + to + "': " + string(strerror(errno)));
|
return ReturnStatus(fd, false, "Can't rename image file '" + from + "' to '" + to + "': " + string(strerror(errno)));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGINFO("%s", string("Renamed image file '" + from + "' to '" + to + "'").c_str());
|
LOGINFO("Renamed image file '%s' to '%s'", from.c_str(), to.c_str());
|
||||||
|
|
||||||
return ReturnStatus(fd);
|
return ReturnStatus(fd);
|
||||||
}
|
}
|
||||||
|
@ -943,24 +969,35 @@ bool CopyImage(int fd, const PbCommand& command)
|
||||||
from = default_image_folder + "/" + from;
|
from = default_image_folder + "/" + from;
|
||||||
to = default_image_folder + "/" + to;
|
to = default_image_folder + "/" + to;
|
||||||
|
|
||||||
struct stat st;
|
struct stat st_dst;
|
||||||
if (!stat(to.c_str(), &st)) {
|
if (!stat(to.c_str(), &st_dst)) {
|
||||||
return ReturnStatus(fd, false, "Image file '" + to + "' already exists");
|
return ReturnStatus(fd, false, "Image file '" + to + "' already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct stat st_src;
|
||||||
|
if (lstat(from.c_str(), &st_src)) {
|
||||||
|
return ReturnStatus(fd, false, "Can't access source image file '" + from + "': " + string(strerror(errno)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Symbolic links need a special handling
|
||||||
|
if ((st_src.st_mode & S_IFMT) == S_IFLNK) {
|
||||||
|
if (symlink(filesystem::read_symlink(from).c_str(), to.c_str())) {
|
||||||
|
return ReturnStatus(fd, false, "Can't copy symlink '" + from + "': " + string(strerror(errno)));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGINFO("Copied symlink '%s' to '%s'", from.c_str(), to.c_str());
|
||||||
|
|
||||||
|
return ReturnStatus(fd);
|
||||||
|
}
|
||||||
|
|
||||||
int fd_src = open(from.c_str(), O_RDONLY, 0);
|
int fd_src = open(from.c_str(), O_RDONLY, 0);
|
||||||
if (fd_src == -1) {
|
if (fd_src == -1) {
|
||||||
return ReturnStatus(fd, false, "Can't open source image file '" + from + "': " + string(strerror(errno)));
|
return ReturnStatus(fd, false, "Can't open source image file '" + from + "': " + string(strerror(errno)));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct stat st_src;
|
|
||||||
if (fstat(fd_src, &st_src) == -1) {
|
|
||||||
return ReturnStatus(fd, false, "Can't read source image file '" + from + "': " + string(strerror(errno)));
|
|
||||||
}
|
|
||||||
|
|
||||||
int fd_dst = open(to.c_str(), O_WRONLY | O_CREAT, st_src.st_mode);
|
int fd_dst = open(to.c_str(), O_WRONLY | O_CREAT, st_src.st_mode);
|
||||||
if (fd_dst == -1) {
|
if (fd_dst == -1) {
|
||||||
close (fd_dst);
|
close(fd_src);
|
||||||
|
|
||||||
return ReturnStatus(fd, false, "Can't open destination image file '" + to + "': " + string(strerror(errno)));
|
return ReturnStatus(fd, false, "Can't open destination image file '" + to + "': " + string(strerror(errno)));
|
||||||
}
|
}
|
||||||
|
@ -975,7 +1012,7 @@ bool CopyImage(int fd, const PbCommand& command)
|
||||||
close(fd_dst);
|
close(fd_dst);
|
||||||
close(fd_src);
|
close(fd_src);
|
||||||
|
|
||||||
LOGINFO("%s", string("Copied image file '" + from + "' to '" + to + "'").c_str());
|
LOGINFO("Copied image file '%s' to '%s'", from.c_str(), to.c_str());
|
||||||
|
|
||||||
return ReturnStatus(fd);
|
return ReturnStatus(fd);
|
||||||
}
|
}
|
||||||
|
@ -1008,10 +1045,10 @@ bool SetImagePermissions(int fd, const PbCommand& command)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (protect) {
|
if (protect) {
|
||||||
LOGINFO("%s", string("Protected image file '" + filename + "'").c_str());
|
LOGINFO("Protected image file '%s'", filename.c_str());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOGINFO("%s", string("Unprotected image file '" + filename + "'").c_str());
|
LOGINFO("Unprotected image file '%s'", filename.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReturnStatus(fd);
|
return ReturnStatus(fd);
|
||||||
|
@ -1532,29 +1569,25 @@ bool ParseArgument(int argc, char* argv[], int& port)
|
||||||
|
|
||||||
opterr = 1;
|
opterr = 1;
|
||||||
int opt;
|
int opt;
|
||||||
while ((opt = getopt(argc, argv, "-IiHhG:g:D:d:B:b:N:n:T:t:P:p:R:r:F:f:")) != -1) {
|
while ((opt = getopt(argc, argv, "-IiHhb:d:n:p:r:t:D:F:L:")) != -1) {
|
||||||
switch (tolower(opt)) {
|
switch (opt) {
|
||||||
|
// The three options below are kind of a compound option with two letters
|
||||||
case 'i':
|
case 'i':
|
||||||
|
case 'I':
|
||||||
is_sasi = false;
|
is_sasi = false;
|
||||||
max_id = 7;
|
max_id = 7;
|
||||||
id = -1;
|
id = -1;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
|
case 'H':
|
||||||
is_sasi = true;
|
is_sasi = true;
|
||||||
max_id = 15;
|
max_id = 15;
|
||||||
id = -1;
|
id = -1;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 'b': {
|
case 'd':
|
||||||
if (!GetAsInt(optarg, block_size)) {
|
case 'D': {
|
||||||
cerr << "Invalid block size " << optarg << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'd': {
|
|
||||||
char* end;
|
char* end;
|
||||||
id = strtol(optarg, &end, 10);
|
id = strtol(optarg, &end, 10);
|
||||||
if (*end || id < 0 || max_id < id) {
|
if (*end || id < 0 || max_id < id) {
|
||||||
|
@ -1564,14 +1597,22 @@ bool ParseArgument(int argc, char* argv[], int& port)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'f':
|
case 'b': {
|
||||||
|
if (!GetAsInt(optarg, block_size)) {
|
||||||
|
cerr << "Invalid block size " << optarg << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'F':
|
||||||
if (!SetDefaultImageFolder(optarg)) {
|
if (!SetDefaultImageFolder(optarg)) {
|
||||||
cerr << "Folder '" << optarg << "' does not exist or is not accessible";
|
cerr << "Folder '" << optarg << "' does not exist or is not accessible";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 'g':
|
case 'L':
|
||||||
log_level = optarg;
|
log_level = optarg;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1739,7 +1780,7 @@ static void *MonThread(void *param)
|
||||||
|
|
||||||
switch(command.operation()) {
|
switch(command.operation()) {
|
||||||
case LOG_LEVEL: {
|
case LOG_LEVEL: {
|
||||||
LOGTRACE(string("Received " + PbOperation_Name(command.operation()) + " command").c_str());
|
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
|
||||||
|
|
||||||
string log_level = GetParam(command, "level");
|
string log_level = GetParam(command, "level");
|
||||||
bool status = SetLogLevel(log_level);
|
bool status = SetLogLevel(log_level);
|
||||||
|
@ -1753,7 +1794,7 @@ static void *MonThread(void *param)
|
||||||
}
|
}
|
||||||
|
|
||||||
case DEFAULT_FOLDER: {
|
case DEFAULT_FOLDER: {
|
||||||
LOGTRACE(string("Received " + PbOperation_Name(command.operation()) + " command").c_str());
|
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
|
||||||
|
|
||||||
string folder = GetParam(command, "folder");
|
string folder = GetParam(command, "folder");
|
||||||
if (folder.empty()) {
|
if (folder.empty()) {
|
||||||
|
@ -1770,7 +1811,7 @@ static void *MonThread(void *param)
|
||||||
}
|
}
|
||||||
|
|
||||||
case DEVICES_INFO: {
|
case DEVICES_INFO: {
|
||||||
LOGTRACE(string("Received " + PbOperation_Name(command.operation()) + " command").c_str());
|
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
|
||||||
|
|
||||||
PbResult result;
|
PbResult result;
|
||||||
result.set_status(true);
|
result.set_status(true);
|
||||||
|
@ -1786,7 +1827,7 @@ static void *MonThread(void *param)
|
||||||
}
|
}
|
||||||
|
|
||||||
case DEVICE_TYPES_INFO: {
|
case DEVICE_TYPES_INFO: {
|
||||||
LOGTRACE(string("Received " + PbOperation_Name(command.operation()) + " command").c_str());
|
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
|
||||||
|
|
||||||
PbResult result;
|
PbResult result;
|
||||||
result.set_status(true);
|
result.set_status(true);
|
||||||
|
@ -1797,7 +1838,7 @@ static void *MonThread(void *param)
|
||||||
|
|
||||||
|
|
||||||
case SERVER_INFO: {
|
case SERVER_INFO: {
|
||||||
LOGTRACE(string("Received " + PbOperation_Name(command.operation()) + " command").c_str());
|
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
|
||||||
|
|
||||||
PbResult result;
|
PbResult result;
|
||||||
result.set_status(true);
|
result.set_status(true);
|
||||||
|
@ -1807,7 +1848,7 @@ static void *MonThread(void *param)
|
||||||
}
|
}
|
||||||
|
|
||||||
case IMAGE_FILES_INFO: {
|
case IMAGE_FILES_INFO: {
|
||||||
LOGTRACE(string("Received " + PbOperation_Name(command.operation()) + " command").c_str());
|
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
|
||||||
|
|
||||||
PbImageFilesInfo *image_files_info = new PbImageFilesInfo();
|
PbImageFilesInfo *image_files_info = new PbImageFilesInfo();
|
||||||
GetAvailableImages(*image_files_info);
|
GetAvailableImages(*image_files_info);
|
||||||
|
@ -1819,7 +1860,7 @@ static void *MonThread(void *param)
|
||||||
}
|
}
|
||||||
|
|
||||||
case NETWORK_INTERFACES_INFO: {
|
case NETWORK_INTERFACES_INFO: {
|
||||||
LOGTRACE(string("Received " + PbOperation_Name(command.operation()) + " command").c_str());
|
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
|
||||||
|
|
||||||
PbNetworkInterfacesInfo *network_interfaces_info = new PbNetworkInterfacesInfo();
|
PbNetworkInterfacesInfo *network_interfaces_info = new PbNetworkInterfacesInfo();
|
||||||
GetNetworkInterfacesInfo(*network_interfaces_info);
|
GetNetworkInterfacesInfo(*network_interfaces_info);
|
||||||
|
@ -1894,13 +1935,16 @@ int main(int argc, char* argv[])
|
||||||
// Create a thread-safe stdout logger to process the log messages
|
// Create a thread-safe stdout logger to process the log messages
|
||||||
auto logger = stdout_color_mt("rascsi stdout logger");
|
auto logger = stdout_color_mt("rascsi stdout logger");
|
||||||
|
|
||||||
// ~/images is the default folder for device image file. For the root user /home/pi/images is the default.
|
// ~/images is the default folder for device image files, for the root user it is /home/pi/images
|
||||||
const int uid = getuid();
|
int uid = getuid();
|
||||||
|
const char *sudo_user = getenv("SUDO_UID");
|
||||||
|
if (sudo_user) {
|
||||||
|
uid = stoi(sudo_user);
|
||||||
|
}
|
||||||
const passwd *passwd = getpwuid(uid);
|
const passwd *passwd = getpwuid(uid);
|
||||||
if (uid && passwd) {
|
if (uid && passwd) {
|
||||||
string folder = passwd->pw_dir;
|
default_image_folder = passwd->pw_dir;
|
||||||
folder += "/images";
|
default_image_folder += "/images";
|
||||||
default_image_folder = folder;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
default_image_folder = "/home/pi/images";
|
default_image_folder = "/home/pi/images";
|
||||||
|
|
|
@ -182,6 +182,7 @@ message PbDeviceTypesInfo {
|
||||||
message PbImageFile {
|
message PbImageFile {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
bool read_only = 2;
|
bool read_only = 2;
|
||||||
|
// The file size in bytes, 0 for block devices
|
||||||
int64 size = 3;
|
int64 size = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -574,10 +574,10 @@ int main(int argc, char* argv[])
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
cerr << "SCSI Target Emulator RaSCSI Controller" << endl;
|
cerr << "SCSI Target Emulator RaSCSI Controller" << endl;
|
||||||
cerr << "version " << rascsi_get_version_string() << " (" << __DATE__ << ", " << __TIME__ << ")" << endl;
|
cerr << "version " << rascsi_get_version_string() << " (" << __DATE__ << ", " << __TIME__ << ")" << endl;
|
||||||
cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-t TYPE] [-b BLOCK_SIZE] [-n NAME] [-f FILE|PARAM] ";
|
cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-C FILE] [-t TYPE] [-b BLOCK_SIZE] [-n NAME] [-f FILE|PARAM] ";
|
||||||
cerr << "[-d IMAGE_FOLDER] [-g LOG_LEVEL] [-h HOST] [-p PORT] [-r RESERVED_IDS] ";
|
cerr << "[-F IMAGE_FOLDER] [-L LOG_LEVEL] [-h HOST] [-p PORT] [-r RESERVED_IDS] ";
|
||||||
cerr << "[-a FILENAME:FILESIZE] [-w FILENAME] [-m CURRENT_NAME:NEW_NAME] [-x CURRENT_NAME:NEW_NAME] ";
|
cerr << "[-C FILENAME:FILESIZE] [-w FILENAME] [-R CURRENT_NAME:NEW_NAME] [-x CURRENT_NAME:NEW_NAME] ";
|
||||||
cerr << "[-e] [-k] [-l] [-v] [-y]" << endl;
|
cerr << "[-L] [-k] [-l] [-v] [-y]" << endl;
|
||||||
cerr << " where ID := {0-7}" << endl;
|
cerr << " where ID := {0-7}" << endl;
|
||||||
cerr << " UNIT := {0|1}, default is 0" << endl;
|
cerr << " UNIT := {0|1}, default is 0" << endl;
|
||||||
cerr << " CMD := {attach|detach|insert|eject|protect|unprotect|show}" << endl;
|
cerr << " CMD := {attach|detach|insert|eject|protect|unprotect|show}" << endl;
|
||||||
|
@ -613,7 +613,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
opterr = 1;
|
opterr = 1;
|
||||||
int opt;
|
int opt;
|
||||||
while ((opt = getopt(argc, argv, "a:b:c:d:f:g:h:i:m:n:p:r:t:u:x:w:eklsvy")) != -1) {
|
while ((opt = getopt(argc, argv, "elsvNTD:L:R:a:b:c:f:h:i:n:p:r:t:u:x:C:F:L:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'i':
|
case 'i':
|
||||||
device->set_id(optarg[0] - '0');
|
device->set_id(optarg[0] - '0');
|
||||||
|
@ -623,7 +623,7 @@ int main(int argc, char* argv[])
|
||||||
device->set_unit(optarg[0] - '0');
|
device->set_unit(optarg[0] - '0');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'a':
|
case 'C':
|
||||||
command.set_operation(CREATE_IMAGE);
|
command.set_operation(CREATE_IMAGE);
|
||||||
image_params = optarg;
|
image_params = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -645,12 +645,12 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'F':
|
||||||
command.set_operation(DEFAULT_FOLDER);
|
command.set_operation(DEFAULT_FOLDER);
|
||||||
default_folder = optarg;
|
default_folder = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case'e':
|
case 'e':
|
||||||
command.set_operation(IMAGE_FILES_INFO);
|
command.set_operation(IMAGE_FILES_INFO);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -658,7 +658,7 @@ int main(int argc, char* argv[])
|
||||||
param = optarg;
|
param = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'k':
|
case 'N':
|
||||||
command.set_operation(NETWORK_INTERFACES_INFO);
|
command.set_operation(NETWORK_INTERFACES_INFO);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -670,7 +670,7 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'L':
|
||||||
command.set_operation(LOG_LEVEL);
|
command.set_operation(LOG_LEVEL);
|
||||||
log_level = optarg;
|
log_level = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -683,7 +683,7 @@ int main(int argc, char* argv[])
|
||||||
list = true;
|
list = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'R':
|
||||||
command.set_operation(RENAME_IMAGE);
|
command.set_operation(RENAME_IMAGE);
|
||||||
image_params = optarg;
|
image_params = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -743,11 +743,11 @@ int main(int argc, char* argv[])
|
||||||
image_params = optarg;
|
image_params = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'y':
|
case 'T':
|
||||||
command.set_operation(DEVICE_TYPES_INFO);
|
command.set_operation(DEVICE_TYPES_INFO);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'w':
|
case 'D':
|
||||||
command.set_operation(DELETE_IMAGE);
|
command.set_operation(DELETE_IMAGE);
|
||||||
image_params = optarg;
|
image_params = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user