35 Commits
v1.5 ... main

Author SHA1 Message Date
Iustin Pop
a07846b2e3 Fix once more the release-tag :(
It's not `v-x.y`, but rather `vx.y`. Sigh.
2025-02-08 21:30:39 +01:00
Iustin Pop
a684fe5a15 Fix the release-tag makefile command
The tags are no longer named `mt-st-xxx`, but simply `v-xxx`. Also
remove the punctuation at the end of the message, since this is
similar to the commit subject.
2025-02-08 21:25:31 +01:00
Iustin Pop
70b24634cf Release version 1.8 2025-02-08 21:22:48 +01:00
Iustin Pop
a76e4ce544 Update changelog for the upcoming release 2025-02-08 21:19:20 +01:00
Iustin Pop
26392d9ae4 Commit vscode settings
These are trivial, but in the future more might be configured centrally.
2025-02-08 21:18:28 +01:00
Iustin Pop
1a074e2c65 Fix wildcard in data files to include all files in data/
This is not very nice, but calling all files `*.data` is superfluous
since they're already in a data file directory.
2025-01-07 22:02:26 +01:00
Iustin Pop
ba46d54458 Add a few more test for error paths
Since there's no virtual tape device, we can only test error paths,
sadly.
2025-01-07 21:53:22 +01:00
Iustin Pop
d4c8e67be0 Change coverage file to align better with vscode plugin
The coverage gutters plugin expects, by default, `lcov.info`, so let's
use that to require less customisation.
2025-01-07 21:20:15 +01:00
Iustin Pop
e14e9af952 Upgrade the codecov action to v5
And also add the token for uploading, as the last
commit ran into rate ACLs. Note entirely sure
about arguments, let's see.
2025-01-07 21:08:10 +01:00
Chris Dinneen
32fba27f78 Update auto completion to suggest stoptions where relevant 2025-01-07 17:04:45 +01:00
Chris Dinneen
aa6539b4b1 Fix Bash Completion: stshowopt isnt a valid choice 2025-01-07 17:04:45 +01:00
Kai Mäkisara
0c7307cc7a Add new density codes for IBM 3592 drives
Codes are added for the newer drives. The TS11xx names are added to
the desciptions of codes for non-encrypted tape.

Signed-off-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
2025-01-07 16:29:51 +01:00
Iustin Pop
72d53ae798 Upgrade the CodeQL action to v2
The v1 was deprecated 2 years ago…
2025-01-05 17:02:06 +01:00
Iustin Pop
b11887d9b4 No-op reformat of the workflow files
Not sure why, but my editor wants this formatting. I won't fight it…
2025-01-05 16:59:18 +01:00
Iustin Pop
459ab4775b Allow manual workflow runs
Turns out, both CI and CodeQL were disabled due to lack of activity,
so all the recent pushes were not tested. Allow manual runs for such
cases i the future.
2025-01-05 16:56:31 +01:00
Chris Dinneen
85738cedc1 Add 3480 too 2025-01-05 16:47:40 +01:00
Chris Dinneen
82d569b489 add 3490E to tape type for code 0x09 2025-01-05 16:47:40 +01:00
Chris Dinneen
547bc649a9 Add 9track Reels to tape struct densities table 2025-01-05 16:43:49 +01:00
Chris Dinneen
5ec6428297 Fix Typo comprssed -> compressed 2025-01-05 16:41:12 +01:00
Iustin Pop
7aa498640d Add source link in the actual comments 2025-01-05 16:39:16 +01:00
Chris Dinneen
ba594d1e78 Add abbreviation explainer for tape types in code comment 2025-01-05 16:39:16 +01:00
Iustin Pop
e6f79d85ec Re-format code via clang-format
Technically, via `make reindent` :)
2025-01-05 16:27:41 +01:00
Kai Mäkisara
42dd44bb90 stinit: Change stinit to return one if setting one or more options fails
Previously, stinit returned zero even if it fails to set the options.
This patch changes the return value to one if one or more of the options
can't be set for a device if the tape numbers are given on command line.
If no numbers are given, stinit returns zero (as before this patch).
After this change, scripts (udev rules) can more easily detect when
stinit fails.

