Index: head/bin/dd/dd.1 =================================================================== --- head/bin/dd/dd.1 (revision 304813) +++ head/bin/dd/dd.1 (revision 304814) @@ -1,457 +1,457 @@ .\"- .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" Keith Muller of the University of California, San Diego. .\" .\" 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. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. .\" .\" @(#)dd.1 8.2 (Berkeley) 1/13/94 .\" $FreeBSD$ .\" -.Dd February 28, 2016 +.Dd August 25, 2016 .Dt DD 1 .Os .Sh NAME .Nm dd .Nd convert and copy a file .Sh SYNOPSIS .Nm .Op Ar operands ... .Sh DESCRIPTION The .Nm utility copies the standard input to the standard output. Input data is read and written in 512-byte blocks. If input reads are short, input from multiple reads are aggregated to form the output block. When finished, .Nm displays the number of complete and partial input and output blocks and truncated input records to the standard error output. .Pp The following operands are available: .Bl -tag -width ".Cm of Ns = Ns Ar file" .It Cm bs Ns = Ns Ar n Set both input and output block size to .Ar n bytes, superseding the .Cm ibs and .Cm obs operands. If no conversion values other than .Cm noerror , .Cm notrunc or .Cm sync are specified, then each input block is copied to the output as a single block without any aggregation of short blocks. .It Cm cbs Ns = Ns Ar n Set the conversion record size to .Ar n bytes. The conversion record size is required by the record oriented conversion values. .It Cm count Ns = Ns Ar n Copy only .Ar n input blocks. .It Cm files Ns = Ns Ar n Copy .Ar n input files before terminating. This operand is only applicable when the input device is a tape. .It Cm fillchar Ns = Ns Ar c When padding a block in conversion mode or due to use of .Cm noerror and .Cm sync modes, fill with the specified .Tn ASCII character, rather than using a space or .Dv NUL . .It Cm ibs Ns = Ns Ar n Set the input block size to .Ar n bytes instead of the default 512. .It Cm if Ns = Ns Ar file Read input from .Ar file instead of the standard input. .It Cm iseek Ns = Ns Ar n Seek on the input file .Ar n blocks. This is synonymous with .Cm skip Ns = Ns Ar n . .It Cm obs Ns = Ns Ar n Set the output block size to .Ar n bytes instead of the default 512. .It Cm of Ns = Ns Ar file Write output to .Ar file instead of the standard output. Any regular output file is truncated unless the .Cm notrunc conversion value is specified. If an initial portion of the output file is seeked past (see the .Cm oseek operand), the output file is truncated at that point. .It Cm oseek Ns = Ns Ar n Seek on the output file .Ar n blocks. This is synonymous with .Cm seek Ns = Ns Ar n . .It Cm seek Ns = Ns Ar n Seek .Ar n blocks from the beginning of the output before copying. On non-tape devices, an .Xr lseek 2 operation is used. Otherwise, existing blocks are read and the data discarded. If the user does not have read permission for the tape, it is positioned using the tape .Xr ioctl 2 function calls. If the seek operation is past the end of file, space from the current end of file to the specified offset is filled with blocks of .Dv NUL bytes. .It Cm skip Ns = Ns Ar n Skip .Ar n blocks from the beginning of the input before copying. On input which supports seeks, an .Xr lseek 2 operation is used. Otherwise, input data is read and discarded. For pipes, the correct number of bytes is read. For all other devices, the correct number of blocks is read without distinguishing between a partial or complete block being read. .It Cm speed Ns = Ns Ar n Limit the copying speed to .Ar n bytes per second. .It Cm status Ns = Ns Ar value Where .Cm value is one of the symbols from the following list. .Bl -tag -width ".Cm noxfer" .It Cm noxfer Do not print the transfer statistics as the last line of status output. .It Cm none Do not print the status output. Error messages are shown; informational messages are not. .El .It Cm conv Ns = Ns Ar value Ns Op , Ns Ar value ... Where .Cm value is one of the symbols from the following list. .Bl -tag -width ".Cm unblock" .It Cm ascii , oldascii The same as the .Cm unblock value except that characters are translated from .Tn EBCDIC to .Tn ASCII before the records are converted. (These values imply .Cm unblock if the operand .Cm cbs is also specified.) There are two conversion maps for .Tn ASCII . The value .Cm ascii specifies the recommended one which is compatible with .At V . The value .Cm oldascii specifies the one used in historic .At and .No pre- Ns Bx 4.3 reno systems. .It Cm block Treats the input as a sequence of newline or end-of-file terminated variable length records independent of input and output block boundaries. Any trailing newline character is discarded. Each input record is converted to a fixed length output record where the length is specified by the .Cm cbs operand. Input records shorter than the conversion record size are padded with spaces. Input records longer than the conversion record size are truncated. The number of truncated input records, if any, are reported to the standard error output at the completion of the copy. .It Cm ebcdic , ibm , oldebcdic , oldibm The same as the .Cm block value except that characters are translated from .Tn ASCII to .Tn EBCDIC after the records are converted. (These values imply .Cm block if the operand .Cm cbs is also specified.) There are four conversion maps for .Tn EBCDIC . The value .Cm ebcdic specifies the recommended one which is compatible with .At V . The value .Cm ibm is a slightly different mapping, which is compatible with the .At V .Cm ibm value. The values .Cm oldebcdic and .Cm oldibm are maps used in historic .At and .No pre- Ns Bx 4.3 reno systems. .It Cm lcase Transform uppercase characters into lowercase characters. .It Cm pareven , parnone , parodd , parset Output data with the specified parity. The parity bit on input is stripped unless .Tn EBCDIC to .Tn ASCII conversions is also specified. .It Cm noerror Do not stop processing on an input error. When an input error occurs, a diagnostic message followed by the current input and output block counts will be written to the standard error output in the same format as the standard completion message. If the .Cm sync conversion is also specified, any missing input data will be replaced with .Dv NUL bytes (or with spaces if a block oriented conversion value was specified) and processed as a normal input buffer. If the .Cm fillchar option is specified, the fill character provided on the command line will override the automatic selection of the fill character. If the .Cm sync conversion is not specified, the input block is omitted from the output. On input files which are not tapes or pipes, the file offset will be positioned past the block in which the error occurred using .Xr lseek 2 . .It Cm notrunc Do not truncate the output file. This will preserve any blocks in the output file not explicitly written by .Nm . The .Cm notrunc value is not supported for tapes. .It Cm osync Pad the final output block to the full output block size. If the input file is not a multiple of the output block size after conversion, this conversion forces the final output block to be the same size as preceding blocks for use on devices that require regularly sized blocks to be written. This option is incompatible with use of the .Cm bs Ns = Ns Ar n block size specification. .It Cm sparse If one or more output blocks would consist solely of .Dv NUL bytes, try to seek the output file by the required space instead of filling them with .Dv NUL Ns s , resulting in a sparse file. .It Cm swab Swap every pair of input bytes. If an input buffer has an odd number of bytes, the last byte will be ignored during swapping. .It Cm sync Pad every input block to the input buffer size. Spaces are used for pad bytes if a block oriented conversion value is specified, otherwise .Dv NUL bytes are used. .It Cm ucase Transform lowercase characters into uppercase characters. .It Cm unblock Treats the input as a sequence of fixed length records independent of input and output block boundaries. The length of the input records is specified by the .Cm cbs operand. Any trailing space characters are discarded and a newline character is appended. .El .El .Pp Where sizes or speed are specified, a decimal, octal, or hexadecimal number of bytes is expected. If the number ends with a .Dq Li b , .Dq Li k , .Dq Li m , .Dq Li g , .Dq Li t , .Dq Li p , or .Dq Li w , the number is multiplied by 512, 1024 (1K), 1048576 (1M), 1073741824 (1G), 1099511627776 (1T), 1125899906842624 (1P) or the number of bytes in an integer, respectively. Two or more numbers may be separated by an .Dq Li x to indicate a product. .Pp When finished, .Nm displays the number of complete and partial input and output blocks, truncated input records and odd-length byte-swapping blocks to the standard error output. A partial input block is one where less than the input block size was read. A partial output block is one where less than the output block size was written. Partial output blocks to tape devices are considered fatal errors. Otherwise, the rest of the block will be written. Partial output blocks to character devices will produce a warning message. A truncated input block is one where a variable length record oriented conversion value was specified and the input line was too long to fit in the conversion record or was not newline terminated. .Pp Normally, data resulting from input or conversion or both are aggregated into output blocks of the specified size. After the end of input is reached, any remaining output is written as a block. This means that the final output block may be shorter than the output block size. .Pp If .Nm receives a .Dv SIGINFO (see the .Cm status argument for .Xr stty 1 ) signal, the current input and output block counts will be written to the standard error output in the same format as the standard completion message. If .Nm receives a .Dv SIGINT signal, the current input and output block counts will be written to the standard error output in the same format as the standard completion message and .Nm will exit. .Sh EXIT STATUS .Ex -std .Sh EXAMPLES Check that a disk drive contains no bad blocks: .Pp .Dl "dd if=/dev/ada0 of=/dev/null bs=1m" .Pp Do a refresh of a disk drive, in order to prevent presently recoverable read errors from progressing into unrecoverable read errors: .Pp .Dl "dd if=/dev/ada0 of=/dev/ada0 bs=1m" .Pp Remove parity bit from a file: .Pp .Dl "dd if=file conv=parnone of=file.txt" .Pp Check for (even) parity errors on a file: .Pp .Dl "dd if=file conv=pareven | cmp -x - file" .Pp To create an image of a Mode-1 CD-ROM, which is a commonly used format for data CD-ROM disks, use a block size of 2048 bytes: .Pp -.Dl "dd if=/dev/acd0 of=filename.iso bs=2048" +.Dl "dd if=/dev/cd0 of=filename.iso bs=2048" .Pp Write a filesystem image to a memory stick, padding the end with zeros, if necessary, to a 1MiB boundary: .Pp .Dl "dd if=memstick.img of=/dev/da0 bs=1m conv=noerror,sync" .Sh SEE ALSO .Xr cp 1 , .Xr mt 1 , .Xr recoverdisk 1 , .Xr tr 1 , .Xr geom 4 .Sh STANDARDS The .Nm utility is expected to be a superset of the .St -p1003.2 standard. The .Cm files and .Cm status operands and the .Cm ascii , .Cm ebcdic , .Cm ibm , .Cm oldascii , .Cm oldebcdic and .Cm oldibm values are extensions to the .Tn POSIX standard. .Sh BUGS Protection mechanisms in the .Xr geom 4 subsystem might prevent the super-user from writing blocks to a disk. Instructions for temporarily disabling these protection mechanisms can be found in the .Xr geom 4 manpage. Index: head/sbin/ggate/ggatec/ggatec.8 =================================================================== --- head/sbin/ggate/ggatec/ggatec.8 (revision 304813) +++ head/sbin/ggate/ggatec/ggatec.8 (revision 304814) @@ -1,180 +1,180 @@ .\" Copyright (c) 2004 Pawel Jakub Dawidek .\" 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 AUTHORS 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 AUTHORS 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. .\" .\" $FreeBSD$ .\" -.Dd July 14, 2015 +.Dd August 25, 2016 .Dt GGATEC 8 .Os .Sh NAME .Nm ggatec .Nd "GEOM Gate network client and control utility" .Sh SYNOPSIS .Nm .Cm create .Op Fl n .Op Fl v .Op Fl o Cm ro | wo | rw .Op Fl p Ar port .Op Fl q Ar queue_size .Op Fl R Ar rcvbuf .Op Fl S Ar sndbuf .Op Fl s Ar sectorsize .Op Fl t Ar timeout .Op Fl u Ar unit .Ar host .Ar path .Nm .Cm rescue .Op Fl n .Op Fl v .Op Fl o Cm ro | wo | rw .Op Fl p Ar port .Op Fl R Ar rcvbuf .Op Fl S Ar sndbuf .Fl u Ar unit .Ar host .Ar path .Nm .Cm destroy .Op Fl f .Fl u Ar unit .Nm .Cm list .Op Fl v .Op Fl u Ar unit .Sh DESCRIPTION The .Nm utility is a network client for the GEOM Gate class. It is responsible for the creation of .Nm ggate devices and forwarding I/O requests between the .Nm GEOM Gate kernel subsystem and the .Xr ggated 8 network daemon. Available commands: .Bl -tag -width ".Cm destroy" .It Cm create Connect to a .Xr ggated 8 daemon on the specified host and create a .Nm ggate provider for the specified remote file or device. .It Cm rescue Create a new connection after the .Nm process has died or been killed. The new connection to the .Xr ggated 8 daemon handles pending and future requests. .It Cm destroy Destroy the given .Nm ggate provider. .It Cm list List .Nm ggate providers. .El .Pp Available options: .Bl -tag -width ".Fl s Cm ro | wo | rw" .It Fl f Forcibly destroy .Nm ggate provider (cancels all pending requests). .It Fl n Do not use .Dv TCP_NODELAY option on TCP sockets. .It Fl o Cm ro | wo | rw Specify permissions to use when opening the file or device: read-only .Pq Cm ro , write-only .Pq Cm wo , or read-write .Pq Cm rw . Default is .Cm rw . .It Fl p Ar port Port to connect to on the remote host. Default is 3080. .It Fl q Ar queue_size Number of pending I/O requests that can be queued before they will start to be canceled. Default is 1024. .It Fl R Ar rcvbuf Size of receive buffer to use. Default is 131072 (128kB). .It Fl S Ar sndbuf Size of send buffer to use. Default is 131072 (128kB). .It Fl s Ar sectorsize Sector size for .Nm ggate provider. If not specified, it is taken from the device, or set to 512 bytes for files. .It Fl t Ar timeout Number of seconds to wait before an I/O request will be canceled. Default is 0, which means no timeout. .It Fl u Ar unit Unit number to use. .It Fl v Do not fork, run in foreground and print debug information on standard output. .It Ar host Remote host to connect to. .It Ar path Path to a regular file or device. .El .Sh EXIT STATUS Exit status is 0 on success, or 1 if the command fails. To get details about the failure, .Nm should be called with the .Fl v option. .Sh EXAMPLES Use a CD-ROM device on a remote host. .Bd -literal -offset indent server# cat /etc/gg.exports -client RO /dev/acd0 +client RO /dev/cd0 server# ggated -client# ggatec create -o ro server /dev/acd0 +client# ggatec create -o ro server /dev/cd0 ggate0 client# mount_cd9660 /dev/ggate0 /cdrom .Ed .Sh SEE ALSO .Xr geom 4 , .Xr ggated 8 , .Xr ggatel 8 , .Xr mount_cd9660 8 .Sh AUTHORS The .Nm utility as well as this manual page was written by .An Pawel Jakub Dawidek Aq Mt pjd@FreeBSD.org . Index: head/sbin/ggate/ggated/ggated.8 =================================================================== --- head/sbin/ggate/ggated/ggated.8 (revision 304813) +++ head/sbin/ggate/ggated/ggated.8 (revision 304814) @@ -1,123 +1,123 @@ .\" Copyright (c) 2004 Pawel Jakub Dawidek .\" 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 AUTHORS 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 AUTHORS 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. .\" .\" $FreeBSD$ .\" -.Dd January 27, 2016 +.Dd August 25, 2016 .Dt GGATED 8 .Os .Sh NAME .Nm ggated .Nd "GEOM Gate network daemon" .Sh SYNOPSIS .Nm .Op Fl h .Op Fl n .Op Fl v .Op Fl a Ar address .Op Fl p Ar port .Op Fl F Ar pidfile .Op Fl R Ar rcvbuf .Op Fl S Ar sndbuf .Op Ar "exports file" .Sh DESCRIPTION The .Nm utility is a network server for the GEOM Gate class. It runs on a server machine to service GEOM Gate requests from workers placed on a client machine. Keep in mind, that connections between .Xr ggatec 8 and .Nm are not encrypted. .Pp Available options: .Bl -tag -width ".Ar exports\ file" .It Fl a Ar address Specifies an IP address to bind to. .It Fl h Print available options. .It Fl n Do not use .Dv TCP_NODELAY option on TCP sockets. .It Fl p Ar port Port on which .Nm listens for connections. Default is 3080. .It Fl F Ar pidfile PID file that .Nm uses. .It Fl R Ar rcvbuf Size of receive buffer to use. Default is 131072 (128kB). .It Fl S Ar sndbuf Size of send buffer to use. Default is 131072 (128kB). .It Fl v Do not fork, run in foreground and print debug information on standard output. .It Ar "exports file" An alternate location for the exports file. .El .Pp The format of an exports file is as follows: .Bd -literal -offset indent -1.2.3.4 RO /dev/acd0 +1.2.3.4 RO /dev/cd0 1.2.3.0/24 RW /tmp/test.img hostname WO /tmp/image .Ed .Sh FILES .Bl -tag -width ".Pa /var/run/ggated.pid" -compact .It Pa /var/run/ggated.pid The default location of the .Nm PID file. .El .Sh EXIT STATUS Exit status is 0 on success, or 1 if the command fails. To get details about the failure, .Nm should be called with the .Fl v option. .Sh EXAMPLES Export CD-ROM device and a file: .Bd -literal -offset indent -# echo "1.2.3.0/24 RO /dev/acd0" > /etc/gg.exports +# echo "1.2.3.0/24 RO /dev/cd0" > /etc/gg.exports # echo "client RW /image" >> /etc/gg.exports # ggated .Ed .Sh SEE ALSO .Xr geom 4 , .Xr ggatec 8 , .Xr ggatel 8 .Sh AUTHORS The .Nm utility as well as this manual page was written by .An Pawel Jakub Dawidek Aq Mt pjd@FreeBSD.org . Index: head/usr.sbin/cdcontrol/cdcontrol.1 =================================================================== --- head/usr.sbin/cdcontrol/cdcontrol.1 (revision 304813) +++ head/usr.sbin/cdcontrol/cdcontrol.1 (revision 304814) @@ -1,222 +1,214 @@ .\" $FreeBSD$ .\" -.Dd June 27, 2008 +.Dd August 25, 2016 .Dt CDCONTROL 1 .Os .Sh NAME .Nm cdcontrol .Nd compact disc control utility .Sh SYNOPSIS .Nm .Op Fl sv .Op Fl f Ar device .Op Ar command ... .Sh DESCRIPTION The .Nm utility is a program to control audio features of a CD drive. The device is a name such as -.Pa cd0 -or -.Pa acd0 . +.Pa cd0 . .Pp If no .Ar command is given, then .Nm enters an interactive mode, reading commands from the standard input. .Pp The following options are available: .Bl -tag -width indent .It Fl s Silent mode. Do not print table headers and human readable comments. .It Fl v Verbose mode. Print as much information as possible. .It Fl f Ar device Specify a device, such as -.Pa /dev/cd0 -or -.Pa acd0 . +.Pa /dev/cd0 . Both absolute path and relative to .Pa /dev filename are possible. The .Fl f option overrides .Ev CDROM . If neither .Ev CDROM nor the .Fl f option is specified, .Nm tries opening first .Pa /dev/cdrom , then -.Pa /dev/cd0 , -and finally -.Pa /dev/acd0 . +.Pa /dev/cd0 . .El .Pp The available commands are listed below. Only as many characters as are required to uniquely identify a command need be specified. The word .Ic play can be omitted or the characters .Ic + and .Ic - can be used in the place of .Ic next and .Ic prev . .Bl -tag -width indent .It Ic play Ar first_track Op Ar last_track Play from track .Ar first_track to track .Ar last_track . The first track has number 1. Can be omitted in all cases. .It Xo .Ic play .Ar start_m : Ns Ar start_s . Ns Ar start_f .Op Ar end_m : Ns Ar end_s . Ns Ar end_f .Xc Play from the absolute address (MSF) defined by .Ar start_m in minutes, .Ar start_s , in seconds and .Ar start_f (frame number) to the absolute address defined by .Ar end_m in minutes, .Ar end_s , in seconds and .Ar end_f (frame number). Minutes are in the range 0-99. Seconds are in the range 0-59. Frame numbers are in the range 0-74. .It Ic play Op # Ns Ar start_block Op Ar length Play starting from the logical block .Ar start_block using .Ar length logical blocks. .It Ic next Op Ar tracks Skip forward a number of tracks (default 1). .It Ic prev Op Ar tracks Skip backward a number of tracks (default 1). .It Ic pause Stop playing. Do not stop the disc. .It Ic resume Resume playing. Used after the .Ic pause command. .It Ic stop Stop the disc. .It Ic eject Eject the disc. .It Ic close Inject the disc. .It Ic volume Same as .Em status volume command. .It Ic volume Ar level Set the volume of both channels to .Ar level . Allowed values are in the range 0-255. .It Ic volume Ar left_channel right_channel Set the volume of left channel to .Ar left_channel and the volume of right channel to .Ar right_channel . Allowed values are in the range 0-255. .It Ic volume Cm mute Turn the sound off. .It Ic volume Cm mono Set the mono mode. .It Ic volume Cm stereo Set the stereo mode. .It Ic volume Cm left Play the left subtrack on both left and right channels. .It Ic volume Cm right Play the right subtrack on both left and right channels. .It Ic info Print the table of contents. .It Ic status Op Cm audio | media | volume Print the information about the disc: .Pp .Bl -tag -width ".Cm volume" -compact .It Cm audio the current playing status and position .It Cm media the current media catalog status .It Cm volume the current values of the volume for left and right channels. .El .It Ic cdid Display the serial number of the CD using the method used by the .Tn CDDB project .Pq Pa http://www.cddb.org/ . .It Ic help Print the list of available commands. .It Ic debug Cm on Enable the debugging mode of the CD device driver. .It Ic debug Cm off Disable the driver debugging mode. .It Ic reset Perform the hardware reset of the device. .It Ic set Cm msf Set minute-second-frame ioctl mode (default). .It Ic set Cm lba Set LBA ioctl mode. .It Ic speed Ar s Set the highest speed that the drive should use for reading data. The units are multiples of a single speed CDROM (150 KB/s). Specify .Dq Li max to use the drive's fastest speed. .It Ic quit Quit the program. .El .Sh ENVIRONMENT The following environment variables affect the execution of .Nm : .Bl -tag -width ".Ev CD_DRIVE" .It Ev CDROM The CD device to use, if one is not specified with the .Fl f option. .It Ev CDPLAY , CD_DRIVE , DISC , MUSIC_CD These variables have been deprecated in favour of .Ev CDROM . .El .Sh FILES -.Bl -tag -width ".Pa /dev/mcd0" -compact +.Bl -tag -width ".Pa /dev/cd0" -compact .It Pa /dev/cd0 -.It Pa /dev/mcd0 -.It Pa /dev/acd0 .El .Sh HISTORY The .Nm command appeared in .Fx 2.1 . .Sh AUTHORS .An Jean-Marc Zucconi .An Andrey A. Chernov .An Serge V. Vakulenko Index: head/usr.sbin/cdcontrol/cdcontrol.c =================================================================== --- head/usr.sbin/cdcontrol/cdcontrol.c (revision 304813) +++ head/usr.sbin/cdcontrol/cdcontrol.c (revision 304814) @@ -1,1310 +1,1308 @@ /* * Compact Disc Control Utility by Serge V. Vakulenko . * Based on the non-X based CD player by Jean-Marc Zucconi and * Andrey A. Chernov. * * Fixed and further modified on 5-Sep-1995 by Jukka Ukkonen . * * 11-Sep-1995: Jukka A. Ukkonen * A couple of further fixes to my own earlier "fixes". * * 18-Sep-1995: Jukka A. Ukkonen * Added an ability to specify addresses relative to the * beginning of a track. This is in fact a variation of * doing the simple play_msf() call. * * 11-Oct-1995: Serge V.Vakulenko * New eject algorithm. * Some code style reformatting. * * 13-Dec-1999: Knut A. Syed * Volume-command modified. If used with only one * parameter it now sets both channels. If used without * parameters it will print volume-info. * Version 2.0.1 * * 27-Jun-2008 Pietro Cerutti * Further enhancement to volume. Values not in range 0-255 * are now reduced to be in range. This prevents overflow in * the uchar storing the volume (256 -> 0, -20 -> 236, ...). * Version 2.0.2 * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define VERSION "2.0.2" #define ASTS_INVALID 0x00 /* Audio status byte not valid */ #define ASTS_PLAYING 0x11 /* Audio play operation in progress */ #define ASTS_PAUSED 0x12 /* Audio play operation paused */ #define ASTS_COMPLETED 0x13 /* Audio play operation successfully completed */ #define ASTS_ERROR 0x14 /* Audio play operation stopped due to error */ #define ASTS_VOID 0x15 /* No current audio status to return */ #ifdef DEFAULT_CD_DRIVE # error "Setting DEFAULT_CD_DRIVE is no longer supported" #endif #define CMD_DEBUG 1 #define CMD_EJECT 2 #define CMD_HELP 3 #define CMD_INFO 4 #define CMD_PAUSE 5 #define CMD_PLAY 6 #define CMD_QUIT 7 #define CMD_RESUME 8 #define CMD_STOP 9 #define CMD_VOLUME 10 #define CMD_CLOSE 11 #define CMD_RESET 12 #define CMD_SET 13 #define CMD_STATUS 14 #define CMD_CDID 15 #define CMD_NEXT 16 #define CMD_PREVIOUS 17 #define CMD_SPEED 18 #define STATUS_AUDIO 0x1 #define STATUS_MEDIA 0x2 #define STATUS_VOLUME 0x4 static struct cmdtab { int command; const char *name; unsigned min; const char *args; } cmdtab[] = { { CMD_CLOSE, "close", 1, "" }, { CMD_DEBUG, "debug", 1, "on | off" }, { CMD_EJECT, "eject", 1, "" }, { CMD_HELP, "?", 1, 0 }, { CMD_HELP, "help", 1, "" }, { CMD_INFO, "info", 1, "" }, { CMD_NEXT, "next", 1, "" }, { CMD_PAUSE, "pause", 2, "" }, { CMD_PLAY, "play", 1, "min1:sec1[.fram1] [min2:sec2[.fram2]]" }, { CMD_PLAY, "play", 1, "track1[.index1] [track2[.index2]]" }, { CMD_PLAY, "play", 1, "tr1 m1:s1[.f1] [[tr2] [m2:s2[.f2]]]" }, { CMD_PLAY, "play", 1, "[#block [len]]" }, { CMD_PREVIOUS, "previous", 2, "" }, { CMD_QUIT, "quit", 1, "" }, { CMD_RESET, "reset", 4, "" }, { CMD_RESUME, "resume", 1, "" }, { CMD_SET, "set", 2, "msf | lba" }, { CMD_STATUS, "status", 1, "[audio | media | volume]" }, { CMD_STOP, "stop", 3, "" }, { CMD_VOLUME, "volume", 1, " | left | right | mute | mono | stereo" }, { CMD_CDID, "cdid", 2, "" }, { CMD_SPEED, "speed", 2, "speed" }, { 0, NULL, 0, NULL } }; static struct cd_toc_entry toc_buffer[100]; static const char *cdname; static int fd = -1; static int verbose = 1; static int msf = 1; static int setvol(int, int); static int read_toc_entrys(int); static int play_msf(int, int, int, int, int, int); static int play_track(int, int, int, int); static int status(int *, int *, int *, int *); static int open_cd(void); static int next_prev(char *arg, int); static int play(char *arg); static int info(char *arg); static int cdid(void); static int pstatus(char *arg); static char *input(int *); static void prtrack(struct cd_toc_entry *e, int lastflag); static void lba2msf(unsigned long lba, u_char *m, u_char *s, u_char *f); static unsigned int msf2lba(u_char m, u_char s, u_char f); static int play_blocks(int blk, int len); static int run(int cmd, char *arg); static char *parse(char *buf, int *cmd); static void help(void); static void usage(void); static char *use_cdrom_instead(const char *); static const char *strstatus(int); static u_int dbprog_discid(void); static const char *cdcontrol_prompt(void); static void help(void) { struct cmdtab *c; const char *s; char n; int i; for (c=cmdtab; c->name; ++c) { if (! c->args) continue; printf("\t"); for (i = c->min, s = c->name; *s; s++, i--) { if (i > 0) n = toupper(*s); else n = *s; putchar(n); } if (*c->args) printf (" %s", c->args); printf ("\n"); } printf ("\n\tThe word \"play\" is not required for the play commands.\n"); printf ("\tThe plain target address is taken as a synonym for play.\n"); } static void usage(void) { fprintf (stderr, "usage: cdcontrol [-sv] [-f device] [command ...]\n"); exit (1); } static char * use_cdrom_instead(const char *old_envvar) { char *device; device = getenv(old_envvar); if (device) warnx("%s environment variable deprecated, " "please use CDROM in the future.", old_envvar); return device; } int main(int argc, char **argv) { int cmd; char *arg; for (;;) { switch (getopt (argc, argv, "svhf:")) { case -1: break; case 's': verbose = 0; continue; case 'v': verbose = 2; continue; case 'f': cdname = optarg; continue; case 'h': default: usage (); } break; } argc -= optind; argv += optind; if (argc > 0 && ! strcasecmp (*argv, "help")) usage (); if (! cdname) { cdname = getenv("CDROM"); } if (! cdname) cdname = use_cdrom_instead("MUSIC_CD"); if (! cdname) cdname = use_cdrom_instead("CD_DRIVE"); if (! cdname) cdname = use_cdrom_instead("DISC"); if (! cdname) cdname = use_cdrom_instead("CDPLAY"); if (argc > 0) { char buf[80], *p; int len, rc; for (p=buf; argc-->0; ++argv) { len = strlen (*argv); if (p + len >= buf + sizeof (buf) - 1) usage (); if (p > buf) *p++ = ' '; strcpy (p, *argv); p += len; } *p = 0; arg = parse (buf, &cmd); rc = run (cmd, arg); if (rc < 0 && verbose) warn(NULL); return (rc); } if (verbose == 1) verbose = isatty (0); if (verbose) { printf ("Compact Disc Control utility, version %s\n", VERSION); printf ("Type `?' for command list\n\n"); } for (;;) { arg = input (&cmd); if (run (cmd, arg) < 0) { if (verbose) warn(NULL); close (fd); fd = -1; } fflush (stdout); } } static int run(int cmd, char *arg) { long speed; int l, r, rc, count; switch (cmd) { case CMD_QUIT: exit (0); case CMD_INFO: if (fd < 0 && ! open_cd ()) return (0); return info (arg); case CMD_CDID: if (fd < 0 && ! open_cd ()) return (0); return cdid (); case CMD_STATUS: if (fd < 0 && ! open_cd ()) return (0); return pstatus (arg); case CMD_NEXT: case CMD_PREVIOUS: if (fd < 0 && ! open_cd ()) return (0); while (isspace (*arg)) arg++; return next_prev (arg, cmd); case CMD_PAUSE: if (fd < 0 && ! open_cd ()) return (0); return ioctl (fd, CDIOCPAUSE); case CMD_RESUME: if (fd < 0 && ! open_cd ()) return (0); return ioctl (fd, CDIOCRESUME); case CMD_STOP: if (fd < 0 && ! open_cd ()) return (0); rc = ioctl (fd, CDIOCSTOP); (void) ioctl (fd, CDIOCALLOW); return (rc); case CMD_RESET: if (fd < 0 && ! open_cd ()) return (0); rc = ioctl (fd, CDIOCRESET); if (rc < 0) return rc; close(fd); fd = -1; return (0); case CMD_DEBUG: if (fd < 0 && ! open_cd ()) return (0); if (! strcasecmp (arg, "on")) return ioctl (fd, CDIOCSETDEBUG); if (! strcasecmp (arg, "off")) return ioctl (fd, CDIOCCLRDEBUG); warnx("invalid command arguments"); return (0); case CMD_EJECT: if (fd < 0 && ! open_cd ()) return (0); (void) ioctl (fd, CDIOCALLOW); rc = ioctl (fd, CDIOCEJECT); if (rc < 0) return (rc); return (0); case CMD_CLOSE: if (fd < 0 && ! open_cd ()) return (0); (void) ioctl (fd, CDIOCALLOW); rc = ioctl (fd, CDIOCCLOSE); if (rc < 0) return (rc); close(fd); fd = -1; return (0); case CMD_PLAY: if (fd < 0 && ! open_cd ()) return (0); while (isspace (*arg)) arg++; return play (arg); case CMD_SET: if (! strcasecmp (arg, "msf")) msf = 1; else if (! strcasecmp (arg, "lba")) msf = 0; else warnx("invalid command arguments"); return (0); case CMD_VOLUME: if (fd < 0 && !open_cd ()) return (0); if (! strlen (arg)) { char volume[] = "volume"; return pstatus (volume); } if (! strncasecmp (arg, "left", strlen(arg))) return ioctl (fd, CDIOCSETLEFT); if (! strncasecmp (arg, "right", strlen(arg))) return ioctl (fd, CDIOCSETRIGHT); if (! strncasecmp (arg, "mono", strlen(arg))) return ioctl (fd, CDIOCSETMONO); if (! strncasecmp (arg, "stereo", strlen(arg))) return ioctl (fd, CDIOCSETSTERIO); if (! strncasecmp (arg, "mute", strlen(arg))) return ioctl (fd, CDIOCSETMUTE); count = sscanf (arg, "%d %d", &l, &r); if (count == 1) return setvol (l, l); if (count == 2) return setvol (l, r); warnx("invalid command arguments"); return (0); case CMD_SPEED: if (fd < 0 && ! open_cd ()) return (0); errno = 0; if (strcasecmp("max", arg) == 0) speed = CDR_MAX_SPEED; else speed = strtol(arg, NULL, 10) * 177; if (speed <= 0 || speed > INT_MAX) { warnx("invalid command arguments %s", arg); return (0); } return ioctl(fd, CDRIOCREADSPEED, &speed); default: case CMD_HELP: help (); return (0); } } static int play(char *arg) { struct ioc_toc_header h; unsigned int n; int rc, start, end = 0, istart = 1, iend = 1; rc = ioctl (fd, CDIOREADTOCHEADER, &h); if (rc < 0) return (rc); n = h.ending_track - h.starting_track + 1; rc = read_toc_entrys ((n + 1) * sizeof (struct cd_toc_entry)); if (rc < 0) return (rc); if (! arg || ! *arg) { /* Play the whole disc */ if (msf) return play_blocks (0, msf2lba (toc_buffer[n].addr.msf.minute, toc_buffer[n].addr.msf.second, toc_buffer[n].addr.msf.frame)); else return play_blocks (0, ntohl(toc_buffer[n].addr.lba)); } if (strchr (arg, '#')) { /* Play block #blk [ len ] */ int blk, len = 0; if (2 != sscanf (arg, "#%d%d", &blk, &len) && 1 != sscanf (arg, "#%d", &blk)) goto Clean_up; if (len == 0) { if (msf) len = msf2lba (toc_buffer[n].addr.msf.minute, toc_buffer[n].addr.msf.second, toc_buffer[n].addr.msf.frame) - blk; else len = ntohl(toc_buffer[n].addr.lba) - blk; } return play_blocks (blk, len); } if (strchr (arg, ':')) { /* * Play MSF m1:s1 [ .f1 ] [ m2:s2 [ .f2 ] ] * * Will now also undestand timed addresses relative * to the beginning of a track in the form... * * tr1 m1:s1[.f1] [[tr2] [m2:s2[.f2]]] */ unsigned tr1, tr2; unsigned m1, m2, s1, s2, f1, f2; unsigned char tm, ts, tf; tr2 = m2 = s2 = f2 = f1 = 0; if (8 == sscanf (arg, "%d %d:%d.%d %d %d:%d.%d", &tr1, &m1, &s1, &f1, &tr2, &m2, &s2, &f2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (7 == sscanf (arg, "%d %d:%d %d %d:%d.%d", &tr1, &m1, &s1, &tr2, &m2, &s2, &f2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (7 == sscanf (arg, "%d %d:%d.%d %d %d:%d", &tr1, &m1, &s1, &f1, &tr2, &m2, &s2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (7 == sscanf (arg, "%d %d:%d.%d %d:%d.%d", &tr1, &m1, &s1, &f1, &m2, &s2, &f2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (6 == sscanf (arg, "%d %d:%d.%d %d:%d", &tr1, &m1, &s1, &f1, &m2, &s2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (6 == sscanf (arg, "%d %d:%d %d:%d.%d", &tr1, &m1, &s1, &m2, &s2, &f2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (6 == sscanf (arg, "%d %d:%d.%d %d %d", &tr1, &m1, &s1, &f1, &tr2, &m2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (5 == sscanf (arg, "%d %d:%d %d:%d", &tr1, &m1, &s1, &m2, &s2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (5 == sscanf (arg, "%d %d:%d %d %d", &tr1, &m1, &s1, &tr2, &m2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (5 == sscanf (arg, "%d %d:%d.%d %d", &tr1, &m1, &s1, &f1, &tr2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (4 == sscanf (arg, "%d %d:%d %d", &tr1, &m1, &s1, &tr2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (4 == sscanf (arg, "%d %d:%d.%d", &tr1, &m1, &s1, &f1)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (3 == sscanf (arg, "%d %d:%d", &tr1, &m1, &s1)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; goto Try_Absolute_Timed_Addresses; Play_Relative_Addresses: if (! tr1) tr1 = 1; else if (tr1 > n) tr1 = n; tr1--; if (msf) { tm = toc_buffer[tr1].addr.msf.minute; ts = toc_buffer[tr1].addr.msf.second; tf = toc_buffer[tr1].addr.msf.frame; } else lba2msf(ntohl(toc_buffer[tr1].addr.lba), &tm, &ts, &tf); if ((m1 > tm) || ((m1 == tm) && ((s1 > ts) || ((s1 == ts) && (f1 > tf))))) { printf ("Track %d is not that long.\n", tr1); return (0); } f1 += tf; if (f1 >= 75) { s1 += f1 / 75; f1 %= 75; } s1 += ts; if (s1 >= 60) { m1 += s1 / 60; s1 %= 60; } m1 += tm; if (! tr2) { if (m2 || s2 || f2) { tr2 = tr1; f2 += f1; if (f2 >= 75) { s2 += f2 / 75; f2 %= 75; } s2 += s1; if (s2 > 60) { m2 += s2 / 60; s2 %= 60; } m2 += m1; } else { tr2 = n; if (msf) { m2 = toc_buffer[n].addr.msf.minute; s2 = toc_buffer[n].addr.msf.second; f2 = toc_buffer[n].addr.msf.frame; } else { lba2msf(ntohl(toc_buffer[n].addr.lba), &tm, &ts, &tf); m2 = tm; s2 = ts; f2 = tf; } } } else if (tr2 > n) { tr2 = n; m2 = s2 = f2 = 0; } else { if (m2 || s2 || f2) tr2--; if (msf) { tm = toc_buffer[tr2].addr.msf.minute; ts = toc_buffer[tr2].addr.msf.second; tf = toc_buffer[tr2].addr.msf.frame; } else lba2msf(ntohl(toc_buffer[tr2].addr.lba), &tm, &ts, &tf); f2 += tf; if (f2 >= 75) { s2 += f2 / 75; f2 %= 75; } s2 += ts; if (s2 > 60) { m2 += s2 / 60; s2 %= 60; } m2 += tm; } if (msf) { tm = toc_buffer[n].addr.msf.minute; ts = toc_buffer[n].addr.msf.second; tf = toc_buffer[n].addr.msf.frame; } else lba2msf(ntohl(toc_buffer[n].addr.lba), &tm, &ts, &tf); if ((tr2 < n) && ((m2 > tm) || ((m2 == tm) && ((s2 > ts) || ((s2 == ts) && (f2 > tf)))))) { printf ("The playing time of the disc is not that long.\n"); return (0); } return (play_msf (m1, s1, f1, m2, s2, f2)); Try_Absolute_Timed_Addresses: if (6 != sscanf (arg, "%d:%d.%d%d:%d.%d", &m1, &s1, &f1, &m2, &s2, &f2) && 5 != sscanf (arg, "%d:%d.%d%d:%d", &m1, &s1, &f1, &m2, &s2) && 5 != sscanf (arg, "%d:%d%d:%d.%d", &m1, &s1, &m2, &s2, &f2) && 3 != sscanf (arg, "%d:%d.%d", &m1, &s1, &f1) && 4 != sscanf (arg, "%d:%d%d:%d", &m1, &s1, &m2, &s2) && 2 != sscanf (arg, "%d:%d", &m1, &s1)) goto Clean_up; if (m2 == 0) { if (msf) { m2 = toc_buffer[n].addr.msf.minute; s2 = toc_buffer[n].addr.msf.second; f2 = toc_buffer[n].addr.msf.frame; } else { lba2msf(ntohl(toc_buffer[n].addr.lba), &tm, &ts, &tf); m2 = tm; s2 = ts; f2 = tf; } } return play_msf (m1, s1, f1, m2, s2, f2); } /* * Play track trk1 [ .idx1 ] [ trk2 [ .idx2 ] ] */ if (4 != sscanf (arg, "%d.%d%d.%d", &start, &istart, &end, &iend) && 3 != sscanf (arg, "%d.%d%d", &start, &istart, &end) && 3 != sscanf (arg, "%d%d.%d", &start, &end, &iend) && 2 != sscanf (arg, "%d.%d", &start, &istart) && 2 != sscanf (arg, "%d%d", &start, &end) && 1 != sscanf (arg, "%d", &start)) goto Clean_up; if (end == 0) end = n; return (play_track (start, istart, end, iend)); Clean_up: warnx("invalid command arguments"); return (0); } static int next_prev(char *arg, int cmd) { struct ioc_toc_header h; int dir, junk, n, off, rc, trk; dir = (cmd == CMD_NEXT) ? 1 : -1; rc = ioctl (fd, CDIOREADTOCHEADER, &h); if (rc < 0) return (rc); n = h.ending_track - h.starting_track + 1; rc = status (&trk, &junk, &junk, &junk); if (rc < 0) return (-1); if (arg && *arg) { if (sscanf (arg, "%u", &off) != 1) { warnx("invalid command argument"); return (0); } else trk += off * dir; } else trk += dir; if (trk > h.ending_track) trk = 1; return (play_track (trk, 1, n, 1)); } static const char * strstatus(int sts) { switch (sts) { case ASTS_INVALID: return ("invalid"); case ASTS_PLAYING: return ("playing"); case ASTS_PAUSED: return ("paused"); case ASTS_COMPLETED: return ("completed"); case ASTS_ERROR: return ("error"); case ASTS_VOID: return ("void"); default: return ("??"); } } static int pstatus(char *arg) { struct ioc_vol v; struct ioc_read_subchannel ss; struct cd_sub_channel_info data; int rc, trk, m, s, f; int what = 0; char *p, vmcn[(4 * 15) + 1]; while ((p = strtok(arg, " \t"))) { arg = 0; if (!strncasecmp(p, "audio", strlen(p))) what |= STATUS_AUDIO; else if (!strncasecmp(p, "media", strlen(p))) what |= STATUS_MEDIA; else if (!strncasecmp(p, "volume", strlen(p))) what |= STATUS_VOLUME; else { warnx("invalid command arguments"); return 0; } } if (!what) what = STATUS_AUDIO|STATUS_MEDIA|STATUS_VOLUME; if (what & STATUS_AUDIO) { rc = status (&trk, &m, &s, &f); if (rc >= 0) if (verbose) printf ("Audio status = %d<%s>, current track = %d, current position = %d:%02d.%02d\n", rc, strstatus (rc), trk, m, s, f); else printf ("%d %d %d:%02d.%02d\n", rc, trk, m, s, f); else printf ("No current status info available\n"); } if (what & STATUS_MEDIA) { bzero (&ss, sizeof (ss)); ss.data = &data; ss.data_len = sizeof (data); ss.address_format = msf ? CD_MSF_FORMAT : CD_LBA_FORMAT; ss.data_format = CD_MEDIA_CATALOG; rc = ioctl (fd, CDIOCREADSUBCHANNEL, (char *) &ss); if (rc >= 0) { printf("Media catalog is %sactive", ss.data->what.media_catalog.mc_valid ? "": "in"); if (ss.data->what.media_catalog.mc_valid && ss.data->what.media_catalog.mc_number[0]) { strvisx (vmcn, ss.data->what.media_catalog.mc_number, (sizeof (vmcn) - 1) / 4, VIS_OCTAL | VIS_NL); printf(", number \"%.*s\"", (int)sizeof (vmcn), vmcn); } putchar('\n'); } else printf("No media catalog info available\n"); } if (what & STATUS_VOLUME) { rc = ioctl (fd, CDIOCGETVOL, &v); if (rc >= 0) if (verbose) printf ("Left volume = %d, right volume = %d\n", v.vol[0], v.vol[1]); else printf ("%d %d\n", v.vol[0], v.vol[1]); else printf ("No volume level info available\n"); } return(0); } /* * dbprog_sum * Convert an integer to its text string representation, and * compute its checksum. Used by dbprog_discid to derive the * disc ID. * * Args: * n - The integer value. * * Return: * The integer checksum. */ static int dbprog_sum(int n) { char buf[12], *p; int ret = 0; /* For backward compatibility this algorithm must not change */ sprintf(buf, "%u", n); for (p = buf; *p != '\0'; p++) ret += (*p - '0'); return(ret); } /* * dbprog_discid * Compute a magic disc ID based on the number of tracks, * the length of each track, and a checksum of the string * that represents the offset of each track. * * Args: * s - Pointer to the curstat_t structure. * * Return: * The integer disc ID. */ static u_int dbprog_discid(void) { struct ioc_toc_header h; int rc; int i, ntr, t = 0, n = 0; rc = ioctl (fd, CDIOREADTOCHEADER, &h); if (rc < 0) return 0; ntr = h.ending_track - h.starting_track + 1; i = msf; msf = 1; rc = read_toc_entrys ((ntr + 1) * sizeof (struct cd_toc_entry)); msf = i; if (rc < 0) return 0; /* For backward compatibility this algorithm must not change */ for (i = 0; i < ntr; i++) { #define TC_MM(a) toc_buffer[a].addr.msf.minute #define TC_SS(a) toc_buffer[a].addr.msf.second n += dbprog_sum((TC_MM(i) * 60) + TC_SS(i)); t += ((TC_MM(i+1) * 60) + TC_SS(i+1)) - ((TC_MM(i) * 60) + TC_SS(i)); } return((n % 0xff) << 24 | t << 8 | ntr); } static int cdid(void) { u_int id; id = dbprog_discid(); if (id) { if (verbose) printf ("CDID="); printf ("%08x\n",id); } return id ? 0 : 1; } static int info(char *arg __unused) { struct ioc_toc_header h; int rc, i, n; rc = ioctl (fd, CDIOREADTOCHEADER, &h); if (rc >= 0) { if (verbose) printf ("Starting track = %d, ending track = %d, TOC size = %d bytes\n", h.starting_track, h.ending_track, h.len); else printf ("%d %d %d\n", h.starting_track, h.ending_track, h.len); } else { warn("getting toc header"); return (rc); } n = h.ending_track - h.starting_track + 1; rc = read_toc_entrys ((n + 1) * sizeof (struct cd_toc_entry)); if (rc < 0) return (rc); if (verbose) { printf ("track start duration block length type\n"); printf ("-------------------------------------------------\n"); } for (i = 0; i < n; i++) { printf ("%5d ", toc_buffer[i].track); prtrack (toc_buffer + i, 0); } printf ("%5d ", toc_buffer[n].track); prtrack (toc_buffer + n, 1); return (0); } static void lba2msf(unsigned long lba, u_char *m, u_char *s, u_char *f) { lba += 150; /* block start offset */ lba &= 0xffffff; /* negative lbas use only 24 bits */ *m = lba / (60 * 75); lba %= (60 * 75); *s = lba / 75; *f = lba % 75; } static unsigned int msf2lba(u_char m, u_char s, u_char f) { return (((m * 60) + s) * 75 + f) - 150; } static void prtrack(struct cd_toc_entry *e, int lastflag) { int block, next, len; u_char m, s, f; if (msf) { /* Print track start */ printf ("%2d:%02d.%02d ", e->addr.msf.minute, e->addr.msf.second, e->addr.msf.frame); block = msf2lba (e->addr.msf.minute, e->addr.msf.second, e->addr.msf.frame); } else { block = ntohl(e->addr.lba); lba2msf(block, &m, &s, &f); /* Print track start */ printf ("%2d:%02d.%02d ", m, s, f); } if (lastflag) { /* Last track -- print block */ printf (" - %6d - -\n", block); return; } if (msf) next = msf2lba (e[1].addr.msf.minute, e[1].addr.msf.second, e[1].addr.msf.frame); else next = ntohl(e[1].addr.lba); len = next - block; /* Take into account a start offset time. */ lba2msf (len - 150, &m, &s, &f); /* Print duration, block, length, type */ printf ("%2d:%02d.%02d %6d %6d %5s\n", m, s, f, block, len, (e->control & 4) ? "data" : "audio"); } static int play_track(int tstart, int istart, int tend, int iend) { struct ioc_play_track t; t.start_track = tstart; t.start_index = istart; t.end_track = tend; t.end_index = iend; return ioctl (fd, CDIOCPLAYTRACKS, &t); } static int play_blocks(int blk, int len) { struct ioc_play_blocks t; t.blk = blk; t.len = len; return ioctl (fd, CDIOCPLAYBLOCKS, &t); } static int setvol(int left, int right) { struct ioc_vol v; left = left < 0 ? 0 : left > 255 ? 255 : left; right = right < 0 ? 0 : right > 255 ? 255 : right; v.vol[0] = left; v.vol[1] = right; v.vol[2] = 0; v.vol[3] = 0; return ioctl (fd, CDIOCSETVOL, &v); } static int read_toc_entrys(int len) { struct ioc_read_toc_entry t; t.address_format = msf ? CD_MSF_FORMAT : CD_LBA_FORMAT; t.starting_track = 0; t.data_len = len; t.data = toc_buffer; return (ioctl (fd, CDIOREADTOCENTRYS, (char *) &t)); } static int play_msf(int start_m, int start_s, int start_f, int end_m, int end_s, int end_f) { struct ioc_play_msf a; a.start_m = start_m; a.start_s = start_s; a.start_f = start_f; a.end_m = end_m; a.end_s = end_s; a.end_f = end_f; return ioctl (fd, CDIOCPLAYMSF, (char *) &a); } static int status(int *trk, int *min, int *sec, int *frame) { struct ioc_read_subchannel s; struct cd_sub_channel_info data; u_char mm, ss, ff; bzero (&s, sizeof (s)); s.data = &data; s.data_len = sizeof (data); s.address_format = msf ? CD_MSF_FORMAT : CD_LBA_FORMAT; s.data_format = CD_CURRENT_POSITION; if (ioctl (fd, CDIOCREADSUBCHANNEL, (char *) &s) < 0) return -1; *trk = s.data->what.position.track_number; if (msf) { *min = s.data->what.position.reladdr.msf.minute; *sec = s.data->what.position.reladdr.msf.second; *frame = s.data->what.position.reladdr.msf.frame; } else { lba2msf(ntohl(s.data->what.position.reladdr.lba), &mm, &ss, &ff); *min = mm; *sec = ss; *frame = ff; } return s.data->header.audio_status; } static const char * cdcontrol_prompt(void) { return ("cdcontrol> "); } static char * input(int *cmd) { #define MAXLINE 80 static EditLine *el = NULL; static History *hist = NULL; HistEvent he; static char buf[MAXLINE]; int num = 0; int len; const char *bp = NULL; char *p; do { if (verbose) { if (!el) { el = el_init("cdcontrol", stdin, stdout, stderr); hist = history_init(); history(hist, &he, H_SETSIZE, 100); el_set(el, EL_HIST, history, hist); el_set(el, EL_EDITOR, "emacs"); el_set(el, EL_PROMPT, cdcontrol_prompt); el_set(el, EL_SIGNAL, 1); el_source(el, NULL); } if ((bp = el_gets(el, &num)) == NULL || num == 0) { *cmd = CMD_QUIT; fprintf (stderr, "\r\n"); return (0); } len = (num > MAXLINE) ? MAXLINE : num; memcpy(buf, bp, len); buf[len] = 0; history(hist, &he, H_ENTER, bp); #undef MAXLINE } else { if (! fgets (buf, sizeof (buf), stdin)) { *cmd = CMD_QUIT; fprintf (stderr, "\r\n"); return (0); } } p = parse (buf, cmd); } while (! p); return (p); } static char * parse(char *buf, int *cmd) { struct cmdtab *c; char *p; unsigned int len; for (p=buf; isspace (*p); p++) continue; if (isdigit (*p) || (p[0] == '#' && isdigit (p[1]))) { *cmd = CMD_PLAY; return (p); } else if (*p == '+') { *cmd = CMD_NEXT; return (p + 1); } else if (*p == '-') { *cmd = CMD_PREVIOUS; return (p + 1); } for (buf = p; *p && ! isspace (*p); p++) continue; len = p - buf; if (! len) return (0); if (*p) { /* It must be a spacing character! */ char *q; *p++ = 0; for (q=p; *q && *q != '\n' && *q != '\r'; q++) continue; *q = 0; } *cmd = -1; for (c=cmdtab; c->name; ++c) { /* Is it an exact match? */ if (! strcasecmp (buf, c->name)) { *cmd = c->command; break; } /* Try short hand forms then... */ if (len >= c->min && ! strncasecmp (buf, c->name, len)) { if (*cmd != -1 && *cmd != c->command) { warnx("ambiguous command"); return (0); } *cmd = c->command; } } if (*cmd == -1) { warnx("invalid command, enter ``help'' for commands"); return (0); } while (isspace (*p)) p++; return p; } static int open_cd(void) { char devbuf[MAXPATHLEN]; const char *dev; if (fd > -1) return (1); if (cdname) { if (*cdname == '/') { snprintf (devbuf, MAXPATHLEN, "%s", cdname); } else { snprintf (devbuf, MAXPATHLEN, "%s%s", _PATH_DEV, cdname); } fd = open (dev = devbuf, O_RDONLY); } else { fd = open(dev = "/dev/cdrom", O_RDONLY); if (fd < 0 && errno == ENOENT) fd = open(dev = "/dev/cd0", O_RDONLY); - if (fd < 0 && errno == ENOENT) - fd = open(dev = "/dev/acd0", O_RDONLY); } if (fd < 0) { if (errno == ENXIO) { /* ENXIO has an overloaded meaning here. * The original "Device not configured" should * be interpreted as "No disc in drive %s". */ warnx("no disc in drive %s", dev); return (0); } err(1, "%s", dev); } return (1); } Index: head/usr.sbin/pc-sysinstall/backend/functions-mountoptical.sh =================================================================== --- head/usr.sbin/pc-sysinstall/backend/functions-mountoptical.sh (revision 304813) +++ head/usr.sbin/pc-sysinstall/backend/functions-mountoptical.sh (revision 304814) @@ -1,152 +1,152 @@ #!/bin/sh #- # Copyright (c) 2010 iXsystems, Inc. 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 AUTHOR 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 AUTHOR 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. # # $FreeBSD$ # Functions which perform mounting / unmounting and switching of # optical / usb media . ${BACKEND}/functions.sh . ${BACKEND}/functions-parse.sh # Displays an optical failure message opt_fail() { # If we got here, we must not have a DVD/USB we can find :( get_value_from_cfg installInteractive if [ "${VAL}" = "yes" ] then # We are running interactive, and didn't find a DVD, prompt user again echo_log "DISK ERROR: Unable to find installation disk!" echo_log "Please insert the installation disk and press enter." read tmp else exit_err "ERROR: Unable to locate installation DVD/USB" fi }; # Performs the extraction of data to disk opt_mount() { FOUND="0" # Ensure we have a directory where its supposed to be if [ ! -d "${CDMNT}" ] then mkdir -p ${CDMNT} fi # Start by checking if we already have a cd mounted at CDMNT mount | grep -q "${CDMNT} " 2>/dev/null if [ $? -eq 0 ] then if [ -e "${CDMNT}/${INSFILE}" ] then echo "MOUNTED" >${TMPDIR}/cdmnt echo_log "FOUND DVD: MOUNTED" FOUND="1" return fi # failed to find optical disk opt_fail return fi # Setup our loop to search for installation media while z=1 do # Loop though and look for an installation disk - for i in `ls -1 /dev/acd* /dev/cd* /dev/scd* /dev/rscd* 2>/dev/null` + for i in `ls -1 /dev/cd* 2>/dev/null` do # Find the CD Device /sbin/mount_cd9660 $i ${CDMNT} # Check the package type to see if we have our install data if [ -e "${CDMNT}/${INSFILE}" ] then echo "${i}" >${TMPDIR}/cdmnt echo_log "FOUND DVD: ${i}" FOUND="1" break fi /sbin/umount ${CDMNT} >/dev/null 2>/dev/null done # If no DVD found, try USB if [ "$FOUND" != "1" ] then # Loop though and look for an installation disk for i in `ls -1 /dev/da* 2>/dev/null` do # Check if we can mount this device UFS /sbin/mount -r $i ${CDMNT} # Check the package type to see if we have our install data if [ -e "${CDMNT}/${INSFILE}" ] then echo "${i}" >${TMPDIR}/cdmnt echo_log "FOUND USB: ${i}" FOUND="1" break fi /sbin/umount ${CDMNT} >/dev/null 2>/dev/null # Also check if it is a FAT mount /sbin/mount -r -t msdosfs $i ${CDMNT} # Check the package type to see if we have our install data if [ -e "${CDMNT}/${INSFILE}" ] then echo "${i}" >${TMPDIR}/cdmnt echo_log "FOUND USB: ${i}" FOUND="1" break fi /sbin/umount ${CDMNT} >/dev/null 2>/dev/null done fi # End of USB Check if [ "$FOUND" = "1" ] then break fi # Failed to find a disk, take action now opt_fail done }; # Function to unmount optical media opt_umount() { /sbin/umount ${CDMNT} >/dev/null 2>/dev/null };