Signed-off-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
2025-01-05 16:26:21 +01:00
Kai Mäkisara
ff108770be mt: stinit: Add support for setting and clearing MT_ST_NOWAIT_EOF
Add code to set/clear the MT_ST_NO_WAIT option bit for MTSETDRVBUFFER.
The string used in the user interface is 'weof-no-wait'.

Signed-off-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
2025-01-05 14:54:06 +01:00
Kai Mäkisara
9c8f170d4a mt: Complain about write protection if write protected
Print the message if status bit is one, not zero.

Signed-off-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
2024-12-14 18:28:43 +01:00
Chris Dinneen
72f9eda87d Backport Linux Kernel WEOFI ioctls 2023-11-04 10:06:45 +01:00
Chris Dinneen
eadc992f2a Fix #26; Add LTO9 Density Code 2023-10-31 17:57:47 +01:00
Iustin Pop
e8e6d543de Release version 1.7 2023-04-20 23:23:56 +02:00
Iustin Pop
34978b4019 Fix a 25-year old bug \o/
This is a trivial bug, but a bug nevertheless. It's present in the
first commit in this (synthetic) Git repository, and from my
investigations into very old versions - mt-st-0.5 from an old RedHat
version - it was already present in the `stinit.c` version from Apr
11, 1998, which makes it 25 years and 9 days old. This is a new record
for me, which I don't think I'll beat :)

The bug is trivial, in retrospect, and was found just by accident
because with the 1.6 release uploaded in Debian, the new test suite is
run on multiple architectures. While amd64/x86 doesn't trigger this
bug in neither '-O2' nor '-g' build, mips64el, arm64, and s390x do
show the bug in the optimised builds (and only in them) as follows:

amd64:

```
$ /sbin/stinit -v -v -v -p -f ./tests/data/bad-definition.data

Parsing modes for ('XYZ', 'UVW1', '').
Mode 1 definition:  blocksize=
Warning: errors in definition for ('XYZ', 'UVW1', ''):
 blocksize=

Definition parse completed. Errors found!
```

s390x:

```
$ ./stinit -p -v -v -v -f tests/data/bad-definition.data

Parsing modes for ('XYZ', 'UVW1', '').
Mode 1 definition:  blocksize=
Warning: errors in definition for ('XYZ', 'UVW1', ''):
 �H

Definition parse completed. Errors found!
```

And shelltest fails to parse that binary output, in 4/5 cases, which
by luck caused the builds to fail. From there it was a fun
investigation into trying to find why it behaves like that.

This bug is caught by the recently introduced MSAN build in the GitHub
CI, so will rely less on luck in the future.

I'm not 100% sure on the semantics of the fix, but it should only
affect this case (missing value to argument), so should be a well
localised fix.

Signed-off-by: Iustin Pop <iustin@k1024.org>
2023-04-20 23:18:23 +02:00
Iustin Pop
8056c1542a Fix CFLAGS for sanitizer
Oops, didn't fail as expected :)
2023-04-20 23:04:14 +02:00
Iustin Pop
c36a4a0fa5 Don't run undefined (UBSAN) on top of MSAN 2023-04-20 23:03:46 +02:00
Iustin Pop
f9c0570e34 Run tests under various sanitizers
This is in preparation for the next commit which will fix a very long
standing bug…
2023-04-20 23:01:20 +02:00
Iustin Pop
aec3bd67f6 CI workflow: install dependencies for the test jobs too
shelltestrunner was already installed for the coverage target, but not
for main test ones (for the same reason that release 1.5 was broken,
in the sense that it was not needed…).
2023-04-19 23:39:12 +02:00
Iustin Pop
52a6c218b9 Release bugfix version 1.6 😅 2023-04-19 23:33:02 +02:00
Iustin Pop
4a72962872 Finish the test migration to shelltest
The shelltest migration was done in 1.4, but not completed - the
distcheck was still doing hard-coded manual tests, and as such, the
"check" target from the dist archive was not working. Sigh.

Now 'distcheck' is using 'check', and the archive is complete.
2023-04-19 23:29:58 +02:00
15 changed files with 231 additions and 77 deletions

View File

@@ -11,7 +11,9 @@ on:
# Weekly run to account for
# changed dependencies.
schedule:
- cron: '17 04 * * 0'
- cron: "17 04 * * 0"
# Manual trigger
workflow_dispatch:
name: CI
jobs:
@@ -21,7 +23,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
compiler: ['gcc', 'clang']
compiler: ["gcc", "clang"]
fail-fast: false
env:
CC: ${{ matrix.compiler }}
@@ -33,6 +35,9 @@ jobs:
- name: Build the code
run: make
- name: Install dependencies
run: sudo apt-get install -yy shelltestrunner
- name: Test creating the release archive
run: make distcheck
@@ -56,9 +61,40 @@ jobs:
run: make check
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v5
with:
name: codecov-gcc
#fail_ci_if_error: true
fail_ci_if_error: true
verbose: true
gcov: true
token: ${{ secrets.CODECOV_TOKEN }}
sanitizers:
name: Test with clang sanitizers
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
compiler: ["clang"]
# These are the various sanitizers from https://github.com/google/sanitizers:
cflags:
- "-fsanitize=address -O1 -fno-omit-frame-pointer -g"
- "-fsanitize=memory -fsanitize-memory-track-origins -fPIE -pie -fno-omit-frame-pointer -g -O2"
- "-fsanitize=undefined"
fail-fast: false
env:
CC: ${{ matrix.compiler }}
CFLAGS: ${{ matrix.cflags }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Build the code
run: make
- name: Install dependencies
run: sudo apt-get install -yy shelltestrunner
- name: Run tests
run: make check

View File

@@ -7,7 +7,9 @@ on:
# The branches below must be a subset of the branches above
branches: [main]
schedule:
- cron: '0 5 * * 1'
- cron: "0 5 * * 1"
# Manual run:
workflow_dispatch:
jobs:
analyze:
@@ -19,44 +21,44 @@ jobs:
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['cpp']
language: ["cpp"]
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

2
.gitignore vendored
View File

@@ -14,4 +14,4 @@
/mt.gcno
/stinit.gcda
/stinit.gcno
/coverage.info
/lcov.info

4
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"spellright.language": ["en"],
"spellright.documentTypes": ["markdown", "latex", "plaintext"]
}

View File

@@ -1,5 +1,41 @@
# Changelog
## Changes in version 1.8 (Sat, 08 Feb 2025)
After almost two years, a number of minor fixes and improvements have accumulated:
- A number of density code updates: LTO-9, 9track Reels, IBM 3480 and 3490E
(from Chris Dinneen) and IBM 3592 (Kai Mäkisara)
- Fix write protect reporting (Kai Mäkisara)
- Implement support for the `MT_ST_NOWAIT_EOF` flag, via the new `weof-no-wait`
for stinit (Kai Mäkisara)
- While at it, correctly report errors if some options cannot be set, rather
than pretending all is good (also Kai Mäkisara)
- Improve the bash completion code to handle option completion better (Chris
Dinneen)
- Very minor build system improvements and coverage extension (Iustin Pop)
Thanks Kai and Chris for the many improvements!
## Changes in version 1.7 (Thu, 20 Apr 2023)
Fixes a single bug in stinit parsing of invalid definitions. This is a
trivial bug, and only affects config files manually installed by root,
so the impact should be minimal.
The bug also does not appear on amd64/x86, but (in Debian) was only
triggered (as undefined behaviour) on mips64el, arm64 and s390x,
likely due to different platform behaviour.
## Changes in version 1.6 (Wed, 19 Apr 2023)
This is bugfix release agains 1.5. In between 1.4 and 1.5, the "make
check" target was migrated to using
[shelltest](https://github.com/simonmichael/shelltestrunner), but the
`make dist` and `distcheck` targets were no, so the built archive was
actually not. This only fixes that and has no functional code changes
from 1.5.
## Changes in version 1.5 (Wed, 19 Apr 2023)
Trivial release:

View File

@@ -28,7 +28,10 @@ DISTFILES = \
.dir-locals.el \
.clang-format
VERSION=1.5
TESTFILES = $(wildcard tests/*.test)
TESTDATAFILES = $(wildcard tests/data/*)
VERSION=1.8
RELEASEDIR=mt-st-$(VERSION)
TARFILE=mt-st-$(VERSION).tar.gz
@@ -58,7 +61,10 @@ dist:
trap "rm -rf $$BASE" EXIT && \
DIST="$$BASE/$(RELEASEDIR)" && \
mkdir "$$DIST" && \
$(INSTALL) -m 0644 -p -t "$$DIST/" $(DISTFILES) && \
mkdir "$$DIST/tests" && mkdir "$$DIST/tests/data" && \
$(INSTALL) -m 0644 -p -t "$$DIST/" $(DISTFILES) && \
$(INSTALL) -m 0644 -p -t "$$DIST/tests" $(TESTFILES) && \
$(INSTALL) -m 0644 -p -t "$$DIST/tests/data" $(TESTDATAFILES) && \
tar czvf $(TARFILE) -C "$$BASE" \
--owner root --group root \
$(RELEASEDIR)
@@ -71,12 +77,7 @@ distcheck: dist
tar xvf $(TARFILE) -C "$$SRC" && \
cd "$$SRC/$(RELEASEDIR)" && \
make CFLAGS="-Wall -Wextra -Werror" && \
echo Checking version output && \
./mt --version && ./stinit --version && \
echo Checking parse status && \
./stinit -p -f stinit.def.examples && \
echo Checking complete stinit parsing && \
( ./stinit -v -v -p -f stinit.def.examples 2>&1 | grep -q 'Mode 1 definition: scsi2logical=1 can-bsr=1 auto-lock=0 two-fms=0 drive-buffering=1 buffer-writes read-ahead=1 async-writes=1 can-partitions=0 fast-eom=1 blocksize=0 sili=1 timeout=900 long-timeout=14400 density=0x44 compression=0' ) && \
make check && \
make dist && \
make install DESTDIR="$$DST" && \
numfiles=$$( \
@@ -93,12 +94,12 @@ check: $(PROGS)
coverage: clean
$(MAKE) CFLAGS=-coverage
$(MAKE) check
lcov --capture --directory . --no-external --output-file coverage.info
genhtml coverage.info --output-directory out
lcov --capture --directory . --no-external --output-file lcov.info
genhtml lcov.info --output-directory out
release-tag:
git tag -s -m 'Release version $(VERSION).' mt-st-$(VERSION)
git tag -s -m 'Release version $(VERSION)' v$(VERSION)
clean:
rm -f *~ \#*\# *.o *.gcno *.gcda coverage.info $(PROGS) version.h

View File

@@ -6,7 +6,8 @@ _mt () {
_init_completion || return
#possible commands
commands="weof wset eof fsf fsfm bsf bsfm fsr bsr fss bss rewind offline rewoffl eject retension eod seod seek tell status erase setblk lock unlock load compression setdensity drvbuffer stwrthreshold stoptions stsetoptions stclearoptions defblksize defdensity defdrvbuffer defcompression stsetcln sttimeout stlongtimeout densities setpartition mkpartition partseek asf stshowopt"
commands="weof wset eof fsf fsfm bsf bsfm fsr bsr fss bss rewind offline rewoffl eject retension eod seod seek tell status erase setblk lock unlock load compression setdensity drvbuffer stwrthreshold stoptions stsetoptions stclearoptions defblksize defdensity defdrvbuffer defcompression stsetcln sttimeout stlongtimeout densities setpartition mkpartition partseek asf stshowoptions"
stoptions="buffer-writes async-writes read-ahead debug two-fms fast-eod no-wait weof-no-wait auto-lock def-writes can-bsr no-blklimits can-partitions scsi2logical sili sysv"
COMPREPLY=()
@@ -22,8 +23,19 @@ _mt () {
COMPREPLY=($(compgen -W "$devs" -- "$cur"))
return
;;
stsetoptions)
# show list of stoptions
COMPREPLY=($(compgen -W "$stoptions" -- "$cur"))
return
;;
esac
# if "$prev" is a substring of "$stoptions" show more "$stoptions"
if [[ "$stoptions" == *"$prev"* ]]; then
COMPREPLY=($(compgen -W "$stoptions" -- "$cur"))
return
fi
if [[ $cur == -* ]]; then
COMPREPLY=($(compgen -W '-f -v' -- "$cur"))
return

2
mt.1
View File

@@ -187,6 +187,8 @@ write two filemarks when file closed
space directly to eod (and lose file number)
.IP no-wait
don't wait until rewind, etc. complete
.IP weof-no-wait
don't wait until writing filemarks completes
.IP auto-lock
automatically lock/unlock drive door
.IP def-writes

41
mt.c
View File

@@ -135,16 +135,25 @@ static struct densities {
char *name;
} density_tbl[] = {
/* clang-format off */
/* Information taken from https://www.t10.org/ftp/x3t9.2/document.93/93-013r0.pdf:
* NZRI: Non-Return to Zero, change on ones
* GCR: Group Code Recording
* PE: Phase Encoding
* IMFM: Inverted Modified Frequency Modulation
* MFM: Modified Frequency Modulation
* DDS: DAT Data Storage
* RLL: Run Length Limited
*/
{ 0x00, "default" },
{ 0x01, "NRZI (800 bpi)" },
{ 0x02, "PE (1600 bpi)" },
{ 0x03, "GCR (6250 bpi)" },
{ 0x01, "NRZI (800 bpi) 9 Track Reel" },
{ 0x02, "PE (1600 bpi) 9 Track Reel" },
{ 0x03, "GCR (6250 bpi) 9 Track Reel" },
{ 0x04, "QIC-11" },
{ 0x05, "QIC-45/60 (GCR, 8000 bpi)" },
{ 0x06, "PE (3200 bpi)" },
{ 0x06, "PE (3200 bpi) 9 Track Reel" },
{ 0x07, "IMFM (6400 bpi)" },
{ 0x08, "GCR (8000 bpi)" },
{ 0x09, "GCR (37871 bpi)" },
{ 0x09, "3480/3490E, GCR (37871 bpi)" },
{ 0x0a, "MFM (6667 bpi)" },
{ 0x0b, "PE (1600 bpi)" },
{ 0x0c, "GCR (12960 bpi)" },
@@ -196,20 +205,27 @@ static struct densities {
{ 0x4c, "T10000C" },
{ 0x4d, "T10000D" },
{ 0x51, "IBM 3592 J1A" },
{ 0x52, "IBM 3592 E05" },
{ 0x53, "IBM 3592 E06" },
{ 0x54, "IBM 3592 E07" },
{ 0x55, "IBM 3592 E08" },
{ 0x52, "IBM 3592 E05 (TS1120)" },
{ 0x53, "IBM 3592 E06 (TS1130)" },
{ 0x54, "IBM 3592 E07 (TS1140)" },
{ 0x55, "IBM 3592 E08 (TS1150)" },
{ 0x56, "IBM 3592 55F (TS1155)" },
{ 0x57, "IBM 3592 60F (TS1160)" },
{ 0x58, "LTO-5" },
{ 0x59, "IBM 3592 70F (TS1170)" },
{ 0x5a, "LTO-6" },
{ 0x5c, "LTO-7" },
{ 0x5d, "LTO-7-M8" },
{ 0x5e, "LTO-8" },
{ 0x60, "LTO-9" },
{ 0x71, "IBM 3592 J1A, encrypted" },
{ 0x72, "IBM 3592 E05, encrypted" },
{ 0x73, "IBM 3592 E06, encrypted" },
{ 0x74, "IBM 3592 E07, encrypted" },
{ 0x75, "IBM 3592 E08, encrypted" },
{ 0x76, "IBM 3592 55F, encrypted" },
{ 0x77, "IBM 3592 60F, encrypted" },
{ 0x79, "IBM 3592 70F, encrypted" },
{ 0x80, "DLT 15GB uncomp. or Ecrix" },
{ 0x81, "DLT 15GB compressed" },
{ 0x82, "DLT 20GB uncompressed" },
@@ -224,7 +240,7 @@ static struct densities {
{ 0x90, "SDLT110 uncompr/EXB-8205 compr" },
{ 0x91, "SDLT110 compressed" },
{ 0x92, "SDLT160 uncompressed" },
{ 0x93, "SDLT160 comprssed" }
{ 0x93, "SDLT160 compressed" }
/* clang-format on */
};
@@ -249,6 +265,7 @@ static struct booleans {
{ "can-partitions", MT_ST_CAN_PARTITIONS, "drive can handle partitioned tapes" },
{ "scsi2logical", MT_ST_SCSI2LOGICAL, "logical block addresses used with SCSI-2" },
{ "no-wait", MT_ST_NOWAIT, "immediate mode for rewind, etc." },
{ "weof-no-wait", MT_ST_NOWAIT_EOF, "immediate mode for writing filemarks" },
#ifdef MT_ST_SYSV
{ "sysv", MT_ST_SYSV, "enable the SystemV semantics" },
#endif
@@ -687,7 +704,7 @@ static int do_status(int mtfd,
#define TAPE_NR(minor) \
((((minor) & ~255) >> (ST_NBR_MODE_BITS + 1)) | \
((minor) & ((1 << ST_MODE_SHIFT) - 1)))
#define TAPE_MODE(minor) (((minor)&ST_MODE_MASK) >> ST_MODE_SHIFT)
#define TAPE_MODE(minor) (((minor) & ST_MODE_MASK) >> ST_MODE_SHIFT)
static const char *st_formats[] = { "", "r", "k", "s", "l", "t", "o", "u",
"m", "v", "p", "x", "a", "y", "q", "z" };
@@ -775,6 +792,6 @@ static void test_error(int mtfd, cmdef_tr *cmd)
if ((cmd->error_tests & ET_ONLINE) && !GMT_ONLINE(status.mt_gstat))
fprintf(stderr,
"mt: The device is offline (not powered on, no tape ?).\n");
if ((cmd->error_tests & ET_WPROT) && !GMT_WR_PROT(status.mt_gstat))
if ((cmd->error_tests & ET_WPROT) && GMT_WR_PROT(status.mt_gstat))
fprintf(stderr, "mt: The tape is write-protected.\n");
}

2
mtio.h
View File

@@ -64,6 +64,7 @@ struct mtop {
#define MTCOMPRESSION 32/* control compression with SCSI mode page 15 */
#define MTSETPART 33 /* Change the active tape partition */
#define MTMKPART 34 /* Format the tape with one or two partitions */
#define MTWEOFI 35 /* write an end-of-file record (mark) in immediate mode */
/* structure for MTIOCGET - mag tape get status command */
@@ -202,6 +203,7 @@ struct mtpos {
#define MT_ST_SYSV 0x1000
#define MT_ST_NOWAIT 0x2000
#define MT_ST_SILI 0x4000
#define MT_ST_NOWAIT_EOF 0x8000
/* The mode parameters to be controlled. Parameter chosen with bits 20-28 */
#define MT_ST_CLEAR_DEFAULT 0xfffff

View File

@@ -159,6 +159,10 @@ The cleaning request notifying parameter is set to
The immediate mode is used with commands like rewind if
.I value
is non-zero (i.e., the driver does not wait for the command to finish).
.IP weof-n[o-wait]
The immediate mode is used when writing filemarks if
.I value
is non-zero (i.e., the driver does not wait for the command to finish).
.IP mode=value
This keyword starts definition of tape mode
.I value.
@@ -259,10 +263,9 @@ The long timeout for the device is set to
seconds.
.SH RETURN VALUE
The program exits with value one if the command line is incorrect, the
definition file is not found, or option -p is given and parsing the
definition file fails. In all other cases the return value is
zero (i.e., failing of initialization is not currently signaled by
the return value).
definition file is not found, option -p is given and parsing the
definition file fails, or defining one or more of the options fails
when the tape number(s) are given on command line.
.SH RESTRICTIONS
With the exception of the -p option, the program can be used only by
the superuser. This is because the program uses ioctls allowed only

View File

@@ -58,6 +58,7 @@ typedef struct _devdef_tr {
int long_timeout;
int cleaning;
int nowait;
int weof_nowait;
int sili;
modepar_tr modedefs[4];
} devdef_tr;
@@ -139,9 +140,13 @@ static char *find_string(char *s, char *target, char *buf, int buflen)
cp++;
for (cp2 = cp; *cp2 != '"' && *cp2 != '\0'; cp2++)
;
} else
for (cp2 = cp + 1; isalnum(*cp2) || *cp2 == '-'; cp2++)
;
} else {
if (*cp == '\0')
return NULL;
else
for (cp2 = cp + 1; isalnum(*cp2) || *cp2 == '-'; cp2++)
;
}
if (*cp2 == '\0')
return NULL;
have_arg = TRUE;
@@ -255,6 +260,7 @@ find_pars(FILE *dbf, char *company, char *product, char *rev, devdef_tr *defs, i
defs->long_timeout = (-1);
defs->cleaning = (-1);
defs->nowait = (-1);
defs->weof_nowait = (-1);
defs->sili = (-1);
for (i = 0; i < NBR_MODES; i++) {
defs->modedefs[i].defined = FALSE;
@@ -364,6 +370,8 @@ find_pars(FILE *dbf, char *company, char *product, char *rev, devdef_tr *defs, i
defs->cleaning = num_arg(t);
if ((t = find_string(modebuf, "no-w", line, LINEMAX)) != NULL)
defs->nowait = num_arg(t);
if ((t = find_string(modebuf, "weof-n", line, LINEMAX)) != NULL)
defs->weof_nowait = num_arg(t);
if ((t = find_string(modebuf, "sili", line, LINEMAX)) != NULL)
defs->sili = num_arg(t);
@@ -673,11 +681,11 @@ static int find_devfiles(int tapeno, char **names)
static int set_defs(devdef_tr *defs, char **fnames)
{
int i, tape;
int i, tape, fails;
int clear_set[2];
struct mtop op;
for (i = 0; i < NBR_MODES; i++) {
for (i = fails = 0; i < NBR_MODES; i++) {
if (*fnames[i] == '\0' || !defs->modedefs[i].defined)
continue;
@@ -691,13 +699,17 @@ static int set_defs(devdef_tr *defs, char **fnames)
if (defs->do_rewind) {
op.mt_op = MTREW;
op.mt_count = 1;
ioctl(tape, MTIOCTOP, &op); /* Don't worry about result */
if (ioctl(tape, MTIOCTOP, &op) != 0) {
fails++;
fprintf(stderr, "Rewind of %s fails.\n", fnames[i]);
}
}
if (defs->drive_buffering >= 0) {
op.mt_op = MTSETDRVBUFFER;
op.mt_count = MT_ST_DEF_DRVBUFFER | defs->drive_buffering;
if (ioctl(tape, MTIOCTOP, &op) != 0) {
fails++;
fprintf(stderr, "Can't set drive buffering to %d.\n", defs->drive_buffering);
}
}
@@ -706,6 +718,7 @@ static int set_defs(devdef_tr *defs, char **fnames)
op.mt_op = MTSETDRVBUFFER;
op.mt_count = MT_ST_SET_TIMEOUT | defs->timeout;
if (ioctl(tape, MTIOCTOP, &op) != 0) {
fails++;
fprintf(stderr, "Can't set device timeout %d s.\n", defs->timeout);
}
}
@@ -714,6 +727,7 @@ static int set_defs(devdef_tr *defs, char **fnames)
op.mt_op = MTSETDRVBUFFER;
op.mt_count = MT_ST_SET_LONG_TIMEOUT | defs->long_timeout;
if (ioctl(tape, MTIOCTOP, &op) != 0) {
fails++;
fprintf(stderr, "Can't set device long timeout %d s.\n",
defs->long_timeout);
}
@@ -723,6 +737,7 @@ static int set_defs(devdef_tr *defs, char **fnames)
op.mt_op = MTSETDRVBUFFER;
op.mt_count = MT_ST_SET_CLN | defs->cleaning;
if (ioctl(tape, MTIOCTOP, &op) != 0) {
fails++;
fprintf(stderr, "Can't set cleaning request parameter to %x\n",
defs->cleaning);
}
@@ -734,6 +749,8 @@ static int set_defs(devdef_tr *defs, char **fnames)
clear_set[0] = clear_set[1] = 0;
if (defs->nowait >= 0)
clear_set[defs->nowait != 0] |= MT_ST_NOWAIT;
if (defs->weof_nowait >= 0)
clear_set[defs->weof_nowait != 0] |= MT_ST_NOWAIT_EOF;
if (defs->sili >= 0)
clear_set[defs->sili != 0] |= MT_ST_SILI;
if (defs->modedefs[i].buffer_writes >= 0)
@@ -764,6 +781,7 @@ static int set_defs(devdef_tr *defs, char **fnames)
if (clear_set[0] != 0) {
op.mt_count = MT_ST_CLEARBOOLEANS | clear_set[0];
if (ioctl(tape, MTIOCTOP, &op) != 0) {
fails++;
fprintf(stderr, "Can't clear the tape options (bits 0x%x, mode %d).\n",
clear_set[0], i);
}
@@ -771,6 +789,7 @@ static int set_defs(devdef_tr *defs, char **fnames)
if (clear_set[1] != 0) {
op.mt_count = MT_ST_SETBOOLEANS | clear_set[1];
if (ioctl(tape, MTIOCTOP, &op) != 0) {
fails++;
fprintf(stderr, "Can't set the tape options (bits 0x%x, mode %d).\n",
clear_set[1], i);
}
@@ -779,6 +798,7 @@ static int set_defs(devdef_tr *defs, char **fnames)
if (defs->modedefs[i].blocksize >= 0) {
op.mt_count = MT_ST_DEF_BLKSIZE | defs->modedefs[i].blocksize;
if (ioctl(tape, MTIOCTOP, &op) != 0) {
fails++;
fprintf(stderr, "Can't set blocksize %d for mode %d.\n",
defs->modedefs[i].blocksize, i);
}
@@ -786,6 +806,7 @@ static int set_defs(devdef_tr *defs, char **fnames)
if (defs->modedefs[i].density >= 0) {
op.mt_count = MT_ST_DEF_DENSITY | defs->modedefs[i].density;
if (ioctl(tape, MTIOCTOP, &op) != 0) {
fails++;
fprintf(stderr, "Can't set density %x for mode %d.\n",
defs->modedefs[i].density, i);
}
@@ -793,6 +814,7 @@ static int set_defs(devdef_tr *defs, char **fnames)
if (defs->modedefs[i].compression >= 0) {
op.mt_count = MT_ST_DEF_COMPRESSION | defs->modedefs[i].compression;
if (ioctl(tape, MTIOCTOP, &op) != 0) {
fails++;
fprintf(stderr, "Can't set compression %d for mode %d.\n",
defs->modedefs[i].compression, i);
}
@@ -800,7 +822,7 @@ static int set_defs(devdef_tr *defs, char **fnames)
close(tape);
}
return TRUE;
return (fails == 0);
}
@@ -866,7 +888,7 @@ static char usage(int retval)
int main(int argc, char **argv)
{
FILE *dbf = NULL;
int argn;
int argn, retval = 0;
int tapeno, parse_only = FALSE;
char *dbname = NULL;
char *convp;
@@ -923,8 +945,10 @@ int main(int argc, char **argv)
fprintf(stderr, "Can't find tape number for name '%s'.\n", argv[argn]);
continue;
}
if (!define_tape(tapeno, dbf, &defs, TRUE))
if (!define_tape(tapeno, dbf, &defs, TRUE)) {
fprintf(stderr, "Definition for '%s' failed.\n", argv[argn]);
retval = 1;
}
}
} else { /* Initialize all SCSI tapes */
for (tapeno = 0; tapeno < MAX_TAPES; tapeno++)
@@ -935,5 +959,5 @@ int main(int argc, char **argv)
}
}
return 0;
return retval;
}

View File

View File

@@ -2,3 +2,18 @@
./mt -f /dev/no-such-tape rewind
>>>2 /no-such-tape: No such file or directory/
>>>= 1
# Wrong file in show options
./mt -f tests/data/not-a-char-device stshowoptions
>>>2 /mt: not a character device/
>>>= 1
# /dev/null is not a tape device. Error message is ugly, though.
./mt -f /dev/null stshowoptions
>>>2 /Can't read the sysfs file '\/sys\/class\/scsi_tape/
>>>= 2
# /dev/null is not a tape device, so status fails.
./mt -f /dev/null status
>>>2 /Inappropriate ioctl for device/
>>>= 2

View File

@@ -39,11 +39,11 @@
# 1000 tapes.
./stinit -f stinit.def.examples 1000
>>>2 /Can't find any device files for tape 1000/
>>>= 0
>>>= 1
./stinit -f stinit.def.examples 1000
>>>2 /Definition for '1000' failed/
>>>= 0
>>>= 1
# Wrong tape number (non-numeric).
./stinit -f stinit.def.examples 1000a