aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-11 05:05:08 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-11 05:05:08 +0000
commit3ac4d4d4c5ea38257efbbe07440006d731b5820c (patch)
treef80bdc436a4e35ebc8c7e05323eab88254845f0c
parent27a3162cec63ff11ceabab0a4c78c526013de305 (diff)
parent67803003190004a55215c16fe9905dbaac1cfe74 (diff)
downloadmtools-3ac4d4d4c5ea38257efbbe07440006d731b5820c.tar.gz
Change-Id: I94ec7f2f2aaace6ee4e95215f319d67a5571cdbf
-rw-r--r--Android.bp22
-rw-r--r--METADATA10
-rw-r--r--Makefile.in123
-rw-r--r--NEWS104
-rw-r--r--buffer.c172
-rw-r--r--buffer.h8
-rw-r--r--byte_dword.h23
-rw-r--r--charsetConv.c70
-rw-r--r--codepage.h2
-rw-r--r--codepages.c8
-rw-r--r--config.c71
-rwxr-xr-xconfig.guess1615
-rw-r--r--config.h48
-rw-r--r--config.h.in34
-rwxr-xr-xconfig.sub2659
-rwxr-xr-xconfigure1089
-rw-r--r--configure.in237
-rw-r--r--copyfile.c18
-rw-r--r--debian/changelog130
-rw-r--r--debian/mtools.manpages1
-rw-r--r--device.c72
-rw-r--r--device.h101
-rw-r--r--devices.c233
-rw-r--r--devices.h20
-rw-r--r--dirCache.c21
-rw-r--r--dirCache.h4
-rw-r--r--directory.c52
-rw-r--r--direntry.c4
-rw-r--r--dos2unix.c86
-rw-r--r--fat.c280
-rw-r--r--fat_free.c5
-rw-r--r--file.c301
-rw-r--r--file_name.c8
-rw-r--r--file_name.h12
-rw-r--r--file_read.c2
-rw-r--r--filter.c175
-rw-r--r--floppyd.12
-rw-r--r--floppyd.c134
-rw-r--r--floppyd_installtest.12
-rw-r--r--floppyd_installtest.c55
-rw-r--r--floppyd_io.c277
-rw-r--r--floppyd_io.h12
-rw-r--r--force_io.c42
-rw-r--r--fs.h19
-rw-r--r--fsP.h92
-rw-r--r--hash.c9
-rw-r--r--htable.h2
-rw-r--r--init.c546
-rw-r--r--lba.c94
-rw-r--r--lba.h1
-rw-r--r--llong.c42
-rw-r--r--llong.h66
-rw-r--r--lockdev.c14
-rw-r--r--m4/ax_lib_socket_nsl.m440
-rw-r--r--mainloop.c79
-rw-r--r--mainloop.h10
-rw-r--r--match.c2
-rw-r--r--mattrib.12
-rw-r--r--mattrib.c36
-rw-r--r--mbadblocks.12
-rw-r--r--mbadblocks.c50
-rw-r--r--mcat.12
-rw-r--r--mcat.c108
-rw-r--r--mcd.12
-rw-r--r--mcd.c37
-rw-r--r--mclasserase.1112
-rw-r--r--mclasserase.c352
-rw-r--r--mcopy.12
-rw-r--r--mcopy.c98
-rw-r--r--mdel.12
-rw-r--r--mdel.c12
-rw-r--r--mdeltree.12
-rw-r--r--mdir.12
-rw-r--r--mdir.c77
-rw-r--r--mdoctorfat.c18
-rw-r--r--mdu.12
-rw-r--r--mdu.c2
-rw-r--r--mformat.12
-rw-r--r--mformat.c1503
-rw-r--r--minfo.12
-rw-r--r--minfo.c246
-rw-r--r--misc.c100
-rw-r--r--missFuncs.c8
-rw-r--r--mk_direntry.c44
-rw-r--r--mkmanifest.12
-rw-r--r--mkmanifest.c8
-rwxr-xr-xmkmanpages1
-rw-r--r--mlabel.12
-rw-r--r--mlabel.c26
-rw-r--r--mmd.12
-rw-r--r--mmd.c10
-rw-r--r--mmount.12
-rw-r--r--mmount.c10
-rw-r--r--mmove.12
-rw-r--r--mmove.c16
-rw-r--r--mpartition.12
-rw-r--r--mpartition.c374
-rw-r--r--mrd.12
-rw-r--r--mren.12
-rw-r--r--msdos.h9
-rw-r--r--mshortname.12
-rw-r--r--mshortname.c4
-rw-r--r--mshowfat.12
-rw-r--r--mshowfat.c2
-rw-r--r--mtools.123
-rw-r--r--mtools.532
-rw-r--r--mtools.c13
-rw-r--r--mtools.h144
-rw-r--r--mtools.info274
-rw-r--r--mtools.spec90
-rw-r--r--mtools.texi82
-rw-r--r--mtools.tmpl.123
-rw-r--r--mtools.tmpl.532
-rw-r--r--mtoolsDirentry.h25
-rw-r--r--mtoolstest.12
-rw-r--r--mtype.12
-rw-r--r--mzip.12
-rw-r--r--mzip.c176
-rw-r--r--nameclash.h8
-rw-r--r--offset.c90
-rw-r--r--offset.h2
-rw-r--r--old_dos.c2
-rw-r--r--old_dos.h43
-rw-r--r--open_image.c143
-rw-r--r--open_image.h17
-rw-r--r--partition.c281
-rw-r--r--partition.h28
-rw-r--r--patchlevel.c6
-rw-r--r--plain_io.c661
-rw-r--r--plain_io.h13
-rw-r--r--precmd.c4
-rw-r--r--privileges.c2
-rw-r--r--read_dword.h30
-rw-r--r--remap.c219
-rw-r--r--remap.h (renamed from subdir.c)33
-rw-r--r--scsi.c34
-rw-r--r--scsi.h6
-rw-r--r--scsi_io.c350
-rw-r--r--scsi_io.h5
-rw-r--r--signal.c2
-rw-r--r--stream.c65
-rw-r--r--stream.h66
-rw-r--r--streamcache.c12
-rw-r--r--strtonum.c47
-rw-r--r--swap.c95
-rw-r--r--swap.h2
-rw-r--r--sysincludes.h39
-rw-r--r--texinfo.tex454
-rw-r--r--tty.c22
-rw-r--r--unix2dos.c117
-rw-r--r--unixdir.c30
-rw-r--r--version.texi6
-rw-r--r--vfat.c91
-rw-r--r--vfat.h4
-rw-r--r--xdf_io.c321
-rw-r--r--xdf_io.h4
156 files changed, 9621 insertions, 7318 deletions
diff --git a/Android.bp b/Android.bp
index a934f94..4f9461f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -25,6 +25,7 @@ license {
name: "external_mtools_license",
visibility: [":__subpackages__"],
license_kinds: [
+ "SPDX-license-identifier-GPL-3.0",
"legacy_by_exception_only", // by exception only
],
license_text: [
@@ -40,29 +41,30 @@ cc_binary_host {
"codepages.c",
"config.c",
"copyfile.c",
+ "device.c",
"devices.c",
"dirCache.c",
"directory.c",
"direntry.c",
+ "dos2unix.c",
"expand.c",
"fat.c",
"fat_free.c",
"file.c",
"file_name.c",
- "filter.c",
"floppyd_io.c",
"force_io.c",
"hash.c",
"init.c",
+ "lba.c",
"llong.c",
"lockdev.c",
- "match.c",
"mainloop.c",
+ "match.c",
"mattrib.c",
"mbadblocks.c",
"mcat.c",
"mcd.c",
- "mclasserase.c",
"mcopy.c",
"mdel.c",
"mdir.c",
@@ -80,24 +82,32 @@ cc_binary_host {
"mpartition.c",
"mshortname.c",
"mshowfat.c",
- "mzip.c",
"mtools.c",
+ "mzip.c",
+ "offset.c",
"old_dos.c",
+ "open_image.c",
+ "partition.c",
"patchlevel.c",
"plain_io.c",
"precmd.c",
"privileges.c",
+ "remap.c",
"scsi.c",
+ "scsi_io.c",
"signal.c",
"stream.c",
"streamcache.c",
"strtonum.c",
- "subdir.c",
- "unixdir.c",
+ "swap.c",
"tty.c",
+ "unix2dos.c",
+ "unixdir.c",
"vfat.c",
"xdf_io.c",
],
+ // Needs C11 language feature.
+ c_std: "experimental",
cflags: [
"-DSYSCONFDIR=\"/etc\"",
"-Wno-missing-field-initializers",
diff --git a/METADATA b/METADATA
index 89ba8a0..57cef2b 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,6 @@
+# *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE
+# CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
+# DEPENDING ON IT IN YOUR PROJECT. ***
name: "mtools"
description:
"Mtools is a collection of utilities to access MS-DOS disks from GNU and "
@@ -10,9 +13,10 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://ftp.gnu.org/gnu/mtools/mtools-4.0.26.tar.lz"
+ value: "https://ftp.gnu.org/gnu/mtools/mtools-4.0.37.tar.lz"
}
- version: "4.0.26"
- last_upgrade_date { year: 2021 month: 2 day: 3 }
+ version: "4.0.37"
+ last_upgrade_date { year: 2022 month: 1 day: 9 }
+ license_note: "contains GFDL documentation"
license_type: BY_EXCEPTION_ONLY
}
diff --git a/Makefile.in b/Makefile.in
index 616d59f..741ec09 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -72,72 +72,61 @@ INSTALL_INFO = @INSTALL_INFO@
.SUFFIXES: .o .c
.SUFFIXES: .o .c
-MAN1 = floppyd.1 floppyd_installtest.1 mattrib.1 mbadblocks.1 mcat.1 mcd.1 \
-mclasserase.1 mcopy.1 mdel.1 mdeltree.1 mdir.1 mdu.1 mformat.1 minfo.1 \
-mkmanifest.1 mlabel.1 mmd.1 mmount.1 mmove.1 mpartition.1 \
-mrd.1 mren.1 mshortname.1 mshowfat.1 mtoolstest.1 mtools.1 mtype.1 mzip.1
-MAN1EXT = 1
+MAN1 = floppyd.1 floppyd_installtest.1 mattrib.1 mbadblocks.1 mcat.1 \
+mcd.1 mcopy.1 mdel.1 mdeltree.1 mdir.1 mdu.1 mformat.1 \
+minfo.1 mkmanifest.1 mlabel.1 mmd.1 mmount.1 mmove.1 mpartition.1 \
+mrd.1 mren.1 mshortname.1 mshowfat.1 mtoolstest.1 mtools.1 mtype.1 \
+mzip.1
+
+MAN1EXT = 1
MAN1DIR = $(DESTDIR)$(mandir)/man${MAN1EXT}
MAN5 = mtools.5
MAN5EXT = 5
MAN5DIR = $(DESTDIR)$(mandir)/man${MAN5EXT}
-# all files in this directory included in the distribution
-DIST = \
-COPYING Changelog INSTALL Makefile Makefile.in README Release.notes \
-buffer.c buffer.h charsetConv.c codepage.h codepages.c config.c \
-config.guess config.h.in config.log config.sub configure configure.in \
-copyfile.c devices.c devices.h dirCache.c dirCache.h directory.c direntry.c \
-expand.c fat.c \
-fat_free.c file.c file.h file_name.h file_name.c files filter.c floppyd.1 \
-floppyd.c floppyd_io.c floppyd_io.h force_io.c fs.h fsP.h \
-getopt.h hash.c htable.h init.c llong.c mainloop.c match.c mattrib.1 \
-mattrib.c mbadblocks.1 mbadblocks.c mcat.1 mcat.c mcd.1 mcd.c mclasserase.c \
-mcopy.1 \
-mcopy.c mdel.1 mdel.c mdeltree.1 mdir.1 mdir.c mdu.c mdu.1 mformat.1 \
-mformat.c minfo.c \
-misc.c tty.c scsi.c missFuncs.c mk_direntry.c mkmanifest.1 mkmanifest.c \
-mlabel.1 mlabel.c mmd.1 mmd.c mmount.1 mmount.c mmove.1 mmove.c \
-mpartition.1 mpartition.c mrd.1 \
-mren.1 msdos.h mshortname.1 mshowfat.1 mtoolstest.1 mtools.1 mtools.5 mtools.c \
-mtools.conf mtools.h mtype.1 nameclash.h patchlevel.c \
-plain_io.c plain_io.h precmd.c privileges.c scripts signal.c stream.c stream.h \
-streamcache.c streamcache.h subdir.c strtonum.c sysincludes.h unixdir.c todo \
-vfat.c vfat.h xdf_io.c xdf_io.h
-
-OBJS1 = buffer.o charsetConv.o codepages.o config.o copyfile.o \
-devices.o dirCache.o directory.o direntry.o expand.o fat.o fat_free.o file.o \
-file_name.o filter.o floppyd_io.o force_io.o hash.o init.o llong.o lockdev.o \
-match.o mainloop.o mattrib.o mbadblocks.o mcat.o mcd.o mclasserase.o mcopy.o \
-mdel.o mdir.o mdoctorfat.o mdu.o \
-mformat.o minfo.o misc.o missFuncs.o mk_direntry.o mlabel.o mmd.o mmount.o \
-mmove.o mpartition.o mshortname.o mshowfat.o mzip.o mtools.o old_dos.o \
-patchlevel.o plain_io.o precmd.o privileges.o scsi.o signal.o stream.o \
-streamcache.o subdir.o unixdir.o tty.o vfat.o xdf_io.o strtonum.o
-
-OBJS2 = missFuncs.o mkmanifest.o misc.o patchlevel.o
-
-OBJS3 = floppyd.o llong.o lockdev.o
-
-OBJS4 = floppyd_installtest.o misc.o expand.o privileges.o strtonum.o
-
-SRCS = buffer.c codepages.c config.c copyfile.c devices.c \
-dirCache.c directory.c direntry.c expand.c fat.c fat_free.c file.c file_name.c \
-file_read.c filter.c floppyd_io.c force_io.c hash.c init.c lockdev.c match.c \
-mainloop.c mattrib.c mbadblocks.c mcat.c mcd.c mclasserase.c mcopy.c mdel.c \
-mdir.c mdu.c mdoctorfat.c mformat.c minfo.c misc.c \
-missFuncs.c mk_direntry.c mlabel.c mmd.c mmount.c mmove.c mpartition.c \
-mshortname.c mshowfat.c mzip.c mtools.c old_dos.c plain_io.c precmd.c \
-privileges.c \
-scsi.c signal.c stream.c streamcache.c subdir.c unixdir.c tty.o vfat.c \
-xdf_io.c mkmanifest.c
-
+# objects for building mtools
+OBJS_MTOOLS = buffer.o charsetConv.o codepages.o config.o copyfile.o \
+device.o devices.o dirCache.o directory.o direntry.o dos2unix.o \
+expand.o fat.o fat_free.o file.o file_name.o force_io.o hash.o init.o \
+lba.o llong.o lockdev.o match.o mainloop.o mattrib.o mbadblocks.o \
+mcat.o mcd.o mcopy.o mdel.o mdir.o mdoctorfat.o mdu.o \
+mformat.o minfo.o misc.o missFuncs.o mk_direntry.o mlabel.o mmd.o \
+mmount.o mmove.o mpartition.o mshortname.o mshowfat.o mzip.o mtools.o \
+offset.o old_dos.o open_image.o patchlevel.o partition.o plain_io.o \
+precmd.o privileges.o remap.o scsi_io.o scsi.o signal.o stream.o \
+streamcache.o swap.o unix2dos.o unixdir.o tty.o vfat.o \
+strtonum.o @FLOPPYD_IO_OBJ@ @XDF_IO_OBJ@
+
+# objects for building mkmanifest
+OBJS_MKMANIFEST = missFuncs.o mkmanifest.o misc.o patchlevel.o
+
+# objects for building floppyd
+OBJS_FLOPPYD = floppyd.o llong.o lockdev.o
+
+# objects for building floppyd_installtest
+OBJS_FLOPPYD_INSTALLTEST = floppyd_installtest.o misc.o expand.o \
+privileges.o strtonum.o
+
+SRCS = buffer.c codepages.c config.c copyfile.c device.c devices.c \
+dirCache.c directory.c direntry.c dos2unix.c expand.c fat.c \
+fat_free.c file.c file_name.c file_read.c force_io.c hash.c init.c \
+lba.c lockdev.c match.c mainloop.c mattrib.c mbadblocks.c mcat.c \
+mcd.c mcopy.c mdel.c mdir.c mdu.c mdoctorfat.c \
+mformat.c minfo.c misc.c missFuncs.c mk_direntry.c mlabel.c mmd.c \
+mmount.c mmove.c mpartition.c mshortname.c mshowfat.c mzip.c mtools.c \
+offset.c old_dos.c open_image.c partition.c plain_io.c precmd.c \
+privileges.c remap.c scsi_io.c scsi.c signal.c stream.c streamcache.c \
+swap.c unix2dos.s unixdir.c tty.c vfat.c mkmanifest.c \
+@FLOPPYD_IO_SRC@ @XDF_IO_SRC@
+
+SRCS-@USE_FLOPPYD@ += floppyd_io.c
+SRCS-@USE_XDF@ += xdf_io.c
SCRIPTS = mcheck mxtar uz tgz mcomp amuFormat.sh
-LINKS=mattrib mcat mcd mclasserase mcopy mdel mdeltree mdir mdu mformat minfo \
-mlabel mmd mmount mmove mpartition mrd mren mtype mtoolstest mshortname \
-mshowfat mbadblocks mzip
+LINKS=mattrib mcat mcd mcopy mdel mdeltree mdir mdu \
+mformat minfo mlabel mmd mmount mmove mpartition mrd mren mtype \
+mtoolstest mshortname mshowfat mbadblocks mzip
X_CFLAGS = @X_CFLAGS@
X_LIBS = @X_LIBS@
@@ -147,7 +136,7 @@ CFLAGS = $(CPPFLAGS) $(DEFS) $(MYCFLAGS) -fno-strict-aliasing -I. @extraincluded
CXXFLAGS = $(CPPFLAGS) $(DEFS) $(MYCXXFLAGS) -I. @extraincludedir@ -I@srcdir@ $(USERCFLAGS)
LINK = $(CC) $(LDFLAGS) $(USERLDFLAGS) @extralibdir@
ALLLIBS = $(USERLDLIBS) $(MACHDEPLIBS) $(SHLIB) $(LIBS)
-X_LDFLAGS = $(X_EXTRA_LIBS) $(X_LIBS) -lXau -lX11 $(LIBS)
+X_LDFLAGS = $(X_EXTRA_LIBS) $(X_LIBS) @FLOPPYD_LIBS@ $(LIBS)
X_CCFLAGS = $(X_CFLAGS) $(CFLAGS)
all: mtools $(LINKS) mkmanifest @FLOPPYD@ mtools.1 mtools.5
@@ -158,19 +147,19 @@ all: mtools $(LINKS) mkmanifest @FLOPPYD@ mtools.1 mtools.5
#%.o: %.cpp
# $(CXX) $(CXXFLAGS) -c $<
-mtools: $(OBJS1)
- $(LINK) $(OBJS1) -o $@ $(ALLLIBS)
+mtools: $(OBJS_MTOOLS)
+ $(LINK) $(OBJS_MTOOLS) -o $@ $(ALLLIBS)
-mkmanifest: $(OBJS2)
- $(LINK) $(OBJS2) -o $@ $(ALLLIBS)
+mkmanifest: $(OBJS_MKMANIFEST)
+ $(LINK) $(OBJS_MKMANIFEST) -o $@ $(ALLLIBS)
floppyd.o: floppyd.c
$(CC) $(X_CCFLAGS) -c $?
-floppyd: $(OBJS3)
- $(LINK) $(OBJS3) -o $@ $(X_LDFLAGS)
-floppyd_installtest: $(OBJS4)
- $(LINK) $(OBJS4) -o $@ $(ALLLIBS)
+floppyd: $(OBJS_FLOPPYD)
+ $(LINK) $(OBJS_FLOPPYD) -o $@ $(X_LDFLAGS)
+floppyd_installtest: $(OBJS_FLOPPYD_INSTALLTEST)
+ $(LINK) $(OBJS_FLOPPYD_INSTALLTEST) -o $@ $(ALLLIBS)
$(LINKS): mtools
diff --git a/NEWS b/NEWS
index 02f8b5c..af046f5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,107 @@
+v4_0_37
+ - Removed mclasserase commands, which doesn't fit the coding
+ structure of the rest of mtools
+ - Add support to -i option to mcd
+ - Document -i in mtools.1
+ - Fix a missing commad error in floppyd_io.c
+
+v4_0_36
+ - Fix error status of recursive listing of empty root directory
+ - If recursive listing, also show matched files at level one
+ - Use "seekless" reads & write internally, where possible
+ - Text mode conversion refactoring
+ - Misc refactoring
+
+v4_0_35
+ - Fix cluster padding at end of file in batch mode, and add
+ comments about what happens here
+
+v4_0_34
+ - Fix mcopy -s issue
+
+v4_0_33
+ - Fix support for partitions (broken in 4.0.30)
+ - Portability fixes for Solaris 10 and 11
+ - General simplification of configure script, and largefile handling
+ - Tested and fixed for platforms *without* largefile support
+ - In cases where lseek works with 32-bit offsets, prefer
+ lseek64 over llseek
+ - Fixed floppy sector size handling on platforms that are not
+ Linux
+ - Added support for image files on command line to mcat
+
+v4_0_32
+ - Simplify algorithm that choses filesystem parameters for
+ format, and align it more closely with what Win7 does
+ - Fix mformatting XDF when XDF not explicitly specified on
+ mformat command line
+ - easier way to enter sizes on mformat command line (mformat -C -T
+ 1440K)
+ - For small sizes, mformat assumes floppy geometries (heads 1 or 2,
+ tracks 40 or 80)
+ - Handle attempts to mformat too small filesystems more gracefully
+ - Enable minfo to print out additional mformat command line
+ parameters, if the present filesystem uses non-default
+ values for these
+ - minfo no longer prints bigsect if smallsect is set
+ - for remap filter, error when trying to write non-zero data
+ to unmapped sectors
+ - Fix misc compilation warnings occuring when disabling
+ certain features (largefiles, raw-term)
+
+v4_0_31
+ - Move Linux-specific block device sizing code into
+ linux-specific section of devices.c
+ - Error messages for all failure cases on fs_init failure
+ - Fix compilation without XDF support (OpenImage signature)
+ - Fix polarity of format_xdf command-line parameter of mformat
+ - In XDF_IO retry enough times to actually succeed, even if
+ FDC was in a bad state before
+ - Remove useless buffer flushing triggered when giving up a
+ reference to a stream node that is still referenced
+ elsewhere.
+ - Clearer error message if neither size nor geometry of drive
+ to be mformatted is known
+ - In mformat, make Fs dynamically allocated rather than
+ on-stack, so as to be able to use utilities supplied by
+ stream.c
+ - Remove duplicate writing of backup boot sector
+ - Allow to infer geometry if only size is specified
+ - Protect against attempt to create zero-sized buffer
+ - Code simplification in mattrib
+ - Remove dead code in mpartition
+
+v4_0_30
+ - Fixed XDF floppy disk access
+ - Fixed faulty behavior at end of image in mcat
+ - Device/Image size handling refactoring
+ - allow remap to write to zero-backed sectors (may happen if
+ buffer is flushed, and is not an error in that case)
+ - Raise an error when trying to mcopy multiple source files
+ over a single destination file (rather than directory)
+ - fix handling of "hidden" sectors (is a 2 byte quantity on
+ small disks, not 4 byte as previously assumed)
+ - Modernize partition support. Tuned consistency check to
+ actually check about important issues (such as overlapping
+ partitions) rather than stuff nobody else cares about
+ (alignment on entire cylinder boundaries)
+ - Move various "filter" options (partition, offset, swap,
+ scsi) into separate classes, rather than leaving almost
+ everything in plain_io
+ - Simplify and centralize geometry handling and LBA code
+ - Fix some more more compiler warnings
+v4_0_29
+ - Fix bug in cluster preallocation, which was accidentally introduced
+ by compiler warning "fixes" from v4_0_28
+v4_0_28
+ - Support remapping of data (for not-quite linear floppy image files)
+ - Re-open floppy devices read-write if geometry parameters need to
+ be changed
+ - relax consistency checks in mpartition (partitions created
+ by current fdisk would almost never pass these checks)
+ - Fix some compiler warnings
+v4_0_27
+ - Fix type error in calls to iconv functions
v4_0_26
- Fix compilation on Macintosh
- Ignore image file locking errors if we are performing a
diff --git a/buffer.c b/buffer.c
index e129ac4..9b40727 100644
--- a/buffer.c
+++ b/buffer.c
@@ -23,11 +23,8 @@
#include "buffer.h"
typedef struct Buffer_t {
- Class_t *Class;
- int refs;
- Stream_t *Next;
- Stream_t *Buffer;
-
+ struct Stream_t head;
+
size_t size; /* size of read/write buffer */
int dirty; /* is the buffer dirty? */
@@ -38,11 +35,28 @@ typedef struct Buffer_t {
int ever_dirty; /* was the buffer ever dirty? */
size_t dirty_pos;
size_t dirty_end;
- mt_off_t current; /* first sector in buffer */
- size_t cur_size; /* the current size */
+ mt_off_t current; /* first sector in buffer */
+ size_t cur_size; /* the current size */
char *buf; /* disk read/write buffer */
} Buffer_t;
+/* Convert position relative to buffer to absolute position */
+static mt_off_t abs_pos(Buffer_t *Buffer, size_t rel) {
+ return Buffer->current + (mt_off_t) rel;
+}
+
+/* End of currently valid buffer */
+static mt_off_t cur_end(Buffer_t *Buffer) {
+ return abs_pos(Buffer, Buffer->cur_size);
+}
+
+/* distance from absolute position until next full cylinder. If position already
+ * *is* on a full cylinder boundary, return size of full cylinder */
+static size_t pos_to_next_full_cyl(Buffer_t *Buffer, mt_off_t pos) {
+ return Buffer->cylinderSize -
+ (size_t) (pos % (mt_off_t) Buffer->cylinderSize);
+}
+
/*
* Flush a dirty buffer to disk. Resets Buffer->dirty to zero.
* All errors are fatal.
@@ -50,14 +64,14 @@ typedef struct Buffer_t {
static int _buf_flush(Buffer_t *Buffer)
{
- int ret;
+ ssize_t ret;
- if (!Buffer->Next || !Buffer->dirty)
+#ifdef HAVE_ASSERT_H
+ assert(Buffer->head.Next != NULL);
+#endif
+
+ if (!Buffer->dirty)
return 0;
- if(Buffer->current < 0L) {
- fprintf(stderr,"Should not happen\n");
- return -1;
- }
#ifdef DEBUG
fprintf(stderr, "write %08x -- %02x %08x %08x\n",
Buffer,
@@ -66,15 +80,17 @@ static int _buf_flush(Buffer_t *Buffer)
Buffer->dirty_end - Buffer->dirty_pos);
#endif
- ret = force_write(Buffer->Next,
- Buffer->buf + Buffer->dirty_pos,
- Buffer->current + Buffer->dirty_pos,
- Buffer->dirty_end - Buffer->dirty_pos);
- if(ret != (signed int) (Buffer->dirty_end - Buffer->dirty_pos)) {
- if(ret < 0)
- perror("buffer_flush: write");
- else
- fprintf(stderr,"buffer_flush: short write\n");
+ ret = force_pwrite(Buffer->head.Next,
+ Buffer->buf + Buffer->dirty_pos,
+ Buffer->current + (mt_off_t) Buffer->dirty_pos,
+ Buffer->dirty_end - Buffer->dirty_pos);
+ if(ret < 0) {
+ perror("buffer_flush: write");
+ return -1;
+ }
+
+ if((size_t) ret != Buffer->dirty_end - Buffer->dirty_pos) {
+ fprintf(stderr,"buffer_flush: short write\n");
return -1;
}
Buffer->dirty = 0;
@@ -91,13 +107,13 @@ static int invalidate_buffer(Buffer_t *Buffer, mt_off_t start)
/* start reading at the beginning of start's sector
* don't start reading too early, or we might not even reach
* start */
- Buffer->current = ROUND_DOWN(start, Buffer->sectorSize);
+ Buffer->current = ROUND_DOWN(start, (mt_off_t) Buffer->sectorSize);
Buffer->cur_size = 0;
return 0;
}
#undef OFFSET
-#define OFFSET (start - This->current)
+#define OFFSET ((size_t)(start - This->current))
typedef enum position_t {
OUTSIDE,
@@ -108,11 +124,10 @@ typedef enum position_t {
static position_t isInBuffer(Buffer_t *This, mt_off_t start, size_t *len)
{
- if(start >= This->current &&
- start < This->current + (mt_off_t) This->cur_size) {
+ if(start >= This->current && start < cur_end(This)) {
maximize(*len, This->cur_size - OFFSET);
return INSIDE;
- } else if(start == This->current + (mt_off_t) This->cur_size &&
+ } else if(start == cur_end(This) &&
This->cur_size < This->size &&
*len >= This->sectorSize) {
/* append to the buffer for this, three conditions have to
@@ -129,39 +144,39 @@ static position_t isInBuffer(Buffer_t *This, mt_off_t start, size_t *len)
if(invalidate_buffer(This, start) < 0)
return ERROR;
maximize(*len, This->cylinderSize - OFFSET);
- maximize(*len, This->cylinderSize - This->current % This->cylinderSize);
+ maximize(*len, pos_to_next_full_cyl(This, This->current));
return OUTSIDE;
}
}
-static int buf_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+static ssize_t buf_pread(Stream_t *Stream, char *buf,
+ mt_off_t start, size_t len)
{
size_t length;
- mt_off_t offset;
+ size_t offset;
char *disk_ptr;
- int ret;
- DeclareThis(Buffer_t);
+ ssize_t ret;
+ DeclareThis(Buffer_t);
if(!len)
- return 0;
+ return 0;
/*fprintf(stderr, "buf read %x %x %x\n", Stream, start, len);*/
switch(isInBuffer(This, start, &len)) {
case OUTSIDE:
case APPEND:
/* always load until the end of the cylinder */
- length = This->cylinderSize -
- (This->current + This->cur_size) % This->cylinderSize;
+ length = pos_to_next_full_cyl(This, cur_end(This));
maximize(length, This->size - This->cur_size);
/* read it! */
- ret=READS(This->Next,
- This->buf + This->cur_size,
- This->current + This->cur_size,
- length);
+ ret=PREADS(This->head.Next,
+ This->buf + This->cur_size,
+ This->current + (mt_off_t) This->cur_size,
+ length);
if ( ret < 0 )
return ret;
- This->cur_size += ret;
+ This->cur_size += (size_t) ret;
if (This->current+(mt_off_t)This->cur_size < start) {
fprintf(stderr, "Short buffer fill\n");
exit(1);
@@ -178,13 +193,14 @@ static int buf_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
disk_ptr = This->buf + offset;
maximize(len, This->cur_size - offset);
memcpy(buf, disk_ptr, len);
- return len;
+ return (ssize_t) len;
}
-static int buf_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+static ssize_t buf_pwrite(Stream_t *Stream, char *buf,
+ mt_off_t start, size_t len)
{
char *disk_ptr;
- DeclareThis(Buffer_t);
+ DeclareThis(Buffer_t);
size_t offset=0;
if(!len)
@@ -206,27 +222,30 @@ static int buf_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
#ifdef DEBUG
fprintf(stderr, "outside\n");
#endif
- if(start % This->cylinderSize ||
+ if(start % (mt_off_t) This->cylinderSize ||
len < This->sectorSize) {
size_t readSize;
- int ret;
+ ssize_t ret;
+ size_t bytes_read;
readSize = This->cylinderSize -
- This->current % This->cylinderSize;
+ (size_t)(This->current % (mt_off_t) This->cylinderSize);
- ret=READS(This->Next, This->buf, This->current, readSize);
+ ret=PREADS(This->head.Next, This->buf,
+ (mt_off_t)This->current, readSize);
/* read it! */
if ( ret < 0 )
return ret;
- if(ret % This->sectorSize) {
- fprintf(stderr, "Weird: read size (%d) not a multiple of sector size (%d)\n", ret, (int) This->sectorSize);
- ret -= ret % This->sectorSize;
- if(ret == 0) {
+ bytes_read = (size_t) ret;
+ if(bytes_read % This->sectorSize) {
+ fprintf(stderr, "Weird: read size (%zd) not a multiple of sector size (%d)\n", bytes_read, (int) This->sectorSize);
+ bytes_read -= bytes_read % This->sectorSize;
+ if(bytes_read == 0) {
fprintf(stderr, "Nothing left\n");
exit(1);
}
}
- This->cur_size = ret;
+ This->cur_size = bytes_read;
/* for dosemu. Autoextend size */
if(!This->cur_size) {
memset(This->buf,0,readSize);
@@ -244,9 +263,8 @@ static int buf_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
offset = OFFSET;
maximize(len, This->size - offset);
This->cur_size += len;
- if(This->Next->Class->pre_allocate)
- PRE_ALLOCATE(This->Next,
- This->current + This->cur_size);
+ if(This->head.Next->Class->pre_allocate)
+ PRE_ALLOCATE(This->head.Next, cur_end(This));
break;
case INSIDE:
/* nothing to do */
@@ -278,7 +296,7 @@ static int buf_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
This->dirty_pos = ROUND_DOWN(offset, This->sectorSize);
if(!This->dirty || offset + len > This->dirty_end)
This->dirty_end = ROUND_UP(offset + len, This->sectorSize);
-
+
if(This->dirty_end > This->cur_size) {
fprintf(stderr,
"Internal error, dirty end too big dirty_end=%x cur_size=%x len=%x offset=%d sectorSize=%x\n",
@@ -296,7 +314,7 @@ static int buf_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
}
This->dirty = 1;
- return len;
+ return (ssize_t) len;
}
static int buf_flush(Stream_t *Stream)
@@ -324,8 +342,10 @@ static int buf_free(Stream_t *Stream)
}
static Class_t BufferClass = {
- buf_read,
- buf_write,
+ 0,
+ 0,
+ buf_pread,
+ buf_pwrite,
buf_flush,
buf_free,
0, /* set_geom */
@@ -335,13 +355,18 @@ static Class_t BufferClass = {
0, /* discard */
};
-Stream_t *buf_init(Stream_t *Next, int size,
- int cylinderSize,
- int sectorSize)
+Stream_t *buf_init(Stream_t *Next, size_t size,
+ size_t cylinderSize,
+ size_t sectorSize)
{
Buffer_t *Buffer;
- Stream_t *Stream;
+#ifdef HAVE_ASSERT_H
+ assert(size != 0);
+ assert(cylinderSize != 0);
+ assert(sectorSize != 0);
+ assert(Next != NULL);
+#endif
if(size % cylinderSize != 0) {
fprintf(stderr, "size not multiple of cylinder size\n");
@@ -352,19 +377,13 @@ Stream_t *buf_init(Stream_t *Next, int size,
exit(1);
}
- if(Next->Buffer){
- Next->refs--;
- Next->Buffer->refs++;
- return Next->Buffer;
- }
-
- Stream = (Stream_t *) malloc (sizeof(Buffer_t));
- if(!Stream)
+ Buffer = New(Buffer_t);
+ if(!Buffer)
return 0;
- Buffer = (Buffer_t *) Stream;
+ init_head(&Buffer->head, &BufferClass, Next);
Buffer->buf = malloc(size);
if ( !Buffer->buf){
- Free(Stream);
+ Free(Buffer);
return 0;
}
Buffer->size = size;
@@ -378,11 +397,6 @@ Stream_t *buf_init(Stream_t *Next, int size,
Buffer->current = 0L;
Buffer->cur_size = 0; /* buffer currently empty */
- Buffer->Next = Next;
- Buffer->Class = &BufferClass;
- Buffer->refs = 1;
- Buffer->Buffer = 0;
- Buffer->Next->Buffer = (Stream_t *) Buffer;
- return Stream;
+ return &Buffer->head;
}
diff --git a/buffer.h b/buffer.h
index 6c79258..401e8d5 100644
--- a/buffer.h
+++ b/buffer.h
@@ -20,9 +20,9 @@
#include "stream.h"
-Stream_t *buf_init(Stream_t *Next,
- int size,
- int cylinderSize,
- int sectorSize);
+Stream_t *buf_init(Stream_t *Next,
+ size_t size,
+ size_t cylinderSize,
+ size_t sectorSize);
#endif
diff --git a/byte_dword.h b/byte_dword.h
index c3c3b97..dd81708 100644
--- a/byte_dword.h
+++ b/byte_dword.h
@@ -22,9 +22,18 @@ static Dword byte2dword(Byte* val)
{
Dword l;
l = (Dword)((val[0] << 24) + (val[1] << 16) + (val[2] << 8) + val[3]);
-
+
+ return l;
+}
+
+UNUSED(static int32_t byte2sdword(Byte* val))
+{
+ int32_t l;
+ l = (int32_t)((val[0] << 24) + (val[1] << 16) + (val[2] << 8) + val[3]);
+
return l;
-}
+}
+
UNUSED(static Qword byte2qword(Byte* val))
{
@@ -38,7 +47,7 @@ UNUSED(static Qword byte2qword(Byte* val))
l = (l << 8) | val[6];
l = (l << 8) | val[7];
return l;
-}
+}
static void dword2byte(Dword parm, Byte* rval)
{
@@ -48,6 +57,14 @@ static void dword2byte(Dword parm, Byte* rval)
rval[3] = parm & 0xff;
}
+UNUSED(static void sdword2byte(int32_t parm, Byte* rval))
+{
+ rval[0] = (parm >> 24) & 0xff;
+ rval[1] = (parm >> 16) & 0xff;
+ rval[2] = (parm >> 8) & 0xff;
+ rval[3] = parm & 0xff;
+}
+
UNUSED(static void qword2byte(Qword parm, Byte* rval))
{
rval[0] = (parm >> 56) & 0xff;
diff --git a/charsetConv.c b/charsetConv.c
index 085d887..dfcaf8e 100644
--- a/charsetConv.c
+++ b/charsetConv.c
@@ -1,13 +1,13 @@
/* Copyright 2008,2009 Alain Knaff.
* This file is part of mtools.
- *
+ *
* Mtools is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Mtools is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
@@ -61,7 +61,7 @@ static int try(const char *testCp) {
size_t outbufLen = 2*sizeof(char);
iconv_t test = 0;
size_t i;
-
+
for(i=0; i < sizeof(asciiTries) / sizeof(asciiTries[0]); i++) {
test = iconv_open(asciiTries[i], testCp);
if(test != (iconv_t) -1)
@@ -88,7 +88,7 @@ static int try(const char *testCp) {
static const char *getWcharCp(void) {
unsigned int i;
if(wcharCp != NULL)
- return wcharCp;
+ return wcharCp;
for(i=0; i< sizeof(wcharTries) / sizeof(wcharTries[0]); i++) {
if(try(wcharTries[i]))
return (wcharCp=wcharTries[i]);
@@ -98,7 +98,7 @@ static const char *getWcharCp(void) {
}
-doscp_t *cp_open(int codepage)
+doscp_t *cp_open(unsigned int codepage)
{
char dosCp[17];
doscp_t *ret;
@@ -107,7 +107,7 @@ doscp_t *cp_open(int codepage)
if(codepage == 0)
codepage = mtools_default_codepage;
- if(codepage < 0 || codepage > 9999) {
+ if(codepage > 9999) {
fprintf(stderr, "Bad codepage %d\n", codepage);
return NULL;
}
@@ -152,19 +152,19 @@ void cp_close(doscp_t *cp)
free(cp);
}
-int dos_to_wchar(doscp_t *cp, const char *dos, wchar_t *wchar, size_t len)
+size_t dos_to_wchar(doscp_t *cp, const char *dos, wchar_t *wchar, size_t len)
{
- int r;
+ size_t r;
size_t in_len=len;
size_t out_len=len*sizeof(wchar_t);
wchar_t *dptr=wchar;
- char *dos2 = (char *) dos; /* Magic to be able to call iconv with its
+ char *dos2 = (char *) dos; /* Magic to be able to call iconv with its
buggy prototype */
r=iconv(cp->from, &dos2, &in_len, (char **)&dptr, &out_len);
- if(r < 0)
+ if(r == (size_t) -1)
return r;
*dptr = L'\0';
- return dptr-wchar;
+ return (size_t) (dptr-wchar);
}
/**
@@ -172,10 +172,10 @@ int dos_to_wchar(doscp_t *cp, const char *dos, wchar_t *wchar, size_t len)
* ensure that dest is large enough.
* mangled will be set if there has been an untranslatable character.
*/
-static int safe_iconv(iconv_t conv, const wchar_t *wchar, char *dest,
+static size_t safe_iconv(iconv_t conv, const wchar_t *wchar, char *dest,
size_t in_len, size_t out_len, int *mangled)
{
- int r;
+ size_t r;
unsigned int i;
char *dptr = dest;
size_t len;
@@ -184,7 +184,7 @@ static int safe_iconv(iconv_t conv, const wchar_t *wchar, char *dest,
while(in_len > 0 && out_len > 0) {
r=iconv(conv, (char**)&wchar, &in_len, &dptr, &out_len);
- if(r >= 0 || errno != EILSEQ) {
+ if(r == (size_t) -1 || errno != EILSEQ) {
/* everything transformed, or error that is _not_ a bad
* character */
break;
@@ -193,7 +193,7 @@ static int safe_iconv(iconv_t conv, const wchar_t *wchar, char *dest,
if(out_len <= 0)
break;
- if(dptr)
+ if(dptr)
*dptr++ = '_';
in_len -= sizeof(wchar_t);
@@ -201,8 +201,8 @@ static int safe_iconv(iconv_t conv, const wchar_t *wchar, char *dest,
out_len--;
}
- len = dptr-dest; /* how many dest characters have there been
- generated */
+ len = (size_t) (dptr-dest); /* how many dest characters have there been
+ generated */
/* eliminate question marks which might have been formed by
untransliterable characters */
@@ -230,7 +230,7 @@ struct doscp_t {
unsigned char to_dos[0x80];
};
-doscp_t *cp_open(int codepage)
+doscp_t *cp_open(unsigned int codepage)
{
doscp_t *ret;
int i;
@@ -269,7 +269,7 @@ void cp_close(doscp_t *cp)
free(cp);
}
-int dos_to_wchar(doscp_t *cp, const char *dos, wchar_t *wchar, size_t len)
+size_t dos_to_wchar(doscp_t *cp, const char *dos, wchar_t *wchar, size_t len)
{
int i;
@@ -317,7 +317,7 @@ static inline size_t wcrtomb(char *s, wchar_t wc, mbstate_t *ps)
return 1;
}
-static inline size_t mbrtowc(wchar_t *pwc, const char *s,
+static inline size_t mbrtowc(wchar_t *pwc, const char *s,
size_t n, mbstate_t *ps)
{
*pwc = *s;
@@ -335,7 +335,7 @@ static iconv_t to_native = NULL;
static void initialize_to_native(void)
{
char *li, *cp;
- int len;
+ size_t len;
if(to_native != NULL)
return;
li = nl_langinfo(CODESET);
@@ -364,12 +364,12 @@ static void initialize_to_native(void)
* Convert wchar string to native, converting at most len wchar characters
* Returns number of generated native characters
*/
-int wchar_to_native(const wchar_t *wchar, char *native, size_t len,
- size_t out_len)
+size_t wchar_to_native(const wchar_t *wchar, char *native, size_t len,
+ size_t out_len)
{
#ifdef HAVE_ICONV_H
int mangled;
- int r;
+ size_t r;
initialize_to_native();
len = wcsnlen(wchar,len);
r=safe_iconv(to_native, wchar, native, len, out_len, &mangled);
@@ -381,13 +381,11 @@ int wchar_to_native(const wchar_t *wchar, char *native, size_t len,
mbstate_t ps;
memset(&ps, 0, sizeof(ps));
for(i=0; i<len && wchar[i] != 0; i++) {
- int r = wcrtomb(dptr, wchar[i], &ps);
- if(r < 0 && errno == EILSEQ) {
+ size_t r = wcrtomb(dptr, wchar[i], &ps);
+ if(r == (size_t) -1 && errno == EILSEQ) {
r=1;
*dptr='_';
}
- if(r < 0)
- return r;
dptr+=r;
}
*dptr='\0';
@@ -400,16 +398,16 @@ int wchar_to_native(const wchar_t *wchar, char *native, size_t len,
* characters. If end is supplied, stop conversion when source pointer
* exceeds end. Returns number of generated wchars
*/
-int native_to_wchar(const char *native, wchar_t *wchar, size_t len,
- const char *end, int *mangled)
+size_t native_to_wchar(const char *native, wchar_t *wchar, size_t len,
+ const char *end, int *mangled)
{
mbstate_t ps;
unsigned int i;
memset(&ps, 0, sizeof(ps));
for(i=0; i<len && (native < end || !end); i++) {
- int r = mbrtowc(wchar+i, native, len, &ps);
- if(r < 0) {
+ size_t r = mbrtowc(wchar+i, native, len, &ps);
+ if(r == (size_t) -1) {
/* Unconvertible character. Just pretend it's Latin1
encoded (if valid Latin1 character) or substitute
with an underscore if not
diff --git a/codepage.h b/codepage.h
index 8775865..de5db7f 100644
--- a/codepage.h
+++ b/codepage.h
@@ -16,7 +16,7 @@
*/
typedef struct Codepage_l {
- int nr;
+ int nr;
unsigned char tounix[128];
} Codepage_t;
diff --git a/codepages.c b/codepages.c
index 5c437e0..ecb99ee 100644
--- a/codepages.c
+++ b/codepages.c
@@ -53,7 +53,7 @@ Codepage_t codepages[]= {
"ÓßÔÒõÕµþÞÚÙýÝÞ¯´"
"­±_¾¶§÷¸°¨·¹³²__"
},
-
+
{ 852,
"ÇüéâäucçlëÕõîZÄC"
"ÉLlôöLlSsÖÜTtL×c"
@@ -64,7 +64,7 @@ Codepage_t codepages[]= {
"ÓßÔNnñSsRÚrUýÝt´"
"­~.~~§÷¸°¨·¹uRr_"
},
-
+
{ 860,
"ÇüéâãàåçêëèÍõìÃÂ"
"ÉÀÈôõòÚùÌÕÜ¢£ÙPÓ"
@@ -75,7 +75,7 @@ Codepage_t codepages[]= {
"abgpSsµtftodøØ_N"
"=±<>||÷~°··Vn²__"
},
-
+
{ 863,
"ÇüéâÂà¶çêëèïî_À§"
"ÉÈÊôËÏûù¤ÔÜ¢£ÙÛf"
@@ -86,7 +86,7 @@ Codepage_t codepages[]= {
"abgpSsµtftodøØ_N"
"=±<>||÷~°··Vn²__"
},
-
+
{ 865,
"ÇüéâäàåçêëèïîìÄÅ"
"ÉæÆôöòûùÿÖÜø£ØPf"
diff --git a/config.c b/config.c
index 550bfbf..173eae0 100644
--- a/config.c
+++ b/config.c
@@ -47,7 +47,7 @@ static unsigned int flag_mask; /* mask of currently set flags */
static unsigned int cur_devs; /* current number of defined devices */
static int cur_dev; /* device being filled in. If negative, none */
static int trusted=0; /* is the currently parsed device entry trusted? */
-static unsigned int nr_dev; /* number of devices that the current table can
+static unsigned int nr_dev; /* number of devices that the current table can
hold */
struct device *devices; /* the device table */
static int token_nr; /* number of tokens in line */
@@ -77,7 +77,8 @@ typedef struct switches_l {
T_STRING,
T_UINT,
T_UINT8,
- T_UINT16
+ T_UINT16,
+ T_UQSTRING
} type;
} switches_t;
@@ -175,7 +176,8 @@ static switches_t dswitches[]= {
{ "HIDDEN", OFFS(hidden), T_UINT },
{ "PRECMD", OFFS(precmd), T_STRING },
{ "BLOCKSIZE", OFFS(blocksize), T_UINT },
- { "CODEPAGE", OFFS(codepage), T_UINT }
+ { "CODEPAGE", OFFS(codepage), T_UINT },
+ { "DATA_MAP", OFFS(data_map), T_UQSTRING }
};
#if (defined HAVE_TOUPPER_L || defined HAVE_STRNCASECMP_L)
@@ -201,12 +203,12 @@ static int canon_drv(int drive) {
#endif
#ifdef HAVE_STRNCASECMP_L
-static int cmp_tok(const char *a, const char *b, int len) {
+static int cmp_tok(const char *a, const char *b, size_t len) {
init_canon();
return strncasecmp_l(a, b, len, C);
}
#else
-static int cmp_tok(const char *a, const char *b, int len) {
+static int cmp_tok(const char *a, const char *b, size_t len) {
return strncasecmp(a, b, len);
}
#endif
@@ -251,6 +253,8 @@ static void syntax(const char *msg, int thisLine)
exit(1);
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
static void get_env_conf(void)
{
char *s;
@@ -274,6 +278,7 @@ static void get_env_conf(void)
* ((uint16_t *)global_switches[i].address) = strtou16(s,0,0);
break;
case T_STRING:
+ case T_UQSTRING:
* ((char **)global_switches[i].address) = s;
break;
}
@@ -286,6 +291,7 @@ static void get_env_conf(void)
}
}
}
+#pragma GCC diagnostic pop
static int mtools_getline(void)
{
@@ -299,7 +305,7 @@ static int mtools_getline(void)
syntax("line too long", 1);
return 0;
}
-
+
static void skip_junk(int expect)
{
lastTokenLinenumber = linenumber;
@@ -361,11 +367,21 @@ static char *get_string(void)
end = strchr(str, '\"');
if(!end)
syntax("unterminated string constant", 1);
- *end = '\0';
+ str = strndup(str, ptrdiff(end, str));
pos = end+1;
return str;
}
+static char *get_unquoted_string(void)
+{
+ if(*pos == '"')
+ return get_string();
+ else {
+ char *str=get_next_token();
+ return strndup(str, token_length);
+ }
+}
+
static unsigned long get_unumber(unsigned long max)
{
char *last;
@@ -426,7 +442,7 @@ static void grow(void)
}
}
}
-
+
static void init_drive(void)
{
@@ -452,7 +468,7 @@ static void prepend(void)
static void append(void)
{
grow();
- cur_dev = cur_devs;
+ cur_dev = (int) cur_devs;
cur_devs++;
init_drive();
}
@@ -479,8 +495,6 @@ static void finish_drive_clause(void)
}
devices[cur_dev].file_nr = file_nr;
devices[cur_dev].cfg_filename = filename;
- if(! (flag_mask & PRIV_FLAG) && IS_SCSI(&devices[cur_dev]))
- devices[cur_dev].misc_flags |= PRIV_FLAG;
if(!trusted && (devices[cur_dev].misc_flags & PRIV_FLAG)) {
fprintf(stderr,
"Warning: privileged flag ignored for drive %c: defined in file %s\n",
@@ -491,6 +505,8 @@ static void finish_drive_clause(void)
cur_dev = -1;
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
static int set_var(struct switches_l *switches, int nr,
caddr_t base_address)
{
@@ -498,6 +514,11 @@ static int set_var(struct switches_l *switches, int nr,
for(i=0; i < nr; i++) {
if(match_token(switches[i].name)) {
expect_char('=');
+ /* All pointers cast back to pointers with alignment
+ * constraints were such pointers with alignment
+ * constraints initially, thus they do indeed fit the
+ * constraint */
+
if(switches[i].type == T_UINT)
* ((unsigned int *)((long)switches[i].address+base_address)) =
(unsigned int) get_unumber(UINT_MAX);
@@ -512,12 +533,16 @@ static int set_var(struct switches_l *switches, int nr,
get_number();
else if (switches[i].type == T_STRING)
* ((char**)((long)switches[i].address+base_address))=
- strdup(get_string());
+ get_string();
+ else if (switches[i].type == T_UQSTRING)
+ * ((char**)((long)switches[i].address+base_address))=
+ get_unquoted_string();
return 0;
}
}
return 1;
}
+#pragma GCC diagnostic pop
static int set_openflags(struct device *dev)
{
@@ -594,7 +619,7 @@ void set_cmd_line_image(char *img) {
devices[cur_dev].name = strdup(img);
devices[cur_dev].offset = 0;
} else {
- devices[cur_dev].name = strndup(img, ofsp - img);
+ devices[cur_dev].name = strndup(img, ptrdiff(ofsp, img));
devices[cur_dev].offset = str_to_offset(ofsp+2);
}
@@ -630,7 +655,7 @@ void check_number_parse_errno(char c, const char *oarg, char *endptr) {
}
static uint16_t tou16(int in, const char *comment) {
- if(in > UINT16_MAX) {
+ if(in > (int) UINT16_MAX) {
fprintf(stderr, "Number of %s %d too big\n", comment, in);
exit(1);
}
@@ -639,7 +664,6 @@ static uint16_t tou16(int in, const char *comment) {
exit(1);
}
return (uint16_t) in;
-
}
static void parse_old_device_line(char drive)
@@ -648,23 +672,22 @@ static void parse_old_device_line(char drive)
int items;
long offset;
- int heads, sectors;
-
+ int heads, sectors, tracks;
+
/* finish any old drive */
finish_drive_clause();
/* purge out data of old configuration files */
purge(drive, file_nr);
-
+
/* reserve slot */
append();
items = sscanf(token,"%c %s %i %i %i %i %li",
&devices[cur_dev].drive,name,&devices[cur_dev].fat_bits,
- &devices[cur_dev].tracks,&heads,
- &sectors, &offset);
+ &tracks,&heads,&sectors, &offset);
devices[cur_dev].heads = tou16(heads, "heads");
devices[cur_dev].sectors = tou16(sectors, "sectors");
-
+ devices[cur_dev].tracks = (unsigned int) tracks;
devices[cur_dev].offset = (off_t) offset;
switch(items){
case 2:
@@ -690,7 +713,7 @@ static void parse_old_device_line(char drive)
devices[cur_dev].sectors = 0;
devices[cur_dev].heads = 0;
}
-
+
devices[cur_dev].drive = ch_canon_drv(devices[cur_dev].drive);
maintain_default_drive(devices[cur_dev].drive);
if (!(devices[cur_dev].name = strdup(name))) {
@@ -722,7 +745,7 @@ static int parse_one(int privilege)
syntax("drive letter expected", 0);
if(action==1 || action==4)
- /* replace existing drive */
+ /* replace existing drive */
purge(token[0], file_nr);
if(action==4)
return 1;
@@ -799,7 +822,7 @@ void read_config(void)
char *envConfFile;
static char conf_file[MAXPATHLEN+sizeof(CFG_FILE1)];
-
+
/* copy compiled-in devices */
file_nr = 0;
cur_devs = nr_const_devices;
diff --git a/config.guess b/config.guess
index 2e9ad7f..b7806a8 100755
--- a/config.guess
+++ b/config.guess
@@ -1,12 +1,14 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2016 Free Software Foundation, Inc.
+# Copyright 1992-2022 Free Software Foundation, Inc.
-timestamp='2016-10-02'
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2022-01-03'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
+# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
@@ -15,7 +17,7 @@ timestamp='2016-10-02'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -27,11 +29,19 @@ timestamp='2016-10-02'
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
#
# Please send patches to <config-patches@gnu.org>.
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX. However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
+
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
@@ -39,7 +49,7 @@ Usage: $0 [OPTION]
Output the configuration name of the system \`$me' is run on.
-Operation modes:
+Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
@@ -50,7 +60,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2016 Free Software Foundation, Inc.
+Copyright 1992-2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -84,7 +94,8 @@ if test $# != 0; then
exit 1
fi
-trap 'exit 1' 1 2 15
+# Just in case it came from the environment.
+GUESS=
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
@@ -96,66 +107,90 @@ trap 'exit 1' 1 2 15
# Portable tmp directory creation inspired by the Autoconf team.
-set_cc_for_build='
-trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
-trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
-: ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
-dummy=$tmp/dummy ;
-tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case $CC_FOR_BUILD,$HOST_CC,$CC in
- ,,) echo "int x;" > $dummy.c ;
- for c in cc gcc c89 c99 ; do
- if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
- CC_FOR_BUILD="$c"; break ;
- fi ;
- done ;
- if test x"$CC_FOR_BUILD" = x ; then
- CC_FOR_BUILD=no_compiler_found ;
- fi
- ;;
- ,,*) CC_FOR_BUILD=$CC ;;
- ,*,*) CC_FOR_BUILD=$HOST_CC ;;
-esac ; set_cc_for_build= ;'
+tmp=
+# shellcheck disable=SC2172
+trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
+
+set_cc_for_build() {
+ # prevent multiple calls if $tmp is already set
+ test "$tmp" && return 0
+ : "${TMPDIR=/tmp}"
+ # shellcheck disable=SC2039,SC3028
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
+ dummy=$tmp/dummy
+ case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
+ ,,) echo "int x;" > "$dummy.c"
+ for driver in cc gcc c89 c99 ; do
+ if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
+ CC_FOR_BUILD=$driver
+ break
+ fi
+ done
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+ esac
+}
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+if test -f /.attbin/uname ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-case "${UNAME_SYSTEM}" in
+case $UNAME_SYSTEM in
Linux|GNU|GNU/*)
- # If the system lacks a compiler, then just pick glibc.
- # We could probably try harder.
- LIBC=gnu
+ LIBC=unknown
- eval $set_cc_for_build
- cat <<-EOF > $dummy.c
+ set_cc_for_build
+ cat <<-EOF > "$dummy.c"
#include <features.h>
#if defined(__UCLIBC__)
LIBC=uclibc
#elif defined(__dietlibc__)
LIBC=dietlibc
- #else
+ #elif defined(__GLIBC__)
LIBC=gnu
+ #else
+ #include <stdarg.h>
+ /* First heuristic to detect musl libc. */
+ #ifdef __DEFINED_va_list
+ LIBC=musl
+ #endif
#endif
EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ eval "$cc_set_libc"
+
+ # Second heuristic to detect musl libc.
+ if [ "$LIBC" = unknown ] &&
+ command -v ldd >/dev/null &&
+ ldd --version 2>&1 | grep -q ^musl; then
+ LIBC=musl
+ fi
+
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ if [ "$LIBC" = unknown ]; then
+ LIBC=gnu
+ fi
;;
esac
# Note: order is significant - the case branches are not exclusive.
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
@@ -167,32 +202,32 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
#
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
- sysctl="sysctl -n hw.machine_arch"
UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
- /sbin/$sysctl 2>/dev/null || \
- /usr/sbin/$sysctl 2>/dev/null || \
+ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
echo unknown)`
- case "${UNAME_MACHINE_ARCH}" in
+ case $UNAME_MACHINE_ARCH in
+ aarch64eb) machine=aarch64_be-unknown ;;
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
earmv*)
- arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
- endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+ arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
machine=${arch}${endian}-unknown
;;
- *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ *) machine=$UNAME_MACHINE_ARCH-unknown ;;
esac
# The Operating System including object format, if it has switched
# to ELF recently (or will in the future) and ABI.
- case "${UNAME_MACHINE_ARCH}" in
+ case $UNAME_MACHINE_ARCH in
earm*)
os=netbsdelf
;;
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
- eval $set_cc_for_build
+ set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ELF__
then
@@ -208,10 +243,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
;;
esac
# Determine ABI tags.
- case "${UNAME_MACHINE_ARCH}" in
+ case $UNAME_MACHINE_ARCH in
earm*)
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
- abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+ abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
;;
esac
# The OS release
@@ -219,47 +254,68 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# thus, need a distinct triplet. However, they do not need
# kernel version information, so it can be replaced with a
# suitable tag, in the style of linux-gnu.
- case "${UNAME_VERSION}" in
+ case $UNAME_VERSION in
Debian*)
release='-gnu'
;;
*)
- release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
+ release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "${machine}-${os}${release}${abi}"
- exit ;;
+ GUESS=$machine-${os}${release}${abi-}
+ ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE
+ ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE
+ ;;
+ *:SecBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE
+ ;;
*:LibertyBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE
+ ;;
+ *:MidnightBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE
+ ;;
*:ekkoBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE
+ ;;
*:SolidBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE
+ ;;
+ *:OS108:*:*)
+ GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE
+ ;;
macppc:MirBSD:*:*)
- echo powerpc-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
+ GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE
+ ;;
*:MirBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE
+ ;;
*:Sortix:*:*)
- echo ${UNAME_MACHINE}-unknown-sortix
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-sortix
+ ;;
+ *:Twizzler:*:*)
+ GUESS=$UNAME_MACHINE-unknown-twizzler
+ ;;
+ *:Redox:*:*)
+ GUESS=$UNAME_MACHINE-unknown-redox
+ ;;
+ mips:OSF1:*.*)
+ GUESS=mips-dec-osf1
+ ;;
alpha:OSF1:*:*)
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ trap '' 0
case $UNAME_RELEASE in
*4.0)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
@@ -273,7 +329,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# covers most systems running today. This code pipes the CPU
# types through head -n 1, so we only detect the type of CPU 0.
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
- case "$ALPHA_CPU_TYPE" in
+ case $ALPHA_CPU_TYPE in
"EV4 (21064)")
UNAME_MACHINE=alpha ;;
"EV4.5 (21064)")
@@ -310,126 +366,121 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
- # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
- exitcode=$?
- trap '' 0
- exit $exitcode ;;
- Alpha\ *:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # Should we change UNAME_MACHINE based on the output of uname instead
- # of the specific Alpha model?
- echo alpha-pc-interix
- exit ;;
- 21064:Windows_NT:50:3)
- echo alpha-dec-winnt3.5
- exit ;;
+ OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ GUESS=$UNAME_MACHINE-dec-osf$OSF_REL
+ ;;
Amiga*:UNIX_System_V:4.0:*)
- echo m68k-unknown-sysv4
- exit ;;
+ GUESS=m68k-unknown-sysv4
+ ;;
*:[Aa]miga[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-amigaos
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-amigaos
+ ;;
*:[Mm]orph[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-morphos
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-morphos
+ ;;
*:OS/390:*:*)
- echo i370-ibm-openedition
- exit ;;
+ GUESS=i370-ibm-openedition
+ ;;
*:z/VM:*:*)
- echo s390-ibm-zvmoe
- exit ;;
+ GUESS=s390-ibm-zvmoe
+ ;;
*:OS400:*:*)
- echo powerpc-ibm-os400
- exit ;;
+ GUESS=powerpc-ibm-os400
+ ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
- echo arm-acorn-riscix${UNAME_RELEASE}
- exit ;;
+ GUESS=arm-acorn-riscix$UNAME_RELEASE
+ ;;
arm*:riscos:*:*|arm*:RISCOS:*:*)
- echo arm-unknown-riscos
- exit ;;
+ GUESS=arm-unknown-riscos
+ ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
- echo hppa1.1-hitachi-hiuxmpp
- exit ;;
+ GUESS=hppa1.1-hitachi-hiuxmpp
+ ;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
- if test "`(/bin/universe) 2>/dev/null`" = att ; then
- echo pyramid-pyramid-sysv3
- else
- echo pyramid-pyramid-bsd
- fi
- exit ;;
+ case `(/bin/universe) 2>/dev/null` in
+ att) GUESS=pyramid-pyramid-sysv3 ;;
+ *) GUESS=pyramid-pyramid-bsd ;;
+ esac
+ ;;
NILE*:*:*:dcosx)
- echo pyramid-pyramid-svr4
- exit ;;
+ GUESS=pyramid-pyramid-svr4
+ ;;
DRS?6000:unix:4.0:6*)
- echo sparc-icl-nx6
- exit ;;
+ GUESS=sparc-icl-nx6
+ ;;
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
case `/usr/bin/uname -p` in
- sparc) echo sparc-icl-nx7; exit ;;
- esac ;;
+ sparc) GUESS=sparc-icl-nx7 ;;
+ esac
+ ;;
s390x:SunOS:*:*)
- echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL
+ ;;
sun4H:SunOS:5.*:*)
- echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-hal-solaris2$SUN_REL
+ ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
- echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-sun-solaris2$SUN_REL
+ ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
- echo i386-pc-auroraux${UNAME_RELEASE}
- exit ;;
+ GUESS=i386-pc-auroraux$UNAME_RELEASE
+ ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
- eval $set_cc_for_build
+ set_cc_for_build
SUN_ARCH=i386
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
- if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
SUN_ARCH=x86_64
fi
fi
- echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=$SUN_ARCH-pc-solaris2$SUN_REL
+ ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
- echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-sun-solaris3$SUN_REL
+ ;;
sun4*:SunOS:*:*)
- case "`/usr/bin/arch -k`" in
+ case `/usr/bin/arch -k` in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
- echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
+ GUESS=sparc-sun-sunos$SUN_REL
+ ;;
sun3*:SunOS:*:*)
- echo m68k-sun-sunos${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-sun-sunos$UNAME_RELEASE
+ ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
- test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
- case "`/bin/arch`" in
+ test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
+ case `/bin/arch` in
sun3)
- echo m68k-sun-sunos${UNAME_RELEASE}
+ GUESS=m68k-sun-sunos$UNAME_RELEASE
;;
sun4)
- echo sparc-sun-sunos${UNAME_RELEASE}
+ GUESS=sparc-sun-sunos$UNAME_RELEASE
;;
esac
- exit ;;
+ ;;
aushp:SunOS:*:*)
- echo sparc-auspex-sunos${UNAME_RELEASE}
- exit ;;
+ GUESS=sparc-auspex-sunos$UNAME_RELEASE
+ ;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
# "atarist" or "atariste" at least should have a processor
@@ -439,44 +490,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-milan-mint$UNAME_RELEASE
+ ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-hades-mint$UNAME_RELEASE
+ ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-unknown-mint$UNAME_RELEASE
+ ;;
m68k:machten:*:*)
- echo m68k-apple-machten${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-apple-machten$UNAME_RELEASE
+ ;;
powerpc:machten:*:*)
- echo powerpc-apple-machten${UNAME_RELEASE}
- exit ;;
+ GUESS=powerpc-apple-machten$UNAME_RELEASE
+ ;;
RISC*:Mach:*:*)
- echo mips-dec-mach_bsd4.3
- exit ;;
+ GUESS=mips-dec-mach_bsd4.3
+ ;;
RISC*:ULTRIX:*:*)
- echo mips-dec-ultrix${UNAME_RELEASE}
- exit ;;
+ GUESS=mips-dec-ultrix$UNAME_RELEASE
+ ;;
VAX*:ULTRIX*:*:*)
- echo vax-dec-ultrix${UNAME_RELEASE}
- exit ;;
+ GUESS=vax-dec-ultrix$UNAME_RELEASE
+ ;;
2020:CLIX:*:* | 2430:CLIX:*:*)
- echo clipper-intergraph-clix${UNAME_RELEASE}
- exit ;;
+ GUESS=clipper-intergraph-clix$UNAME_RELEASE
+ ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#ifdef __cplusplus
#include <stdio.h> /* for printf() prototype */
int main (int argc, char *argv[]) {
@@ -485,95 +536,96 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
- printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
- printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
- printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
- $CC_FOR_BUILD -o $dummy $dummy.c &&
- dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
- SYSTEM_NAME=`$dummy $dummyarg` &&
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
+ dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
{ echo "$SYSTEM_NAME"; exit; }
- echo mips-mips-riscos${UNAME_RELEASE}
- exit ;;
+ GUESS=mips-mips-riscos$UNAME_RELEASE
+ ;;
Motorola:PowerMAX_OS:*:*)
- echo powerpc-motorola-powermax
- exit ;;
+ GUESS=powerpc-motorola-powermax
+ ;;
Motorola:*:4.3:PL8-*)
- echo powerpc-harris-powermax
- exit ;;
+ GUESS=powerpc-harris-powermax
+ ;;
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
- echo powerpc-harris-powermax
- exit ;;
+ GUESS=powerpc-harris-powermax
+ ;;
Night_Hawk:Power_UNIX:*:*)
- echo powerpc-harris-powerunix
- exit ;;
+ GUESS=powerpc-harris-powerunix
+ ;;
m88k:CX/UX:7*:*)
- echo m88k-harris-cxux7
- exit ;;
+ GUESS=m88k-harris-cxux7
+ ;;
m88k:*:4*:R4*)
- echo m88k-motorola-sysv4
- exit ;;
+ GUESS=m88k-motorola-sysv4
+ ;;
m88k:*:3*:R3*)
- echo m88k-motorola-sysv3
- exit ;;
+ GUESS=m88k-motorola-sysv3
+ ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
- if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
then
- if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
- [ ${TARGET_BINARY_INTERFACE}x = x ]
+ if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
+ test "$TARGET_BINARY_INTERFACE"x = x
then
- echo m88k-dg-dgux${UNAME_RELEASE}
+ GUESS=m88k-dg-dgux$UNAME_RELEASE
else
- echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ GUESS=m88k-dg-dguxbcs$UNAME_RELEASE
fi
else
- echo i586-dg-dgux${UNAME_RELEASE}
+ GUESS=i586-dg-dgux$UNAME_RELEASE
fi
- exit ;;
+ ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
- echo m88k-dolphin-sysv3
- exit ;;
+ GUESS=m88k-dolphin-sysv3
+ ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
- echo m88k-motorola-sysv3
- exit ;;
+ GUESS=m88k-motorola-sysv3
+ ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
- echo m88k-tektronix-sysv3
- exit ;;
+ GUESS=m88k-tektronix-sysv3
+ ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
- echo m68k-tektronix-bsd
- exit ;;
+ GUESS=m68k-tektronix-bsd
+ ;;
*:IRIX*:*:*)
- echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
- exit ;;
+ IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'`
+ GUESS=mips-sgi-irix$IRIX_REL
+ ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
- echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
- exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*)
- echo i386-ibm-aix
- exit ;;
+ GUESS=i386-ibm-aix
+ ;;
ia64:AIX:*:*)
- if [ -x /usr/bin/oslevel ] ; then
+ if test -x /usr/bin/oslevel ; then
IBM_REV=`/usr/bin/oslevel`
else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
fi
- echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
- exit ;;
+ GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV
+ ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#include <sys/systemcfg.h>
main()
@@ -584,77 +636,77 @@ EOF
exit(0);
}
EOF
- if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
then
- echo "$SYSTEM_NAME"
+ GUESS=$SYSTEM_NAME
else
- echo rs6000-ibm-aix3.2.5
+ GUESS=rs6000-ibm-aix3.2.5
fi
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
- echo rs6000-ibm-aix3.2.4
+ GUESS=rs6000-ibm-aix3.2.4
else
- echo rs6000-ibm-aix3.2
+ GUESS=rs6000-ibm-aix3.2
fi
- exit ;;
+ ;;
*:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
- if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
- if [ -x /usr/bin/lslpp ] ; then
- IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ if test -x /usr/bin/lslpp ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
fi
- echo ${IBM_ARCH}-ibm-aix${IBM_REV}
- exit ;;
+ GUESS=$IBM_ARCH-ibm-aix$IBM_REV
+ ;;
*:AIX:*:*)
- echo rs6000-ibm-aix
- exit ;;
- ibmrt:4.4BSD:*|romp-ibm:BSD:*)
- echo romp-ibm-bsd4.4
- exit ;;
+ GUESS=rs6000-ibm-aix
+ ;;
+ ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
+ GUESS=romp-ibm-bsd4.4
+ ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
- echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
- exit ;; # report: romp-ibm BSD 4.3
+ GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to
+ ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
- echo rs6000-bull-bosx
- exit ;;
+ GUESS=rs6000-bull-bosx
+ ;;
DPX/2?00:B.O.S.:*:*)
- echo m68k-bull-sysv3
- exit ;;
+ GUESS=m68k-bull-sysv3
+ ;;
9000/[34]??:4.3bsd:1.*:*)
- echo m68k-hp-bsd
- exit ;;
+ GUESS=m68k-hp-bsd
+ ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
- echo m68k-hp-bsd4.4
- exit ;;
+ GUESS=m68k-hp-bsd4.4
+ ;;
9000/[34678]??:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- case "${UNAME_MACHINE}" in
- 9000/31? ) HP_ARCH=m68000 ;;
- 9000/[34]?? ) HP_ARCH=m68k ;;
+ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+ case $UNAME_MACHINE in
+ 9000/31?) HP_ARCH=m68000 ;;
+ 9000/[34]??) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
- if [ -x /usr/bin/getconf ]; then
+ if test -x /usr/bin/getconf; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
- case "${sc_cpu_version}" in
+ case $sc_cpu_version in
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
- case "${sc_kernel_bits}" in
+ case $sc_kernel_bits in
32) HP_ARCH=hppa2.0n ;;
64) HP_ARCH=hppa2.0w ;;
'') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
esac ;;
esac
fi
- if [ "${HP_ARCH}" = "" ]; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ if test "$HP_ARCH" = ""; then
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#define _HPUX_SOURCE
#include <stdlib.h>
@@ -687,13 +739,13 @@ EOF
exit (0);
}
EOF
- (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
- if [ ${HP_ARCH} = hppa2.0w ]
+ if test "$HP_ARCH" = hppa2.0w
then
- eval $set_cc_for_build
+ set_cc_for_build
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
@@ -712,15 +764,15 @@ EOF
HP_ARCH=hppa64
fi
fi
- echo ${HP_ARCH}-hp-hpux${HPUX_REV}
- exit ;;
+ GUESS=$HP_ARCH-hp-hpux$HPUX_REV
+ ;;
ia64:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- echo ia64-hp-hpux${HPUX_REV}
- exit ;;
+ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+ GUESS=ia64-hp-hpux$HPUX_REV
+ ;;
3050*:HI-UX:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#include <unistd.h>
int
main ()
@@ -745,38 +797,38 @@ EOF
exit (0);
}
EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
{ echo "$SYSTEM_NAME"; exit; }
- echo unknown-hitachi-hiuxwe2
- exit ;;
- 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
- echo hppa1.1-hp-bsd
- exit ;;
+ GUESS=unknown-hitachi-hiuxwe2
+ ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
+ GUESS=hppa1.1-hp-bsd
+ ;;
9000/8??:4.3bsd:*:*)
- echo hppa1.0-hp-bsd
- exit ;;
+ GUESS=hppa1.0-hp-bsd
+ ;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
- echo hppa1.0-hp-mpeix
- exit ;;
- hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
- echo hppa1.1-hp-osf
- exit ;;
+ GUESS=hppa1.0-hp-mpeix
+ ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
+ GUESS=hppa1.1-hp-osf
+ ;;
hp8??:OSF1:*:*)
- echo hppa1.0-hp-osf
- exit ;;
+ GUESS=hppa1.0-hp-osf
+ ;;
i*86:OSF1:*:*)
- if [ -x /usr/sbin/sysversion ] ; then
- echo ${UNAME_MACHINE}-unknown-osf1mk
+ if test -x /usr/sbin/sysversion ; then
+ GUESS=$UNAME_MACHINE-unknown-osf1mk
else
- echo ${UNAME_MACHINE}-unknown-osf1
+ GUESS=$UNAME_MACHINE-unknown-osf1
fi
- exit ;;
+ ;;
parisc*:Lites*:*:*)
- echo hppa1.1-hp-lites
- exit ;;
+ GUESS=hppa1.1-hp-lites
+ ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
- echo c1-convex-bsd
- exit ;;
+ GUESS=c1-convex-bsd
+ ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
@@ -784,139 +836,145 @@ EOF
fi
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
- echo c34-convex-bsd
- exit ;;
+ GUESS=c34-convex-bsd
+ ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
- echo c38-convex-bsd
- exit ;;
+ GUESS=c38-convex-bsd
+ ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
- echo c4-convex-bsd
- exit ;;
+ GUESS=c4-convex-bsd
+ ;;
CRAY*Y-MP:*:*:*)
- echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=ymp-cray-unicos$CRAY_REL
+ ;;
CRAY*[A-Z]90:*:*:*)
- echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
- echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=t90-cray-unicos$CRAY_REL
+ ;;
CRAY*T3E:*:*:*)
- echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=alphaev5-cray-unicosmk$CRAY_REL
+ ;;
CRAY*SV1:*:*:*)
- echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=sv1-cray-unicos$CRAY_REL
+ ;;
*:UNICOS/mp:*:*)
- echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=craynv-cray-unicosmp$CRAY_REL
+ ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
+ GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+ ;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+ ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
- echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE
+ ;;
sparc*:BSD/OS:*:*)
- echo sparc-unknown-bsdi${UNAME_RELEASE}
- exit ;;
+ GUESS=sparc-unknown-bsdi$UNAME_RELEASE
+ ;;
*:BSD/OS:*:*)
- echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE
+ ;;
+ arm:FreeBSD:*:*)
+ UNAME_PROCESSOR=`uname -p`
+ set_cc_for_build
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi
+ else
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf
+ fi
+ ;;
*:FreeBSD:*:*)
UNAME_PROCESSOR=`/usr/bin/uname -p`
- case ${UNAME_PROCESSOR} in
+ case $UNAME_PROCESSOR in
amd64)
- echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- *)
- echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ UNAME_PROCESSOR=x86_64 ;;
+ i386)
+ UNAME_PROCESSOR=i586 ;;
esac
- exit ;;
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL
+ ;;
i*:CYGWIN*:*)
- echo ${UNAME_MACHINE}-pc-cygwin
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-cygwin
+ ;;
*:MINGW64*:*)
- echo ${UNAME_MACHINE}-pc-mingw64
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-mingw64
+ ;;
*:MINGW*:*)
- echo ${UNAME_MACHINE}-pc-mingw32
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-mingw32
+ ;;
*:MSYS*:*)
- echo ${UNAME_MACHINE}-pc-msys
- exit ;;
- i*:windows32*:*)
- # uname -m includes "-pc" on this system.
- echo ${UNAME_MACHINE}-mingw32
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-msys
+ ;;
i*:PW*:*)
- echo ${UNAME_MACHINE}-pc-pw32
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-pw32
+ ;;
*:Interix*:*)
- case ${UNAME_MACHINE} in
+ case $UNAME_MACHINE in
x86)
- echo i586-pc-interix${UNAME_RELEASE}
- exit ;;
+ GUESS=i586-pc-interix$UNAME_RELEASE
+ ;;
authenticamd | genuineintel | EM64T)
- echo x86_64-unknown-interix${UNAME_RELEASE}
- exit ;;
+ GUESS=x86_64-unknown-interix$UNAME_RELEASE
+ ;;
IA64)
- echo ia64-unknown-interix${UNAME_RELEASE}
- exit ;;
+ GUESS=ia64-unknown-interix$UNAME_RELEASE
+ ;;
esac ;;
- [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
- echo i${UNAME_MACHINE}-pc-mks
- exit ;;
- 8664:Windows_NT:*)
- echo x86_64-pc-mks
- exit ;;
- i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
- # UNAME_MACHINE based on the output of uname instead of i386?
- echo i586-pc-interix
- exit ;;
i*:UWIN*:*)
- echo ${UNAME_MACHINE}-pc-uwin
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-uwin
+ ;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
- echo x86_64-unknown-cygwin
- exit ;;
- p*:CYGWIN*:*)
- echo powerpcle-unknown-cygwin
- exit ;;
+ GUESS=x86_64-pc-cygwin
+ ;;
prep*:SunOS:5.*:*)
- echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=powerpcle-unknown-solaris2$SUN_REL
+ ;;
*:GNU:*:*)
# the GNU system
- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
- exit ;;
+ GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'`
+ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'`
+ GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL
+ ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
- exit ;;
- i*86:Minix:*:*)
- echo ${UNAME_MACHINE}-pc-minix
- exit ;;
+ GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"`
+ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
+ ;;
+ *:Minix:*:*)
+ GUESS=$UNAME_MACHINE-unknown-minix
+ ;;
aarch64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
alpha:Linux:*:*)
- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
@@ -927,183 +985,225 @@ EOF
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
- arc:Linux:*:* | arceb:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
arm*:Linux:*:*)
- eval $set_cc_for_build
+ set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi
else
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf
fi
fi
- exit ;;
+ ;;
avr32*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
cris:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+ ;;
crisv32:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+ ;;
e2k:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
frv:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
hexagon:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
i*86:Linux:*:*)
- echo ${UNAME_MACHINE}-pc-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-linux-$LIBC
+ ;;
ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
k1om:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
m32r*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
mips:Linux:*:* | mips64:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ IS_GLIBC=0
+ test x"${LIBC}" = xgnu && IS_GLIBC=1
+ sed 's/^ //' << EOF > "$dummy.c"
#undef CPU
- #undef ${UNAME_MACHINE}
- #undef ${UNAME_MACHINE}el
+ #undef mips
+ #undef mipsel
+ #undef mips64
+ #undef mips64el
+ #if ${IS_GLIBC} && defined(_ABI64)
+ LIBCABI=gnuabi64
+ #else
+ #if ${IS_GLIBC} && defined(_ABIN32)
+ LIBCABI=gnuabin32
+ #else
+ LIBCABI=${LIBC}
+ #endif
+ #endif
+
+ #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa64r6
+ #else
+ #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa32r6
+ #else
+ #if defined(__mips64)
+ CPU=mips64
+ #else
+ CPU=mips
+ #endif
+ #endif
+ #endif
+
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=${UNAME_MACHINE}el
+ MIPS_ENDIAN=el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=${UNAME_MACHINE}
+ MIPS_ENDIAN=
#else
- CPU=
+ MIPS_ENDIAN=
#endif
#endif
EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+ cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`
+ eval "$cc_set_vars"
+ test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
;;
mips64el:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
openrisc*:Linux:*:*)
- echo or1k-unknown-linux-${LIBC}
- exit ;;
+ GUESS=or1k-unknown-linux-$LIBC
+ ;;
or32:Linux:*:* | or1k*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
padre:Linux:*:*)
- echo sparc-unknown-linux-${LIBC}
- exit ;;
+ GUESS=sparc-unknown-linux-$LIBC
+ ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-${LIBC}
- exit ;;
+ GUESS=hppa64-unknown-linux-$LIBC
+ ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
- PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
- *) echo hppa-unknown-linux-${LIBC} ;;
+ PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;;
+ PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;;
+ *) GUESS=hppa-unknown-linux-$LIBC ;;
esac
- exit ;;
+ ;;
ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-${LIBC}
- exit ;;
+ GUESS=powerpc64-unknown-linux-$LIBC
+ ;;
ppc:Linux:*:*)
- echo powerpc-unknown-linux-${LIBC}
- exit ;;
+ GUESS=powerpc-unknown-linux-$LIBC
+ ;;
ppc64le:Linux:*:*)
- echo powerpc64le-unknown-linux-${LIBC}
- exit ;;
+ GUESS=powerpc64le-unknown-linux-$LIBC
+ ;;
ppcle:Linux:*:*)
- echo powerpcle-unknown-linux-${LIBC}
- exit ;;
- riscv32:Linux:*:* | riscv64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=powerpcle-unknown-linux-$LIBC
+ ;;
+ riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-ibm-linux-$LIBC
+ ;;
sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
tile*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
vax:Linux:*:*)
- echo ${UNAME_MACHINE}-dec-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-dec-linux-$LIBC
+ ;;
x86_64:Linux:*:*)
- echo ${UNAME_MACHINE}-pc-linux-${LIBC}
- exit ;;
+ set_cc_for_build
+ LIBCABI=$LIBC
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_X32 >/dev/null
+ then
+ LIBCABI=${LIBC}x32
+ fi
+ fi
+ GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI
+ ;;
xtensa*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
# sysname and nodename.
- echo i386-sequent-sysv4
- exit ;;
+ GUESS=i386-sequent-sysv4
+ ;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
- echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
+ ;;
i*86:OS/2:*:*)
# If we were able to find `uname', then EMX Unix compatibility
# is probably installed.
- echo ${UNAME_MACHINE}-pc-os2-emx
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-os2-emx
+ ;;
i*86:XTS-300:*:STOP)
- echo ${UNAME_MACHINE}-unknown-stop
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-stop
+ ;;
i*86:atheos:*:*)
- echo ${UNAME_MACHINE}-unknown-atheos
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-atheos
+ ;;
i*86:syllable:*:*)
- echo ${UNAME_MACHINE}-pc-syllable
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-syllable
+ ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
- echo i386-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ GUESS=i386-unknown-lynxos$UNAME_RELEASE
+ ;;
i*86:*DOS:*:*)
- echo ${UNAME_MACHINE}-pc-msdosdjgpp
- exit ;;
- i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
- UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ GUESS=$UNAME_MACHINE-pc-msdosdjgpp
+ ;;
+ i*86:*:4.*:*)
+ UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
- echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL
else
- echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL
fi
- exit ;;
+ ;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
@@ -1111,12 +1211,12 @@ EOF
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
- echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ ;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
- echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ GUESS=$UNAME_MACHINE-pc-isc$UNAME_REL
elif /bin/uname -X 2>/dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
@@ -1126,11 +1226,11 @@ EOF
&& UNAME_MACHINE=i686
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
&& UNAME_MACHINE=i686
- echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL
else
- echo ${UNAME_MACHINE}-pc-sysv32
+ GUESS=$UNAME_MACHINE-pc-sysv32
fi
- exit ;;
+ ;;
pc:*:*:*)
# Left here for compatibility:
# uname -m prints for DJGPP always 'pc', but it prints nothing about
@@ -1138,31 +1238,31 @@ EOF
# Note: whatever this is, it MUST be the same as what config.sub
# prints for the "djgpp" host, or else GDB configure will decide that
# this is a cross-build.
- echo i586-pc-msdosdjgpp
- exit ;;
+ GUESS=i586-pc-msdosdjgpp
+ ;;
Intel:Mach:3*:*)
- echo i386-pc-mach3
- exit ;;
+ GUESS=i386-pc-mach3
+ ;;
paragon:*:*:*)
- echo i860-intel-osf1
- exit ;;
+ GUESS=i860-intel-osf1
+ ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
- echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
- echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4
fi
- exit ;;
+ ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
- echo m68010-convergent-sysv
- exit ;;
+ GUESS=m68010-convergent-sysv
+ ;;
mc68k:UNIX:SYSTEM5:3.51m)
- echo m68k-convergent-sysv
- exit ;;
+ GUESS=m68k-convergent-sysv
+ ;;
M680?0:D-NIX:5.3:*)
- echo m68k-diab-dnix
- exit ;;
+ GUESS=m68k-diab-dnix
+ ;;
M68*:*:R3V[5678]*:*)
test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
@@ -1170,9 +1270,9 @@ EOF
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
@@ -1181,249 +1281,437 @@ EOF
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
- echo m68k-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-unknown-lynxos$UNAME_RELEASE
+ ;;
mc68030:UNIX_System_V:4.*:*)
- echo m68k-atari-sysv4
- exit ;;
+ GUESS=m68k-atari-sysv4
+ ;;
TSUNAMI:LynxOS:2.*:*)
- echo sparc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ GUESS=sparc-unknown-lynxos$UNAME_RELEASE
+ ;;
rs6000:LynxOS:2.*:*)
- echo rs6000-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ GUESS=rs6000-unknown-lynxos$UNAME_RELEASE
+ ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
- echo powerpc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ GUESS=powerpc-unknown-lynxos$UNAME_RELEASE
+ ;;
SM[BE]S:UNIX_SV:*:*)
- echo mips-dde-sysv${UNAME_RELEASE}
- exit ;;
+ GUESS=mips-dde-sysv$UNAME_RELEASE
+ ;;
RM*:ReliantUNIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
+ GUESS=mips-sni-sysv4
+ ;;
RM*:SINIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
+ GUESS=mips-sni-sysv4
+ ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
- echo ${UNAME_MACHINE}-sni-sysv4
+ GUESS=$UNAME_MACHINE-sni-sysv4
else
- echo ns32k-sni-sysv
+ GUESS=ns32k-sni-sysv
fi
- exit ;;
+ ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
- echo i586-unisys-sysv4
- exit ;;
+ GUESS=i586-unisys-sysv4
+ ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
- echo hppa1.1-stratus-sysv4
- exit ;;
+ GUESS=hppa1.1-stratus-sysv4
+ ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
- echo i860-stratus-sysv4
- exit ;;
+ GUESS=i860-stratus-sysv4
+ ;;
i*86:VOS:*:*)
# From Paul.Green@stratus.com.
- echo ${UNAME_MACHINE}-stratus-vos
- exit ;;
+ GUESS=$UNAME_MACHINE-stratus-vos
+ ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
- echo hppa1.1-stratus-vos
- exit ;;
+ GUESS=hppa1.1-stratus-vos
+ ;;
mc68*:A/UX:*:*)
- echo m68k-apple-aux${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-apple-aux$UNAME_RELEASE
+ ;;
news*:NEWS-OS:6*:*)
- echo mips-sony-newsos6
- exit ;;
+ GUESS=mips-sony-newsos6
+ ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
- if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
+ if test -d /usr/nec; then
+ GUESS=mips-nec-sysv$UNAME_RELEASE
else
- echo mips-unknown-sysv${UNAME_RELEASE}
+ GUESS=mips-unknown-sysv$UNAME_RELEASE
fi
- exit ;;
+ ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
- echo powerpc-be-beos
- exit ;;
+ GUESS=powerpc-be-beos
+ ;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
- echo powerpc-apple-beos
- exit ;;
+ GUESS=powerpc-apple-beos
+ ;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
- echo i586-pc-beos
- exit ;;
+ GUESS=i586-pc-beos
+ ;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
- echo i586-pc-haiku
- exit ;;
+ GUESS=i586-pc-haiku
+ ;;
x86_64:Haiku:*:*)
- echo x86_64-unknown-haiku
- exit ;;
+ GUESS=x86_64-unknown-haiku
+ ;;
SX-4:SUPER-UX:*:*)
- echo sx4-nec-superux${UNAME_RELEASE}
- exit ;;
+ GUESS=sx4-nec-superux$UNAME_RELEASE
+ ;;
SX-5:SUPER-UX:*:*)
- echo sx5-nec-superux${UNAME_RELEASE}
- exit ;;
+ GUESS=sx5-nec-superux$UNAME_RELEASE
+ ;;
SX-6:SUPER-UX:*:*)
- echo sx6-nec-superux${UNAME_RELEASE}
- exit ;;
+ GUESS=sx6-nec-superux$UNAME_RELEASE
+ ;;
SX-7:SUPER-UX:*:*)
- echo sx7-nec-superux${UNAME_RELEASE}
- exit ;;
+ GUESS=sx7-nec-superux$UNAME_RELEASE
+ ;;
SX-8:SUPER-UX:*:*)
- echo sx8-nec-superux${UNAME_RELEASE}
- exit ;;
+ GUESS=sx8-nec-superux$UNAME_RELEASE
+ ;;
SX-8R:SUPER-UX:*:*)
- echo sx8r-nec-superux${UNAME_RELEASE}
- exit ;;
+ GUESS=sx8r-nec-superux$UNAME_RELEASE
+ ;;
SX-ACE:SUPER-UX:*:*)
- echo sxace-nec-superux${UNAME_RELEASE}
- exit ;;
+ GUESS=sxace-nec-superux$UNAME_RELEASE
+ ;;
Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody${UNAME_RELEASE}
- exit ;;
+ GUESS=powerpc-apple-rhapsody$UNAME_RELEASE
+ ;;
*:Rhapsody:*:*)
- echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE
+ ;;
+ arm64:Darwin:*:*)
+ GUESS=aarch64-apple-darwin$UNAME_RELEASE
+ ;;
*:Darwin:*:*)
- UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
- eval $set_cc_for_build
- if test "$UNAME_PROCESSOR" = unknown ; then
- UNAME_PROCESSOR=powerpc
+ UNAME_PROCESSOR=`uname -p`
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ if command -v xcode-select > /dev/null 2> /dev/null && \
+ ! xcode-select --print-path > /dev/null 2> /dev/null ; then
+ # Avoid executing cc if there is no toolchain installed as
+ # cc will be a stub that puts up a graphical alert
+ # prompting the user to install developer tools.
+ CC_FOR_BUILD=no_compiler_found
+ else
+ set_cc_for_build
fi
- if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
- if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- case $UNAME_PROCESSOR in
- i386) UNAME_PROCESSOR=x86_64 ;;
- powerpc) UNAME_PROCESSOR=powerpc64 ;;
- esac
- fi
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+ if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_PPC >/dev/null
+ then
+ UNAME_PROCESSOR=powerpc
fi
elif test "$UNAME_PROCESSOR" = i386 ; then
- # Avoid executing cc on OS X 10.9, as it ships with a stub
- # that puts up a graphical alert prompting to install
- # developer tools. Any system running Mac OS X 10.7 or
- # later (Darwin 11 and later) is required to have a 64-bit
- # processor. This is not true of the ARM version of Darwin
- # that Apple uses in portable devices.
- UNAME_PROCESSOR=x86_64
+ # uname -m returns i386 or x86_64
+ UNAME_PROCESSOR=$UNAME_MACHINE
fi
- echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE
+ ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
if test "$UNAME_PROCESSOR" = x86; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
- echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE
+ ;;
*:QNX:*:4*)
- echo i386-pc-qnx
- exit ;;
- NEO-?:NONSTOP_KERNEL:*:*)
- echo neo-tandem-nsk${UNAME_RELEASE}
- exit ;;
+ GUESS=i386-pc-qnx
+ ;;
+ NEO-*:NONSTOP_KERNEL:*:*)
+ GUESS=neo-tandem-nsk$UNAME_RELEASE
+ ;;
NSE-*:NONSTOP_KERNEL:*:*)
- echo nse-tandem-nsk${UNAME_RELEASE}
- exit ;;
- NSR-?:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk${UNAME_RELEASE}
- exit ;;
+ GUESS=nse-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSR-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsr-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSV-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsv-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSX-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsx-tandem-nsk$UNAME_RELEASE
+ ;;
*:NonStop-UX:*:*)
- echo mips-compaq-nonstopux
- exit ;;
+ GUESS=mips-compaq-nonstopux
+ ;;
BS2000:POSIX*:*:*)
- echo bs2000-siemens-sysv
- exit ;;
+ GUESS=bs2000-siemens-sysv
+ ;;
DS/*:UNIX_System_V:*:*)
- echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE
+ ;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
- if test "$cputype" = 386; then
+ if test "${cputype-}" = 386; then
UNAME_MACHINE=i386
- else
- UNAME_MACHINE="$cputype"
+ elif test "x${cputype-}" != x; then
+ UNAME_MACHINE=$cputype
fi
- echo ${UNAME_MACHINE}-unknown-plan9
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-plan9
+ ;;
*:TOPS-10:*:*)
- echo pdp10-unknown-tops10
- exit ;;
+ GUESS=pdp10-unknown-tops10
+ ;;
*:TENEX:*:*)
- echo pdp10-unknown-tenex
- exit ;;
+ GUESS=pdp10-unknown-tenex
+ ;;
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
- echo pdp10-dec-tops20
- exit ;;
+ GUESS=pdp10-dec-tops20
+ ;;
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
- echo pdp10-xkl-tops20
- exit ;;
+ GUESS=pdp10-xkl-tops20
+ ;;
*:TOPS-20:*:*)
- echo pdp10-unknown-tops20
- exit ;;
+ GUESS=pdp10-unknown-tops20
+ ;;
*:ITS:*:*)
- echo pdp10-unknown-its
- exit ;;
+ GUESS=pdp10-unknown-its
+ ;;
SEI:*:*:SEIUX)
- echo mips-sei-seiux${UNAME_RELEASE}
- exit ;;
+ GUESS=mips-sei-seiux$UNAME_RELEASE
+ ;;
*:DragonFly:*:*)
- echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
- exit ;;
+ DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL
+ ;;
*:*VMS:*:*)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
- case "${UNAME_MACHINE}" in
- A*) echo alpha-dec-vms ; exit ;;
- I*) echo ia64-dec-vms ; exit ;;
- V*) echo vax-dec-vms ; exit ;;
+ case $UNAME_MACHINE in
+ A*) GUESS=alpha-dec-vms ;;
+ I*) GUESS=ia64-dec-vms ;;
+ V*) GUESS=vax-dec-vms ;;
esac ;;
*:XENIX:*:SysV)
- echo i386-pc-xenix
- exit ;;
+ GUESS=i386-pc-xenix
+ ;;
i*86:skyos:*:*)
- echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
- exit ;;
+ SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`
+ GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL
+ ;;
i*86:rdos:*:*)
- echo ${UNAME_MACHINE}-pc-rdos
- exit ;;
- i*86:AROS:*:*)
- echo ${UNAME_MACHINE}-pc-aros
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-rdos
+ ;;
+ i*86:Fiwix:*:*)
+ GUESS=$UNAME_MACHINE-pc-fiwix
+ ;;
+ *:AROS:*:*)
+ GUESS=$UNAME_MACHINE-unknown-aros
+ ;;
x86_64:VMkernel:*:*)
- echo ${UNAME_MACHINE}-unknown-esx
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-esx
+ ;;
amd64:Isilon\ OneFS:*:*)
- echo x86_64-unknown-onefs
- exit ;;
+ GUESS=x86_64-unknown-onefs
+ ;;
+ *:Unleashed:*:*)
+ GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
+ ;;
+esac
+
+# Do we have a guess based on uname results?
+if test "x$GUESS" != x; then
+ echo "$GUESS"
+ exit
+fi
+
+# No uname command or uname output not recognized.
+set_cc_for_build
+cat > "$dummy.c" <<EOF
+#ifdef _SEQUENT_
+#include <sys/types.h>
+#include <sys/utsname.h>
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#include <signal.h>
+#if defined(_SIZE_T_) || defined(SIGLOST)
+#include <sys/utsname.h>
+#endif
+#endif
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+#include <sys/param.h>
+#if defined (BSD)
+#if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+#else
+#if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#endif
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#else
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname un;
+ uname (&un);
+ printf ("vax-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname *un;
+ uname (&un);
+ printf ("mips-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("mips-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
+
+echo "$0: unable to guess system type" >&2
+
+case $UNAME_MACHINE:$UNAME_SYSTEM in
+ mips:Linux | mips64:Linux)
+ # If we got here on MIPS GNU/Linux, output extra information.
+ cat >&2 <<EOF
+
+NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+the system type. Please install a C compiler and try again.
+EOF
+ ;;
esac
cat >&2 <<EOF
-$0: unable to guess system type
This script (version $timestamp), has failed to recognize the
-operating system you are using. If your script is old, overwrite
-config.guess and config.sub with the latest versions from:
+operating system you are using. If your script is old, overwrite *all*
+copies of config.guess and config.sub with the latest versions from:
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+ https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
and
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+ https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
+EOF
+
+our_year=`echo $timestamp | sed 's,-.*,,'`
+thisyear=`date +%Y`
+# shellcheck disable=SC2003
+script_age=`expr "$thisyear" - "$our_year"`
+if test "$script_age" -lt 3 ; then
+ cat >&2 <<EOF
If $0 has already been updated, send the following data and any
information you think might be pertinent to config-patches@gnu.org to
@@ -1446,16 +1734,17 @@ hostinfo = `(hostinfo) 2>/dev/null`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
-UNAME_MACHINE = ${UNAME_MACHINE}
-UNAME_RELEASE = ${UNAME_RELEASE}
-UNAME_SYSTEM = ${UNAME_SYSTEM}
-UNAME_VERSION = ${UNAME_VERSION}
+UNAME_MACHINE = "$UNAME_MACHINE"
+UNAME_RELEASE = "$UNAME_RELEASE"
+UNAME_SYSTEM = "$UNAME_SYSTEM"
+UNAME_VERSION = "$UNAME_VERSION"
EOF
+fi
exit 1
# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
diff --git a/config.h b/config.h
index 66661fe..582e419 100644
--- a/config.h
+++ b/config.h
@@ -5,7 +5,7 @@
/* #undef DEBUG */
/* Define when sys_errlist is defined in the standard include files */
-#define DECL_SYS_ERRLIST 1
+/* #undef DECL_SYS_ERRLIST */
/* Define to 1 if you have the `alarm' function. */
#define HAVE_ALARM 1
@@ -41,7 +41,7 @@
#define HAVE_GETOPT_H 1
/* Define to 1 if you have the `getpass' function. */
-#define HAVE_GETPASS 1
+/* #undef HAVE_GETPASS */
/* Define to 1 if you have the `gettimeofday' function. */
#define HAVE_GETTIMEOFDAY 1
@@ -100,17 +100,17 @@
/* Define to 1 if you have the `lockf' function. */
#define HAVE_LOCKF 1
-/* Define when the compiler supports LOFF_T type */
-#define HAVE_LOFF_T 1
+/* Define to 1 if the system has the type `loff_t'. */
+/* #undef HAVE_LOFF_T */
-/* Define when the compiler supports LONG_LONG type */
+/* Define to 1 if the system has the type `long long'. */
#define HAVE_LONG_LONG 1
/* Define to 1 if you have the `lseek64' function. */
-#define HAVE_LSEEK64 1
+/* #undef HAVE_LSEEK64 */
/* Define when you have an LSEEK64 prototype */
-#define HAVE_LSEEK64_PROTOTYPE 1
+/* #undef HAVE_LSEEK64_PROTOTYPE */
/* Define to 1 if you have the <malloc.h> header file. */
#define HAVE_MALLOC_H 1
@@ -142,11 +142,11 @@
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#define HAVE_NETINET_TCP_H 1
-/* Define when the compiler supports OFFSET_T type */
-/* #undef HAVE_OFFSET_T */
+/* Define to 1 if the system has the type `off64_t'. */
+/* #undef HAVE_OFF64_T */
-/* Define when the system has a 64 bit off_t type */
-#define HAVE_OFF_T_64 1
+/* Define to 1 if the system has the type `offset_t'. */
+/* #undef HAVE_OFFSET_T */
/* Define to 1 if you have the `on_exit' function. */
#define HAVE_ON_EXIT 1
@@ -188,7 +188,13 @@
#define HAVE_SRANDOM 1
/* Define to 1 if you have the `stat64' function. */
-#define HAVE_STAT64 1
+/* #undef HAVE_STAT64 */
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
@@ -253,6 +259,9 @@
/* Define to 1 if you have the `strtoul' function. */
#define HAVE_STRTOUL 1
+/* Define to 1 if you have the <sys/fdio.h> header file. */
+/* #undef HAVE_SYS_FDIO_H */
+
/* Define to 1 if you have the <sys/file.h> header file. */
#define HAVE_SYS_FILE_H 1
@@ -302,7 +311,9 @@
#define HAVE_TERMIOS_H 1
/* Define to 1 if you have the <termio.h> header file. */
+#if !defined(ANDROID_HOST_MUSL)
#define HAVE_TERMIO_H 1
+#endif
/* Define to 1 if you have the `toupper_l' function. */
#define HAVE_TOUPPER_L 1
@@ -343,6 +354,9 @@
/* Define to 1 if you have the <xlocale.h> header file. */
/* #undef HAVE_XLOCALE_H */
+/* Define to 1 if the system has the type `_Bool'. */
+#define HAVE__BOOL 1
+
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
@@ -370,8 +384,8 @@
/* The size of `long', as computed by sizeof. */
#define SIZEOF_LONG 8
-/* The size of `long long', as computed by sizeof. */
-#define SIZEOF_LONG_LONG 8
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T 8
@@ -437,6 +451,12 @@
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
+/* Needed for off64_t / lseek64 */
+/* #undef _LARGEFILE64_SOURCE */
+
+/* Might be needed for loff_t / llseek64 */
+/* #undef _LARGEFILE_SOURCE */
+
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
diff --git a/config.h.in b/config.h.in
index 783ee60..601d4f0 100644
--- a/config.h.in
+++ b/config.h.in
@@ -99,10 +99,10 @@
/* Define to 1 if you have the `lockf' function. */
#undef HAVE_LOCKF
-/* Define when the compiler supports LOFF_T type */
+/* Define to 1 if the system has the type `loff_t'. */
#undef HAVE_LOFF_T
-/* Define when the compiler supports LONG_LONG type */
+/* Define to 1 if the system has the type `long long'. */
#undef HAVE_LONG_LONG
/* Define to 1 if you have the `lseek64' function. */
@@ -141,11 +141,11 @@
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#undef HAVE_NETINET_TCP_H
-/* Define when the compiler supports OFFSET_T type */
-#undef HAVE_OFFSET_T
+/* Define to 1 if the system has the type `off64_t'. */
+#undef HAVE_OFF64_T
-/* Define when the system has a 64 bit off_t type */
-#undef HAVE_OFF_T_64
+/* Define to 1 if the system has the type `offset_t'. */
+#undef HAVE_OFFSET_T
/* Define to 1 if you have the `on_exit' function. */
#undef HAVE_ON_EXIT
@@ -189,6 +189,12 @@
/* Define to 1 if you have the `stat64' function. */
#undef HAVE_STAT64
+/* Define to 1 if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
@@ -252,6 +258,9 @@
/* Define to 1 if you have the `strtoul' function. */
#undef HAVE_STRTOUL
+/* Define to 1 if you have the <sys/fdio.h> header file. */
+#undef HAVE_SYS_FDIO_H
+
/* Define to 1 if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H
@@ -342,6 +351,9 @@
/* Define to 1 if you have the <xlocale.h> header file. */
#undef HAVE_XLOCALE_H
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
@@ -369,8 +381,8 @@
/* The size of `long', as computed by sizeof. */
#undef SIZEOF_LONG
-/* The size of `long long', as computed by sizeof. */
-#undef SIZEOF_LONG_LONG
+/* The size of `off_t', as computed by sizeof. */
+#undef SIZEOF_OFF_T
/* The size of `size_t', as computed by sizeof. */
#undef SIZEOF_SIZE_T
@@ -436,6 +448,12 @@
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
+/* Needed for off64_t / lseek64 */
+#undef _LARGEFILE64_SOURCE
+
+/* Might be needed for loff_t / llseek64 */
+#undef _LARGEFILE_SOURCE
+
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES
diff --git a/config.sub b/config.sub
index dd2ca93..dba16e8 100755
--- a/config.sub
+++ b/config.sub
@@ -1,12 +1,14 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2016 Free Software Foundation, Inc.
+# Copyright 1992-2022 Free Software Foundation, Inc.
-timestamp='2016-11-04'
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2022-01-03'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
+# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
@@ -15,7 +17,7 @@ timestamp='2016-11-04'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -33,7 +35,7 @@ timestamp='2016-11-04'
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
@@ -50,6 +52,13 @@ timestamp='2016-11-04'
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX. However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
@@ -57,7 +66,7 @@ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
-Operation modes:
+Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
@@ -67,7 +76,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2016 Free Software Foundation, Inc.
+Copyright 1992-2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -89,12 +98,12 @@ while test $# -gt 0 ; do
- ) # Use stdin as input.
break ;;
-* )
- echo "$me: invalid option $1$help"
+ echo "$me: invalid option $1$help" >&2
exit 1 ;;
*local*)
# First pass through any local machine types.
- echo $1
+ echo "$1"
exit ;;
* )
@@ -110,1244 +119,1186 @@ case $# in
exit 1;;
esac
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
-case $maybe_os in
- nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
- linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
- knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
- kopensolaris*-gnu* | cloudabi*-eabi* | \
- storm-chaos* | os2-emx* | rtmk-nova*)
- os=-$maybe_os
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
- ;;
- android-linux)
- os=-linux-android
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
- ;;
- *)
- basic_machine=`echo $1 | sed 's/-[^-]*$//'`
- if [ $basic_machine != $1 ]
- then os=`echo $1 | sed 's/.*-/-/'`
- else os=; fi
- ;;
-esac
+# Split fields of configuration type
+# shellcheck disable=SC2162
+saved_IFS=$IFS
+IFS="-" read field1 field2 field3 field4 <<EOF
+$1
+EOF
+IFS=$saved_IFS
-### Let's recognize common machines as not being operating systems so
-### that things like config.sub decstation-3100 work. We also
-### recognize some manufacturers as not being operating systems, so we
-### can provide default operating systems below.
-case $os in
- -sun*os*)
- # Prevent following clause from handling this invalid input.
- ;;
- -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
- -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
- -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
- -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
- -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
- -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray | -microblaze*)
- os=
- basic_machine=$1
- ;;
- -bluegene*)
- os=-cnk
- ;;
- -sim | -cisco | -oki | -wec | -winbond)
- os=
- basic_machine=$1
- ;;
- -scout)
- ;;
- -wrs)
- os=-vxworks
- basic_machine=$1
- ;;
- -chorusos*)
- os=-chorusos
- basic_machine=$1
- ;;
- -chorusrdb)
- os=-chorusrdb
- basic_machine=$1
- ;;
- -hiux*)
- os=-hiuxwe2
- ;;
- -sco6)
- os=-sco5v6
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5)
- os=-sco3.2v5
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco4)
- os=-sco3.2v4
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2.[4-9]*)
- os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2v[4-9]*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5v6*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco*)
- os=-sco3.2v2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -udk*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -isc)
- os=-isc2.2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -clix*)
- basic_machine=clipper-intergraph
- ;;
- -isc*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -lynx*178)
- os=-lynxos178
- ;;
- -lynx*5)
- os=-lynxos5
- ;;
- -lynx*)
- os=-lynxos
+# Separate into logical components for further validation
+case $1 in
+ *-*-*-*-*)
+ echo Invalid configuration \`"$1"\': more than four components >&2
+ exit 1
;;
- -ptx*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ *-*-*-*)
+ basic_machine=$field1-$field2
+ basic_os=$field3-$field4
;;
- -windowsnt*)
- os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ *-*-*)
+ # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
+ # parts
+ maybe_os=$field2-$field3
+ case $maybe_os in
+ nto-qnx* | linux-* | uclinux-uclibc* \
+ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
+ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
+ | storm-chaos* | os2-emx* | rtmk-nova*)
+ basic_machine=$field1
+ basic_os=$maybe_os
+ ;;
+ android-linux)
+ basic_machine=$field1-unknown
+ basic_os=linux-android
+ ;;
+ *)
+ basic_machine=$field1-$field2
+ basic_os=$field3
+ ;;
+ esac
;;
- -psos*)
- os=-psos
+ *-*)
+ # A lone config we happen to match not fitting any pattern
+ case $field1-$field2 in
+ decstation-3100)
+ basic_machine=mips-dec
+ basic_os=
+ ;;
+ *-*)
+ # Second component is usually, but not always the OS
+ case $field2 in
+ # Prevent following clause from handling this valid os
+ sun*os*)
+ basic_machine=$field1
+ basic_os=$field2
+ ;;
+ zephyr*)
+ basic_machine=$field1-unknown
+ basic_os=$field2
+ ;;
+ # Manufacturers
+ dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
+ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
+ | unicom* | ibm* | next | hp | isi* | apollo | altos* \
+ | convergent* | ncr* | news | 32* | 3600* | 3100* \
+ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
+ | ultra | tti* | harris | dolphin | highlevel | gould \
+ | cbm | ns | masscomp | apple | axis | knuth | cray \
+ | microblaze* | sim | cisco \
+ | oki | wec | wrs | winbond)
+ basic_machine=$field1-$field2
+ basic_os=
+ ;;
+ *)
+ basic_machine=$field1
+ basic_os=$field2
+ ;;
+ esac
+ ;;
+ esac
;;
- -mint | -mint[0-9]*)
- basic_machine=m68k-atari
- os=-mint
+ *)
+ # Convert single-component short-hands not valid as part of
+ # multi-component configurations.
+ case $field1 in
+ 386bsd)
+ basic_machine=i386-pc
+ basic_os=bsd
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ basic_os=scout
+ ;;
+ alliant)
+ basic_machine=fx80-alliant
+ basic_os=
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ basic_os=
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ basic_os=bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ basic_os=sysv
+ ;;
+ amiga)
+ basic_machine=m68k-unknown
+ basic_os=
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ basic_os=amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ basic_os=sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ basic_os=sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ basic_os=bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ basic_os=aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ basic_os=aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ basic_os=dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ basic_os=linux
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ basic_os=cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ basic_os=bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ basic_os=bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ basic_os=bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ basic_os=bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ basic_os=bsd
+ ;;
+ cray)
+ basic_machine=j90-cray
+ basic_os=unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ basic_os=
+ ;;
+ da30)
+ basic_machine=m68k-da30
+ basic_os=
+ ;;
+ decstation | pmax | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ basic_os=
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ basic_os=sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ basic_os=dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ basic_os=msdosdjgpp
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ basic_os=ebmon
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ basic_os=ose
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ basic_os=sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ basic_os=go32
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ basic_os=hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ basic_os=xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ basic_os=hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ basic_os=sysv3
+ ;;
+ hp300 | hp300hpux)
+ basic_machine=m68k-hp
+ basic_os=hpux
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ basic_os=bsd
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ basic_os=osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ basic_os=proelf
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ basic_os=mach
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ basic_os=sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ basic_os=linux
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ basic_os=sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ basic_os=sysv
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ basic_os=mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ basic_os=mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ basic_os=mingw32ce
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ basic_os=coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ basic_os=morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ basic_os=moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ basic_os=msdos
+ ;;
+ msys)
+ basic_machine=i686-pc
+ basic_os=msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ basic_os=mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ basic_os=nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ basic_os=sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-pc
+ basic_os=netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ basic_os=linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ basic_os=newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ basic_os=newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ basic_os=sysv
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ basic_os=cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ basic_os=cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ basic_os=nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ basic_os=mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ basic_os=nonstopux
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ basic_os=os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ basic_os=ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ basic_os=os68k
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ basic_os=osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ basic_os=linux
+ ;;
+ psp)
+ basic_machine=mipsallegrexel-sony
+ basic_os=psp
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ basic_os=pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ basic_os=rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ basic_os=rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ basic_os=coff
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ sei)
+ basic_machine=mips-sei
+ basic_os=seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ basic_os=
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ basic_os=sysv2
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ basic_os=
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ basic_os=sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ basic_os=
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ basic_os=sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ basic_os=sunos4
+ ;;
+ sun3)
+ basic_machine=m68k-sun
+ basic_os=
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ basic_os=sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ basic_os=sunos4
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ basic_os=
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ basic_os=sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ basic_os=sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ basic_os=solaris2
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ basic_os=
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ basic_os=unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ basic_os=dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ basic_os=unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ basic_os=unicos
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ basic_os=tops20
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ basic_os=tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ basic_os=sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ basic_os=none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ basic_os=sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ basic_os=vms
+ ;;
+ vsta)
+ basic_machine=i386-pc
+ basic_os=vsta
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ basic_os=vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ basic_os=vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ basic_os=vxworks
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ basic_os=mingw32
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ basic_os=unicos
+ ;;
+ *)
+ basic_machine=$1
+ basic_os=
+ ;;
+ esac
;;
esac
-# Decode aliases for certain CPU-COMPANY combinations.
+# Decode 1-component or ad-hoc basic machines
case $basic_machine in
- # Recognize the basic CPU types without company name.
- # Some are omitted here because they have special meanings below.
- 1750a | 580 \
- | a29k \
- | aarch64 | aarch64_be \
- | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
- | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
- | am33_2.0 \
- | arc | arceb \
- | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
- | avr | avr32 \
- | ba \
- | be32 | be64 \
- | bfin \
- | c4x | c8051 | clipper \
- | d10v | d30v | dlx | dsp16xx \
- | e2k | epiphany \
- | fido | fr30 | frv | ft32 \
- | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
- | hexagon \
- | i370 | i860 | i960 | ia64 \
- | ip2k | iq2000 \
- | k1om \
- | le32 | le64 \
- | lm32 \
- | m32c | m32r | m32rle | m68000 | m68k | m88k \
- | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64el \
- | mips64octeon | mips64octeonel \
- | mips64orion | mips64orionel \
- | mips64r5900 | mips64r5900el \
- | mips64vr | mips64vrel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa32r6 | mipsisa32r6el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
- | mipsisa64r6 | mipsisa64r6el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipsr5900 | mipsr5900el \
- | mipstx39 | mipstx39el \
- | mn10200 | mn10300 \
- | moxie \
- | mt \
- | msp430 \
- | nds32 | nds32le | nds32be \
- | nios | nios2 | nios2eb | nios2el \
- | ns16k | ns32k \
- | open8 | or1k | or1knd | or32 \
- | pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle \
- | pru \
- | pyramid \
- | riscv32 | riscv64 \
- | rl78 | rx \
- | score \
- | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
- | sh64 | sh64le \
- | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
- | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
- | spu \
- | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
- | ubicom32 \
- | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
- | visium \
- | we32k \
- | x86 | xc16x | xstormy16 | xtensa \
- | z8k | z80)
- basic_machine=$basic_machine-unknown
- ;;
- c54x)
- basic_machine=tic54x-unknown
- ;;
- c55x)
- basic_machine=tic55x-unknown
- ;;
- c6x)
- basic_machine=tic6x-unknown
- ;;
- leon|leon[3-9])
- basic_machine=sparc-$basic_machine
- ;;
- m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
- basic_machine=$basic_machine-unknown
- os=-none
+ # Here we handle the default manufacturer of certain CPU types. It is in
+ # some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ cpu=hppa1.1
+ vendor=winbond
;;
- m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ op50n)
+ cpu=hppa1.1
+ vendor=oki
;;
- ms1)
- basic_machine=mt-unknown
+ op60c)
+ cpu=hppa1.1
+ vendor=oki
;;
-
- strongarm | thumb | xscale)
- basic_machine=arm-unknown
+ ibm*)
+ cpu=i370
+ vendor=ibm
;;
- xgate)
- basic_machine=$basic_machine-unknown
- os=-none
+ orion105)
+ cpu=clipper
+ vendor=highlevel
;;
- xscaleeb)
- basic_machine=armeb-unknown
+ mac | mpw | mac-mpw)
+ cpu=m68k
+ vendor=apple
;;
-
- xscaleel)
- basic_machine=armel-unknown
+ pmac | pmac-mpw)
+ cpu=powerpc
+ vendor=apple
;;
- # We use `pc' rather than `unknown'
- # because (1) that's what they normally are, and
- # (2) the word "unknown" tends to confuse beginning users.
- i*86 | x86_64)
- basic_machine=$basic_machine-pc
- ;;
- # Object if more than one company name word.
- *-*-*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
- ;;
- # Recognize the basic CPU types with company name.
- 580-* \
- | a29k-* \
- | aarch64-* | aarch64_be-* \
- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
- | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
- | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
- | avr-* | avr32-* \
- | ba-* \
- | be32-* | be64-* \
- | bfin-* | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* \
- | c8051-* | clipper-* | craynv-* | cydra-* \
- | d10v-* | d30v-* | dlx-* \
- | e2k-* | elxsi-* \
- | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
- | h8300-* | h8500-* \
- | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
- | hexagon-* \
- | i*86-* | i860-* | i960-* | ia64-* \
- | ip2k-* | iq2000-* \
- | k1om-* \
- | le32-* | le64-* \
- | lm32-* \
- | m32c-* | m32r-* | m32rle-* \
- | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
- | microblaze-* | microblazeel-* \
- | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
- | mips16-* \
- | mips64-* | mips64el-* \
- | mips64octeon-* | mips64octeonel-* \
- | mips64orion-* | mips64orionel-* \
- | mips64r5900-* | mips64r5900el-* \
- | mips64vr-* | mips64vrel-* \
- | mips64vr4100-* | mips64vr4100el-* \
- | mips64vr4300-* | mips64vr4300el-* \
- | mips64vr5000-* | mips64vr5000el-* \
- | mips64vr5900-* | mips64vr5900el-* \
- | mipsisa32-* | mipsisa32el-* \
- | mipsisa32r2-* | mipsisa32r2el-* \
- | mipsisa32r6-* | mipsisa32r6el-* \
- | mipsisa64-* | mipsisa64el-* \
- | mipsisa64r2-* | mipsisa64r2el-* \
- | mipsisa64r6-* | mipsisa64r6el-* \
- | mipsisa64sb1-* | mipsisa64sb1el-* \
- | mipsisa64sr71k-* | mipsisa64sr71kel-* \
- | mipsr5900-* | mipsr5900el-* \
- | mipstx39-* | mipstx39el-* \
- | mmix-* \
- | mt-* \
- | msp430-* \
- | nds32-* | nds32le-* | nds32be-* \
- | nios-* | nios2-* | nios2eb-* | nios2el-* \
- | none-* | np1-* | ns16k-* | ns32k-* \
- | open8-* \
- | or1k*-* \
- | orion-* \
- | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
- | pru-* \
- | pyramid-* \
- | riscv32-* | riscv64-* \
- | rl78-* | romp-* | rs6000-* | rx-* \
- | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
- | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
- | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
- | sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
- | tahoe-* \
- | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
- | tile*-* \
- | tron-* \
- | ubicom32-* \
- | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
- | vax-* \
- | visium-* \
- | we32k-* \
- | x86-* | x86_64-* | xc16x-* | xps100-* \
- | xstormy16-* | xtensa*-* \
- | ymp-* \
- | z8k-* | z80-*)
- ;;
- # Recognize the basic CPU types without company name, with glob match.
- xtensa*)
- basic_machine=$basic_machine-unknown
- ;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
- 386bsd)
- basic_machine=i386-unknown
- os=-bsd
- ;;
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
- basic_machine=m68000-att
+ cpu=m68000
+ vendor=att
;;
3b*)
- basic_machine=we32k-att
- ;;
- a29khif)
- basic_machine=a29k-amd
- os=-udi
- ;;
- abacus)
- basic_machine=abacus-unknown
- ;;
- adobe68k)
- basic_machine=m68010-adobe
- os=-scout
- ;;
- alliant | fx80)
- basic_machine=fx80-alliant
- ;;
- altos | altos3068)
- basic_machine=m68k-altos
- ;;
- am29k)
- basic_machine=a29k-none
- os=-bsd
- ;;
- amd64)
- basic_machine=x86_64-pc
- ;;
- amd64-*)
- basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- amdahl)
- basic_machine=580-amdahl
- os=-sysv
- ;;
- amiga | amiga-*)
- basic_machine=m68k-unknown
- ;;
- amigaos | amigados)
- basic_machine=m68k-unknown
- os=-amigaos
- ;;
- amigaunix | amix)
- basic_machine=m68k-unknown
- os=-sysv4
- ;;
- apollo68)
- basic_machine=m68k-apollo
- os=-sysv
- ;;
- apollo68bsd)
- basic_machine=m68k-apollo
- os=-bsd
- ;;
- aros)
- basic_machine=i386-pc
- os=-aros
- ;;
- asmjs)
- basic_machine=asmjs-unknown
- ;;
- aux)
- basic_machine=m68k-apple
- os=-aux
- ;;
- balance)
- basic_machine=ns32k-sequent
- os=-dynix
- ;;
- blackfin)
- basic_machine=bfin-unknown
- os=-linux
- ;;
- blackfin-*)
- basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
+ cpu=we32k
+ vendor=att
;;
bluegene*)
- basic_machine=powerpc-ibm
- os=-cnk
- ;;
- c54x-*)
- basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c55x-*)
- basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c6x-*)
- basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c90)
- basic_machine=c90-cray
- os=-unicos
- ;;
- cegcc)
- basic_machine=arm-unknown
- os=-cegcc
- ;;
- convex-c1)
- basic_machine=c1-convex
- os=-bsd
- ;;
- convex-c2)
- basic_machine=c2-convex
- os=-bsd
- ;;
- convex-c32)
- basic_machine=c32-convex
- os=-bsd
- ;;
- convex-c34)
- basic_machine=c34-convex
- os=-bsd
- ;;
- convex-c38)
- basic_machine=c38-convex
- os=-bsd
- ;;
- cray | j90)
- basic_machine=j90-cray
- os=-unicos
- ;;
- craynv)
- basic_machine=craynv-cray
- os=-unicosmp
- ;;
- cr16 | cr16-*)
- basic_machine=cr16-unknown
- os=-elf
- ;;
- crds | unos)
- basic_machine=m68k-crds
- ;;
- crisv32 | crisv32-* | etraxfs*)
- basic_machine=crisv32-axis
- ;;
- cris | cris-* | etrax*)
- basic_machine=cris-axis
- ;;
- crx)
- basic_machine=crx-unknown
- os=-elf
- ;;
- da30 | da30-*)
- basic_machine=m68k-da30
- ;;
- decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
- basic_machine=mips-dec
+ cpu=powerpc
+ vendor=ibm
+ basic_os=cnk
;;
decsystem10* | dec10*)
- basic_machine=pdp10-dec
- os=-tops10
+ cpu=pdp10
+ vendor=dec
+ basic_os=tops10
;;
decsystem20* | dec20*)
- basic_machine=pdp10-dec
- os=-tops20
+ cpu=pdp10
+ vendor=dec
+ basic_os=tops20
;;
delta | 3300 | motorola-3300 | motorola-delta \
| 3300-motorola | delta-motorola)
- basic_machine=m68k-motorola
- ;;
- delta88)
- basic_machine=m88k-motorola
- os=-sysv3
- ;;
- dicos)
- basic_machine=i686-pc
- os=-dicos
+ cpu=m68k
+ vendor=motorola
;;
- djgpp)
- basic_machine=i586-pc
- os=-msdosdjgpp
- ;;
- dpx20 | dpx20-*)
- basic_machine=rs6000-bull
- os=-bosx
- ;;
- dpx2* | dpx2*-bull)
- basic_machine=m68k-bull
- os=-sysv3
- ;;
- e500v[12])
- basic_machine=powerpc-unknown
- os=$os"spe"
- ;;
- e500v[12]-*)
- basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=$os"spe"
- ;;
- ebmon29k)
- basic_machine=a29k-amd
- os=-ebmon
- ;;
- elxsi)
- basic_machine=elxsi-elxsi
- os=-bsd
+ dpx2*)
+ cpu=m68k
+ vendor=bull
+ basic_os=sysv3
;;
encore | umax | mmax)
- basic_machine=ns32k-encore
+ cpu=ns32k
+ vendor=encore
;;
- es1800 | OSE68k | ose68k | ose | OSE)
- basic_machine=m68k-ericsson
- os=-ose
+ elxsi)
+ cpu=elxsi
+ vendor=elxsi
+ basic_os=${basic_os:-bsd}
;;
fx2800)
- basic_machine=i860-alliant
+ cpu=i860
+ vendor=alliant
;;
genix)
- basic_machine=ns32k-ns
- ;;
- gmicro)
- basic_machine=tron-gmicro
- os=-sysv
- ;;
- go32)
- basic_machine=i386-pc
- os=-go32
+ cpu=ns32k
+ vendor=ns
;;
h3050r* | hiux*)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- h8300hms)
- basic_machine=h8300-hitachi
- os=-hms
- ;;
- h8300xray)
- basic_machine=h8300-hitachi
- os=-xray
- ;;
- h8500hms)
- basic_machine=h8500-hitachi
- os=-hms
- ;;
- harris)
- basic_machine=m88k-harris
- os=-sysv3
- ;;
- hp300-*)
- basic_machine=m68k-hp
- ;;
- hp300bsd)
- basic_machine=m68k-hp
- os=-bsd
- ;;
- hp300hpux)
- basic_machine=m68k-hp
- os=-hpux
+ cpu=hppa1.1
+ vendor=hitachi
+ basic_os=hiuxwe2
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
- basic_machine=hppa1.0-hp
+ cpu=hppa1.0
+ vendor=hp
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
- basic_machine=m68000-hp
+ cpu=m68000
+ vendor=hp
;;
hp9k3[2-9][0-9])
- basic_machine=m68k-hp
+ cpu=m68k
+ vendor=hp
;;
hp9k6[0-9][0-9] | hp6[0-9][0-9])
- basic_machine=hppa1.0-hp
+ cpu=hppa1.0
+ vendor=hp
;;
hp9k7[0-79][0-9] | hp7[0-79][0-9])
- basic_machine=hppa1.1-hp
+ cpu=hppa1.1
+ vendor=hp
;;
hp9k78[0-9] | hp78[0-9])
# FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
+ cpu=hppa1.1
+ vendor=hp
;;
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
# FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
+ cpu=hppa1.1
+ vendor=hp
;;
hp9k8[0-9][13679] | hp8[0-9][13679])
- basic_machine=hppa1.1-hp
+ cpu=hppa1.1
+ vendor=hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hppa-next)
- os=-nextstep3
- ;;
- hppaosf)
- basic_machine=hppa1.1-hp
- os=-osf
- ;;
- hppro)
- basic_machine=hppa1.1-hp
- os=-proelf
- ;;
- i370-ibm* | ibm*)
- basic_machine=i370-ibm
+ cpu=hppa1.0
+ vendor=hp
;;
i*86v32)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv32
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv32
;;
i*86v4*)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv4
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv4
;;
i*86v)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv
;;
i*86sol2)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-solaris2
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=solaris2
;;
- i386mach)
- basic_machine=i386-mach
- os=-mach
- ;;
- i386-vsta | vsta)
- basic_machine=i386-unknown
- os=-vsta
+ j90 | j90-cray)
+ cpu=j90
+ vendor=cray
+ basic_os=${basic_os:-unicos}
;;
iris | iris4d)
- basic_machine=mips-sgi
- case $os in
- -irix*)
+ cpu=mips
+ vendor=sgi
+ case $basic_os in
+ irix*)
;;
*)
- os=-irix4
+ basic_os=irix4
;;
esac
;;
- isi68 | isi)
- basic_machine=m68k-isi
- os=-sysv
- ;;
- leon-*|leon[3-9]-*)
- basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
- ;;
- m68knommu)
- basic_machine=m68k-unknown
- os=-linux
- ;;
- m68knommu-*)
- basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
- ;;
- m88k-omron*)
- basic_machine=m88k-omron
- ;;
- magnum | m3230)
- basic_machine=mips-mips
- os=-sysv
- ;;
- merlin)
- basic_machine=ns32k-utek
- os=-sysv
- ;;
- microblaze*)
- basic_machine=microblaze-xilinx
- ;;
- mingw64)
- basic_machine=x86_64-pc
- os=-mingw64
- ;;
- mingw32)
- basic_machine=i686-pc
- os=-mingw32
- ;;
- mingw32ce)
- basic_machine=arm-unknown
- os=-mingw32ce
- ;;
miniframe)
- basic_machine=m68000-convergent
- ;;
- *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
- mips3*-*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
- ;;
- mips3*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
- ;;
- monitor)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- morphos)
- basic_machine=powerpc-unknown
- os=-morphos
- ;;
- moxiebox)
- basic_machine=moxie-unknown
- os=-moxiebox
- ;;
- msdos)
- basic_machine=i386-pc
- os=-msdos
- ;;
- ms1-*)
- basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
- ;;
- msys)
- basic_machine=i686-pc
- os=-msys
- ;;
- mvs)
- basic_machine=i370-ibm
- os=-mvs
- ;;
- nacl)
- basic_machine=le32-unknown
- os=-nacl
+ cpu=m68000
+ vendor=convergent
;;
- ncr3000)
- basic_machine=i486-ncr
- os=-sysv4
- ;;
- netbsd386)
- basic_machine=i386-unknown
- os=-netbsd
- ;;
- netwinder)
- basic_machine=armv4l-rebel
- os=-linux
- ;;
- news | news700 | news800 | news900)
- basic_machine=m68k-sony
- os=-newsos
- ;;
- news1000)
- basic_machine=m68030-sony
- os=-newsos
+ *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ cpu=m68k
+ vendor=atari
+ basic_os=mint
;;
news-3600 | risc-news)
- basic_machine=mips-sony
- os=-newsos
- ;;
- necv70)
- basic_machine=v70-nec
- os=-sysv
- ;;
- next | m*-next )
- basic_machine=m68k-next
- case $os in
- -nextstep* )
+ cpu=mips
+ vendor=sony
+ basic_os=newsos
+ ;;
+ next | m*-next)
+ cpu=m68k
+ vendor=next
+ case $basic_os in
+ openstep*)
+ ;;
+ nextstep*)
;;
- -ns2*)
- os=-nextstep2
+ ns2*)
+ basic_os=nextstep2
;;
*)
- os=-nextstep3
+ basic_os=nextstep3
;;
esac
;;
- nh3000)
- basic_machine=m68k-harris
- os=-cxux
- ;;
- nh[45]000)
- basic_machine=m88k-harris
- os=-cxux
- ;;
- nindy960)
- basic_machine=i960-intel
- os=-nindy
- ;;
- mon960)
- basic_machine=i960-intel
- os=-mon960
- ;;
- nonstopux)
- basic_machine=mips-compaq
- os=-nonstopux
- ;;
np1)
- basic_machine=np1-gould
- ;;
- neo-tandem)
- basic_machine=neo-tandem
- ;;
- nse-tandem)
- basic_machine=nse-tandem
- ;;
- nsr-tandem)
- basic_machine=nsr-tandem
+ cpu=np1
+ vendor=gould
;;
op50n-* | op60c-*)
- basic_machine=hppa1.1-oki
- os=-proelf
- ;;
- openrisc | openrisc-*)
- basic_machine=or32-unknown
- ;;
- os400)
- basic_machine=powerpc-ibm
- os=-os400
- ;;
- OSE68000 | ose68000)
- basic_machine=m68000-ericsson
- os=-ose
- ;;
- os68k)
- basic_machine=m68k-none
- os=-os68k
+ cpu=hppa1.1
+ vendor=oki
+ basic_os=proelf
;;
pa-hitachi)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- paragon)
- basic_machine=i860-intel
- os=-osf
- ;;
- parisc)
- basic_machine=hppa-unknown
- os=-linux
- ;;
- parisc-*)
- basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
+ cpu=hppa1.1
+ vendor=hitachi
+ basic_os=hiuxwe2
;;
pbd)
- basic_machine=sparc-tti
+ cpu=sparc
+ vendor=tti
;;
pbb)
- basic_machine=m68k-tti
- ;;
- pc532 | pc532-*)
- basic_machine=ns32k-pc532
- ;;
- pc98)
- basic_machine=i386-pc
+ cpu=m68k
+ vendor=tti
;;
- pc98-*)
- basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentium | p5 | k5 | k6 | nexgen | viac3)
- basic_machine=i586-pc
- ;;
- pentiumpro | p6 | 6x86 | athlon | athlon_*)
- basic_machine=i686-pc
- ;;
- pentiumii | pentium2 | pentiumiii | pentium3)
- basic_machine=i686-pc
- ;;
- pentium4)
- basic_machine=i786-pc
- ;;
- pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
- basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumpro-* | p6-* | 6x86-* | athlon-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentium4-*)
- basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ pc532)
+ cpu=ns32k
+ vendor=pc532
;;
pn)
- basic_machine=pn-gould
- ;;
- power) basic_machine=power-ibm
- ;;
- ppc | ppcbe) basic_machine=powerpc-unknown
+ cpu=pn
+ vendor=gould
;;
- ppc-* | ppcbe-*)
- basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppcle | powerpclittle)
- basic_machine=powerpcle-unknown
- ;;
- ppcle-* | powerpclittle-*)
- basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64) basic_machine=powerpc64-unknown
- ;;
- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64le | powerpc64little)
- basic_machine=powerpc64le-unknown
- ;;
- ppc64le-* | powerpc64little-*)
- basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ power)
+ cpu=power
+ vendor=ibm
;;
ps2)
- basic_machine=i386-ibm
- ;;
- pw32)
- basic_machine=i586-unknown
- os=-pw32
- ;;
- rdos | rdos64)
- basic_machine=x86_64-pc
- os=-rdos
- ;;
- rdos32)
- basic_machine=i386-pc
- os=-rdos
- ;;
- rom68k)
- basic_machine=m68k-rom68k
- os=-coff
+ cpu=i386
+ vendor=ibm
;;
rm[46]00)
- basic_machine=mips-siemens
+ cpu=mips
+ vendor=siemens
;;
rtpc | rtpc-*)
- basic_machine=romp-ibm
- ;;
- s390 | s390-*)
- basic_machine=s390-ibm
+ cpu=romp
+ vendor=ibm
;;
- s390x | s390x-*)
- basic_machine=s390x-ibm
- ;;
- sa29200)
- basic_machine=a29k-amd
- os=-udi
+ sde)
+ cpu=mipsisa32
+ vendor=sde
+ basic_os=${basic_os:-elf}
;;
- sb1)
- basic_machine=mipsisa64sb1-unknown
+ simso-wrs)
+ cpu=sparclite
+ vendor=wrs
+ basic_os=vxworks
;;
- sb1el)
- basic_machine=mipsisa64sb1el-unknown
+ tower | tower-32)
+ cpu=m68k
+ vendor=ncr
;;
- sde)
- basic_machine=mipsisa32-sde
- os=-elf
+ vpp*|vx|vx-*)
+ cpu=f301
+ vendor=fujitsu
;;
- sei)
- basic_machine=mips-sei
- os=-seiux
+ w65)
+ cpu=w65
+ vendor=wdc
;;
- sequent)
- basic_machine=i386-sequent
+ w89k-*)
+ cpu=hppa1.1
+ vendor=winbond
+ basic_os=proelf
;;
- sh)
- basic_machine=sh-hitachi
- os=-hms
+ none)
+ cpu=none
+ vendor=none
;;
- sh5el)
- basic_machine=sh5le-unknown
+ leon|leon[3-9])
+ cpu=sparc
+ vendor=$basic_machine
;;
- sh64)
- basic_machine=sh64-unknown
+ leon-*|leon[3-9]-*)
+ cpu=sparc
+ vendor=`echo "$basic_machine" | sed 's/-.*//'`
;;
- sparclite-wrs | simso-wrs)
- basic_machine=sparclite-wrs
- os=-vxworks
+
+ *-*)
+ # shellcheck disable=SC2162
+ saved_IFS=$IFS
+ IFS="-" read cpu vendor <<EOF
+$basic_machine
+EOF
+ IFS=$saved_IFS
;;
- sps7)
- basic_machine=m68k-bull
- os=-sysv2
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ cpu=$basic_machine
+ vendor=pc
;;
- spur)
- basic_machine=spur-unknown
+ # These rules are duplicated from below for sake of the special case above;
+ # i.e. things that normalized to x86 arches should also default to "pc"
+ pc98)
+ cpu=i386
+ vendor=pc
;;
- st2000)
- basic_machine=m68k-tandem
+ x64 | amd64)
+ cpu=x86_64
+ vendor=pc
;;
- stratus)
- basic_machine=i860-stratus
- os=-sysv4
+ # Recognize the basic CPU types without company name.
+ *)
+ cpu=$basic_machine
+ vendor=unknown
;;
- strongarm-* | thumb-*)
- basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+esac
+
+unset -v basic_machine
+
+# Decode basic machines in the full and proper CPU-Company form.
+case $cpu-$vendor in
+ # Here we handle the default manufacturer of certain CPU types in canonical form. It is in
+ # some cases the only manufacturer, in others, it is the most popular.
+ craynv-unknown)
+ vendor=cray
+ basic_os=${basic_os:-unicosmp}
;;
- sun2)
- basic_machine=m68000-sun
+ c90-unknown | c90-cray)
+ vendor=cray
+ basic_os=${Basic_os:-unicos}
;;
- sun2os3)
- basic_machine=m68000-sun
- os=-sunos3
+ fx80-unknown)
+ vendor=alliant
;;
- sun2os4)
- basic_machine=m68000-sun
- os=-sunos4
+ romp-unknown)
+ vendor=ibm
;;
- sun3os3)
- basic_machine=m68k-sun
- os=-sunos3
+ mmix-unknown)
+ vendor=knuth
;;
- sun3os4)
- basic_machine=m68k-sun
- os=-sunos4
+ microblaze-unknown | microblazeel-unknown)
+ vendor=xilinx
;;
- sun4os3)
- basic_machine=sparc-sun
- os=-sunos3
+ rs6000-unknown)
+ vendor=ibm
;;
- sun4os4)
- basic_machine=sparc-sun
- os=-sunos4
+ vax-unknown)
+ vendor=dec
;;
- sun4sol2)
- basic_machine=sparc-sun
- os=-solaris2
+ pdp11-unknown)
+ vendor=dec
;;
- sun3 | sun3-*)
- basic_machine=m68k-sun
+ we32k-unknown)
+ vendor=att
;;
- sun4)
- basic_machine=sparc-sun
+ cydra-unknown)
+ vendor=cydrome
;;
- sun386 | sun386i | roadrunner)
- basic_machine=i386-sun
+ i370-ibm*)
+ vendor=ibm
;;
- sv1)
- basic_machine=sv1-cray
- os=-unicos
+ orion-unknown)
+ vendor=highlevel
;;
- symmetry)
- basic_machine=i386-sequent
- os=-dynix
+ xps-unknown | xps100-unknown)
+ cpu=xps100
+ vendor=honeywell
;;
- t3e)
- basic_machine=alphaev5-cray
- os=-unicos
+
+ # Here we normalize CPU types with a missing or matching vendor
+ armh-unknown | armh-alt)
+ cpu=armv7l
+ vendor=alt
+ basic_os=${basic_os:-linux-gnueabihf}
;;
- t90)
- basic_machine=t90-cray
- os=-unicos
+ dpx20-unknown | dpx20-bull)
+ cpu=rs6000
+ vendor=bull
+ basic_os=${basic_os:-bosx}
;;
- tile*)
- basic_machine=$basic_machine-unknown
- os=-linux-gnu
+
+ # Here we normalize CPU types irrespective of the vendor
+ amd64-*)
+ cpu=x86_64
;;
- tx39)
- basic_machine=mipstx39-unknown
+ blackfin-*)
+ cpu=bfin
+ basic_os=linux
;;
- tx39el)
- basic_machine=mipstx39el-unknown
+ c54x-*)
+ cpu=tic54x
;;
- toad1)
- basic_machine=pdp10-xkl
- os=-tops20
+ c55x-*)
+ cpu=tic55x
;;
- tower | tower-32)
- basic_machine=m68k-ncr
+ c6x-*)
+ cpu=tic6x
;;
- tpf)
- basic_machine=s390x-ibm
- os=-tpf
+ e500v[12]-*)
+ cpu=powerpc
+ basic_os=${basic_os}"spe"
;;
- udi29k)
- basic_machine=a29k-amd
- os=-udi
+ mips3*-*)
+ cpu=mips64
;;
- ultra3)
- basic_machine=a29k-nyu
- os=-sym1
+ ms1-*)
+ cpu=mt
;;
- v810 | necv810)
- basic_machine=v810-nec
- os=-none
+ m68knommu-*)
+ cpu=m68k
+ basic_os=linux
;;
- vaxv)
- basic_machine=vax-dec
- os=-sysv
+ m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
+ cpu=s12z
;;
- vms)
- basic_machine=vax-dec
- os=-vms
+ openrisc-*)
+ cpu=or32
;;
- vpp*|vx|vx-*)
- basic_machine=f301-fujitsu
+ parisc-*)
+ cpu=hppa
+ basic_os=linux
;;
- vxworks960)
- basic_machine=i960-wrs
- os=-vxworks
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ cpu=i586
;;
- vxworks68)
- basic_machine=m68k-wrs
- os=-vxworks
+ pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
+ cpu=i686
;;
- vxworks29k)
- basic_machine=a29k-wrs
- os=-vxworks
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ cpu=i686
;;
- w65*)
- basic_machine=w65-wdc
- os=-none
+ pentium4-*)
+ cpu=i786
;;
- w89k-*)
- basic_machine=hppa1.1-winbond
- os=-proelf
+ pc98-*)
+ cpu=i386
;;
- xbox)
- basic_machine=i686-pc
- os=-mingw32
+ ppc-* | ppcbe-*)
+ cpu=powerpc
;;
- xps | xps100)
- basic_machine=xps100-honeywell
+ ppcle-* | powerpclittle-*)
+ cpu=powerpcle
;;
- xscale-* | xscalee[bl]-*)
- basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ppc64-*)
+ cpu=powerpc64
;;
- ymp)
- basic_machine=ymp-cray
- os=-unicos
+ ppc64le-* | powerpc64little-*)
+ cpu=powerpc64le
;;
- z8k-*-coff)
- basic_machine=z8k-unknown
- os=-sim
+ sb1-*)
+ cpu=mipsisa64sb1
;;
- z80-*-coff)
- basic_machine=z80-unknown
- os=-sim
+ sb1el-*)
+ cpu=mipsisa64sb1el
;;
- none)
- basic_machine=none-none
- os=-none
+ sh5e[lb]-*)
+ cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
;;
-
-# Here we handle the default manufacturer of certain CPU types. It is in
-# some cases the only manufacturer, in others, it is the most popular.
- w89k)
- basic_machine=hppa1.1-winbond
+ spur-*)
+ cpu=spur
;;
- op50n)
- basic_machine=hppa1.1-oki
+ strongarm-* | thumb-*)
+ cpu=arm
;;
- op60c)
- basic_machine=hppa1.1-oki
+ tx39-*)
+ cpu=mipstx39
;;
- romp)
- basic_machine=romp-ibm
+ tx39el-*)
+ cpu=mipstx39el
;;
- mmix)
- basic_machine=mmix-knuth
+ x64-*)
+ cpu=x86_64
;;
- rs6000)
- basic_machine=rs6000-ibm
+ xscale-* | xscalee[bl]-*)
+ cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
;;
- vax)
- basic_machine=vax-dec
+ arm64-* | aarch64le-*)
+ cpu=aarch64
;;
- pdp10)
- # there are many clones, so DEC is not a safe bet
- basic_machine=pdp10-unknown
+
+ # Recognize the canonical CPU Types that limit and/or modify the
+ # company names they are paired with.
+ cr16-*)
+ basic_os=${basic_os:-elf}
;;
- pdp11)
- basic_machine=pdp11-dec
+ crisv32-* | etraxfs*-*)
+ cpu=crisv32
+ vendor=axis
;;
- we32k)
- basic_machine=we32k-att
+ cris-* | etrax*-*)
+ cpu=cris
+ vendor=axis
;;
- sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
- basic_machine=sh-unknown
+ crx-*)
+ basic_os=${basic_os:-elf}
;;
- sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
- basic_machine=sparc-sun
+ neo-tandem)
+ cpu=neo
+ vendor=tandem
;;
- cydra)
- basic_machine=cydra-cydrome
+ nse-tandem)
+ cpu=nse
+ vendor=tandem
;;
- orion)
- basic_machine=orion-highlevel
+ nsr-tandem)
+ cpu=nsr
+ vendor=tandem
;;
- orion105)
- basic_machine=clipper-highlevel
+ nsv-tandem)
+ cpu=nsv
+ vendor=tandem
;;
- mac | mpw | mac-mpw)
- basic_machine=m68k-apple
+ nsx-tandem)
+ cpu=nsx
+ vendor=tandem
;;
- pmac | pmac-mpw)
- basic_machine=powerpc-apple
+ mipsallegrexel-sony)
+ cpu=mipsallegrexel
+ vendor=sony
;;
- *-unknown)
- # Make sure to match an already-canonicalized machine name.
+ tile*-*)
+ basic_os=${basic_os:-linux-gnu}
;;
+
*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
+ # Recognize the canonical CPU types that are allowed with any
+ # company name.
+ case $cpu in
+ 1750a | 580 \
+ | a29k \
+ | aarch64 | aarch64_be \
+ | abacus \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
+ | alphapca5[67] | alpha64pca5[67] \
+ | am33_2.0 \
+ | amdgcn \
+ | arc | arceb | arc32 | arc64 \
+ | arm | arm[lb]e | arme[lb] | armv* \
+ | avr | avr32 \
+ | asmjs \
+ | ba \
+ | be32 | be64 \
+ | bfin | bpf | bs2000 \
+ | c[123]* | c30 | [cjt]90 | c4x \
+ | c8051 | clipper | craynv | csky | cydra \
+ | d10v | d30v | dlx | dsp16xx \
+ | e2k | elxsi | epiphany \
+ | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
+ | h8300 | h8500 \
+ | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i*86 | i860 | i960 | ia16 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | loongarch32 | loongarch64 | loongarchx32 \
+ | m32c | m32r | m32rle \
+ | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
+ | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
+ | m88110 | m88k | maxq | mb | mcore | mep | metag \
+ | microblaze | microblazeel \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64eb | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r3 | mipsisa32r3el \
+ | mipsisa32r5 | mipsisa32r5el \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r3 | mipsisa64r3el \
+ | mipsisa64r5 | mipsisa64r5el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mmix \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nfp \
+ | nios | nios2 | nios2eb | nios2el \
+ | none | np1 | ns16k | ns32k | nvptx \
+ | open8 \
+ | or1k* \
+ | or32 \
+ | orion \
+ | picochip \
+ | pdp10 | pdp11 | pj | pjl | pn | power \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
+ | pru \
+ | pyramid \
+ | riscv | riscv32 | riscv32be | riscv64 | riscv64be \
+ | rl78 | romp | rs6000 | rx \
+ | s390 | s390x \
+ | score \
+ | sh | shl \
+ | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
+ | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
+ | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
+ | spu \
+ | tahoe \
+ | thumbv7* \
+ | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
+ | tron \
+ | ubicom32 \
+ | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
+ | vax \
+ | visium \
+ | w65 \
+ | wasm32 | wasm64 \
+ | we32k \
+ | x86 | x86_64 | xc16x | xgate | xps100 \
+ | xstormy16 | xtensa* \
+ | ymp \
+ | z8k | z80)
+ ;;
+
+ *)
+ echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
+ exit 1
+ ;;
+ esac
;;
esac
# Here we canonicalize certain aliases for manufacturers.
-case $basic_machine in
- *-digital*)
- basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+case $vendor in
+ digital*)
+ vendor=dec
;;
- *-commodore*)
- basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ commodore*)
+ vendor=cbm
;;
*)
;;
@@ -1355,203 +1306,215 @@ esac
# Decode manufacturer-specific aliases for certain operating systems.
-if [ x"$os" != x"" ]
+if test x$basic_os != x
then
-case $os in
- # First match some system type aliases
- # that might get confused with valid system types.
- # -solaris* is a basic system type, with this one exception.
- -auroraux)
- os=-auroraux
+
+# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
+# set os.
+case $basic_os in
+ gnu/linux*)
+ kernel=linux
+ os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
+ ;;
+ os2-emx)
+ kernel=os2
+ os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
+ ;;
+ nto-qnx*)
+ kernel=nto
+ os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
+ ;;
+ *-*)
+ # shellcheck disable=SC2162
+ saved_IFS=$IFS
+ IFS="-" read kernel os <<EOF
+$basic_os
+EOF
+ IFS=$saved_IFS
+ ;;
+ # Default OS when just kernel was specified
+ nto*)
+ kernel=nto
+ os=`echo "$basic_os" | sed -e 's|nto|qnx|'`
+ ;;
+ linux*)
+ kernel=linux
+ os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
;;
- -solaris1 | -solaris1.*)
- os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ *)
+ kernel=
+ os=$basic_os
+ ;;
+esac
+
+# Now, normalize the OS (knowing we just have one component, it's not a kernel,
+# etc.)
+case $os in
+ # First match some system type aliases that might get confused
+ # with valid system types.
+ # solaris* is a basic system type, with this one exception.
+ auroraux)
+ os=auroraux
;;
- -solaris)
- os=-solaris2
+ bluegene*)
+ os=cnk
;;
- -svr4*)
- os=-sysv4
+ solaris1 | solaris1.*)
+ os=`echo "$os" | sed -e 's|solaris1|sunos4|'`
;;
- -unixware*)
- os=-sysv4.2uw
+ solaris)
+ os=solaris2
;;
- -gnu/linux*)
- os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ unixware*)
+ os=sysv4.2uw
;;
- # First accept the basic system types.
- # The portable systems comes first.
- # Each alternative MUST END IN A *, to match a version number.
- # -sysv* is not here because it comes later, after sysvr4.
- -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
- | -sym* | -kopensolaris* | -plan9* \
- | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* | -aros* | -cloudabi* | -sortix* \
- | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
- | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
- | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
- | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
- | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
- | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
- | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
- | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -chorusos* | -chorusrdb* | -cegcc* \
- | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
- | -linux-newlib* | -linux-musl* | -linux-uclibc* \
- | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
- | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
- | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
- | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
- | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
- | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
- | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
- | -onefs* | -tirtos* | -phoenix* | -fuchsia*)
- # Remember, each alternative MUST END IN *, to match a version number.
- ;;
- -qnx*)
- case $basic_machine in
- x86-* | i*86-*)
- ;;
- *)
- os=-nto$os
- ;;
- esac
+ # es1800 is here to avoid being matched by es* (a different OS)
+ es1800*)
+ os=ose
;;
- -nto-qnx*)
+ # Some version numbers need modification
+ chorusos*)
+ os=chorusos
;;
- -nto*)
- os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ isc)
+ os=isc2.2
;;
- -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
- | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
- | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ sco6)
+ os=sco5v6
;;
- -mac*)
- os=`echo $os | sed -e 's|mac|macos|'`
+ sco5)
+ os=sco3.2v5
;;
- -linux-dietlibc)
- os=-linux-dietlibc
+ sco4)
+ os=sco3.2v4
;;
- -linux*)
- os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ sco3.2.[4-9]*)
+ os=`echo "$os" | sed -e 's/sco3.2./sco3.2v/'`
;;
- -sunos5*)
- os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ sco*v* | scout)
+ # Don't match below
;;
- -sunos6*)
- os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ sco*)
+ os=sco3.2v2
;;
- -opened*)
- os=-openedition
+ psos*)
+ os=psos
;;
- -os400*)
- os=-os400
+ qnx*)
+ os=qnx
;;
- -wince*)
- os=-wince
+ hiux*)
+ os=hiuxwe2
;;
- -osfrose*)
- os=-osfrose
+ lynx*178)
+ os=lynxos178
;;
- -osf*)
- os=-osf
+ lynx*5)
+ os=lynxos5
;;
- -utek*)
- os=-bsd
+ lynxos*)
+ # don't get caught up in next wildcard
;;
- -dynix*)
- os=-bsd
+ lynx*)
+ os=lynxos
;;
- -acis*)
- os=-aos
+ mac[0-9]*)
+ os=`echo "$os" | sed -e 's|mac|macos|'`
;;
- -atheos*)
- os=-atheos
+ opened*)
+ os=openedition
;;
- -syllable*)
- os=-syllable
+ os400*)
+ os=os400
;;
- -386bsd)
- os=-bsd
+ sunos5*)
+ os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
;;
- -ctix* | -uts*)
- os=-sysv
+ sunos6*)
+ os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
;;
- -nova*)
- os=-rtmk-nova
+ wince*)
+ os=wince
;;
- -ns2 )
- os=-nextstep2
+ utek*)
+ os=bsd
;;
- -nsk*)
- os=-nsk
+ dynix*)
+ os=bsd
;;
- # Preserve the version number of sinix5.
- -sinix5.*)
- os=`echo $os | sed -e 's|sinix|sysv|'`
+ acis*)
+ os=aos
;;
- -sinix*)
- os=-sysv4
+ atheos*)
+ os=atheos
;;
- -tpf*)
- os=-tpf
+ syllable*)
+ os=syllable
;;
- -triton*)
- os=-sysv3
+ 386bsd)
+ os=bsd
;;
- -oss*)
- os=-sysv3
+ ctix* | uts*)
+ os=sysv
;;
- -svr4)
- os=-sysv4
+ nova*)
+ os=rtmk-nova
;;
- -svr3)
- os=-sysv3
+ ns2)
+ os=nextstep2
;;
- -sysvr4)
- os=-sysv4
+ # Preserve the version number of sinix5.
+ sinix5.*)
+ os=`echo "$os" | sed -e 's|sinix|sysv|'`
;;
- # This must come after -sysvr4.
- -sysv*)
+ sinix*)
+ os=sysv4
;;
- -ose*)
- os=-ose
+ tpf*)
+ os=tpf
;;
- -es1800*)
- os=-ose
+ triton*)
+ os=sysv3
;;
- -xenix)
- os=-xenix
+ oss*)
+ os=sysv3
;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- os=-mint
+ svr4*)
+ os=sysv4
;;
- -aros*)
- os=-aros
+ svr3)
+ os=sysv3
;;
- -zvmoe)
- os=-zvmoe
+ sysvr4)
+ os=sysv4
;;
- -dicos*)
- os=-dicos
+ ose*)
+ os=ose
;;
- -nacl*)
+ *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
+ os=mint
;;
- -ios)
+ dicos*)
+ os=dicos
;;
- -none)
+ pikeos*)
+ # Until real need of OS specific support for
+ # particular features comes up, bare metal
+ # configurations are quite functional.
+ case $cpu in
+ arm*)
+ os=eabi
+ ;;
+ *)
+ os=elf
+ ;;
+ esac
;;
*)
- # Get rid of the `-' at the beginning of $os.
- os=`echo $os | sed 's/[^-]*-//'`
- echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
- exit 1
+ # No normalization, but not necessarily accepted, that comes below.
;;
esac
+
else
# Here we handle the default operating systems that come with various machines.
@@ -1564,261 +1527,363 @@ else
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.
-case $basic_machine in
+kernel=
+case $cpu-$vendor in
score-*)
- os=-elf
+ os=elf
;;
spu-*)
- os=-elf
+ os=elf
;;
*-acorn)
- os=-riscix1.2
+ os=riscix1.2
;;
arm*-rebel)
- os=-linux
+ kernel=linux
+ os=gnu
;;
arm*-semi)
- os=-aout
+ os=aout
;;
c4x-* | tic4x-*)
- os=-coff
+ os=coff
;;
c8051-*)
- os=-elf
+ os=elf
+ ;;
+ clipper-intergraph)
+ os=clix
;;
hexagon-*)
- os=-elf
+ os=elf
;;
tic54x-*)
- os=-coff
+ os=coff
;;
tic55x-*)
- os=-coff
+ os=coff
;;
tic6x-*)
- os=-coff
+ os=coff
;;
# This must come before the *-dec entry.
pdp10-*)
- os=-tops20
+ os=tops20
;;
pdp11-*)
- os=-none
+ os=none
;;
*-dec | vax-*)
- os=-ultrix4.2
+ os=ultrix4.2
;;
m68*-apollo)
- os=-domain
+ os=domain
;;
i386-sun)
- os=-sunos4.0.2
+ os=sunos4.0.2
;;
m68000-sun)
- os=-sunos3
+ os=sunos3
;;
m68*-cisco)
- os=-aout
+ os=aout
;;
mep-*)
- os=-elf
+ os=elf
;;
mips*-cisco)
- os=-elf
+ os=elf
;;
mips*-*)
- os=-elf
+ os=elf
;;
or32-*)
- os=-coff
+ os=coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
- os=-sysv3
+ os=sysv3
;;
sparc-* | *-sun)
- os=-sunos4.1.1
+ os=sunos4.1.1
;;
- *-be)
- os=-beos
+ pru-*)
+ os=elf
;;
- *-haiku)
- os=-haiku
+ *-be)
+ os=beos
;;
*-ibm)
- os=-aix
+ os=aix
;;
*-knuth)
- os=-mmixware
+ os=mmixware
;;
*-wec)
- os=-proelf
+ os=proelf
;;
*-winbond)
- os=-proelf
+ os=proelf
;;
*-oki)
- os=-proelf
+ os=proelf
;;
*-hp)
- os=-hpux
+ os=hpux
;;
*-hitachi)
- os=-hiux
+ os=hiux
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
- os=-sysv
+ os=sysv
;;
*-cbm)
- os=-amigaos
+ os=amigaos
;;
*-dg)
- os=-dgux
+ os=dgux
;;
*-dolphin)
- os=-sysv3
+ os=sysv3
;;
m68k-ccur)
- os=-rtu
+ os=rtu
;;
m88k-omron*)
- os=-luna
+ os=luna
;;
- *-next )
- os=-nextstep
+ *-next)
+ os=nextstep
;;
*-sequent)
- os=-ptx
+ os=ptx
;;
*-crds)
- os=-unos
+ os=unos
;;
*-ns)
- os=-genix
+ os=genix
;;
i370-*)
- os=-mvs
- ;;
- *-next)
- os=-nextstep3
+ os=mvs
;;
*-gould)
- os=-sysv
+ os=sysv
;;
*-highlevel)
- os=-bsd
+ os=bsd
;;
*-encore)
- os=-bsd
+ os=bsd
;;
*-sgi)
- os=-irix
+ os=irix
;;
*-siemens)
- os=-sysv4
+ os=sysv4
;;
*-masscomp)
- os=-rtu
+ os=rtu
;;
f30[01]-fujitsu | f700-fujitsu)
- os=-uxpv
+ os=uxpv
;;
*-rom68k)
- os=-coff
+ os=coff
;;
*-*bug)
- os=-coff
+ os=coff
;;
*-apple)
- os=-macos
+ os=macos
;;
*-atari*)
- os=-mint
+ os=mint
+ ;;
+ *-wrs)
+ os=vxworks
;;
*)
- os=-none
+ os=none
;;
esac
+
fi
+# Now, validate our (potentially fixed-up) OS.
+case $os in
+ # Sometimes we do "kernel-libc", so those need to count as OSes.
+ musl* | newlib* | relibc* | uclibc*)
+ ;;
+ # Likewise for "kernel-abi"
+ eabi* | gnueabi*)
+ ;;
+ # VxWorks passes extra cpu info in the 4th filed.
+ simlinux | simwindows | spe)
+ ;;
+ # Now accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST end in a * to match a version number.
+ gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
+ | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
+ | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
+ | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
+ | hiux* | abug | nacl* | netware* | windows* \
+ | os9* | macos* | osx* | ios* \
+ | mpw* | magic* | mmixware* | mon960* | lnews* \
+ | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
+ | aos* | aros* | cloudabi* | sortix* | twizzler* \
+ | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
+ | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
+ | mirbsd* | netbsd* | dicos* | openedition* | ose* \
+ | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
+ | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
+ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
+ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+ | udi* | lites* | ieee* | go32* | aux* | hcos* \
+ | chorusrdb* | cegcc* | glidix* | serenity* \
+ | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+ | midipix* | mingw32* | mingw64* | mint* \
+ | uxpv* | beos* | mpeix* | udk* | moxiebox* \
+ | interix* | uwin* | mks* | rhapsody* | darwin* \
+ | openstep* | oskit* | conix* | pw32* | nonstopux* \
+ | storm-chaos* | tops10* | tenex* | tops20* | its* \
+ | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
+ | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
+ | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
+ | skyos* | haiku* | rdos* | toppers* | drops* | es* \
+ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
+ | fiwix* )
+ ;;
+ # This one is extra strict with allowed versions
+ sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ ;;
+ none)
+ ;;
+ *)
+ echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# As a final step for OS-related things, validate the OS-kernel combination
+# (given a valid OS), if there is a kernel.
+case $kernel-$os in
+ linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
+ | linux-musl* | linux-relibc* | linux-uclibc* )
+ ;;
+ uclinux-uclibc* )
+ ;;
+ -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* )
+ # These are just libc implementations, not actual OSes, and thus
+ # require a kernel.
+ echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+ exit 1
+ ;;
+ kfreebsd*-gnu* | kopensolaris*-gnu*)
+ ;;
+ vxworks-simlinux | vxworks-simwindows | vxworks-spe)
+ ;;
+ nto-qnx*)
+ ;;
+ os2-emx)
+ ;;
+ *-eabi* | *-gnueabi*)
+ ;;
+ -*)
+ # Blank kernel with real OS is always fine.
+ ;;
+ *-*)
+ echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+ exit 1
+ ;;
+esac
+
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
-vendor=unknown
-case $basic_machine in
- *-unknown)
- case $os in
- -riscix*)
+case $vendor in
+ unknown)
+ case $cpu-$os in
+ *-riscix*)
vendor=acorn
;;
- -sunos*)
+ *-sunos*)
vendor=sun
;;
- -cnk*|-aix*)
+ *-cnk* | *-aix*)
vendor=ibm
;;
- -beos*)
+ *-beos*)
vendor=be
;;
- -hpux*)
+ *-hpux*)
vendor=hp
;;
- -mpeix*)
+ *-mpeix*)
vendor=hp
;;
- -hiux*)
+ *-hiux*)
vendor=hitachi
;;
- -unos*)
+ *-unos*)
vendor=crds
;;
- -dgux*)
+ *-dgux*)
vendor=dg
;;
- -luna*)
+ *-luna*)
vendor=omron
;;
- -genix*)
+ *-genix*)
vendor=ns
;;
- -mvs* | -opened*)
+ *-clix*)
+ vendor=intergraph
+ ;;
+ *-mvs* | *-opened*)
+ vendor=ibm
+ ;;
+ *-os400*)
vendor=ibm
;;
- -os400*)
+ s390-* | s390x-*)
vendor=ibm
;;
- -ptx*)
+ *-ptx*)
vendor=sequent
;;
- -tpf*)
+ *-tpf*)
vendor=ibm
;;
- -vxsim* | -vxworks* | -windiss*)
+ *-vxsim* | *-vxworks* | *-windiss*)
vendor=wrs
;;
- -aux*)
+ *-aux*)
vendor=apple
;;
- -hms*)
+ *-hms*)
vendor=hitachi
;;
- -mpw* | -macos*)
+ *-mpw* | *-macos*)
vendor=apple
;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
vendor=atari
;;
- -vos*)
+ *-vos*)
vendor=stratus
;;
esac
- basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
esac
-echo $basic_machine$os
+echo "$cpu-$vendor-${kernel:+$kernel-}$os"
exit
# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
diff --git a/configure b/configure
index bf65254..256f170 100755
--- a/configure
+++ b/configure
@@ -626,13 +626,18 @@ SHLIB
MACHDEPLIBS
extralibdir
extraincludedir
+FLOPPYD_IO_OBJ
+FLOPPYD_IO_SRC
BINFLOPPYD
FLOPPYD
+FLOPPYD_LIBS
X_EXTRA_LIBS
X_LIBS
X_PRE_LIBS
X_CFLAGS
XMKMF
+XDF_IO_OBJ
+XDF_IO_SRC
target_os
target_vendor
target_cpu
@@ -1733,6 +1738,60 @@ fi
} # ac_fn_c_try_link
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
# ac_fn_c_find_intX_t LINENO BITS VAR
# -----------------------------------
# Finds a signed integer type with width BITS, setting cache variable VAR
@@ -1863,60 +1922,6 @@ $as_echo "$ac_res" >&6; }
} # ac_fn_c_find_uintX_t
-# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
-# -------------------------------------------
-# Tests whether TYPE exists after having included INCLUDES, setting cache
-# variable VAR accordingly.
-ac_fn_c_check_type ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=no"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-if (sizeof ($2))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-if (sizeof (($2)))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
- eval "$3=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_type
-
# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
# --------------------------------------------
# Tries to find the compile-time value of EXPR in a program that includes
@@ -2518,6 +2523,58 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_lib_socket_nsl.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_LIB_SOCKET_NSL
+#
+# DESCRIPTION
+#
+# This macro figures out what libraries are required on this platform to
+# link sockets programs.
+#
+# The common cases are not to need any extra libraries, or to need
+# -lsocket and -lnsl. We need to avoid linking with libnsl unless we need
+# it, though, since on some OSes where it isn't necessary it will totally
+# break networking. Unisys also includes gethostbyname() in libsocket but
+# needs libnsl for socket().
+#
+# LICENSE
+#
+# Copyright (c) 2008 Russ Allbery <rra@stanford.edu>
+# Copyright (c) 2008 Stepan Kasal <kasal@ucw.cz>
+# Copyright (c) 2008 Warren Young <warren@etr-usa.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 7
+
+# This is what autoupdate's m4 run will expand. It fires
+# the warning (with _au_warn_XXX), outputs it into the
+# updated configure.ac (with AC_DIAGNOSE), and then outputs
+# the replacement expansion.
+
+
+# This is an auxiliary macro that is also run when
+# autoupdate runs m4. It simply calls m4_warning, but
+# we need a wrapper so that each warning is emitted only
+# once. We break the quoting in m4_warning's argument in
+# order to expand this macro's arguments, not AU_DEFUN's.
+
+
+# Finally, this is the expansion that is picked up by
+# autoconf. It tells the user to run autoupdate, and
+# then outputs the replacement expansion. We do not care
+# about autoupdate's warning because that contains
+# information on what to do *after* running autoupdate.
+
+
ac_config_headers="$ac_config_headers config.h"
@@ -4230,15 +4287,22 @@ if test "${enable_xdf+set}" = set; then :
$as_echo "#define USE_XDF 1" >>confdefs.h
+ XDF_IO_SRC=xdf_io.c
+ XDF_IO_OBJ=xdf_io.o
fi
else
$as_echo "#define USE_XDF 1" >>confdefs.h
+XDF_IO_SRC=xdf_io.c
+XDF_IO_OBJ=xdf_io.o
+
+
fi
+
# Check whether --enable-vold was given.
if test "${enable_vold+set}" = set; then :
enableval=$enable_vold; if test x$enableval = xyes; then
@@ -4425,6 +4489,241 @@ _ACEOF
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsocket" >&5
+$as_echo_n "checking for main in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_main+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_socket_main=yes
+else
+ ac_cv_lib_socket_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_main" >&5
+$as_echo "$ac_cv_lib_socket_main" >&6; }
+if test "x$ac_cv_lib_socket_main" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSOCKET 1
+_ACEOF
+
+ LIBS="-lsocket $LIBS"
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5
+$as_echo_n "checking for library containing gethostbyname... " >&6; }
+if ${ac_cv_search_gethostbyname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' nsl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_gethostbyname=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_gethostbyname+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_gethostbyname+:} false; then :
+
+else
+ ac_cv_search_gethostbyname=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5
+$as_echo "$ac_cv_search_gethostbyname" >&6; }
+ac_res=$ac_cv_search_gethostbyname
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5
+$as_echo_n "checking for library containing socket... " >&6; }
+if ${ac_cv_search_socket+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' socket; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_socket=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_socket+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_socket+:} false; then :
+
+else
+ ac_cv_search_socket=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5
+$as_echo "$ac_cv_search_socket" >&6; }
+ac_res=$ac_cv_search_socket
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5
+$as_echo_n "checking for socket in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_socket+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket -lnsl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_socket_socket=yes
+else
+ ac_cv_lib_socket_socket=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5
+$as_echo "$ac_cv_lib_socket_socket" >&6; }
+if test "x$ac_cv_lib_socket_socket" = xyes; then :
+ LIBS="-lsocket -lnsl $LIBS"
+fi
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lbsd" >&5
+$as_echo_n "checking for main in -lbsd... " >&6; }
+if ${ac_cv_lib_bsd_main+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lbsd $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_bsd_main=yes
+else
+ ac_cv_lib_bsd_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_main" >&5
+$as_echo "$ac_cv_lib_bsd_main" >&6; }
+if test "x$ac_cv_lib_bsd_main" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBBSD 1
+_ACEOF
+
+ LIBS="-lbsd $LIBS"
+
+fi
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
$as_echo_n "checking for ANSI C header files... " >&6; }
if ${ac_cv_header_stdc+:} false; then :
@@ -4578,7 +4877,100 @@ $as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
fi
-for ac_header in getopt.h sys/stat.h stdlib.h unistd.h linux/unistd.h \
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
+$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; }
+if ${ac_cv_header_stdbool_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <stdbool.h>
+ #ifndef bool
+ "error: bool is not defined"
+ #endif
+ #ifndef false
+ "error: false is not defined"
+ #endif
+ #if false
+ "error: false is not 0"
+ #endif
+ #ifndef true
+ "error: true is not defined"
+ #endif
+ #if true != 1
+ "error: true is not 1"
+ #endif
+ #ifndef __bool_true_false_are_defined
+ "error: __bool_true_false_are_defined is not defined"
+ #endif
+
+ struct s { _Bool s: 1; _Bool t; } s;
+
+ char a[true == 1 ? 1 : -1];
+ char b[false == 0 ? 1 : -1];
+ char c[__bool_true_false_are_defined == 1 ? 1 : -1];
+ char d[(bool) 0.5 == true ? 1 : -1];
+ /* See body of main program for 'e'. */
+ char f[(_Bool) 0.0 == false ? 1 : -1];
+ char g[true];
+ char h[sizeof (_Bool)];
+ char i[sizeof s.t];
+ enum { j = false, k = true, l = false * true, m = true * 256 };
+ /* The following fails for
+ HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
+ _Bool n[m];
+ char o[sizeof n == m * sizeof n[0] ? 1 : -1];
+ char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
+ /* Catch a bug in an HP-UX C compiler. See
+ http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+ http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
+ */
+ _Bool q = true;
+ _Bool *pq = &q;
+
+int
+main ()
+{
+
+ bool e = &s;
+ *pq |= q;
+ *pq |= ! q;
+ /* Refer to every declared value, to avoid compiler optimizations. */
+ return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
+ + !m + !n + !o + !p + !q + !pq);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdbool_h=yes
+else
+ ac_cv_header_stdbool_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
+$as_echo "$ac_cv_header_stdbool_h" >&6; }
+ ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
+if test "x$ac_cv_type__Bool" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE__BOOL 1
+_ACEOF
+
+
+fi
+
+
+if test $ac_cv_header_stdbool_h = yes; then
+
+$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
+
+fi
+
+for ac_header in getopt.h stdarg.h stdlib.h unistd.h linux/unistd.h \
libc.h fcntl.h limits.h sys/file.h sys/ioctl.h sys/time.h strings.h string.h \
sys/param.h memory.h malloc.h io.h signal.h sys/signal.h utime.h sgtty.h \
sys/floppy.h mntent.h sys/sysmacros.h netinet/in.h netinet/tcp.h assert.h \
@@ -4622,6 +5014,32 @@ fi
done
+for ac_header in sys/fdio.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/fdio.h" "ac_cv_header_sys_fdio_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_fdio_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_FDIO_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in sys/socket.h arpa/inet.h netdb.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
# Check whether --enable-largefile was given.
if test "${enable_largefile+set}" = set; then :
enableval=$enable_largefile;
@@ -5002,6 +5420,16 @@ _ACEOF
fi
+ac_fn_c_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default"
+if test "x$ac_cv_type_long_long" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LONG_LONG 1
+_ACEOF
+
+
+fi
+
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
@@ -5039,6 +5467,39 @@ _ACEOF
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of off_t" >&5
+$as_echo_n "checking size of off_t... " >&6; }
+if ${ac_cv_sizeof_off_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (off_t))" "ac_cv_sizeof_off_t" "$ac_includes_default"; then :
+
+else
+ if test "$ac_cv_type_off_t" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (off_t)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_off_t=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_off_t" >&5
+$as_echo "$ac_cv_sizeof_off_t" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_OFF_T $ac_cv_sizeof_off_t
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5
$as_echo_n "checking size of time_t... " >&6; }
if ${ac_cv_sizeof_time_t+:} false; then :
@@ -5101,108 +5562,194 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
-$as_echo_n "checking size of long long... " >&6; }
-if ${ac_cv_sizeof_long_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"; then :
-else
- if test "$ac_cv_type_long_long" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (long long)
-See \`config.log' for more details" "$LINENO" 5; }
- else
- ac_cv_sizeof_long_long=0
- fi
-fi
+seek_function=
+if test $ac_cv_sizeof_off_t -ge 8 ; then
+ seek_function=lseek
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
-$as_echo "$ac_cv_sizeof_long_long" >&6; }
+if test X$seek_function = X ; then
+
+$as_echo "#define _LARGEFILE64_SOURCE 1" >>confdefs.h
+ ac_fn_c_check_type "$LINENO" "off64_t" "ac_cv_type_off64_t" "$ac_includes_default"
+if test "x$ac_cv_type_off64_t" = xyes; then :
cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
+#define HAVE_OFF64_T 1
+_ACEOF
+
+ for ac_func in lseek64
+do :
+ ac_fn_c_check_func "$LINENO" "lseek64" "ac_cv_func_lseek64"
+if test "x$ac_cv_func_lseek64" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LSEEK64 1
_ACEOF
+ seek_function=lseek64
+fi
+done
+fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether llseek declared in unistd.h" >&5
-$as_echo_n "checking whether llseek declared in unistd.h... " >&6; }
-if ${mtools_cv_have_llseek_prototype+:} false; then :
+ for ac_func in stat64
+do :
+ ac_fn_c_check_func "$LINENO" "stat64" "ac_cv_func_stat64"
+if test "x$ac_cv_func_stat64" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_STAT64 1
+_ACEOF
+
+fi
+done
+
+ if test X$seek_function = Xlseek64 ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lseek64 declared in unistd.h" >&5
+$as_echo_n "checking whether lseek64 declared in unistd.h... " >&6; }
+ if ${mtools_cv_have_lseek64_prototype+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <unistd.h>
+
+ #define _LARGEFILE64_SOURCE
+ #include <sys/types.h>
+ #include <unistd.h>
+
int
main ()
{
-extern int llseek(int);
+extern int lseek64(int);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
- mtools_cv_have_llseek_prototype=no
+ mtools_cv_have_lseek64_prototype=no
else
- mtools_cv_have_llseek_prototype=yes
+ mtools_cv_have_lseek64_prototype=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $mtools_cv_have_llseek_prototype" >&5
-$as_echo "$mtools_cv_have_llseek_prototype" >&6; }
-if test "$mtools_cv_have_llseek_prototype" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mtools_cv_have_lseek64_prototype" >&5
+$as_echo "$mtools_cv_have_lseek64_prototype" >&6; }
+ if test "$mtools_cv_have_lseek64_prototype" = yes; then
-$as_echo "#define HAVE_LLSEEK_PROTOTYPE 1" >>confdefs.h
+$as_echo "#define HAVE_LSEEK64_PROTOTYPE 1" >>confdefs.h
+ fi
+ fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lseek64 declared in unistd.h" >&5
-$as_echo_n "checking whether lseek64 declared in unistd.h... " >&6; }
-if ${mtools_cv_have_lseek64_prototype+:} false; then :
+if test X$seek_function = X ; then
+
+$as_echo "#define _LARGEFILE_SOURCE 1" >>confdefs.h
+
+ ac_fn_c_check_type "$LINENO" "loff_t" "ac_cv_type_loff_t" "$ac_includes_default"
+if test "x$ac_cv_type_loff_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LOFF_T 1
+_ACEOF
+
+ for ac_func in llseek
+do :
+ ac_fn_c_check_func "$LINENO" "llseek" "ac_cv_func_llseek"
+if test "x$ac_cv_func_llseek" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LLSEEK 1
+_ACEOF
+ seek_function=llseek
+fi
+done
+
+
+fi
+ac_fn_c_check_type "$LINENO" "offset_t" "ac_cv_type_offset_t" "$ac_includes_default"
+if test "x$ac_cv_type_offset_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_OFFSET_T 1
+_ACEOF
+
+ for ac_func in llseek
+do :
+ ac_fn_c_check_func "$LINENO" "llseek" "ac_cv_func_llseek"
+if test "x$ac_cv_func_llseek" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LLSEEK 1
+_ACEOF
+ seek_function=llseek
+fi
+done
+
+
+fi
+ac_fn_c_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default"
+if test "x$ac_cv_type_long_long" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LONG_LONG 1
+_ACEOF
+
+ for ac_func in llseek
+do :
+ ac_fn_c_check_func "$LINENO" "llseek" "ac_cv_func_llseek"
+if test "x$ac_cv_func_llseek" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LLSEEK 1
+_ACEOF
+ seek_function=llseek
+fi
+done
+
+
+fi
+
+
+ if test X$seek_function = Xllseek ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether llseek declared in unistd.h" >&5
+$as_echo_n "checking whether llseek declared in unistd.h... " >&6; }
+ if ${mtools_cv_have_llseek_prototype+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include "sysincludes.h"
-#include <unistd.h>
+ #define _LARGEFILE_SOURCE
+ #define _LARGEFILE64_SOURCE
+ #include <sys/types.h>
+ #include <unistd.h>
int
main ()
{
-extern int lseek64(int);
+extern int llseek(int);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
- mtools_cv_have_lseek64_prototype=no
+ mtools_cv_have_llseek_prototype=no
else
- mtools_cv_have_lseek64_prototype=yes
+ mtools_cv_have_llseek_prototype=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $mtools_cv_have_lseek64_prototype" >&5
-$as_echo "$mtools_cv_have_lseek64_prototype" >&6; }
-if test "$mtools_cv_have_lseek64_prototype" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mtools_cv_have_llseek_prototype" >&5
+$as_echo "$mtools_cv_have_llseek_prototype" >&6; }
+ if test "$mtools_cv_have_llseek_prototype" = yes; then
-$as_echo "#define HAVE_LSEEK64_PROTOTYPE 1" >>confdefs.h
+$as_echo "#define HAVE_LLSEEK_PROTOTYPE 1" >>confdefs.h
+ fi
+ fi
fi
-
for ac_func in htons
do :
ac_fn_c_check_func "$LINENO" "htons" "ac_cv_func_htons"
@@ -5459,8 +6006,8 @@ for ac_func in strerror random srandom strchr strrchr lockf flock \
strcasecmp strncasecmp strnlen atexit on_exit getpass memmove \
strdup strndup strcspn strspn strtoul strtol strtoll strtoi strtoui \
memcpy strpbrk memset setenv seteuid setresuid setpgrp \
-tcsetattr tcflush basename fchdir media_oldaliases llseek lseek64 \
-snprintf stat64 setlocale toupper_l strncasecmp_l \
+tcsetattr tcflush basename fchdir media_oldaliases \
+snprintf setlocale toupper_l strncasecmp_l \
wcsdup wcscasecmp wcsnlen putwc \
getuserid getgroupid \
alarm sigaction usleep
@@ -5477,156 +6024,6 @@ done
-
-
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit off_t" >&5
-$as_echo_n "checking for 64-bit off_t... " >&6; }
-if ${sfs_cv_off_t_64+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#include <unistd.h>
-#include <sys/types.h>
-
-int
-main ()
-{
-
-switch (0) case 0: case (sizeof (off_t) <= 4):;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- sfs_cv_off_t_64=no
-else
- sfs_cv_off_t_64=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $sfs_cv_off_t_64" >&5
-$as_echo "$sfs_cv_off_t_64" >&6; }
-if test $sfs_cv_off_t_64 = yes; then
-
-$as_echo "#define HAVE_OFF_T_64 1" >>confdefs.h
-
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports loff_t type" >&5
-$as_echo_n "checking whether ${CC} supports loff_t type... " >&6; }
-if ${ice_cv_have_loff_t+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
-int
-main ()
-{
-loff_t a;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ice_cv_have_loff_t=yes
-else
- ice_cv_have_loff_t=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ice_cv_have_loff_t" >&5
-$as_echo "$ice_cv_have_loff_t" >&6; }
-if test "$ice_cv_have_loff_t" = yes; then
-
-$as_echo "#define HAVE_LOFF_T 1" >>confdefs.h
-
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports offset_t type" >&5
-$as_echo_n "checking whether ${CC} supports offset_t type... " >&6; }
-if ${ice_cv_have_offset_t+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
-int
-main ()
-{
-offset_t a;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ice_cv_have_offset_t=yes
-else
- ice_cv_have_offset_t=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ice_cv_have_offset_t" >&5
-$as_echo "$ice_cv_have_offset_t" >&6; }
-if test "$ice_cv_have_offset_t" = yes; then
-
-$as_echo "#define HAVE_OFFSET_T 1" >>confdefs.h
-
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports long long type" >&5
-$as_echo_n "checking whether ${CC} supports long long type... " >&6; }
-if ${ice_cv_have_long_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-long long a;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ice_cv_have_long_long=yes
-else
- ice_cv_have_long_long=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ice_cv_have_long_long" >&5
-$as_echo "$ice_cv_have_long_long" >&6; }
-if test "$ice_cv_have_long_long" = yes; then
-
-$as_echo "#define HAVE_LONG_LONG 1" >>confdefs.h
-
-fi
-
-
-
for ac_func in utimes utime
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
@@ -6460,98 +6857,6 @@ fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsocket" >&5
-$as_echo_n "checking for main in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-return main ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_socket_main=yes
-else
- ac_cv_lib_socket_main=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_main" >&5
-$as_echo "$ac_cv_lib_socket_main" >&6; }
-if test "x$ac_cv_lib_socket_main" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBSOCKET 1
-_ACEOF
-
- LIBS="-lsocket $LIBS"
-
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lbsd" >&5
-$as_echo_n "checking for main in -lbsd... " >&6; }
-if ${ac_cv_lib_bsd_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lbsd $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-return main ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_bsd_main=yes
-else
- ac_cv_lib_bsd_main=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_main" >&5
-$as_echo "$ac_cv_lib_bsd_main" >&6; }
-if test "x$ac_cv_lib_bsd_main" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBBSD 1
-_ACEOF
-
- LIBS="-lbsd $LIBS"
-
-fi
-
-for ac_header in sys/socket.h arpa/inet.h netdb.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
if test X$use_floppyd = X -a X$no_x = X ; then
use_floppyd="yes"
fi
@@ -6564,6 +6869,8 @@ if test X$use_floppyd = Xyes; then
fi
FLOPPYD="floppyd floppyd_installtest"
BINFLOPPYD="\$(DESTDIR)\$(bindir)/floppyd \$(DESTDIR)\$(bindir)/floppyd_installtest"
+ FLOPPYD_IO_SRC=floppyd_io.c
+ FLOPPYD_IO_OBJ=floppyd_io.o
$as_echo "#define USE_FLOPPYD 1" >>confdefs.h
@@ -6607,9 +6914,94 @@ $as_echo "#define SETPGRP_VOID 1" >>confdefs.h
fi
+
+ FLOPPYD_LIBS=""
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XOpenDisplay in -lX11" >&5
+$as_echo_n "checking for XOpenDisplay in -lX11... " >&6; }
+if ${ac_cv_lib_X11_XOpenDisplay+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lX11 $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XOpenDisplay ();
+int
+main ()
+{
+return XOpenDisplay ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_X11_XOpenDisplay=yes
+else
+ ac_cv_lib_X11_XOpenDisplay=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_X11_XOpenDisplay" >&5
+$as_echo "$ac_cv_lib_X11_XOpenDisplay" >&6; }
+if test "x$ac_cv_lib_X11_XOpenDisplay" = xyes; then :
+ FLOPPYD_LIBS="-lX11 $FLOPPYD_LIBS"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XauFileName in -lXau" >&5
+$as_echo_n "checking for XauFileName in -lXau... " >&6; }
+if ${ac_cv_lib_Xau_XauFileName+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXau $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XauFileName ();
+int
+main ()
+{
+return XauFileName ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_Xau_XauFileName=yes
+else
+ ac_cv_lib_Xau_XauFileName=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xau_XauFileName" >&5
+$as_echo "$ac_cv_lib_Xau_XauFileName" >&6; }
+if test "x$ac_cv_lib_Xau_XauFileName" = xyes; then :
+ FLOPPYD_LIBS="-lXau $FLOPPYD_LIBS"
+fi
+
else
FLOPPYD=
BINFLOPPYD=
+ FLOPPYD_IO_SRC=
+ FLOPPYD_IO_OBJ=
+ FLOPPYD_LIBS=
fi
@@ -6621,6 +7013,11 @@ fi
+
+
+
+
+
ac_config_files="$ac_config_files Makefile"
cat >confcache <<\_ACEOF
diff --git a/configure.in b/configure.in
index 5ff75c1..72cf205 100644
--- a/configure.in
+++ b/configure.in
@@ -16,7 +16,7 @@ dnl along with Mtools. If not, see <http://www.gnu.org/licenses/>.
dnl
dnl Process this file with autoconf to produce a configure script.
AC_INIT(buffer.c)
-
+m4_include([m4/ax_lib_socket_nsl.m4])
AC_CONFIG_HEADER(config.h)
dnl Checks for compiler
@@ -41,8 +41,15 @@ AC_ARG_ENABLE(xdf,
[ --enable-xdf support for OS/2 extended density format disks],
[if test x$enableval = xyes; then
AC_DEFINE([USE_XDF],1,[Define this if you want to use Xdf])
-fi],AC_DEFINE([USE_XDF],1,[Define this if you want to use Xdf]))
-
+ XDF_IO_SRC=xdf_io.c
+ XDF_IO_OBJ=xdf_io.o
+fi],[AC_DEFINE([USE_XDF],1,[Define this if you want to use Xdf])
+XDF_IO_SRC=xdf_io.c
+XDF_IO_OBJ=xdf_io.o
+]
+)
+AC_SUBST(XDF_IO_SRC)
+AC_SUBST(XDF_IO_OBJ)
dnl Check for configuration options
dnl Enable usage of vold on Solaris
@@ -89,10 +96,16 @@ AC_CHECK_LIB(sun, getpwnam)
AC_CHECK_LIB(cam, cam_open_device)
AC_CHECK_LIB(iconv, iconv)
+dnl Check for platform-specific libraries
+AC_CHECK_LIB(socket,main)
+AX_LIB_SOCKET_NSL
+AC_CHECK_LIB(bsd,main)
+
dnl Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS(getopt.h sys/stat.h stdlib.h unistd.h linux/unistd.h \
+AC_HEADER_STDBOOL
+AC_CHECK_HEADERS(getopt.h stdarg.h stdlib.h unistd.h linux/unistd.h \
libc.h fcntl.h limits.h sys/file.h sys/ioctl.h sys/time.h strings.h string.h \
sys/param.h memory.h malloc.h io.h signal.h sys/signal.h utime.h sgtty.h \
sys/floppy.h mntent.h sys/sysmacros.h netinet/in.h netinet/tcp.h assert.h \
@@ -100,6 +113,10 @@ iconv.h wctype.h wchar.h locale.h xlocale.h linux/fs.h)
AC_CHECK_HEADERS(termio.h sys/termio.h, [break])
AC_CHECK_HEADERS(termios.h sys/termios.h, [break])
+dnl Check for platform-specific header files
+AC_CHECK_HEADERS(sys/fdio.h)
+AC_CHECK_HEADERS(sys/socket.h arpa/inet.h netdb.h)
+
dnl Check for types
AC_SYS_LARGEFILE
AC_TYPE_INT8_T
@@ -115,43 +132,75 @@ AC_TYPE_SIGNAL
AC_TYPE_UID_T
AC_CHECK_TYPES(caddr_t)
+AC_CHECK_TYPES(long long)
AC_CHECK_SIZEOF(size_t)
+AC_CHECK_SIZEOF(off_t)
AC_CHECK_SIZEOF(time_t)
AC_CHECK_SIZEOF(long)
-AC_CHECK_SIZEOF(long long)
-dnl
-dnl Check to see if llseek() is declared in unistd.h. On some libc's
-dnl it is, and on others it isn't..... Thank you glibc developers....
-dnl
-dnl Warning! Use of --enable-gcc-wall may throw off this test.
-dnl
-dnl
-AC_MSG_CHECKING(whether llseek declared in unistd.h)
-AC_CACHE_VAL(mtools_cv_have_llseek_prototype,
- AC_TRY_COMPILE(
-[#include <unistd.h>], [extern int llseek(int);],
- [mtools_cv_have_llseek_prototype=no],
- [mtools_cv_have_llseek_prototype=yes]))
-AC_MSG_RESULT($mtools_cv_have_llseek_prototype)
-if test "$mtools_cv_have_llseek_prototype" = yes; then
- AC_DEFINE([HAVE_LLSEEK_PROTOTYPE],1,[Define when you have an LLSEEK prototype])
+seek_function=
+
+if test $ac_cv_sizeof_off_t -ge 8 ; then
+ seek_function=lseek
fi
-AC_MSG_CHECKING(whether lseek64 declared in unistd.h)
-AC_CACHE_VAL(mtools_cv_have_lseek64_prototype,
- AC_TRY_COMPILE(
-[
-#include "sysincludes.h"
-#include <unistd.h>
-], [extern int lseek64(int);],
+dnl Fallback if we have no suitable 64 bit seek function yet
+if test X$seek_function = X ; then
+ AC_DEFINE([_LARGEFILE64_SOURCE],1,[Needed for off64_t / lseek64 ])
+ AC_CHECK_TYPES(off64_t,
+ [ AC_CHECK_FUNCS(lseek64, [ seek_function=lseek64 ])
+ ])
+ AC_CHECK_FUNCS(stat64)
+ if test X$seek_function = Xlseek64 ; then
+ AC_MSG_CHECKING(whether lseek64 declared in unistd.h)
+ AC_CACHE_VAL(mtools_cv_have_lseek64_prototype,
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[
+ #define _LARGEFILE64_SOURCE
+ #include <sys/types.h>
+ #include <unistd.h>
+ ]], [[extern int lseek64(int);]])],
[mtools_cv_have_lseek64_prototype=no],
[mtools_cv_have_lseek64_prototype=yes]))
-AC_MSG_RESULT($mtools_cv_have_lseek64_prototype)
-if test "$mtools_cv_have_lseek64_prototype" = yes; then
- AC_DEFINE([HAVE_LSEEK64_PROTOTYPE],1,[Define when you have an LSEEK64 prototype])
+ AC_MSG_RESULT($mtools_cv_have_lseek64_prototype)
+ if test "$mtools_cv_have_lseek64_prototype" = yes; then
+ AC_DEFINE([HAVE_LSEEK64_PROTOTYPE],1,[Define when you have an LSEEK64 prototype])
+ fi
+ fi
fi
+dnl Fallback if we have no suitable 64 bit seek function yet
+if test X$seek_function = X ; then
+ AC_DEFINE([_LARGEFILE_SOURCE],1,[Might be needed for loff_t / llseek64 ])
+ AC_CHECK_TYPES([loff_t, offset_t, long long],
+ [ AC_CHECK_FUNCS(llseek, [ seek_function=llseek ])
+ ])
+
+ if test X$seek_function = Xllseek ; then
+ dnl
+ dnl Check to see if llseek() is declared in unistd.h. On some libc's
+ dnl it is, and on others it isn't..... Thank you glibc developers....
+ dnl
+ dnl Warning! Use of --enable-gcc-wall may throw off this test.
+ dnl
+ dnl
+ AC_MSG_CHECKING(whether llseek declared in unistd.h)
+ AC_CACHE_VAL(mtools_cv_have_llseek_prototype,
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[
+ #define _LARGEFILE_SOURCE
+ #define _LARGEFILE64_SOURCE
+ #include <sys/types.h>
+ #include <unistd.h>
+ ]], [[extern int llseek(int);]])],
+ [mtools_cv_have_llseek_prototype=no],
+ [mtools_cv_have_llseek_prototype=yes]))
+ AC_MSG_RESULT($mtools_cv_have_llseek_prototype)
+ if test "$mtools_cv_have_llseek_prototype" = yes; then
+ AC_DEFINE([HAVE_LLSEEK_PROTOTYPE],1,[Define when you have an LLSEEK prototype])
+ fi
+ fi
+fi
AC_CHECK_FUNCS(htons)
@@ -171,115 +220,12 @@ AC_CHECK_FUNCS(strerror random srandom strchr strrchr lockf flock \
strcasecmp strncasecmp strnlen atexit on_exit getpass memmove \
strdup strndup strcspn strspn strtoul strtol strtoll strtoi strtoui \
memcpy strpbrk memset setenv seteuid setresuid setpgrp \
-tcsetattr tcflush basename fchdir media_oldaliases llseek lseek64 \
-snprintf stat64 setlocale toupper_l strncasecmp_l \
+tcsetattr tcflush basename fchdir media_oldaliases \
+snprintf setlocale toupper_l strncasecmp_l \
wcsdup wcscasecmp wcsnlen putwc \
getuserid getgroupid \
alarm sigaction usleep)
-dnl
-dnl Check for 64-bit off_t
-dnl
-AC_DEFUN(SFS_CHECK_OFF_T_64,
-[AC_CACHE_CHECK(for 64-bit off_t, sfs_cv_off_t_64,
-AC_TRY_COMPILE([
-#include <unistd.h>
-#include <sys/types.h>
-],[
-switch (0) case 0: case (sizeof (off_t) <= 4):;
-], sfs_cv_off_t_64=no, sfs_cv_off_t_64=yes))
-if test $sfs_cv_off_t_64 = yes; then
- AC_DEFINE([HAVE_OFF_T_64],1,[Define when the system has a 64 bit off_t type])
-fi])
-
-
-dnl ICE_CC_LOFF_T
-dnl -------------
-dnl
-dnl If the CC compiler supports `loff_t' type, define `HAVE_LOFF_T'.
-dnl
-AC_DEFUN(ICE_CC_LOFF_T,
-[
-AC_MSG_CHECKING(whether ${CC} supports loff_t type)
-AC_CACHE_VAL(ice_cv_have_loff_t,
-[
-AC_TRY_COMPILE([#include <sys/types.h>],[loff_t a;],
-ice_cv_have_loff_t=yes,
-ice_cv_have_loff_t=no)
-])
-AC_MSG_RESULT($ice_cv_have_loff_t)
-if test "$ice_cv_have_loff_t" = yes; then
-AC_DEFINE([HAVE_LOFF_T],1,[Define when the compiler supports LOFF_T type])
-fi
-])dnl
-
-
-dnl ICE_CC_OFFSET_T
-dnl -------------
-dnl
-dnl If the CC compiler supports `offset_t' type, define `HAVE_OFFSET_T'.
-dnl
-AC_DEFUN(ICE_CC_OFFSET_T,
-[
-AC_MSG_CHECKING(whether ${CC} supports offset_t type)
-AC_CACHE_VAL(ice_cv_have_offset_t,
-[
-AC_TRY_COMPILE([#include <sys/types.h>],[offset_t a;],
-ice_cv_have_offset_t=yes,
-ice_cv_have_offset_t=no)
-])
-AC_MSG_RESULT($ice_cv_have_offset_t)
-if test "$ice_cv_have_offset_t" = yes; then
-AC_DEFINE([HAVE_OFFSET_T],1,[Define when the compiler supports OFFSET_T type])
-fi
-])dnl
-
-dnl ICE_CC_LONG_LONG
-dnl -------------
-dnl
-dnl If the CC compiler supports `long long' type, define `HAVE_LONG_LONG'.
-dnl
-AC_DEFUN(ICE_CC_LONG_LONG,
-[
-AC_MSG_CHECKING(whether ${CC} supports long long type)
-AC_CACHE_VAL(ice_cv_have_long_long,
-[
-AC_TRY_COMPILE(,[long long a;],
-ice_cv_have_long_long=yes,
-ice_cv_have_long_long=no)
-])
-AC_MSG_RESULT($ice_cv_have_long_long)
-if test "$ice_cv_have_long_long" = yes; then
-AC_DEFINE([HAVE_LONG_LONG],1,[Define when the compiler supports LONG_LONG type])
-fi
-])dnl
-
-dnl ICE_CC_OFF64_T
-dnl -------------
-dnl
-dnl If the CC compiler supports `long long' type, define `HAVE_OFF64_T'.
-dnl
-AC_DEFUN(ICE_CC_OFF64_T,
-[
-AC_MSG_CHECKING(whether ${CC} supports off64_t type)
-AC_CACHE_VAL(ice_cv_have_off64_t,
-[
-AC_TRY_COMPILE(,[off64_t a;],
-ice_cv_have_off64_t=yes,
-ice_cv_have_off64_t=no)
-])
-AC_MSG_RESULT($ice_cv_have_off64_t)
-if test "$ice_cv_have_off64_t" = yes; then
-AC_DEFINE([HAVE_OFF64_T],1,[Define when the compiler supports OFF64_T type])
-fi
-])dnl
-
-
-SFS_CHECK_OFF_T_64
-ICE_CC_LOFF_T
-ICE_CC_OFFSET_T
-ICE_CC_LONG_LONG
-
AC_CHECK_FUNCS(utimes utime, [break])
AC_CHECK_FUNCS(tzset gettimeofday)
@@ -376,11 +322,6 @@ AC_ARG_ENABLE(floppyd,
use_floppyd=$enableval
fi])
-AC_CHECK_LIB(socket,main)
-dnl AC_CHECK_LIB(nsl,getpwnam)
-AC_CHECK_LIB(bsd,main)
-AC_CHECK_HEADERS(sys/socket.h arpa/inet.h netdb.h)
-
if test X$use_floppyd = X -a X$no_x = X ; then
use_floppyd="yes"
fi
@@ -393,16 +334,30 @@ if test X$use_floppyd = Xyes; then
fi
FLOPPYD="floppyd floppyd_installtest"
BINFLOPPYD="\$(DESTDIR)\$(bindir)/floppyd \$(DESTDIR)\$(bindir)/floppyd_installtest"
+ FLOPPYD_IO_SRC=floppyd_io.c
+ FLOPPYD_IO_OBJ=floppyd_io.o
AC_DEFINE([USE_FLOPPYD],1,[Define when you want to include floppyd support])
AC_FUNC_SETPGRP
+
+ FLOPPYD_LIBS=""
+ AC_CHECK_LIB(X11, XOpenDisplay, [ FLOPPYD_LIBS="-lX11 $FLOPPYD_LIBS" ])
+ AC_CHECK_LIB(Xau, XauFileName, [ FLOPPYD_LIBS="-lXau $FLOPPYD_LIBS" ])
else
FLOPPYD=
BINFLOPPYD=
+ FLOPPYD_IO_SRC=
+ FLOPPYD_IO_OBJ=
+ FLOPPYD_LIBS=
fi
+
+AC_SUBST(FLOPPYD_LIBS)
AC_SUBST(FLOPPYD)
AC_SUBST(BINFLOPPYD)
+AC_SUBST(FLOPPYD_IO_SRC)
+AC_SUBST(FLOPPYD_IO_OBJ)
+
AC_SUBST(extraincludedir)
AC_SUBST(extralibdir)
AC_SUBST(MACHDEPLIBS)
diff --git a/copyfile.c b/copyfile.c
index ad5b3d0..cf0eeeb 100644
--- a/copyfile.c
+++ b/copyfile.c
@@ -24,14 +24,12 @@
* Copy the data from source to target
*/
-int copyfile(Stream_t *Source, Stream_t *Target)
+mt_off_t copyfile(Stream_t *Source, Stream_t *Target)
{
char buffer[8*16384];
mt_off_t pos;
- int ret;
+ ssize_t ret;
ssize_t retw;
-/* size_t len;*/
- mt_size_t mt_len;
if (!Source){
fprintf(stderr,"Couldn't open source file\n");
@@ -44,9 +42,8 @@ int copyfile(Stream_t *Source, Stream_t *Target)
}
pos = 0;
- GET_DATA(Source, 0, &mt_len, 0, 0);
while(1){
- ret = READS(Source, buffer, (mt_off_t) pos, 8*16384);
+ ret = READS(Source, buffer, 8*16384);
if (ret < 0 ){
perror("file read");
return -1;
@@ -57,19 +54,18 @@ int copyfile(Stream_t *Source, Stream_t *Target)
return -1;
if (ret == 0)
break;
- if ((retw = force_write(Target, buffer,
- (mt_off_t) pos, (size_t) ret)) != ret){
+ if ((retw = force_write(Target, buffer, (size_t) ret)) != ret){
if(retw < 0 )
perror("write in copy");
else
fprintf(stderr,
- "Short write %lu instead of %d\n",
- (unsigned long) retw, ret);
+ "Short write %zd instead of %zd\n",
+ retw, ret);
if(errno == ENOSPC)
got_signal = 1;
return ret;
}
pos += ret;
}
- return 0;
+ return pos;
}
diff --git a/debian/changelog b/debian/changelog
index f98e47c..a8a1f6a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,133 @@
+mtools (4.0.37) stable; urgency=low
+
+ * Removed mclasserase commands, which doesn't fit the coding
+ structure of the rest of mtools
+ * Add support to -i option to mcd
+ * Document -i in mtools.1
+ * Fix a missing commad error in floppyd_io.c
+
+ -- Alain Knaff <alain@knaff.lu> Sun, 26 Dec 2021 18:57:02 +0100
+mtools (4.0.36) stable; urgency=low
+
+ * Fix error status of recursive listing of empty root directory
+ * If recursive listing, also show matched files at level one
+ * Use "seekless" reads & write internally, where possible
+ * Text mode conversion refactoring
+ * Misc refactoring
+
+ -- Alain Knaff <alain@knaff.lu> Sun, 21 Nov 2021 16:41:10 +0100
+mtools (4.0.35) stable; urgency=low
+
+ * Fix cluster padding at end of file in batch mode, and add comments
+ about what happens here
+
+ -- Alain Knaff <alain@knaff.lu> Fri, 6 Aug 2021 20:13:59 +0200
+mtools (4.0.34) stable; urgency=low
+
+ * Fix mcopy -s issue
+
+ -- Alain Knaff <alain@knaff.lu> Fri, 23 Jul 2021 12:41:11 +0200
+mtools (4.0.33) stable; urgency=low
+
+ * Fix support for partitions (broken in 4.0.30)
+ * Portability fixes for Solaris 10 and 11
+ * General simplification of configure script, and largefile handling
+ * Tested and fixed for platforms *without* largefile support
+ * In cases where lseek works with 32-bit offsets, prefer lseek64 over llseek
+ * Fixed floppy sector size handling on platforms that are not Linux
+ * Added support for image files on command line to mcat
+
+ -- Alain Knaff <alain@knaff.lu> Sat, 17 Jul 2021 18:31:38 +0200
+mtools (4.0.32) stable; urgency=low
+
+ * Simplify algorithm that choses filesystem parameters for format, and align
+ it more closely with what Win7 does
+
+ * Fix mformatting XDF when XDF not explicitly specified on mformat command
+ line
+
+ * easier way to enter sizes on mformat command line (mformat -C -T 1440K)
+
+ * For small sizes, mformat assumes floppy geometries (heads 1 or 2,
+ tracks 40 or 80)
+
+ * Handle attempts to mformat too small filesystems more gracefully
+
+ * Enable minfo to print out additional mformat command line parameters, if
+ the present filesystem uses non-default values for these
+
+ * minfo no longer prints bigsect if smallsect is set
+
+ * for remap filter, error when trying to write non-zero data to unmapped
+ sectors
+
+ * Fix misc compilation warnings occuring when disabling certain features
+ (largefiles, raw-term)
+
+ -- Alain Knaff <alain@knaff.lu> Sat, 10 Jul 2021 14:31:23 +0200
+mtools (4.0.31) stable; urgency=low
+
+ * Move Linux-specific block device sizing code into
+ linux-specific section of devices.c
+ * Error messages for all failure cases on fs_init failure
+ * Fix compilation without XDF support (OpenImage signature)
+ * Fix polarity of format_xdf command-line parameter of mformat
+ * In XDF_IO retry enough times to actually succeed, even if
+ FDC was in a bad state before
+ * Remove useless buffer flushing triggered when giving up a
+ reference to a stream node that is still referenced
+ elsewhere.
+ * Clearer error message if neither size nor geometry of drive
+ to be mformatted is known
+ * In mformat, make Fs dynamically allocated rather than
+ on-stack, so as to be able to use utilities supplied by
+ stream.c
+ * Remove duplicate writing of backup boot sector
+ * Allow to infer geometry if only size is specified
+ * Protect against attempt to create zero-sized buffer
+ * Code simplification in mattrib
+ * Remove dead code in mpartition
+
+ -- Alain Knaff <alain@knaff.lu> Sat, 19 Jun 2021 17:22:27 +0200
+mtools (4.0.30) stable; urgency=low
+
+ * Fixed XDF floppy disk access
+ * Fixed faulty behavior at end of image in mcat
+ * Device/Image size handling refactoring
+ * allow remap to write to zero-backed sectors (may happen if
+ buffer is flushed, and is not an error in that case)
+ * Raise an error when trying to mcopy multiple source files
+ over a single destination file (rather than directory)
+ * fix handling of "hidden" sectors (is a 2 byte quantity on
+ small disks, not 4 byte as previously assumed)
+ * Modernize partition support. Tuned consistency check to
+ actually check about important issues (such as overlapping
+ partitions) rather than stuff nobody else cares about
+ (alignment on entire cylinder boundaries)
+ * Move various "filter" options (partition, offset, swap,
+ scsi) into separate classes, rather than leaving almost
+ everything in plain_io
+ * Simplify and centralize geometry handling and LBA code
+ * Fix some more more compiler warnings
+
+ -- Alain Knaff <alain@knaff.lu> Thu, 17 Jun 2021 22:23:39 +0200
+mtools (4.0.29) stable; urgency=low
+
+ * -Fix bug in cluster preallocation, which was accidentally introduced by compiler warning "fixes" from v4_0_28
+
+ -- Alain Knaff <alain@knaff.lu> Mon, 31 May 2021 19:07:43 +0200
+mtools (4.0.28) stable; urgency=low
+
+ * Support remapping of data (for not-quite linear floppy image files)
+ * Re-open floppy devices read-write if geometry parameters need to be changed
+ * relax consistency checks in mpartition (partitions created by current fdisk would almost never pass these checks)
+ * Fix some compiler warnings
+
+ -- Alain Knaff <alain@knaff.lu> Sun, 30 May 2021 18:33:09 +0200
+mtools (4.0.27) stable; urgency=low
+ * Fix type error in calls to iconv functions
+
+ -- Alain Knaff <alain@knaff.lu> Fri, 16 Apr 2021 20:54:49 +0200
mtools (4.0.26) stable; urgency=low
* Fix compilation on Macintosh
* Ignore image file locking errors if we are performing a read-only access anyways
diff --git a/debian/mtools.manpages b/debian/mtools.manpages
index be24a60..5d03275 100644
--- a/debian/mtools.manpages
+++ b/debian/mtools.manpages
@@ -3,7 +3,6 @@ mattrib.1
mbadblocks.1
mcat.1
mcd.1
-mclasserase.1
mcopy.1
mdel.1
mdeltree.1
diff --git a/device.c b/device.c
new file mode 100644
index 0000000..4bbf7b8
--- /dev/null
+++ b/device.c
@@ -0,0 +1,72 @@
+/* Copyright 2021 Alain Knaff.
+ * This file is part of mtools.
+ *
+ * Mtools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysincludes.h"
+#include "llong.h"
+#include "device.h"
+
+int check_if_sectors_fit(uint32_t tot_sectors,
+ mt_off_t maxBytes,
+ uint32_t sectorSize,
+ char *errmsg)
+{
+ if(!maxBytes)
+ return 0; /* Maxbytes = 0 => no checking */
+ if(tot_sectors > (smt_off_t) maxBytes / (smt_off_t) sectorSize) {
+ sprintf(errmsg,
+ "%d sectors too large for this platform\n",
+ tot_sectors);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Calculate number of total sectors on device if needed, and check that
+ * they fit into
+ */
+int chs_to_totsectors(struct device *dev, char *errmsg)
+{
+ uint32_t sect_per_track, tot_sectors;
+
+ if(dev->tot_sectors)
+ return 0;
+
+ if(!dev->heads || !dev->sectors || !dev->tracks)
+ return 0; /* not fully specified => we cannot do
+ anything anyways */
+
+ /* Cannot overflow as both dev->heads and dev->sectors are 16
+ * bit quantities, whose product will be put into a 32 bit
+ * field */
+ sect_per_track = dev->heads * dev->sectors;
+
+ if(dev->tracks > UINT32_MAX / sect_per_track) {
+ /* Would not fit in 32 bits */
+
+ if(errmsg)
+ sprintf(errmsg,
+ "Number of sectors larger than 2^32\n");
+ return -1;
+ }
+
+ tot_sectors = dev->tracks * sect_per_track;
+ if(tot_sectors > dev->hidden % sect_per_track)
+ tot_sectors -= dev->hidden % sect_per_track;
+ dev->tot_sectors = tot_sectors;
+ return 0;
+}
diff --git a/device.h b/device.h
new file mode 100644
index 0000000..e577029
--- /dev/null
+++ b/device.h
@@ -0,0 +1,101 @@
+#ifndef MTOOLS_DEVICE_H
+#define MTOOLS_DEVICE_H
+/* Copyright 2021 Alain Knaff.
+ * This file is part of mtools.
+ *
+ * Mtools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Functions needed to work with struct device */
+
+#include "llong.h"
+
+/* Stuff related to particular device definitions are in devices.c
+ (note the plural) */
+
+#define SCSI_FLAG 0x001u
+#define PRIV_FLAG 0x002u
+#define NOLOCK_FLAG 0x004u
+#define USE_XDF_FLAG 0x008u
+#define MFORMAT_ONLY_FLAG 0x010u
+#define VOLD_FLAG 0x020u
+#define FLOPPYD_FLAG 0x040u
+#define FILTER_FLAG 0x080u
+#define SWAP_FLAG 0x100u
+
+#define IS_SCSI(x) ((x) && ((x)->misc_flags & SCSI_FLAG))
+#define IS_PRIVILEGED(x) ((x) && ((x)->misc_flags & PRIV_FLAG))
+#define IS_NOLOCK(x) ((x) && ((x)->misc_flags & NOLOCK_FLAG))
+#define IS_MFORMAT_ONLY(x) ((x) && ((x)->misc_flags & MFORMAT_ONLY_FLAG))
+#define SHOULD_USE_VOLD(x) ((x)&& ((x)->misc_flags & VOLD_FLAG))
+#define SHOULD_USE_XDF(x) ((x)&& ((x)->misc_flags & USE_XDF_FLAG))
+#define DO_SWAP(x) ((x) && ((x)->misc_flags & SWAP_FLAG))
+
+typedef struct device {
+ const char *name; /* full path to device */
+
+ char drive; /* the drive letter */
+ int fat_bits; /* FAT encoding scheme */
+
+ int mode; /* any special open() flags */
+ unsigned int tracks; /* tracks */
+ uint16_t heads; /* heads */
+ uint16_t sectors; /* sectors */
+ unsigned int hidden; /* number of hidden sectors. Used for
+ * mformatting partitioned devices */
+
+ off_t offset; /* skip this many bytes */
+
+ unsigned int partition;
+
+ unsigned int misc_flags;
+
+ /* Linux only stuff */
+ uint8_t ssize;
+ unsigned int use_2m;
+
+ char *precmd; /* command to be executed before opening
+ * the drive */
+
+ /* internal variables */
+ int file_nr; /* used during parsing */
+ unsigned int blocksize; /* size of disk block in bytes */
+
+ unsigned int codepage; /* codepage for shortname encoding */
+
+ const char *data_map;
+
+ uint32_t tot_sectors; /* Amount of total sectors, more
+ * precise than tracks (in case of
+ * partitions which may take up parts
+ * of a track) */
+
+ uint16_t sector_size; /* Non-default sector size */
+
+ const char *cfg_filename; /* used for debugging purposes */
+} device_t;
+
+extern struct device *devices;
+extern struct device const_devices[];
+extern const unsigned int nr_const_devices;
+
+int lock_dev(int fd, int mode, struct device *dev);
+
+void precmd(struct device *dev);
+
+int check_if_sectors_fit(uint32_t tot_sectors, mt_off_t maxBytes,
+ uint32_t sectorSize, char *errmsg);
+int chs_to_totsectors(struct device *dev, char *errmsg);
+
+#endif
diff --git a/devices.c b/devices.c
index f9d894e..134d830 100644
--- a/devices.c
+++ b/devices.c
@@ -28,11 +28,15 @@
#define INIT_NOOP
-#define DEF_ARG1(x) (x), 0x2,0,(char *)0, 0, 0
+#define DEF_ARG1(x) (x), 0x2,0,(char *)0, 0, 0, 0, 0, 0, 0, NULL
#define DEF_ARG0(x) 0,DEF_ARG1(x)
#define MDEF_ARG 0L,DEF_ARG0(MFORMAT_ONLY_FLAG)
#define FDEF_ARG 0L,DEF_ARG0(0)
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
#define VOLD_DEF_ARG 0L,DEF_ARG0(VOLD_FLAG|MFORMAT_ONLY_FLAG)
#define MED312 12,0,80,2,36,0,MDEF_ARG /* 3 1/2 extra density */
@@ -66,7 +70,9 @@
#define ZIP(x) ZIPJAZ(x,96, 64, 32, 0)
#define RZIP(x) ZIPJAZ(x,96, 64, 32, SCSI_FLAG|PRIV_FLAG)
-#define REMOTE {"$DISPLAY", 'X', 0,0, 0,0, 0,0,0L, DEF_ARG0(FLOPPYD_FLAG),0,0}
+#pragma GCC diagnostic pop
+
+#define REMOTE {"$DISPLAY", 'X', 0,0, 0,0, 0,0,0L, DEF_ARG0(FLOPPYD_FLAG)}
@@ -170,7 +176,7 @@ static inline int get_parameters(int fd, struct generic_floppy_struct *floppy)
perror("FLOPPY_GET_GEOMETRY");
return(1);
}
-
+
return 0;
}
@@ -180,21 +186,21 @@ static inline int get_parameters(int fd, struct generic_floppy_struct *floppy)
#define FD_SECTSIZE(floppy) floppy.fg.sector_size
#define FD_SET_SECTSIZE(floppy,v) { floppy.fg.sector_size = v; }
-static inline int set_parameters(int fd, struct generic_floppy_struct *floppy,
+static inline int set_parameters(int fd, struct generic_floppy_struct *floppy,
struct MT_STAT *buf)
{
if (ioctl(fd, FLOPPY_SET_GEOMETRY, &(floppy->fg)) != 0) {
perror("");
return(1);
}
-
+
return 0;
}
#define INIT_GENERIC
#endif
#endif /* hpux */
-
+
#if (defined(OS_sinix) || defined(VENDOR_sni) || defined(SNI))
#define predefined_devices
@@ -314,7 +320,7 @@ struct device devices[] = {
};
#endif /* aix */
-
+
#ifdef OS_osf4
/* modified by Chris Samuel <chris@rivers.dra.hmg.gb> */
#define predefined_devices
@@ -330,14 +336,14 @@ struct device devices[] = {
#ifdef USING_NEW_VOLD
char *alias_name = NULL;
-
+
extern char *media_oldaliases(char *);
extern char *media_findname(char *);
char *getVoldName(struct device *dev, char *name)
{
char *rname;
-
+
if(!SHOULD_USE_VOLD(dev))
return name;
@@ -353,8 +359,8 @@ char *getVoldName(struct device *dev, char *name)
}
#endif
if (rname == NULL) {
- fprintf(stderr,
- "No such volume or no media in device: %s.\n",
+ fprintf(stderr,
+ "No such volume or no media in device: %s.\n",
name);
exit(1);
}
@@ -380,6 +386,7 @@ struct device devices[] = {
+#ifdef HAVE_SYS_FDIO_H
/*
* Ofer Licht <ofer@stat.Berkeley.EDU>, May 14, 1997.
*/
@@ -414,8 +421,8 @@ static inline int get_parameters(int fd, struct generic_floppy_struct *floppy)
#define FD_SECTSIZE(floppy) floppy.fdchar.fdc_sec_size
#define FD_SET_SECTSIZE(floppy,v) { floppy.fdchar.fdc_sec_size = v; }
-static inline int set_parameters(int fd, struct generic_floppy_struct *floppy,
- struct MT_STAT *buf)
+static inline int set_parameters(int fd, struct generic_floppy_struct *floppy,
+ struct MT_STAT *buf UNUSEDP)
{
if (ioctl(fd, FDIOSCHAR, &(floppy->fdchar)) != 0) {
ioctl(fd, FDEJECT, NULL);
@@ -424,7 +431,7 @@ static inline int set_parameters(int fd, struct generic_floppy_struct *floppy,
}
return 0;
}
-#define INIT_GENERIC
+#endif
#endif /* solaris */
#ifdef OS_sunos3
@@ -490,7 +497,7 @@ struct device devices[] = {
/*
* Stuffing back the floppy parameters into the driver allows for gems
* like 10 sector or single sided floppies from Atari ST systems.
- *
+ *
* Martin Schulz, Universite de Moncton, N.B., Canada, March 11, 1991.
*/
@@ -512,7 +519,7 @@ static inline int get_parameters(int fd, struct generic_floppy_struct *floppy)
ioctl(fd, FDKEJECT, NULL);
return(1);
}
-
+
if (ioctl(fd, FDKIOGCHAR, &( floppy->dkbuf)) != 0) {
perror("");
ioctl(fd, FDKEJECT, NULL);
@@ -528,7 +535,7 @@ static inline int get_parameters(int fd, struct generic_floppy_struct *floppy)
#define FD_SECTSIZE(floppy) floppy.dkbuf.sec_size
#define FD_SET_SECTSIZE(floppy,v) { floppy.dkbuf.sec_size = v; }
-static inline int set_parameters(int fd, struct generic_floppy_struct *floppy,
+static inline int set_parameters(int fd, struct generic_floppy_struct *floppy,
struct MT_STAT *buf)
{
if (ioctl(fd, FDKIOSCHAR, &(floppy->dkbuf)) != 0) {
@@ -536,7 +543,7 @@ static inline int set_parameters(int fd, struct generic_floppy_struct *floppy,
perror("");
return(1);
}
-
+
if (ioctl(fd, ( unsigned int) DKIOCSPART, &(floppy->dkmap)) != 0) {
ioctl(fd, FDKEJECT, NULL);
perror("");
@@ -611,15 +618,15 @@ static __inline__ void print_message(RawRequest_t *raw_cmd,const char *message)
fprintf(stderr," ");
for (i=0; i< raw_cmd->cmd_count; i++)
- fprintf(stderr,"%2.2x ",
+ fprintf(stderr,"%2.2x ",
(int)raw_cmd->cmd[i] );
fprintf(stderr,"\n");
for (i=0; i< raw_cmd->reply_count; i++)
fprintf(stderr,"%2.2x ",
(int)raw_cmd->reply[i] );
fprintf(stderr,"\n");
- code = (raw_cmd->reply[0] <<16) +
- (raw_cmd->reply[1] << 8) +
+ code = (raw_cmd->reply[0] <<16) +
+ (raw_cmd->reply[1] << 8) +
raw_cmd->reply[2];
for(i=0; i<22; i++){
if ((code & (1 << i)) && error_msg[i])
@@ -641,7 +648,7 @@ int send_one_cmd(int fd, RawRequest_t *raw_cmd, const char *message)
if (raw_cmd->reply_count < 7) {
fprintf(stderr,"Short reply from FDC\n");
return -1;
- }
+ }
return 0;
}
@@ -673,10 +680,10 @@ int send_one_cmd(int fd, RawRequest_t *raw_cmd, const char *message)
int analyze_one_reply(RawRequest_t *raw_cmd, int *bytes, int do_print)
{
-
+
if(raw_cmd->reply_count == 7) {
int end;
-
+
if (raw_cmd->reply[3] != raw_cmd->cmd[2]) {
/* end of cylinder */
end = raw_cmd->cmd[6] + 1;
@@ -688,7 +695,7 @@ int analyze_one_reply(RawRequest_t *raw_cmd, int *bytes, int do_print)
/* FIXME: over/under run */
*bytes = *bytes << (7 + raw_cmd->cmd[5]);
} else
- *bytes = 0;
+ *bytes = 0;
switch(raw_cmd->reply[0] & 0xc0){
case 0x40:
@@ -720,7 +727,7 @@ int analyze_one_reply(RawRequest_t *raw_cmd, int *bytes, int do_print)
return -1;
default:
break;
- }
+ }
#ifdef FD_RAW_MORE
if(raw_cmd->flags & FD_RAW_MORE)
return 1;
@@ -730,19 +737,19 @@ int analyze_one_reply(RawRequest_t *raw_cmd, int *bytes, int do_print)
#define predefined_devices
struct device devices[] = {
- {"/dev/fd0", 'A', 0, 0, 80,2, 18,0, MDEF_ARG, 0, 0},
- {"/dev/fd1", 'B', 0, 0, 0,0, 0,0, FDEF_ARG, 0, 0},
+ {"/dev/fd0", 'A', 0, 0, 80,2, 18,0, MDEF_ARG },
+ {"/dev/fd1", 'B', 0, 0, 0,0, 0,0, FDEF_ARG },
/* we assume that the Zip or Jaz drive is the second on the SCSI bus */
- {"/dev/sdb4",'J', GENHD, 0, 0 },
- {"/dev/sdb4",'Z', GENHD, 0, 0 },
- /* {"/dev/sda4",'D', GENHD, 0, 0 },*/
+ {"/dev/sdb4",'J', GENHD },
+ {"/dev/sdb4",'Z', GENHD },
+ /* {"/dev/sda4",'D', GENHD },*/
REMOTE
};
/*
* Stuffing back the floppy parameters into the driver allows for gems
* like 21 sector or single sided floppies from Atari ST systems.
- *
+ *
* Alain Knaff, Université Joseph Fourier, France, November 12, 1993.
*/
@@ -758,31 +765,32 @@ struct device devices[] = {
#define USE_2M(floppy) ((floppy.rate & FD_2M) ? 0xff : 0x80 )
#define SSIZE(floppy) ((((floppy.rate & 0x38) >> 3 ) + 2) % 8)
-static __inline__ void set_2m(struct floppy_struct *floppy, int value)
+static __inline__ void set_2m(struct floppy_struct *floppy, unsigned int value)
{
+ uint8_t v;
if (value & 0x7f)
- value = FD_2M;
+ v = FD_2M;
else
- value = 0;
- floppy->rate = (floppy->rate & ~FD_2M) | value;
+ v = 0;
+ floppy->rate = (floppy->rate & ~FD_2M) | v;
}
#define SET_2M set_2m
static __inline__ void set_ssize(struct floppy_struct *floppy, int value)
{
- value = (( (value & 7) + 6 ) % 8) << 3;
+ uint8_t v = (uint8_t) ((( (value & 7) + 6 ) % 8) << 3);
- floppy->rate = (floppy->rate & ~0x38) | value;
+ floppy->rate = (floppy->rate & ~0x38) | v;
}
#define SET_SSIZE set_ssize
-static __inline__ int set_parameters(int fd, struct floppy_struct *floppy,
+static __inline__ int set_parameters(int fd, struct floppy_struct *floppy,
struct MT_STAT *buf)
{
if ( ( MINOR(buf->st_rdev ) & 0x7f ) > 3 )
return 1;
-
+
return ioctl(fd, FDSETPRM, floppy);
}
@@ -791,6 +799,86 @@ static __inline__ int get_parameters(int fd, struct floppy_struct *floppy)
return ioctl(fd, FDGETPRM, floppy);
}
+#include "linux/hdreg.h"
+#include "linux/fs.h"
+
+static uint32_t ulong_to_sectors(unsigned long raw_sect) {
+ /* Number of sectors must fit into 32bit value */
+ if (raw_sect > ULONG_MAX) {
+ fprintf(stderr, "Too many sectors for FAT %8lx\n",raw_sect);
+ exit(1);
+ }
+ return (uint32_t) raw_sect;
+}
+
+int get_sector_size(int fd) {
+ int sec_size;
+ if (ioctl(fd, BLKSSZGET, &sec_size) != 0 || sec_size <= 0) {
+ fprintf(stderr, "Could not get sector size of device (%s)",
+ strerror(errno));
+ return -1;
+ }
+
+ /* Cap sector size at 4096 */
+ if(sec_size > 4096)
+ sec_size = 4096;
+ return sec_size;
+}
+
+static int get_block_geom(int fd, struct device *dev) {
+ struct hd_geometry geom;
+ int sec_size;
+ unsigned long size;
+ uint16_t heads=dev->heads;
+ uint16_t sectors=dev->sectors;
+ uint32_t sect_per_track;
+
+ if (ioctl(fd, HDIO_GETGEO, &geom) < 0) {
+ fprintf(stderr, "Could not get geometry of device (%s)",
+ strerror(errno));
+ return -1;
+ }
+
+ if (ioctl(fd, BLKGETSIZE, &size) < 0) {
+ fprintf(stderr, "Could not get size of device (%s)",
+ strerror(errno));
+ return -1;
+ }
+
+ sec_size = get_sector_size(fd);
+ if(sec_size < 0)
+ return -1;
+
+ dev->ssize = 0;
+ while (dev->ssize < 0x7F && (128 << dev->ssize) < sec_size)
+ dev->ssize++;
+
+ if(!heads)
+ heads = geom.heads;
+ if(!sectors)
+ sectors = geom.sectors;
+
+ sect_per_track = heads * sectors;
+ if(!dev->hidden) {
+ uint32_t hidden;
+ hidden = geom.start % sect_per_track;
+ if(hidden && hidden != sectors) {
+ fprintf(stderr,
+ "Hidden (%d) does not match sectors (%d)\n",
+ hidden, sectors);
+ return -1;
+ }
+ dev->hidden = hidden;
+ }
+ dev->heads = heads;
+ dev->sectors = sectors;
+ if(!dev->tracks)
+ dev->tracks = ulong_to_sectors((size + dev->hidden % sect_per_track) / sect_per_track);
+ return 0;
+}
+
+#define HAVE_GET_BLOCK_GEOM
+
#endif /* linux */
@@ -818,7 +906,7 @@ struct device devices[] = {
REMOTE
};
#endif /* __FreeBSD__ */
-
+
/*** /jes -- for ALR 486 DX4/100 ***/
#if defined(OS_netbsd) || defined(OS_netbsdelf)
#define predefined_devices
@@ -871,7 +959,7 @@ int init_geom(int fd, struct device *dev, struct device *orig_dev,
}
if((dev->use_2m & 0x7f) || (dev->ssize & 0x7f))
return 1;
-
+
SET_INT(gdbuf.params.cyls,dev->ntracks);
SET_INT(gdbuf.params.heads,dev->nheads);
SET_INT(gdbuf.params.psectrk,dev->nsect);
@@ -879,7 +967,7 @@ int init_geom(int fd, struct device *dev, struct device *orig_dev,
dev->nheads = gdbuf.params.heads;
dev->nsect = gdbuf.params.psectrk;
dev->use_2m = 0x80;
- dev->ssize = 0x82;
+ dev->ssize = 0x02;
gdbuf.params.pseccyl = gdbuf.params.psectrk * gdbuf.params.heads;
gdbuf.params.flags = 1; /* disk type flag */
@@ -967,7 +1055,7 @@ struct device devices[] = {
#endif
#ifndef SSIZE
-#define SSIZE(x) 0x82
+#define SSIZE(x) 0x02
#endif
#ifndef SET_2M
@@ -984,52 +1072,63 @@ int init_geom(int fd, struct device *dev, struct device *orig_dev,
{
struct generic_floppy_struct floppy;
int change;
-
- /*
+
+#ifdef HAVE_GET_BLOCK_GEOM
+ /**
+ * Block device which *isn't* a floppy device
+ */
+ if (S_ISBLK(statbuf->st_mode) &&
+ major(statbuf->st_rdev) != BLOCK_MAJOR) {
+ get_block_geom(fd, dev);
+ return compare_geom(dev, orig_dev);
+ }
+#endif
+
+ /*
* succeed if we don't have a floppy
* this is the case for dosemu floppy image files for instance
*/
- if (!((S_ISBLK(statbuf->st_mode) &&
+ if (!((S_ISBLK(statbuf->st_mode) &&
major(statbuf->st_rdev) == BLOCK_MAJOR)
#ifdef CHAR_MAJOR
- || (S_ISCHR(statbuf->st_mode) &&
- major(statbuf->st_rdev) == CHAR_MAJOR)
+ || (S_ISCHR(statbuf->st_mode) &&
+ major(statbuf->st_rdev) == CHAR_MAJOR)
#endif
))
return compare_geom(dev, orig_dev);
-
+
/*
* We first try to get the current floppy parameters from the kernel.
* This allows us to
* 1. get the rate
* 2. skip the parameter setting if the parameters are already o.k.
*/
-
+
if (get_parameters( fd, & floppy ) )
- /*
+ /*
* autodetection failure.
* This mostly occurs because of an absent or unformatted disks.
*
- * It might also occur because of bizarre formats (for example
+ * It might also occur because of bizarre formats (for example
* rate 1 on a 3 1/2 disk).
- * If this is the case, the user should do an explicit
+ * If this is the case, the user should do an explicit
* setfdprm before calling mtools
*
- * Another cause might be pre-existing wrong parameters. The
+ * Another cause might be pre-existing wrong parameters. The
* user should do an setfdprm -c to repair this situation.
*
* ...fail immediately... ( Theoretically, we could try to save
- * the situation by trying out all rates, but it would be slow
+ * the situation by trying out all rates, but it would be slow
* and awkward)
*/
return 1;
- /*
+ /*
* if we have already have the correct parameters, keep them.
* the number of tracks doesn't need to match exactly, it may be bigger.
- * the number of heads and sectors must match exactly, to avoid
+ * the number of heads and sectors must match exactly, to avoid
* miscalculation of the location of a block on the disk
*/
change = 0;
@@ -1037,15 +1136,15 @@ int init_geom(int fd, struct device *dev, struct device *orig_dev,
SECTORS(floppy) = dev->sectors;
change = 1;
} else
- dev->sectors = SECTORS(floppy);
+ dev->sectors = (uint16_t) SECTORS(floppy);
if(compare(dev->heads, HEADS(floppy))){
HEADS(floppy) = dev->heads;
change = 1;
} else
- dev->heads = HEADS(floppy);
-
- if(compare(dev->tracks, TRACKS(floppy))){
+ dev->heads = (uint16_t) HEADS(floppy);
+
+ if(compare(dev->tracks, (unsigned int) TRACKS(floppy))){
TRACKS(floppy) = dev->tracks;
change = 1;
} else
@@ -1057,7 +1156,7 @@ int init_geom(int fd, struct device *dev, struct device *orig_dev,
change = 1;
} else
dev->use_2m = USE_2M(floppy);
-
+
if( ! (dev->ssize & 0x80) )
dev->ssize = 0;
if(compare(dev->ssize, SSIZE(floppy) + 128)){
@@ -1077,18 +1176,18 @@ int init_geom(int fd, struct device *dev, struct device *orig_dev,
#ifdef SECTORS_PER_DISK
SECTORS_PER_DISK(floppy) = dev->sectors * dev->heads * dev->tracks;
#endif
-
+
#ifdef STRETCH
/* ... and the stretch */
- if ( dev->tracks > 41 )
+ if ( dev->tracks > 41 )
STRETCH(floppy) = 0;
else
STRETCH(floppy) = 1;
#endif
-
+
return set_parameters( fd, &floppy, statbuf);
}
-#endif /* INIT_GENERIC */
+#endif /* INIT_GENERIC */
#ifdef INIT_NOOP
int init_geom(int fd, struct device *dev, struct device *orig_dev,
diff --git a/devices.h b/devices.h
index 7ca2feb..34f0ceb 100644
--- a/devices.h
+++ b/devices.h
@@ -29,7 +29,7 @@
#endif /* MINOR not defined */
#else
-
+
#include <linux/fs.h> /* get MAJOR/MINOR from Linux kernel */
#ifndef major
#define major(x) MAJOR(x)
@@ -91,14 +91,14 @@ UNUSED(static __inline__ void RR_SETHEAD(struct floppy_raw_cmd *request, uint8_t
request->cmd[3] = head;
}
-UNUSED(static __inline__ void RR_SETSECTOR(struct floppy_raw_cmd *request,
+UNUSED(static __inline__ void RR_SETSECTOR(struct floppy_raw_cmd *request,
uint8_t sector))
{
request->cmd[4] = sector;
request->cmd[6] = sector-1;
}
-UNUSED(static __inline__ void RR_SETSIZECODE(struct floppy_raw_cmd *request,
+UNUSED(static __inline__ void RR_SETSIZECODE(struct floppy_raw_cmd *request,
uint8_t sizecode))
{
request->cmd[5] = sizecode;
@@ -113,7 +113,7 @@ static inline void RR_SETEND(struct floppy_raw_cmd *request, int end)
}
#endif
-UNUSED(static __inline__ void RR_SETDIRECTION(struct floppy_raw_cmd *request,
+UNUSED(static __inline__ void RR_SETDIRECTION(struct floppy_raw_cmd *request,
int direction))
{
if(direction == MT_READ) {
@@ -126,7 +126,7 @@ UNUSED(static __inline__ void RR_SETDIRECTION(struct floppy_raw_cmd *request,
}
-UNUSED(static __inline__ void RR_SETDATA(struct floppy_raw_cmd *request,
+UNUSED(static __inline__ void RR_SETDATA(struct floppy_raw_cmd *request,
caddr_t data))
{
request->data = data;
@@ -169,12 +169,12 @@ UNUSED(static __inline__ int GET_DRIVE(int fd))
perror("stat");
return -1;
}
-
+
if (!S_ISBLK(statbuf.st_mode) ||
MAJOR(statbuf.st_rdev) != FLOPPY_MAJOR)
return -1;
-
- return MINOR( statbuf.st_rdev );
+
+ return (int) MINOR( statbuf.st_rdev );
}
@@ -183,5 +183,7 @@ UNUSED(static __inline__ int GET_DRIVE(int fd))
int send_one_cmd(int fd, RawRequest_t *raw_cmd, const char *message);
int analyze_one_reply(RawRequest_t *raw_cmd, int *bytes, int do_print);
-
#endif
+
+int init_geom(int fd, struct device *dev, struct device *orig_dev,
+ struct MT_STAT *statbuf);
diff --git a/dirCache.c b/dirCache.c
index 006c544..8e6479f 100644
--- a/dirCache.c
+++ b/dirCache.c
@@ -46,7 +46,7 @@ static uint32_t calcHash(wchar_t *name)
* prime with 32, which makes sure that
* successive letters cannot cover each
* other easily */
- c = towupper((wint_t)*name);
+ c = towupper((wint_t)*name);
hash ^= (c * (c+2)) ^ (i * (i+2));
hash &= 0xffffffff;
i++;
@@ -68,7 +68,7 @@ static unsigned int addBit(unsigned int *bitmap,
bit = 1u << (hash % BITS_PER_INT);
entry = (hash / BITS_PER_INT) % DC_BITMAP_SIZE;
-
+
if(checkOnly)
return bitmap[entry] & bit;
else {
@@ -87,7 +87,7 @@ static int _addHash(dirCache_t *cache, unsigned int hash, int checkOnly)
static void addNameToHash(dirCache_t *cache, wchar_t *name)
-{
+{
_addHash(cache, calcHash(name), 0);
}
@@ -118,7 +118,7 @@ int growDirCache(dirCache_t *cache, unsigned int slot)
if( cache->nr_entries <= slot) {
unsigned int i;
-
+
cache->entries = realloc(cache->entries,
(slot+1) * 2 *
sizeof(dirCacheEntry_t *));
@@ -191,16 +191,17 @@ static int freeDirCacheRange(dirCache_t *cache,
beginSlot++;
continue;
}
-
+
/* Due to the way this is called, we _always_ de-allocate
* starting from beginning... */
+#ifdef HAVE_ASSERT_H
assert(entry->beginSlot == beginSlot);
-
+#endif
clearEnd = entry->endSlot;
if(clearEnd > endSlot)
clearEnd = endSlot;
clearBegin = beginSlot;
-
+
for(i = clearBegin; i <clearEnd; i++)
cache->entries[i] = 0;
@@ -274,7 +275,7 @@ dirCacheEntry_t *addUsedEntry(dirCache_t *cache,
entry = allocDirCacheEntry(cache, beginSlot, endSlot, DCET_USED);
if(!entry)
return 0;
-
+
entry->beginSlot = beginSlot;
entry->endSlot = endSlot;
if(longName)
@@ -305,7 +306,7 @@ static void mergeFreeSlots(dirCache_t *cache, unsigned int slot)
cache->entries[i] = previous;
previous->endSlot = next->endSlot;
previous->endMarkPos = next->endMarkPos;
- free(next);
+ free(next);
}
}
@@ -353,7 +354,7 @@ dirCacheEntry_t *lookupInDircache(dirCache_t *cache, unsigned int pos)
{
if(growDirCache(cache, pos+1) < 0)
return 0;
- return cache->entries[pos];
+ return cache->entries[pos];
}
void freeDirCache(Stream_t *Stream)
diff --git a/dirCache.h b/dirCache.h
index 04f9f3e..161c9a5 100644
--- a/dirCache.h
+++ b/dirCache.h
@@ -45,9 +45,9 @@ dirCacheEntry_t *addUsedEntry(dirCache_t *Stream,
wchar_t *longName, wchar_t *shortName,
struct directory *dir);
void freeDirCache(Stream_t *Stream);
-dirCacheEntry_t *addFreeEntry(dirCache_t *Stream,
+dirCacheEntry_t *addFreeEntry(dirCache_t *Stream,
unsigned int begin, unsigned int end);
-dirCacheEntry_t *addFreeEndEntry(dirCache_t *Stream,
+dirCacheEntry_t *addFreeEndEntry(dirCache_t *Stream,
unsigned int begin, unsigned int end,
int isAtEnd);
dirCacheEntry_t *addEndEntry(dirCache_t *Stream, unsigned int pos);
diff --git a/directory.c b/directory.c
index 6a17aa0..79a4624 100644
--- a/directory.c
+++ b/directory.c
@@ -30,11 +30,11 @@
*/
struct directory *dir_read(direntry_t *entry, int *error)
{
- int n;
+ ssize_t n;
*error = 0;
- if((n=force_read(entry->Dir, (char *) (&entry->dir),
- (mt_off_t) entry->entry * MDIR_SIZE,
- MDIR_SIZE)) != MDIR_SIZE) {
+ if((n=force_pread(entry->Dir, (char *) (&entry->dir),
+ (mt_off_t) entry->entry * MDIR_SIZE,
+ MDIR_SIZE)) != MDIR_SIZE) {
if (n < 0) {
*error = -1;
}
@@ -52,23 +52,23 @@ struct directory *dir_read(direntry_t *entry, int *error)
int dir_grow(Stream_t *Dir, int size)
{
Stream_t *Stream = GetFs(Dir);
- DeclareThis(FsPublic_t);
- int ret;
+ DeclareThis(Fs_t);
+ ssize_t ret;
unsigned int buflen;
char *buffer;
-
+
if (!getfreeMinClusters(Dir, 1))
return -1;
- buflen = This->cluster_size * This->sector_size;
+ buflen = getClusterBytes(This);
if(! (buffer=malloc(buflen)) ){
perror("dir_grow: malloc");
return -1;
}
-
+
memset((char *) buffer, '\0', buflen);
- ret = force_write(Dir, buffer, (mt_off_t) size * MDIR_SIZE, buflen);
+ ret = force_pwrite(Dir, buffer, (mt_off_t) size * MDIR_SIZE, buflen);
free(buffer);
if(ret < (int) buflen)
return -1;
@@ -78,15 +78,15 @@ int dir_grow(Stream_t *Dir, int size)
void low_level_dir_write(direntry_t *entry)
{
- force_write(entry->Dir,
- (char *) (&entry->dir),
- (mt_off_t) entry->entry * MDIR_SIZE, MDIR_SIZE);
+ force_pwrite(entry->Dir,
+ (char *) (&entry->dir),
+ (mt_off_t) entry->entry * MDIR_SIZE, MDIR_SIZE);
}
void low_level_dir_write_end(Stream_t *Dir, int entry)
{
char zero = ENDMARK;
- force_write(Dir, &zero, (mt_off_t) entry * MDIR_SIZE, 1);
+ force_pwrite(Dir, &zero, (mt_off_t) entry * MDIR_SIZE, 1);
}
/*
@@ -96,28 +96,28 @@ void low_level_dir_write_end(Stream_t *Dir, int entry)
*/
struct directory *mk_entry(const dos_name_t *dn, unsigned char attr,
- unsigned int fat, size_t size, time_t date,
+ unsigned int fat, uint32_t size, time_t date,
struct directory *ndir)
{
struct tm *now;
time_t date2 = date;
- unsigned char hour, min_hi, min_low, sec;
- unsigned char year, month_hi, month_low, day;
+ uint8_t hour, min_hi, min_low, sec;
+ uint8_t year, month_hi, month_low, day;
now = localtime(&date2);
dosnameToDirentry(dn, ndir);
ndir->attr = attr;
ndir->ctime_ms = 0;
- hour = now->tm_hour << 3;
- min_hi = now->tm_min >> 3;
- min_low = now->tm_min << 5;
- sec = now->tm_sec / 2;
+ hour = (uint8_t) (now->tm_hour << 3);
+ min_hi = (uint8_t) (now->tm_min >> 3);
+ min_low = (uint8_t) (now->tm_min << 5);
+ sec = (uint8_t) (now->tm_sec / 2);
ndir->ctime[1] = ndir->time[1] = hour + min_hi;
ndir->ctime[0] = ndir->time[0] = min_low + sec;
- year = (now->tm_year - 80) << 1;
- month_hi = (now->tm_mon + 1) >> 3;
- month_low = (now->tm_mon + 1) << 5;
- day = now->tm_mday;
+ year = (uint8_t) ((now->tm_year - 80) << 1);
+ month_hi = (uint8_t) ((now->tm_mon + 1) >> 3);
+ month_low = (uint8_t) ((now->tm_mon + 1) << 5);
+ day = (uint8_t) (now->tm_mday);
ndir -> adate[1] = ndir->cdate[1] = ndir->date[1] = year + month_hi;
ndir -> adate[0] = ndir->cdate[0] = ndir->date[0] = month_low + day;
@@ -133,7 +133,7 @@ struct directory *mk_entry(const dos_name_t *dn, unsigned char attr,
* Thus it doesn't bother with character set conversions
*/
struct directory *mk_entry_from_base(const char *base, unsigned char attr,
- unsigned int fat, size_t size, time_t date,
+ unsigned int fat, uint32_t size, time_t date,
struct directory *ndir)
{
struct dos_name_t dn;
diff --git a/direntry.c b/direntry.c
index 3d79dc9..1dbb240 100644
--- a/direntry.c
+++ b/direntry.c
@@ -49,7 +49,7 @@ static size_t getPathLen(direntry_t *entry)
while(1) {
if(entry->entry == -3) /* rootDir */
return length + 3;
-
+
length += 1 + wcslen(entry->name);
entry = getDirentry(entry->Dir);
}
@@ -171,5 +171,5 @@ int isSubdirOf(Stream_t *inside, Stream_t *outside)
return 0;
/* look further up */
inside = getDirentry(inside)->Dir;
- }
+ }
}
diff --git a/dos2unix.c b/dos2unix.c
new file mode 100644
index 0000000..78982d1
--- /dev/null
+++ b/dos2unix.c
@@ -0,0 +1,86 @@
+/* Copyright 1996,1997,1999,2001-2003,2008,2009,2021 Alain Knaff.
+ * This file is part of mtools.
+ *
+ * Mtools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "codepage.h"
+
+typedef struct Filter_t {
+ struct Stream_t head;
+
+ int mode;
+ /* int convertCharset; */
+} Filter_t;
+
+/* read filter filters out messy dos' bizarre end of lines and final 0x1a's */
+
+static ssize_t read_filter(Stream_t *Stream, char *buf, size_t len)
+{
+ DeclareThis(Filter_t);
+ size_t i,j;
+ ssize_t ret;
+ char newchar;
+
+ ret = READS(This->head.Next, buf, len);
+ if ( ret < 0 )
+ return ret;
+
+ j = 0;
+ for (i=0; i< (size_t) ret; i++){
+ if ( buf[i] == '\r' )
+ continue;
+ if (buf[i] == 0x1a)
+ break;
+ newchar = buf[i];
+ /*
+ if (This->convertCharset) newchar = contents_to_unix(newchar);
+ */
+ buf[j++] = newchar;
+ }
+
+ return (ssize_t) j;
+}
+
+static Class_t FilterClass = {
+ read_filter,
+ 0,
+ 0,
+ 0,
+ 0, /* flush */
+ 0,
+ 0, /* set geometry */
+ get_data_pass_through,
+ 0,
+ 0, /* get_dosconvert */
+ 0 /* discard */
+};
+
+Stream_t *open_dos2unix(Stream_t *Next, int convertCharset UNUSEDP)
+{
+ Filter_t *This;
+
+ This = New(Filter_t);
+ if (!This)
+ return NULL;
+ init_head(&This->head, &FilterClass, Next);
+ /*
+ This->convertCharset = convertCharset;
+ */
+
+ return &This->head;
+}
diff --git a/fat.c b/fat.c
index e4419c3..3a2f9e3 100644
--- a/fat.c
+++ b/fat.c
@@ -15,6 +15,7 @@
* along with Mtools. If not, see <http://www.gnu.org/licenses/>.
*/
+
#include "sysincludes.h"
#include "msdos.h"
#include "stream.h"
@@ -37,27 +38,27 @@ typedef struct FatMap_t {
#define SECT_PER_ENTRY (sizeof(fatBitMask)*8)
#define ONE ((fatBitMask) 1)
-static __inline__ int readSector(Fs_t *This, char *buf, unsigned int off,
- size_t size)
+static __inline__ ssize_t readSector(Fs_t *This, char *buf, unsigned int off,
+ size_t size)
{
- return READS(This->Next, buf, sectorsToBytes((Stream_t *)This, off),
- size << This->sectorShift);
+ return PREADS(This->head.Next, buf, sectorsToBytes(This, off),
+ size << This->sectorShift);
}
-static __inline__ int forceReadSector(Fs_t *This, char *buf, unsigned int off,
- size_t size)
+static __inline__ ssize_t forceReadSector(Fs_t *This, char *buf,
+ unsigned int off, size_t size)
{
- return force_read(This->Next, buf, sectorsToBytes((Stream_t *)This, off),
- size << This->sectorShift);
+ return force_pread(This->head.Next, buf, sectorsToBytes(This, off),
+ size << This->sectorShift);
}
-static __inline__ int forceWriteSector(Fs_t *This, char *buf, unsigned int off,
- size_t size)
+static __inline__ ssize_t forceWriteSector(Fs_t *This, char *buf, unsigned int off,
+ size_t size)
{
- return force_write(This->Next, buf, sectorsToBytes((Stream_t*)This, off),
- size << This->sectorShift);
+ return force_pwrite(This->head.Next, buf, sectorsToBytes(This, off),
+ size << This->sectorShift);
}
@@ -82,7 +83,8 @@ static FatMap_t *GetFatMap(Fs_t *Stream)
return map;
}
-static __inline__ int locate(Fs_t *Stream, size_t offset, int *slot, int *bit)
+static __inline__ int locate(Fs_t *Stream, uint32_t offset,
+ uint32_t *slot, uint32_t *bit)
{
if(offset >= Stream->fat_len)
return -1;
@@ -91,15 +93,19 @@ static __inline__ int locate(Fs_t *Stream, size_t offset, int *slot, int *bit)
return 0;
}
-static __inline__ int fatReadSector(Fs_t *This, int sector, int slot,
- int bit, int dupe, fatBitMask bitmap)
+static __inline__ ssize_t fatReadSector(Fs_t *This,
+ unsigned int sector,
+ unsigned int slot,
+ unsigned int bit, unsigned int dupe,
+ fatBitMask bitmap)
{
- int fat_start, ret;
- int nr_sectors;
+ unsigned int fat_start;
+ ssize_t ret;
+ unsigned int nr_sectors;
dupe = (dupe + This->primaryFat) % This->num_fat;
fat_start = This->fat_start + This->fat_len * dupe;
-
+
if(bitmap == 0) {
nr_sectors = SECT_PER_ENTRY - bit%SECT_PER_ENTRY;
} else {
@@ -114,11 +120,11 @@ static __inline__ int fatReadSector(Fs_t *This, int sector, int slot,
if(ret < 0)
return 0;
- if((unsigned int) ret < This->sector_size) {
+ if((size_t) ret < This->sector_size) {
/* if we got less than one sector's worth, insist to get at
* least one sector */
ret = forceReadSector(This,
- (char *) (This->FatMap[slot].data +
+ (char *) (This->FatMap[slot].data +
(bit << This->sectorShift)),
fat_start+sector, 1);
if(ret < (int) This->sector_size)
@@ -130,9 +136,13 @@ static __inline__ int fatReadSector(Fs_t *This, int sector, int slot,
}
-static int fatWriteSector(Fs_t *This, int sector, int slot, int bit, int dupe)
+static ssize_t fatWriteSector(Fs_t *This,
+ unsigned int sector,
+ unsigned int slot,
+ unsigned int bit,
+ unsigned int dupe)
{
- int fat_start;
+ unsigned int fat_start;
dupe = (dupe + This->primaryFat) % This->num_fat;
if(dupe && !This->writeAllFats)
@@ -141,7 +151,7 @@ static int fatWriteSector(Fs_t *This, int sector, int slot, int bit, int dupe)
fat_start = This->fat_start + This->fat_len * dupe;
return forceWriteSector(This,
- (char *)
+ (char *)
(This->FatMap[slot].data + bit * This->sector_size),
fat_start+sector, 1);
}
@@ -150,7 +160,8 @@ static unsigned char *loadSector(Fs_t *This,
unsigned int sector, fatAccessMode_t mode,
int recurs)
{
- int slot, bit, ret;
+ uint32_t slot, bit;
+ ssize_t ret;
if(locate(This,sector, &slot, &bit) < 0)
return 0;
@@ -159,7 +170,7 @@ static unsigned char *loadSector(Fs_t *This,
fprintf(stderr,"This should not happen\n");
fprintf(stderr, "fat_len = %d\n", This->fat_len);
fprintf(stderr, "SECT_PER_ENTRY=%d\n", (int)SECT_PER_ENTRY);
- fprintf(stderr, "sector = %d slot = %d bit=%d\n",
+ fprintf(stderr, "sector = %d slot = %d bit=%d\n",
sector, slot, bit);
fprintf(stderr, "left = %d",(int)
((This->fat_len+SECT_PER_ENTRY-1) / SECT_PER_ENTRY));
@@ -168,7 +179,7 @@ static unsigned char *loadSector(Fs_t *This,
#endif
if(!This->FatMap[slot].data) {
/* allocate the storage space */
- This->FatMap[slot].data =
+ This->FatMap[slot].data =
malloc(This->sector_size * SECT_PER_ENTRY);
if(!This->FatMap[slot].data)
return 0;
@@ -225,15 +236,15 @@ static unsigned char *getAddress(Fs_t *Stream,
unsigned int num, fatAccessMode_t mode)
{
unsigned char *ret;
- int sector;
- int offset;
+ unsigned int sector;
+ unsigned int offset;
sector = num >> Stream->sectorShift;
ret = 0;
if(sector == Stream->lastFatSectorNr &&
Stream->lastFatAccessMode >= mode)
ret = Stream->lastFatSectorData;
- if(!ret) {
+ if(!ret) {
ret = loadSector(Stream, sector, mode, 0);
if(!ret)
return 0;
@@ -246,10 +257,10 @@ static unsigned char *getAddress(Fs_t *Stream,
}
-static int readByte(Fs_t *Stream, int start)
+static int readByte(Fs_t *Stream, unsigned int start)
{
unsigned char *address;
-
+
address = getAddress(Stream, start, FAT_ACCESS_READ);
if(!address)
return -1;
@@ -269,7 +280,7 @@ static int readByte(Fs_t *Stream, int start)
* | n+1.5 | n+0.0 | n+0.5 | n+2.0 | n+2.5 | n+1.0 |
* | FAT entry k | FAT entry k+1 |
*/
-
+
/*
* Get and decode a FAT (file allocation table) entry. Returns the cluster
* number on success or 1 on failure.
@@ -280,16 +291,16 @@ static unsigned int fat12_decode(Fs_t *Stream, unsigned int num)
unsigned int start = num * 3 / 2;
int byte0 = readByte(Stream, start);
int byte1 = readByte(Stream, start+1);
-
+
if (num < 2 || byte0 < 0 || byte1 < 0 || num > Stream->num_clus+1) {
fprintf(stderr,"[1] Bad address %d\n", num);
return 1;
}
if (num & 1)
- return (byte1 << 4) | ((byte0 & 0xf0)>>4);
+ return ((uint32_t)byte1 << 4) | (((uint32_t)byte0 & 0xf0)>>4);
else
- return ((byte1 & 0xf) << 8) | byte0;
+ return (((uint32_t)byte1 & 0xf) << 8) | (uint32_t)byte0;
}
@@ -299,7 +310,7 @@ static unsigned int fat12_decode(Fs_t *Stream, unsigned int num)
*/
static void fat12_encode(Fs_t *Stream, unsigned int num, unsigned int code)
{
- int start = num * 3 / 2;
+ unsigned int start = num * 3 / 2;
unsigned char *address0 = getAddress(Stream, start, FAT_ACCESS_WRITE);
unsigned char *address1 = getAddress(Stream, start+1, FAT_ACCESS_WRITE);
@@ -332,16 +343,26 @@ static unsigned int fat16_decode(Fs_t *Stream, unsigned int num)
}
static void fat16_encode(Fs_t *Stream, unsigned int num, unsigned int code)
-{
+{
+ if(code > UINT16_MAX) {
+ fprintf(stderr, "FAT16 code %x too big\n", code);
+ exit(1);
+ }
unsigned char *address = getAddress(Stream, num << 1, FAT_ACCESS_WRITE);
- set_word(address, code);
+ set_word(address, (uint16_t) code);
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+/* Ignore alignment warnings about casting to type with higher
+ * alignment requirement. Requirement is met, as initial pointer is an
+ * even offset into a buffer allocated by malloc, which according to
+ * manpage is "suitably aligned for any built-in type */
static unsigned int fast_fat16_decode(Fs_t *Stream, unsigned int num)
{
- unsigned short *address =
- (unsigned short *) getAddress(Stream, num << 1,
+ unsigned short *address =
+ (unsigned short *) getAddress(Stream, num << 1,
FAT_ACCESS_READ);
if(!address)
return 1;
@@ -349,13 +370,17 @@ static unsigned int fast_fat16_decode(Fs_t *Stream, unsigned int num)
}
static void fast_fat16_encode(Fs_t *Stream, unsigned int num, unsigned int code)
-{
- unsigned short *address =
- (unsigned short *) getAddress(Stream, num << 1,
+{
+ unsigned short *address =
+ (unsigned short *) getAddress(Stream, num << 1,
FAT_ACCESS_WRITE);
- *address = code;
+ if(code > UINT16_MAX) {
+ fprintf(stderr, "FAT16 code %x too big\n", code);
+ exit(1);
+ }
+ *address = (uint16_t) code;
}
-
+#pragma GCC diagnostic pop
@@ -374,16 +399,17 @@ static unsigned int fat32_decode(Fs_t *Stream, unsigned int num)
}
static void fat32_encode(Fs_t *Stream, unsigned int num, unsigned int code)
-{
+{
unsigned char *address = getAddress(Stream, num << 2, FAT_ACCESS_WRITE);
set_dword(address,(code&FAT32_ADDR) | (_DWORD(address)&FAT32_HIGH));
}
-
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
static unsigned int fast_fat32_decode(Fs_t *Stream, unsigned int num)
{
- unsigned int *address =
- (unsigned int *) getAddress(Stream, num << 2,
+ unsigned int *address =
+ (unsigned int *) getAddress(Stream, num << 2,
FAT_ACCESS_READ);
if(!address)
return 1;
@@ -391,13 +417,13 @@ static unsigned int fast_fat32_decode(Fs_t *Stream, unsigned int num)
}
static void fast_fat32_encode(Fs_t *Stream, unsigned int num, unsigned int code)
-{
- unsigned int *address =
- (unsigned int *) getAddress(Stream, num << 2,
+{
+ unsigned int *address =
+ (unsigned int *) getAddress(Stream, num << 2,
FAT_ACCESS_WRITE);
*address = (*address & FAT32_HIGH) | (code & FAT32_ADDR);
}
-
+#pragma GCC diagnostic pop
/*
* Write the FAT table to the disk. Up to now the FAT manipulation has
@@ -408,7 +434,7 @@ static void fast_fat32_encode(Fs_t *Stream, unsigned int num, unsigned int code)
void fat_write(Fs_t *This)
{
unsigned int i, j, dups, bit, slot;
- int ret;
+ ssize_t ret;
/*fprintf(stderr, "Fat write\n");*/
@@ -427,7 +453,7 @@ void fat_write(Fs_t *This)
j += SECT_PER_ENTRY;
continue;
}
- for(bit=0;
+ for(bit=0;
bit < SECT_PER_ENTRY && j<This->fat_len;
bit++,j++) {
if(!(This->FatMap[slot].dirty & (ONE << bit)))
@@ -481,7 +507,7 @@ void fat_write(Fs_t *This)
* Zero-Fat
* Used by mformat.
*/
-int zero_fat(Fs_t *Stream, int media_descriptor)
+int zero_fat(Fs_t *Stream, uint8_t media_descriptor)
{
unsigned int i, j;
unsigned int fat_start;
@@ -520,7 +546,7 @@ int zero_fat(Fs_t *Stream, int media_descriptor)
}
}
}
-
+
free(buf);
Stream->FatMap = GetFatMap(Stream);
if (Stream->FatMap == NULL) {
@@ -531,7 +557,7 @@ int zero_fat(Fs_t *Stream, int media_descriptor)
}
-void set_fat12(Fs_t *This)
+static void set_fat12(Fs_t *This)
{
This->fat_bits = 12;
This->end_fat = 0xfff;
@@ -540,16 +566,16 @@ void set_fat12(Fs_t *This)
This->fat_encode = fat12_encode;
}
-static char word_endian_test[] = { 0x34, 0x12 };
+static uint16_t word_endian_test = 0x1234;
-void set_fat16(Fs_t *This)
+static void set_fat16(Fs_t *This)
{
+ uint8_t *t = (uint8_t *) &word_endian_test;
This->fat_bits = 16;
This->end_fat = 0xffff;
This->last_fat = 0xfff6;
- if(sizeof(unsigned short) == 2 &&
- * (unsigned short *) word_endian_test == 0x1234) {
+ if(t[0] == 0x34 && t[1] == 0x12) {
This->fat_decode = fast_fat16_decode;
This->fat_encode = fast_fat16_encode;
} else {
@@ -558,16 +584,16 @@ void set_fat16(Fs_t *This)
}
}
-static char dword_endian_test[] = { 0x78, 0x56, 0x34, 0x12 };
+static uint32_t dword_endian_test = 0x12345678;
-void set_fat32(Fs_t *This)
+static void set_fat32(Fs_t *This)
{
+ uint8_t *t = (uint8_t *) &dword_endian_test;
This->fat_bits = 32;
This->end_fat = 0xfffffff;
This->last_fat = 0xffffff6;
-
- if(sizeof(unsigned int) == 4 &&
- * (unsigned int *) dword_endian_test == 0x12345678) {
+
+ if(t[0] == 0x78 && t[1] == 0x56 && t[2] == 0x34 && t[3] == 0x12) {
This->fat_decode = fast_fat32_decode;
This->fat_encode = fast_fat32_encode;
} else {
@@ -576,10 +602,18 @@ void set_fat32(Fs_t *This)
}
}
+void set_fat(Fs_t *This) {
+ if(This->num_clus < FAT12)
+ set_fat12(This);
+ else if(This->num_clus < FAT16)
+ set_fat16(This);
+ else
+ set_fat32(This);
+}
static int check_fat(Fs_t *This)
{
- /*
+ /*
* This is only a sanity check. For disks with really big FATs,
* there is no point in checking the whole FAT.
*/
@@ -590,12 +624,14 @@ static int check_fat(Fs_t *This)
return 0;
/* too few sectors in the FAT */
- if(This->fat_len < NEEDED_FAT_SIZE(This))
+ if(This->fat_len < NEEDED_FAT_SIZE(This)) {
+ fprintf(stderr, "Too few sectors in FAT\n");
return -1;
+ }
/* we do not warn about too much sectors in FAT, which may
* happen when a partition has been shrunk using FIPS, or on
* other occurrences */
-
+
tocheck = This->num_clus;
if (tocheck + 1 >= This->last_fat) {
fprintf(stderr, "Too many clusters in FAT\n");
@@ -622,13 +658,10 @@ static int check_fat(Fs_t *This)
* Read the first sector of FAT table into memory. Crude error detection on
* wrong FAT encoding scheme.
*/
-static int check_media_type(Fs_t *This, union bootsector *boot,
- unsigned int tot_sectors)
+static int check_media_type(Fs_t *This, union bootsector *boot)
{
unsigned char *address;
- This->num_clus = (tot_sectors - This->clus_start) / This->cluster_size;
-
This->FatMap = GetFatMap(This);
if (This->FatMap == NULL) {
perror("alloc fat map");
@@ -649,27 +682,26 @@ static int check_media_type(Fs_t *This, union bootsector *boot,
/* Some Atari disks have zeroes where Dos has media descriptor
* and 0xff. Do not consider this as an error */
return 0;
-
+
if((address[0] != boot->boot.descr && boot->boot.descr >= 0xf0 &&
- ((address[0] != 0xf9 && address[0] != 0xf7)
+ ((address[0] != 0xf9 && address[0] != 0xf7)
|| boot->boot.descr != 0xf0)) || address[0] < 0xf0) {
fprintf(stderr,
- "Bad media types %02x/%02x, probably non-MSDOS disk\n",
+ "Bad media types %02x/%02x, probably non-MSDOS disk\n",
address[0],
boot->boot.descr);
return -1;
}
if(address[1] != 0xff || address[2] != 0xff){
- fprintf(stderr,"Initial byte of fat is not 0xff\n");
+ fprintf(stderr,"Initial bytes of fat is not 0xff\n");
return -1;
}
return 0;
}
-static int fat_32_read(Fs_t *This, union bootsector *boot,
- unsigned int tot_sectors)
+static int fat_32_read(Fs_t *This, union bootsector *boot)
{
size_t size;
@@ -687,7 +719,7 @@ static int fat_32_read(Fs_t *This, union bootsector *boot,
InfoSector_t *infoSector;
infoSector = (InfoSector_t *) safe_malloc(size);
if(forceReadSector(This, (char *)infoSector,
- This->infoSectorLoc, 1) ==
+ This->infoSectorLoc, 1) ==
(signed int) This->sector_size &&
_DWORD(infoSector->signature1) == INFOSECT_SIGNATURE1 &&
_DWORD(infoSector->signature2) == INFOSECT_SIGNATURE2) {
@@ -696,45 +728,37 @@ static int fat_32_read(Fs_t *This, union bootsector *boot,
}
free(infoSector);
}
-
- set_fat32(This);
- return(check_media_type(This, boot, tot_sectors) ||
- check_fat(This));
+
+ return(check_media_type(This, boot) || check_fat(This));
}
-static int old_fat_read(Fs_t *This, union bootsector *boot,
- size_t tot_sectors, int nodups)
+static int old_fat_read(Fs_t *This, union bootsector *boot, int nodups)
{
This->writeAllFats = 1;
This->primaryFat = 0;
This->dir_start = This->fat_start + This->num_fat * This->fat_len;
- This->clus_start = This->dir_start + This->dir_len;
This->infoSectorLoc = MAX32;
if(nodups)
This->num_fat = 1;
- if(check_media_type(This,boot, tot_sectors))
+ if(check_media_type(This, boot))
return -1;
- if(This->num_clus >= FAT12) {
- set_fat16(This);
+ if(This->num_clus >= FAT12)
/* third FAT byte must be 0xff */
if(!mtools_skip_check && readByte(This, 3) != 0xff)
return -1;
- } else
- set_fat12(This);
return check_fat(This);
}
/*
- * Read the first sector of the FAT table into memory and initialize
+ * Read the first sector of the FAT table into memory and initialize
* structures.
*/
-int fat_read(Fs_t *This, union bootsector *boot,
- size_t tot_sectors, int nodups)
+int fat_read(Fs_t *This, union bootsector *boot, int nodups)
{
This->fat_error = 0;
This->fat_dirty = 0;
@@ -743,10 +767,10 @@ int fat_read(Fs_t *This, union bootsector *boot,
This->lastFatSectorNr = 0;
This->lastFatSectorData = 0;
- if(This->fat_len)
- return old_fat_read(This, boot, tot_sectors, nodups);
+ if(This->num_clus < FAT16)
+ return old_fat_read(This, boot, nodups);
else
- return fat_32_read(This, boot, tot_sectors);
+ return fat_32_read(This, boot);
}
@@ -839,6 +863,18 @@ unsigned int get_next_free_cluster(Fs_t *This, unsigned int last)
return 1;
}
+bool getSerialized(Fs_t *Fs) {
+ return Fs->serialized;
+}
+
+unsigned long getSerialNumber(Fs_t *Fs) {
+ return Fs->serial_number;
+}
+
+uint32_t getClusterBytes(Fs_t *Fs) {
+ return Fs->cluster_size * Fs->sector_size;
+}
+
int fat_error(Stream_t *Dir)
{
Stream_t *Stream = GetFs(Dir);
@@ -850,11 +886,11 @@ int fat_error(Stream_t *Dir)
return This->fat_error;
}
-int fat32RootCluster(Stream_t *Dir)
+uint32_t fat32RootCluster(Stream_t *Dir)
{
Stream_t *Stream = GetFs(Dir);
DeclareThis(Fs_t);
-
+
if(This->fat_bits == 32)
return This->rootCluster;
else
@@ -865,15 +901,14 @@ int fat32RootCluster(Stream_t *Dir)
/*
* Get the amount of free space on the diskette
*/
-
-mt_size_t getfree(Stream_t *Dir)
+mt_off_t getfree(Stream_t *Dir)
{
Stream_t *Stream = GetFs(Dir);
DeclareThis(Fs_t);
if(This->freeSpace == MAX32 || This->freeSpace == 0) {
register unsigned int i;
- size_t total;
+ uint32_t total;
total = 0L;
for (i = 2; i < This->num_clus + 2; i++) {
@@ -886,15 +921,15 @@ mt_size_t getfree(Stream_t *Dir)
}
This->freeSpace = total;
}
- return sectorsToBytes((Stream_t*)This,
- This->freeSpace * This->cluster_size);
+ return sectorsToBytes(This,
+ This->freeSpace * This->cluster_size);
}
/*
* Ensure that there is a minimum of total sectors free
*/
-int getfreeMinClusters(Stream_t *Dir, size_t size)
+int getfreeMinClusters(Stream_t *Dir, uint32_t size)
{
Stream_t *Stream = GetFs(Dir);
DeclareThis(Fs_t);
@@ -918,10 +953,10 @@ int getfreeMinClusters(Stream_t *Dir, size_t size)
/* we start at the same place where we'll start later to actually
* allocate the sectors. That way, the same sectors of the FAT, which
- * are already loaded during getfreeMin will be able to be reused
+ * are already loaded during getfreeMin will be able to be reused
* during get_next_free_cluster */
last = This->last;
-
+
if ( last < 2 || last >= This->num_clus + 2)
last = 1;
for (i=last+1; i< This->num_clus+2; i++){
@@ -932,10 +967,10 @@ int getfreeMinClusters(Stream_t *Dir, size_t size)
if (!r)
total++;
if(total >= size)
- return 1;
+ return 1;
}
for(i=2; i < last+1; i++){
- unsigned int r = fatDecode(This, i);
+ unsigned int r = fatDecode(This, i);
if(r == 1) {
goto exit_0;
}
@@ -953,27 +988,32 @@ int getfreeMinClusters(Stream_t *Dir, size_t size)
}
-int getfreeMinBytes(Stream_t *Dir, mt_size_t size)
+int getfreeMinBytes(Stream_t *Dir, mt_off_t size)
{
Stream_t *Stream = GetFs(Dir);
DeclareThis(Fs_t);
- size_t size2;
+ mt_off_t size2;
size2 = size / (This->sector_size * This->cluster_size);
if(size % (This->sector_size * This->cluster_size))
size2++;
- return getfreeMinClusters(Dir, size2);
+ if((smt_off_t)size2 > UINT32_MAX) {
+ fprintf(stderr, "Requested size too big\n");
+ exit(1);
+ }
+ return getfreeMinClusters(Dir, (uint32_t) size2);
}
-unsigned int getStart(Stream_t *Dir, struct directory *dir)
+uint32_t getStart(Stream_t *Dir, struct directory *dir)
{
Stream_t *Stream = GetFs(Dir);
- unsigned int first;
+ uint32_t first;
first = START(dir);
- if(fat32RootCluster(Stream))
- first |= STARTHI(dir) << 16;
+ if(fat32RootCluster(Stream)) {
+ first |= (uint32_t) STARTHI(dir) << 16;
+ }
return first;
}
@@ -983,11 +1023,11 @@ int fs_free(Stream_t *Stream)
if(This->FatMap) {
int i, nr_entries;
- nr_entries = (This->fat_len + SECT_PER_ENTRY - 1) /
+ nr_entries = (This->fat_len + SECT_PER_ENTRY - 1) /
SECT_PER_ENTRY;
for(i=0; i< nr_entries; i++)
if(This->FatMap[i].data)
- free(This->FatMap[i].data);
+ free(This->FatMap[i].data);
free(This->FatMap);
}
if(This->cp)
diff --git a/fat_free.c b/fat_free.c
index 6d49018..f7c1d5b 100644
--- a/fat_free.c
+++ b/fat_free.c
@@ -50,7 +50,7 @@ int fat_free(Stream_t *Dir, unsigned int fat)
int fatFreeWithDir(Stream_t *Dir, struct directory *dir)
{
- unsigned int first;
+ uint32_t first;
if((!strncmp(dir->name,". ",8) ||
!strncmp(dir->name,".. ",8)) &&
@@ -61,7 +61,7 @@ int fatFreeWithDir(Stream_t *Dir, struct directory *dir)
first = START(dir);
if(fat32RootCluster(Dir))
- first |= STARTHI(dir) << 16;
+ first |= (uint32_t) STARTHI(dir) << 16;
return fat_free(Dir, first);
}
@@ -69,4 +69,3 @@ int fatFreeWithDirentry(direntry_t *entry)
{
return fatFreeWithDir(entry->Dir, &entry->dir);
}
-
diff --git a/file.c b/file.c
index 6ae7555..8165d4f 100644
--- a/file.c
+++ b/file.c
@@ -23,19 +23,25 @@
#include "file.h"
#include "htable.h"
#include "dirCache.h"
+#include "buffer.h"
typedef struct File_t {
- Class_t *Class;
- int refs;
- struct Fs_t *Fs; /* Filesystem that this fat file belongs to */
- Stream_t *Buffer;
+ struct Stream_t head;
- int (*map)(struct File_t *this, off_t where, size_t *len, int mode,
+ struct Stream_t *Buffer;
+
+ int (*map)(struct File_t *this, uint32_t where, uint32_t *len, int mode,
mt_off_t *res);
- size_t FileSize;
+ uint32_t FileSize;
+
+ /* How many bytes do we project to need for this file
+ (includes those already in FileSize) */
+ uint32_t preallocatedSize;
- size_t preallocatedSize;
- int preallocatedClusters;
+ /* How many clusters we have asked the lower layer to reserve
+ for us (only what we will need in the future, excluding already
+ allocated clusters in FileSize) */
+ uint32_t preallocatedClusters;
/* Absolute position of first cluster of file */
unsigned int FirstAbsCluNr;
@@ -51,6 +57,8 @@ typedef struct File_t {
unsigned int loopDetectRel;
unsigned int loopDetectAbs;
+
+ uint32_t where;
} File_t;
static Class_t FileClass;
@@ -63,9 +71,14 @@ static File_t *getUnbufferedFile(Stream_t *Stream)
return (File_t *) Stream;
}
+static inline Fs_t *_getFs(File_t *File)
+{
+ return (Fs_t *) File->head.Next;
+}
+
Fs_t *getFs(Stream_t *Stream)
{
- return getUnbufferedFile(Stream)->Fs;
+ return (Fs_t *)getUnbufferedFile(Stream)->head.Next;
}
struct dirCache_t **getDirCacheP(Stream_t *Stream)
@@ -78,14 +91,22 @@ direntry_t *getDirentry(Stream_t *Stream)
return &getUnbufferedFile(Stream)->direntry;
}
+/**
+ * Overflow-safe conversion of bytes to cluster
+ */
+static uint32_t filebytesToClusters(uint32_t bytes, uint32_t clus_size) {
+ uint32_t ret = bytes / clus_size;
+ if(bytes % clus_size)
+ ret++;
+ return ret;
+}
static int recalcPreallocSize(File_t *This)
{
- size_t currentClusters, neededClusters;
+ uint32_t currentClusters, neededClusters;
unsigned int clus_size;
- int neededPrealloc;
- Fs_t *Fs = This->Fs;
- int r;
+ uint32_t neededPrealloc;
+ Fs_t *Fs = _getFs(This);
#if 0
if(This->FileSize & 0xc0000000) {
@@ -97,15 +118,21 @@ static int recalcPreallocSize(File_t *This)
}
#endif
clus_size = Fs->cluster_size * Fs->sector_size;
-
- currentClusters = (This->FileSize + clus_size - 1) / clus_size;
- neededClusters = (This->preallocatedSize + clus_size - 1) / clus_size;
- neededPrealloc = neededClusters - currentClusters;
- if(neededPrealloc < 0)
+ currentClusters = filebytesToClusters(This->FileSize, clus_size);
+ neededClusters = filebytesToClusters(This->preallocatedSize, clus_size);
+ if(neededClusters < currentClusters)
neededPrealloc = 0;
- r = fsPreallocateClusters(Fs, neededPrealloc - This->preallocatedClusters);
- if(r)
- return r;
+ else
+ neededPrealloc = neededClusters - currentClusters;
+ if(neededPrealloc > This->preallocatedClusters) {
+ int r = fsPreallocateClusters(Fs, neededPrealloc-
+ This->preallocatedClusters);
+ if(r)
+ return r;
+ } else {
+ fsReleasePreallocateClusters(Fs, This->preallocatedClusters -
+ neededPrealloc);
+ }
This->preallocatedClusters = neededPrealloc;
return 0;
}
@@ -138,7 +165,7 @@ static unsigned int _countBlocks(Fs_t *This, unsigned int block)
unsigned int rel, oldabs, oldrel;
blocks = 0;
-
+
oldabs = oldrel = rel = 0;
while (block <= This->last_fat && block != 1 && block) {
@@ -162,7 +189,7 @@ unsigned int countBlocks(Stream_t *Dir, unsigned int block)
/* returns number of bytes in a directory. Represents a file size, and
* can hence be not bigger than 2^32
*/
-static size_t countBytes(Stream_t *Dir, unsigned int block)
+static uint32_t countBytes(Stream_t *Dir, unsigned int block)
{
Stream_t *Stream = GetFs(Dir);
DeclareThis(Fs_t);
@@ -174,7 +201,7 @@ static size_t countBytes(Stream_t *Dir, unsigned int block)
void printFat(Stream_t *Stream)
{
File_t *This = getUnbufferedFile(Stream);
- unsigned long n;
+ uint32_t n;
unsigned int rel;
unsigned long begin, end;
int first;
@@ -201,11 +228,11 @@ void printFat(Stream_t *Stream)
end++;
}
first = 0;
- n = fatDecode(This->Fs, n);
+ n = fatDecode(_getFs(This), n);
rel++;
if(loopDetect(This, rel, n) < 0)
n = 1;
- } while (n <= This->Fs->last_fat && n != 1);
+ } while (n <= _getFs(This)->last_fat && n != 1);
if(!first) {
if (begin != end)
printf("-%lu", end);
@@ -215,8 +242,8 @@ void printFat(Stream_t *Stream)
void printFatWithOffset(Stream_t *Stream, off_t offset) {
File_t *This = getUnbufferedFile(Stream);
- unsigned long n;
- int rel;
+ uint32_t n;
+ unsigned int rel;
off_t clusSize;
n = This->FirstAbsCluNr;
@@ -225,34 +252,34 @@ void printFatWithOffset(Stream_t *Stream, off_t offset) {
return;
}
- clusSize = This->Fs->cluster_size * This->Fs->sector_size;
+ clusSize = _getFs(This)->cluster_size * _getFs(This)->sector_size;
rel = 0;
while(offset >= clusSize) {
- n = fatDecode(This->Fs, n);
+ n = fatDecode(_getFs(This), n);
rel++;
if(loopDetect(This, rel, n) < 0)
return;
- if(n > This->Fs->last_fat)
+ if(n > _getFs(This)->last_fat)
return;
offset -= clusSize;
}
- printf("%lu", n);
+ printf("%lu", (unsigned long) n);
}
-static int normal_map(File_t *This, off_t where, size_t *len, int mode,
- mt_off_t *res)
+static int normal_map(File_t *This, uint32_t where, uint32_t *len, int mode,
+ mt_off_t *res)
{
unsigned int offset;
size_t end;
- int NrClu; /* number of clusters to read */
- unsigned int RelCluNr;
- unsigned int CurCluNr;
- unsigned int NewCluNr;
- unsigned int AbsCluNr;
- unsigned int clus_size;
- Fs_t *Fs = This->Fs;
+ uint32_t NrClu; /* number of clusters to read */
+ uint32_t RelCluNr;
+ uint32_t CurCluNr;
+ uint32_t NewCluNr;
+ uint32_t AbsCluNr;
+ uint32_t clus_size;
+ Fs_t *Fs = _getFs(This);
*res = 0;
clus_size = Fs->cluster_size * Fs->sector_size;
@@ -268,7 +295,7 @@ static int normal_map(File_t *This, off_t where, size_t *len, int mode,
*len = 0;
return 0;
}
- NewCluNr = get_next_free_cluster(This->Fs, 1);
+ NewCluNr = get_next_free_cluster(_getFs(This), 1);
if (NewCluNr == 1 ){
errno = ENOSPC;
return -2;
@@ -276,11 +303,11 @@ static int normal_map(File_t *This, off_t where, size_t *len, int mode,
hash_remove(filehash, (void *) This, This->hint);
This->FirstAbsCluNr = NewCluNr;
hash_add(filehash, (void *) This, &This->hint);
- fatAllocate(This->Fs, NewCluNr, Fs->end_fat);
+ fatAllocate(_getFs(This), NewCluNr, Fs->end_fat);
}
RelCluNr = where / clus_size;
-
+
if (RelCluNr >= This->PreviousRelCluNr){
CurCluNr = This->PreviousRelCluNr;
AbsCluNr = This->PreviousAbsCluNr;
@@ -298,22 +325,22 @@ static int normal_map(File_t *This, off_t where, size_t *len, int mode,
This->PreviousRelCluNr = RelCluNr;
This->PreviousAbsCluNr = AbsCluNr;
}
- NewCluNr = fatDecode(This->Fs, AbsCluNr);
+ NewCluNr = fatDecode(_getFs(This), AbsCluNr);
if (NewCluNr == 1 || NewCluNr == 0){
fprintf(stderr,"Fat problem while decoding %d %x\n",
AbsCluNr, NewCluNr);
exit(1);
}
- if(CurCluNr == RelCluNr + NrClu)
+ if(CurCluNr == RelCluNr + NrClu)
break;
if (NewCluNr > Fs->last_fat && mode == MT_WRITE){
/* if at end, and writing, extend it */
- NewCluNr = get_next_free_cluster(This->Fs, AbsCluNr);
+ NewCluNr = get_next_free_cluster(_getFs(This), AbsCluNr);
if (NewCluNr == 1 ){ /* no more space */
errno = ENOSPC;
return -2;
}
- fatAppend(This->Fs, AbsCluNr, NewCluNr);
+ fatAppend(_getFs(This), AbsCluNr, NewCluNr);
}
if (CurCluNr < RelCluNr && NewCluNr > Fs->last_fat){
@@ -332,11 +359,14 @@ static int normal_map(File_t *This, off_t where, size_t *len, int mode,
}
maximize(*len, (1 + CurCluNr - RelCluNr) * clus_size - offset);
-
+
end = where + *len;
if(batchmode &&
mode == MT_WRITE &&
end >= This->FileSize) {
+ /* In batch mode, when writing at end of file, "pad"
+ * to nearest cluster boundary so that we don't have
+ * to read that data back from disk. */
*len += ROUND_UP(end, clus_size) - end;
}
@@ -346,76 +376,108 @@ static int normal_map(File_t *This, off_t where, size_t *len, int mode,
exit(1);
}
- *res = sectorsToBytes((Stream_t*)Fs,
- (This->PreviousAbsCluNr-2) * Fs->cluster_size +
- Fs->clus_start) + offset;
+ *res = sectorsToBytes(Fs,
+ (This->PreviousAbsCluNr-2) * Fs->cluster_size +
+ Fs->clus_start) + to_mt_off_t(offset);
return 1;
}
-static int root_map(File_t *This, off_t where, size_t *len, int mode UNUSEDP,
- mt_off_t *res)
+static int root_map(File_t *This, uint32_t where, uint32_t *len,
+ int mode UNUSEDP, mt_off_t *res)
{
- Fs_t *Fs = This->Fs;
+ Fs_t *Fs = _getFs(This);
- if(Fs->dir_len * Fs->sector_size < (size_t) where) {
+ if(Fs->dir_len * Fs->sector_size < where) {
*len = 0;
errno = ENOSPC;
return -2;
}
- sizemaximize(*len, Fs->dir_len * Fs->sector_size - where);
+ maximize(*len, Fs->dir_len * Fs->sector_size - where);
if (*len == 0)
return 0;
-
- *res = sectorsToBytes((Stream_t*)Fs, Fs->dir_start) + where;
+
+ *res = sectorsToBytes(Fs, Fs->dir_start) +
+ to_mt_off_t(where);
return 1;
}
-
-static int read_file(Stream_t *Stream, char *buf, mt_off_t iwhere,
- size_t len)
+static ssize_t read_file(Stream_t *Stream, char *buf, size_t ilen)
{
DeclareThis(File_t);
mt_off_t pos;
int err;
- off_t where = truncBytes32(iwhere);
-
- Stream_t *Disk = This->Fs->Next;
+ uint32_t len = truncSizeTo32u(ilen);
+ ssize_t ret;
- err = This->map(This, where, &len, MT_READ, &pos);
+ Stream_t *Disk = _getFs(This)->head.Next;
+
+ err = This->map(This, This->where, &len, MT_READ, &pos);
if(err <= 0)
return err;
- return READS(Disk, buf, pos, len);
+ ret = PREADS(Disk, buf, pos, len);
+ if(ret < 0)
+ return ret;
+ This->where += (size_t) ret;
+ return ret;
}
-static int write_file(Stream_t *Stream, char *buf, mt_off_t iwhere, size_t len)
+static ssize_t write_file(Stream_t *Stream, char *buf, size_t ilen)
{
DeclareThis(File_t);
mt_off_t pos;
- int ret;
- size_t requestedLen;
- Stream_t *Disk = This->Fs->Next;
- off_t where = truncBytes32(iwhere);
+ ssize_t ret;
+ uint32_t requestedLen;
+ uint32_t bytesWritten;
+ Stream_t *Disk = _getFs(This)->head.Next;
+ uint32_t maxLen = UINT32_MAX-This->where;
+ uint32_t len;
int err;
+ if(ilen > maxLen) {
+ len = maxLen;
+ } else
+ len = (uint32_t) ilen;
requestedLen = len;
- err = This->map(This, where, &len, MT_WRITE, &pos);
+ err = This->map(This, This->where, &len, MT_WRITE, &pos);
if( err <= 0)
return err;
if(batchmode)
- ret = force_write(Disk, buf, pos, len);
+ ret = force_pwrite(Disk, buf, pos, len);
else
- ret = WRITES(Disk, buf, pos, len);
- if(ret > (signed int) requestedLen)
- ret = requestedLen;
- if (ret > 0 &&
- where + ret > (off_t) This->FileSize )
- This->FileSize = where + ret;
+ ret = PWRITES(Disk, buf, pos, len);
+ if(ret < 0)
+ /* Error occured */
+ return ret;
+ if((uint32_t)ret > requestedLen)
+ /* More data than requested may be written to lower
+ * levels if batch mode is active, in order to "pad"
+ * the last cluster of a file, so that we don't have
+ * to read that back from disk */
+ bytesWritten = requestedLen;
+ else
+ bytesWritten = (uint32_t)ret;
+ This->where += bytesWritten;
+ if (This->where > This->FileSize )
+ This->FileSize = This->where;
recalcPreallocSize(This);
- return ret;
+ return (ssize_t) bytesWritten;
}
+static ssize_t pread_file(Stream_t *Stream, char *buf, mt_off_t where,
+ size_t ilen) {
+ DeclareThis(File_t);
+ This->where = truncMtOffTo32u(where);
+ return read_file(Stream, buf, ilen);
+}
+
+static ssize_t pwrite_file(Stream_t *Stream, char *buf, mt_off_t where,
+ size_t ilen) {
+ DeclareThis(File_t);
+ This->where = truncMtOffTo32u(where);
+ return write_file(Stream, buf, ilen);
+}
/*
* Convert an MSDOS time & date stamp to the Unix time() format
@@ -449,7 +511,7 @@ static __inline__ time_t conv_stamp(struct directory *dir)
{
struct timeval tv;
struct timezone tz;
-
+
gettimeofday(&tv, &tz);
tzone = tz.tz_minuteswest * 60L;
}
@@ -481,15 +543,15 @@ static __inline__ time_t conv_stamp(struct directory *dir)
}
-static int get_file_data(Stream_t *Stream, time_t *date, mt_size_t *size,
- int *type, int *address)
+static int get_file_data(Stream_t *Stream, time_t *date, mt_off_t *size,
+ int *type, uint32_t *address)
{
DeclareThis(File_t);
if(date)
*date = conv_stamp(& This->direntry.dir);
if(size)
- *size = (mt_size_t) This->FileSize;
+ *size = to_mt_off_t(This->FileSize);
if(type)
*type = This->direntry.dir.attr & ATTR_DIR;
if(address)
@@ -501,8 +563,8 @@ static int get_file_data(Stream_t *Stream, time_t *date, mt_size_t *size,
static int free_file(Stream_t *Stream)
{
DeclareThis(File_t);
- Fs_t *Fs = This->Fs;
- fsPreallocateClusters(Fs, -This->preallocatedClusters);
+ Fs_t *Fs = _getFs(This);
+ fsReleasePreallocateClusters(Fs, This->preallocatedClusters);
FREE(&This->direntry.Dir);
freeDirCache(Stream);
return hash_remove(filehash, (void *) Stream, This->hint);
@@ -527,11 +589,11 @@ static int flush_file(Stream_t *Stream)
}
-static int pre_allocate_file(Stream_t *Stream, mt_size_t isize)
+static int pre_allocate_file(Stream_t *Stream, mt_off_t isize)
{
DeclareThis(File_t);
- size_t size = truncBytes32(isize);
+ uint32_t size = truncMtOffTo32u(isize);
if(size > This->FileSize &&
size > This->preallocatedSize) {
@@ -544,6 +606,8 @@ static int pre_allocate_file(Stream_t *Stream, mt_size_t isize)
static Class_t FileClass = {
read_file,
write_file,
+ pread_file,
+ pwrite_file,
flush_file, /* flush */
free_file, /* free */
0, /* get_geom */
@@ -562,14 +626,14 @@ static unsigned int getAbsCluNr(File_t *This)
return 1;
}
-static size_t func1(void *Stream)
+static uint32_t func1(void *Stream)
{
DeclareThis(File_t);
- return getAbsCluNr(This) ^ (long) This->Fs;
+ return getAbsCluNr(This) ^ (uint32_t) (unsigned long) This->head.Next;
}
-static size_t func2(void *Stream)
+static uint32_t func2(void *Stream)
{
DeclareThis(File_t);
@@ -582,14 +646,14 @@ static int comp(void *Stream, void *Stream2)
File_t *This2 = (File_t *) Stream2;
- return This->Fs != This2->Fs ||
+ return _getFs(This) != _getFs(This2) ||
getAbsCluNr(This) != getAbsCluNr(This2);
}
static void init_hash(void)
{
static int is_initialised=0;
-
+
if(!is_initialised){
make_ht(func1, func2, comp, 20, &filehash);
is_initialised = 1;
@@ -598,7 +662,7 @@ static void init_hash(void)
static Stream_t *_internalFileOpen(Stream_t *Dir, unsigned int first,
- size_t size, direntry_t *entry)
+ uint32_t size, direntry_t *entry)
{
Stream_t *Stream = GetFs(Dir);
DeclareThis(Fs_t);
@@ -606,13 +670,12 @@ static Stream_t *_internalFileOpen(Stream_t *Dir, unsigned int first,
File_t *File;
init_hash();
- This->refs++;
+ This->head.refs++;
if(first != 1){
/* we use the illegal cluster 1 to mark newly created files.
* do not manage those by hashtable */
- Pattern.Fs = This;
- Pattern.Class = &FileClass;
+ init_head(&Pattern.head, &FileClass, &This->head);
if(first || (entry && !IS_DIR(entry)))
Pattern.map = normal_map;
else
@@ -622,8 +685,8 @@ static Stream_t *_internalFileOpen(Stream_t *Dir, unsigned int first,
Pattern.loopDetectAbs = first;
if(!hash_lookup(filehash, (T_HashTableEl) &Pattern,
(T_HashTableEl **)&File, 0)){
- File->refs++;
- This->refs--;
+ File->head.refs++;
+ This->head.refs--;
return (Stream_t *) File;
}
}
@@ -631,6 +694,8 @@ static Stream_t *_internalFileOpen(Stream_t *Dir, unsigned int first,
File = New(File_t);
if (!File)
return NULL;
+ init_head(&File->head, &FileClass, &This->head);
+ File->Buffer = NULL;
File->dcp = 0;
File->preallocatedClusters = 0;
File->preallocatedSize = 0;
@@ -640,9 +705,7 @@ static Stream_t *_internalFileOpen(Stream_t *Dir, unsigned int first,
File->direntry.Dir = (Stream_t *) File; /* root directory */
else
COPY(File->direntry.Dir);
-
- File->Class = &FileClass;
- File->Fs = This;
+ File->where = 0;
if(first || (entry && !IS_DIR(entry)))
File->map = normal_map;
else
@@ -657,17 +720,41 @@ static Stream_t *_internalFileOpen(Stream_t *Dir, unsigned int first,
File->PreviousRelCluNr = 0xffff;
File->FileSize = size;
- File->refs = 1;
- File->Buffer = 0;
hash_add(filehash, (void *) File, &File->hint);
return (Stream_t *) File;
}
+static void bufferize(Stream_t **Dir)
+{
+ Stream_t *BDir;
+ File_t *file = (File_t *) *Dir;
+
+ if(!*Dir)
+ return;
+
+ if(file->Buffer){
+ (*Dir)->refs--;
+ file->Buffer->refs++;
+ *Dir = file->Buffer;
+ return;
+ }
+
+ BDir = buf_init(*Dir, 64*16384, 512, MDIR_SIZE);
+ if(!BDir){
+ FREE(Dir);
+ *Dir = NULL;
+ } else {
+ file->Buffer = BDir;
+ *Dir = BDir;
+ }
+}
+
+
Stream_t *OpenRoot(Stream_t *Dir)
{
unsigned int num;
direntry_t entry;
- size_t size;
+ uint32_t size;
Stream_t *file;
memset(&entry, 0, sizeof(direntry_t));
@@ -695,7 +782,7 @@ Stream_t *OpenFileByDirentry(direntry_t *entry)
{
Stream_t *file;
unsigned int first;
- size_t size;
+ uint32_t size;
first = getStart(entry->Dir, &entry->dir);
diff --git a/file_name.c b/file_name.c
index 8dac0aa..4456492 100644
--- a/file_name.c
+++ b/file_name.c
@@ -30,7 +30,7 @@ char *unix_normalize (doscp_t *cp, char *ans, dos_name_t *dn, size_t ans_size)
wchar_t wbuffer[13];
char *a;
int j;
-
+
for (a=buffer,j=0; (j<8) && (dn->base[j] > ' '); ++j,++a)
*a = dn->base[j];
if(dn->ext[0] > ' ') {
@@ -112,10 +112,10 @@ void dos_name(doscp_t *toDos, const char *name, int verbose UNUSEDP,
name = &name[2];
/* zap the leading path */
- name = (char *) _basename(name);
+ name = _basename(name);
if ((s = strrchr(name, '\\')))
name = s + 1;
-
+
memset(dn, ' ', 11);
/* skip leading dots and spaces */
@@ -152,7 +152,7 @@ void dos_name(doscp_t *toDos, const char *name, int verbose UNUSEDP,
*/
wchar_t *unix_name(doscp_t *dosCp,
- const char *base, const char *ext, char Case, wchar_t *ret)
+ const char *base, const char *ext, uint8_t Case, wchar_t *ret)
{
char *s, tname[9], text[4], ans[13];
int i;
diff --git a/file_name.h b/file_name.h
index cc7039a..0e29af2 100644
--- a/file_name.h
+++ b/file_name.h
@@ -31,19 +31,19 @@ struct dos_name_t {
char sentinel;
};
-int dos_to_wchar(doscp_t *fromDos, const char *dos, wchar_t *wchar, size_t len);
+size_t dos_to_wchar(doscp_t *fromDos, const char *dos, wchar_t *wchar, size_t len);
void wchar_to_dos(doscp_t *toDos, wchar_t *wchar, char *dos, size_t len, int *mangled);
-doscp_t *cp_open(int codepage);
+doscp_t *cp_open(unsigned int codepage);
void cp_close(doscp_t *cp);
-int wchar_to_native(const wchar_t *wchar, char *native,
- size_t len, size_t out_len);
+size_t wchar_to_native(const wchar_t *wchar, char *native,
+ size_t len, size_t out_len);
#define WCHAR_TO_NATIVE(wchar,native,len) \
wchar_to_native((wchar),(native),(len),sizeof(native))
-int native_to_wchar(const char *native, wchar_t *wchar, size_t len,
- const char *end, int *mangled);
+size_t native_to_wchar(const char *native, wchar_t *wchar, size_t len,
+ const char *end, int *mangled);
#endif
diff --git a/file_read.c b/file_read.c
index 60e336f..5345ae2 100644
--- a/file_read.c
+++ b/file_read.c
@@ -35,7 +35,7 @@ int file_read(FILE *fp, Stream_t *Source, int textmode, int stripmode)
fprintf(stderr,"Couldn't open source file\n");
return -1;
}
-
+
pos = 0;
while(1){
ret = Source->Class->read(Source, buffer, pos, 16384);
diff --git a/filter.c b/filter.c
deleted file mode 100644
index 00b9eff..0000000
--- a/filter.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/* Copyright 1996,1997,1999,2001-2003,2008,2009 Alain Knaff.
- * This file is part of mtools.
- *
- * Mtools is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Mtools is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "sysincludes.h"
-#include "msdos.h"
-#include "mtools.h"
-#include "codepage.h"
-
-typedef struct Filter_t {
- Class_t *Class;
- int refs;
- Stream_t *Next;
- Stream_t *Buffer;
-
- int dospos;
- int unixpos;
- int mode;
- int rw;
- int lastchar;
- /* int convertCharset; */
-} Filter_t;
-
-#define F_READ 1
-#define F_WRITE 2
-
-/* read filter filters out messy dos' bizarre end of lines and final 0x1a's */
-
-static int read_filter(Stream_t *Stream, char *buf, mt_off_t iwhere, size_t len)
-{
- DeclareThis(Filter_t);
- int i,j,ret;
- unsigned char newchar;
-
- off_t where = truncBytes32(iwhere);
-
- if ( where != This->unixpos ){
- fprintf(stderr,"Bad offset\n");
- exit(1);
- }
- if (This->rw == F_WRITE){
- fprintf(stderr,"Change of transfer direction!\n");
- exit(1);
- }
- This->rw = F_READ;
-
- ret = READS(This->Next, buf, (mt_off_t) This->dospos, len);
- if ( ret < 0 )
- return ret;
-
- j = 0;
- for (i=0; i< ret; i++){
- if ( buf[i] == '\r' )
- continue;
- if (buf[i] == 0x1a)
- break;
- newchar = buf[i];
- /*
- if (This->convertCharset) newchar = contents_to_unix(newchar);
- */
- This->lastchar = buf[j++] = newchar;
- }
-
- This->dospos += i;
- This->unixpos += j;
- return j;
-}
-
-static int write_filter(Stream_t *Stream, char *buf, mt_off_t iwhere,
- size_t len)
-{
- DeclareThis(Filter_t);
- unsigned int i,j;
- int ret;
- char buffer[1025];
- unsigned char newchar;
-
- off_t where = truncBytes32(iwhere);
-
- if(This->unixpos == -1)
- return -1;
-
- if (where != This->unixpos ){
- fprintf(stderr,"Bad offset\n");
- exit(1);
- }
-
- if (This->rw == F_READ){
- fprintf(stderr,"Change of transfer direction!\n");
- exit(1);
- }
- This->rw = F_WRITE;
-
- j=i=0;
- while(i < 1024 && j < len){
- if (buf[j] == '\n' ){
- buffer[i++] = '\r';
- buffer[i++] = '\n';
- j++;
- continue;
- }
- newchar = buf[j++];
- /*
- if (This->convertCharset) newchar = to_dos(newchar);
- */
- buffer[i++] = newchar;
- }
- This->unixpos += j;
-
- ret = force_write(This->Next, buffer, (mt_off_t) This->dospos, i);
- if(ret >0 )
- This->dospos += ret;
- if ( ret != (signed int) i ){
- /* no space on target file ? */
- This->unixpos = -1;
- return -1;
- }
- return j;
-}
-
-static int free_filter(Stream_t *Stream)
-{
- DeclareThis(Filter_t);
- char buffer=0x1a;
-
- /* write end of file */
- if (This->rw == F_WRITE)
- return force_write(This->Next, &buffer, (mt_off_t) This->dospos, 1);
- else
- return 0;
-}
-
-static Class_t FilterClass = {
- read_filter,
- write_filter,
- 0, /* flush */
- free_filter,
- 0, /* set geometry */
- get_data_pass_through,
- 0,
- 0, /* get_dosconvert */
- 0 /* discard */
-};
-
-Stream_t *open_filter(Stream_t *Next, int convertCharset UNUSEDP)
-{
- Filter_t *This;
-
- This = New(Filter_t);
- if (!This)
- return NULL;
- This->Class = &FilterClass;
- This->dospos = This->unixpos = This->rw = 0;
- This->Next = Next;
- This->refs = 1;
- This->Buffer = 0;
- /*
- This->convertCharset = convertCharset;
- */
-
- return (Stream_t *) This;
-}
diff --git a/floppyd.1 b/floppyd.1
index b6aa567..6da4919 100644
--- a/floppyd.1
+++ b/floppyd.1
@@ -1,5 +1,5 @@
'\" t
-.TH floppyd 1 "28Nov20" mtools-4.0.26
+.TH floppyd 1 "08Jan22" mtools-4.0.37
.SH Name
floppyd - floppy daemon for remote access to floppy drive
'\" t
diff --git a/floppyd.c b/floppyd.c
index 0dee036..1601271 100644
--- a/floppyd.c
+++ b/floppyd.c
@@ -23,7 +23,7 @@
*
* udbz@rz.uni-karlsruhe.de
*
- * Large parts of the network code shamelessly stolen from
+ * Large parts of the network code shamelessly stolen from
* transproxy by John Saunders <john@nlc.net.au>
*
* Rewritten in C by Alain Knaff. Apparently C++ is still not as
@@ -66,7 +66,7 @@
Client sends his protocol-version. If the version between server and client
differ: bail out.
- After that,we send our .Xauthority-file (a maximum of MAX_XAUTHORITY_LENGTH
+ After that,we send our .Xauthority-file (a maximum of MAX_XAUTHORITY_LENGTH
Bytes long) to the server.
The server then checks, if it already has a .Xauthority file. If so
@@ -98,7 +98,7 @@
read the expected bytes from the socket stream. Don't know
why this is necessary. Maybe the socket stream is nonblocking
or something IT SHOULD NOT BE!
-
+
*/
@@ -108,7 +108,7 @@
unsigned int mtools_lock_timeout=30;
-void serve_client(int sock, char **device_name, unsigned int n_dev,
+void serve_client(int sock, const char *const*device_name, unsigned int n_dev,
int close_stderr);
@@ -116,11 +116,11 @@ void serve_client(int sock, char **device_name, unsigned int n_dev,
typedef struct io_buffer {
Byte out_buffer[BUFFERED_IO_SIZE];
Byte in_buffer[BUFFERED_IO_SIZE];
-
+
size_t in_valid;
size_t in_start;
size_t out_valid;
-
+
int handle;
} *io_buffer;
@@ -153,15 +153,15 @@ static void free_io_buffer(io_buffer buffer) {
static size_t buf_read (io_buffer buf, Byte* buffer, size_t nbytes) {
size_t ret;
-
+
if (nbytes <= buf->in_valid) {
memcpy(buffer, buf->in_buffer+buf->in_start, nbytes);
buf->in_valid -= nbytes;
buf->in_start += nbytes;
ret = nbytes;
} else {
- if (buf->in_valid)
- memcpy(buffer, buf->in_buffer+buf->in_start,
+ if (buf->in_valid)
+ memcpy(buffer, buf->in_buffer+buf->in_start,
buf->in_valid);
nbytes -= buf->in_valid;
buffer += buf->in_valid;
@@ -175,7 +175,7 @@ static size_t buf_read (io_buffer buf, Byte* buffer, size_t nbytes) {
}
buf->in_valid = buf->in_start = 0;
} else {
- ssize_t rval = read(buf->handle, buf->in_buffer,
+ ssize_t rval = read(buf->handle, buf->in_buffer,
BUFFERED_IO_SIZE);
if (rval >= 0) {
if (rval < (ssize_t) nbytes) {
@@ -251,16 +251,16 @@ static Dword read_dword(io_buffer fp)
if (buf_read(fp, val, 4) < 4) {
return 0xffffffff;
}
-
+
return byte2dword(val);
}
static void write_dword(io_buffer fp, Dword parm)
{
Byte val[4];
-
+
dword2byte(parm, val);
-
+
buf_write(fp, val,4);
}
@@ -320,7 +320,7 @@ static char send_packet(Packet packet, io_buffer fp)
fprintf(stderr, "%d ", packet->data[i]);
}
fprintf(stderr, "\n");
-#endif
+#endif
}
return (packet->data != NULL);
@@ -351,14 +351,14 @@ static char recv_packet(Packet packet, io_buffer fp, Dword maxlength)
#if DEBUG
fprintf(stderr, "*** read: %li\n", packet->len);
#endif
-
+
#if DEBUG
fprintf(stderr, "recv_packet(): ");
for (i = 0; i < packet->len; i++) {
fprintf(stderr, "%d ", packet->data[i]);
}
fprintf(stderr, "\n");
-#endif
+#endif
return 1;
}
@@ -386,11 +386,11 @@ static void put_qword(Packet packet, int my_index, Qword val) {
static Dword get_dword(Packet packet, int my_index) {
return byte2dword(packet->data+my_index);
-}
+}
static Qword get_qword(Packet packet, int my_index) {
return byte2qword(packet->data+my_index);
-}
+}
static Dword get_length(Packet packet) {
return packet->len;
@@ -398,7 +398,7 @@ static Dword get_length(Packet packet) {
static int eat(unsigned char **ptr, size_t *len, unsigned char c) {
/* remove length + size code + terminating 0 */
- if (*len < c + 3)
+ if (*len < c + 3u)
return -1;
(*ptr) += c + 2;
(*len) -= c + 2;
@@ -409,7 +409,7 @@ static const char *dispName;
static char XAUTHORITY[]="XAUTHORITY";
-static char do_auth(io_buffer sock, unsigned int *version)
+static char do_auth(io_buffer sock, unsigned int *version)
{
int fd;
Display* displ;
@@ -434,7 +434,7 @@ static char do_auth(io_buffer sock, unsigned int *version)
}
*version = get_dword(proto_version, 0);
- if (*version > FLOPPYD_PROTOCOL_VERSION ||
+ if (*version > FLOPPYD_PROTOCOL_VERSION ||
*version < FLOPPYD_PROTOCOL_VERSION_OLD) {
/* fail if client requests a newer version than us */
put_dword(reply, 0, AUTH_WRONGVERSION);
@@ -560,14 +560,14 @@ static uint16_t getportnum(char *portnum)
for (port = 0; isdigit(*digits); ++digits)
{
- port = (port * 10) + (*digits - '0');
+ port = (port * 10) + (uint8_t)(*digits - '0');
}
if ((*digits != '\0') || (port <= 0))
{
if ((serv = getservbyname(portnum, "tcp")) != NULL)
{
- port = ntohs(serv->s_port);
+ port = ntohs((uint16_t)serv->s_port);
}
else
{
@@ -695,7 +695,7 @@ static int bind_to_port(in_addr_t bind_ip, uint16_t bind_port)
*/
{
int on = 1;
- if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(char *)&on, sizeof(on)) < 0) {
perror("setsockopt");
exit(1);
@@ -731,7 +731,7 @@ static int bind_to_port(in_addr_t bind_ip, uint16_t bind_port)
}
static int sockethandle_now = -1;
-
+
/*
* Catch alarm signals and exit.
*/
@@ -750,9 +750,9 @@ static void alarm_signal(int a UNUSEDP)
/*
* This is the main loop when running as a server.
*/
-static void server_main_loop(int sock, char **device_name,
- unsigned int n_dev) NORETURN;
-static void server_main_loop(int sock, char **device_name,
+static void server_main_loop(int sock, const char *const*device_name,
+ unsigned int n_dev) NORETURN;
+static void server_main_loop(int sock, const char *const*device_name,
unsigned int n_dev)
{
struct sockaddr_in addr;
@@ -770,7 +770,7 @@ static void server_main_loop(int sock, char **device_name,
*/
len = sizeof(addr);
while ((new_sock = accept(sock, (struct sockaddr *)&addr, &len)) < 0){}
-
+
/*
* Create a new process to handle the connection.
*/
@@ -781,13 +781,13 @@ static void server_main_loop(int sock, char **device_name,
* Under load conditions just ignore new connections.
*/
break;
-
+
case 0:
/*
* Start the proxy work in the new socket.
*/
#endif
- serve_client(new_sock,device_name, n_dev, 0);
+ serve_client(new_sock, device_name, n_dev, 0);
exit(0);
#if DEBUG == 0
}
@@ -810,7 +810,7 @@ static void usage(char *prog, const char *opt, int ret)
{
fprintf(stderr, "%s: %s\n", prog, opt);
}
- fprintf(stderr, "usage: %s [-s port [-r user] [-b ipaddr]] devicename [Names of local host]\n",
+ fprintf(stderr, "usage: %s [-s port [-r user] [-b ipaddr]] devicename [Names of local host]\n",
prog);
fprintf(stderr, " -d Run as a server (default port 5703 + DISPLAY)\n");
fprintf(stderr, " -s port Run as a server bound to the specified port.\n");
@@ -828,7 +828,7 @@ static char *makeDisplayName(int dispNr)
return strdup(result);
}
-int main (int argc, char** argv)
+int main (int argc, char** argv)
{
int sockfd = 0;
int arg;
@@ -840,7 +840,7 @@ int main (int argc, char** argv)
char* username = strdup("nobody");
int sock;
- char **device_name = NULL;
+ const char *const* device_name = NULL;
const char *floppy0 = "/dev/fd0";
unsigned int n_dev;
@@ -884,10 +884,10 @@ int main (int argc, char** argv)
}
if(optind < argc) {
- device_name = argv + optind;
- n_dev = argc - optind;
+ device_name = (const char * const *) argv + optind;
+ n_dev = (unsigned int) (argc - optind);
} else {
- device_name = (char **)&floppy0;
+ device_name = &floppy0;
n_dev = 1;
}
@@ -895,7 +895,7 @@ int main (int argc, char** argv)
dispName = getenv("DISPLAY");
if(dispName==NULL && bind_port != 0)
dispName=makeDisplayName((unsigned short)(bind_port - 5703));
- if(dispName==NULL)
+ if(dispName==NULL)
dispName=":0";
if(bind_port == 0) {
@@ -908,9 +908,9 @@ int main (int argc, char** argv)
if(!run_as_server) {
struct sockaddr_in addr;
unsigned int len = sizeof(addr);
-
+
/* try to find out port that we are connected to */
- if(getsockname(0, (struct sockaddr*) &addr, &len) >= 0 &&
+ if(getsockname(0, (struct sockaddr*) &addr, &len) >= 0 &&
len == sizeof(addr)) {
bind_port = ntohs(addr.sin_port);
}
@@ -937,7 +937,7 @@ int main (int argc, char** argv)
* Start by binding to the port, the child inherits this socket.
*/
sock = bind_to_port(bind_ip, bind_port);
-
+
/*
* Start a server process. When DEBUG is defined, just run
* in the foreground.
@@ -951,7 +951,7 @@ int main (int argc, char** argv)
case -1:
perror("fork()");
exit(1);
-
+
case 0:
/*
* Ignore some signals.
@@ -965,14 +965,14 @@ int main (int argc, char** argv)
signal(SIGCONT, SIG_IGN);
signal(SIGPIPE, alarm_signal);
/*signal(SIGALRM, alarm_signal);*/
-
+
/*
* Drop back to an untrusted user.
*/
setgid(run_gid);
initgroups(username, run_gid);
setuid(run_uid);
-
+
/*
* Start a new session and group.
*/
@@ -994,7 +994,7 @@ int main (int argc, char** argv)
server_main_loop(sock, device_name,
n_dev);
}
-
+
/*
* Parent exits at this stage.
*/
@@ -1036,7 +1036,7 @@ static void send_reply64(int rval, io_buffer sock, mt_off_t len) {
Packet reply = newPacket();
make_new(reply, 12);
- put_qword(reply, 0, len);
+ put_qword(reply, 0, (Qword) len);
if (rval == -1) {
put_dword(reply, 8, 0);
} else {
@@ -1054,8 +1054,8 @@ static void cleanup(int x UNUSEDP) {
#include "lockdev.h"
-void serve_client(int sockhandle, char **device_name, unsigned int n_dev,
- int close_stderr) {
+void serve_client(int sockhandle, const char *const*device_name,
+ unsigned int n_dev, int close_stderr) {
Packet opcode;
Packet parm;
@@ -1066,13 +1066,13 @@ void serve_client(int sockhandle, char **device_name, unsigned int n_dev,
unsigned int version;
int needSendReply=0;
int rval=0;
-
+
/*
* Set the keepalive socket option to on.
*/
{
int on = 1;
- if(setsockopt(sockhandle, SOL_SOCKET,
+ if(setsockopt(sockhandle, SOL_SOCKET,
SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) {
perror("setsockopt");
exit(1);
@@ -1089,12 +1089,12 @@ void serve_client(int sockhandle, char **device_name, unsigned int n_dev,
#endif
sock = new_io_buffer(sockhandle);
-
+
/*
* Allow 60 seconds for any activity.
*/
alarm(60);
-
+
version = 0;
if (!do_auth(sock, &version)) {
free_io_buffer(sock);
@@ -1122,10 +1122,10 @@ void serve_client(int sockhandle, char **device_name, unsigned int n_dev,
/* old protocol */
readOnly = 0;
devFd = open(device_name[0], O_RDWR|O_LARGEFILE);
-
+
if (devFd < 0) {
readOnly = 1;
- devFd = open(device_name[0],
+ devFd = open(device_name[0],
O_RDONLY|O_LARGEFILE);
}
if(devFd < 0) {
@@ -1228,17 +1228,18 @@ void serve_client(int sockhandle, char **device_name, unsigned int n_dev,
} else {
rval = write_packet(parm, devFd);
}
- send_reply(devFd, sock, rval);
+ send_reply(devFd, sock, (Dword) rval);
break;
case OP_SEEK:
#if DEBUG
fprintf(stderr, "SEEK:\n");
#endif
- lseek(devFd,
- get_dword(parm, 0), get_dword(parm, 4));
- send_reply(devFd,
- sock,
+ lseek(devFd,
+ (off_t) get_dword(parm, 0),
+ (int) get_dword(parm, 4));
+ send_reply(devFd,
+ sock,
(Dword) lseek(devFd, 0, SEEK_CUR));
break;
case OP_SEEK64:
@@ -1253,10 +1254,11 @@ void serve_client(int sockhandle, char **device_name, unsigned int n_dev,
#if DEBUG
fprintf(stderr, "SEEK64:\n");
#endif
- mt_lseek(devFd,
- get_qword(parm,0), get_dword(parm,8));
- send_reply64(devFd,
- sock,
+ mt_lseek(devFd,
+ (mt_off_t) get_qword(parm,0),
+ (int) get_dword(parm,8));
+ send_reply64(devFd,
+ sock,
mt_lseek(devFd, 0, SEEK_CUR));
break;
case OP_FLUSH:
@@ -1293,7 +1295,7 @@ void serve_client(int sockhandle, char **device_name, unsigned int n_dev,
alarm(0);
}
-
+
#if DEBUG
fprintf(stderr, "Closing down...\n");
@@ -1318,10 +1320,10 @@ void serve_client(int sockhandle, char **device_name, unsigned int n_dev,
#else
#include <stdio.h>
-int main(int argc, char **argv)
+int main(int argc, char **argv)
{
puts("Floppyd support not included!");
return -1;
}
-
+
#endif
diff --git a/floppyd_installtest.1 b/floppyd_installtest.1
index 5be5466..ec951d7 100644
--- a/floppyd_installtest.1
+++ b/floppyd_installtest.1
@@ -1,5 +1,5 @@
'\" t
-.TH floppyd_installtest 1 "28Nov20" mtools-4.0.26
+.TH floppyd_installtest 1 "08Jan22" mtools-4.0.37
.SH Name
floppyd_installtest - tests whether floppyd is installed and running
'\" t
diff --git a/floppyd_installtest.c b/floppyd_installtest.c
index 98043c8..2a128c8 100644
--- a/floppyd_installtest.c
+++ b/floppyd_installtest.c
@@ -31,7 +31,6 @@
#include "mtools.h"
#include "msdos.h"
#include "scsi.h"
-#include "partition.h"
#include "floppyd_io.h"
#ifdef USE_FLOPPYD
@@ -66,10 +65,10 @@ static int write_dword(int handle, Dword parm)
/* ######################################################################## */
-static uint32_t authenticate_to_floppyd(char fullauth, int sock, char *display,
+static uint32_t authenticate_to_floppyd(char fullauth, int sock, char *display,
uint32_t protoversion)
{
- size_t filelen=0;
+ uint32_t filelen=0;
Byte buf[16];
const char *command[] = { "xauth", "xauth", "extract", "-", 0, 0 };
char *xcookie = NULL;
@@ -80,11 +79,11 @@ static uint32_t authenticate_to_floppyd(char fullauth, int sock, char *display,
if (fullauth) {
command[4] = display;
- filelen=strlen(display);
+ filelen=(uint32_t)strlen(display);
filelen += 100;
xcookie = (char *) safe_malloc(filelen+4);
- filelen = safePopenOut(command, xcookie+4, filelen);
+ filelen = (uint32_t) safePopenOut(command, xcookie+4, filelen);
if(filelen < 1)
return AUTH_AUTHFAILED;
}
@@ -106,15 +105,15 @@ static uint32_t authenticate_to_floppyd(char fullauth, int sock, char *display,
return errcode;
}
- protoversion = FLOPPYD_PROTOCOL_VERSION_OLD;
+ protoversion = FLOPPYD_PROTOCOL_VERSION_OLD;
if(bytesRead >= 12) {
protoversion = read_dword(sock);
cap = read_dword(sock);
}
-
+
fprintf(stderr, "Protocol Version=%d\n", protoversion);
if(protoversion >= FLOPPYD_PROTOCOL_VERSION) {
- fprintf(stderr, "Capabilities:%s%s\n",
+ fprintf(stderr, "Capabilities:%s%s\n",
(cap & FLOPPYD_CAP_EXPLICIT_OPEN) ? " ExplicitOpen" : "",
(cap & FLOPPYD_CAP_LARGE_SEEK) ? " LargeFiles" : "");
}
@@ -150,10 +149,10 @@ static int get_host_and_port(const char* name, char** hostname, char **display,
p2 = p;
if (*p) p++;
*p2 = 0;
-
+
*port = atou16(p);
if (*port == 0) {
- *port = FLOPPYD_DEFAULT_PORT;
+ *port = FLOPPYD_DEFAULT_PORT;
}
*display = strdup(newname);
@@ -180,24 +179,24 @@ static int get_host_and_port(const char* name, char** hostname, char **display,
* */
static in_addr_t getipaddress(char *ipaddr)
{
-
+
struct hostent *host;
in_addr_t ip;
-
+
if (((ip = inet_addr(ipaddr)) == INADDR_NONE) &&
(strcmp(ipaddr, "255.255.255.255") != 0)) {
-
+
if ((host = gethostbyname(ipaddr)) != NULL) {
memcpy(&ip, host->h_addr, sizeof(ip));
}
-
+
endhostent();
}
-
+
#ifdef DEBUG
fprintf(stderr, "IP lookup %s -> 0x%08lx\n", ipaddr, ip);
#endif
-
+
return (ip);
}
@@ -206,25 +205,25 @@ static in_addr_t getipaddress(char *ipaddr)
* */
static int connect_to_server(in_addr_t ip, uint16_t port)
{
-
+
struct sockaddr_in addr;
int sock;
-
+
/*
* Allocate a socket.
*/
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
return (-1);
}
-
+
/*
* Set the address to connect to.
*/
-
+
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = ip;
-
+
/*
* Connect our socket to the above address.
*/
@@ -237,15 +236,15 @@ static int connect_to_server(in_addr_t ip, uint16_t port)
*/
{
int on = 1;
- setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
+ setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
(char *)&on, sizeof(on));
}
-
+
return (sock);
}
-int main (int argc, char** argv)
+int main (int argc, char** argv)
{
char* hostname;
char* display;
@@ -271,7 +270,7 @@ int main (int argc, char** argv)
}
rval = get_host_and_port(name, &hostname, &display, &port);
-
+
if (!rval) return -1;
sock = connect_to_server(getipaddress(hostname), port);
@@ -282,7 +281,7 @@ int main (int argc, char** argv)
hostname, port);
return -1;
}
-
+
protoversion = FLOPPYD_PROTOCOL_VERSION;
while(1) {
reply = authenticate_to_floppyd(fullauth, sock, display,
@@ -298,12 +297,12 @@ int main (int argc, char** argv)
}
if (reply != 0) {
- fprintf(stderr,
+ fprintf(stderr,
"Connection to floppyd failed:\n"
"%s\n", AuthErrors[reply]);
return -1;
}
-
+
free(hostname);
free(display);
diff --git a/floppyd_io.c b/floppyd_io.c
index d243bc4..d884f94 100644
--- a/floppyd_io.c
+++ b/floppyd_io.c
@@ -30,11 +30,8 @@
#include "mtools.h"
#include "msdos.h"
#include "scsi.h"
-#include "partition.h"
#include "floppyd_io.h"
-#ifdef USE_FLOPPYD
-
/* ######################################################################## */
@@ -43,17 +40,15 @@ static const char* AuthErrors[] = {
"Auth failed: Packet oversized",
"Auth failed: X-Cookie doesn't match",
"Auth failed: Wrong transmission protocol version",
- "Auth failed: Device locked"
+ "Auth failed: Device locked",
"Auth failed: Bad packet",
"Auth failed: I/O Error"
};
typedef struct RemoteFile_t {
- Class_t *Class;
- int refs;
- Stream_t *Next;
- Stream_t *Buffer;
+ struct Stream_t head;
+
int fd;
mt_off_t offset;
mt_off_t lastwhere;
@@ -73,7 +68,8 @@ typedef struct RemoteFile_t {
static unsigned int authenticate_to_floppyd(RemoteFile_t *floppyd,
int sock, char *display)
{
- size_t filelen;
+ size_t cookielen;
+ uint16_t filelen;
ssize_t newlen;
Byte buf[16];
const char *command[] = { "xauth", "xauth", "extract", "-", 0, 0 };
@@ -83,15 +79,15 @@ static unsigned int authenticate_to_floppyd(RemoteFile_t *floppyd,
command[4] = display;
- filelen=strlen(display);
- filelen += 100;
+ cookielen=strlen(display);
+ cookielen += 100;
- xcookie = (char *) safe_malloc(filelen+4);
- newlen = safePopenOut(command, xcookie+4, filelen);
- if(newlen < 1)
+ xcookie = (char *) safe_malloc(cookielen+4);
+ newlen = safePopenOut(command, xcookie+4, cookielen);
+ if(newlen < 1 || newlen > UINT16_MAX)
return AUTH_AUTHFAILED;
- filelen = (size_t) newlen;
-
+ filelen = (uint16_t) newlen;
+
/* Version negotiation */
dword2byte(4,buf);
dword2byte(floppyd->version,buf+4);
@@ -122,12 +118,12 @@ static unsigned int authenticate_to_floppyd(RemoteFile_t *floppyd,
}
errcode = read_dword(sock);
-
+
return errcode;
}
-static int floppyd_reader(int fd, char* buffer, size_t len)
+static ssize_t floppyd_reader(int fd, char* buffer, uint32_t len)
{
Dword errcode;
Dword gotlen;
@@ -166,16 +162,17 @@ static int floppyd_reader(int fd, char* buffer, size_t len)
l = (size_t) ret;
}
} else {
- errno = errcode;
+ errno = (int) errcode;
}
- return gotlen;
+ return (ssize_t) gotlen;
}
-static int floppyd_writer(int fd, char* buffer, size_t len)
+static ssize_t floppyd_writer(int fd, char* buffer, uint32_t len)
{
- Dword errcode;
- Dword gotlen;
+ int errcode;
+ int32_t gotlen;
Byte buf[16];
+ ssize_t ret;
dword2byte(1, buf);
buf[4] = OP_WRITE;
@@ -184,17 +181,18 @@ static int floppyd_writer(int fd, char* buffer, size_t len)
cork(fd, 1);
if(write(fd, buf, 9) < 9)
return AUTH_IO_ERROR;
- if(write(fd, buffer, len) < len)
+ ret = write(fd, buffer, len);
+ if(ret == -1 || (size_t) ret < len)
return AUTH_IO_ERROR;
cork(fd, 0);
-
+
if (read_dword(fd) != 8) {
errno = EIO;
return -1;
}
- gotlen = read_dword(fd);
- errcode = read_dword(fd);
+ gotlen = read_sdword(fd);
+ errcode = read_sdword(fd);
errno = errcode;
if(errno != 0 && gotlen == 0) {
@@ -206,70 +204,72 @@ static int floppyd_writer(int fd, char* buffer, size_t len)
return gotlen;
}
-static int floppyd_lseek(int fd, mt_off_t offset, int whence)
+static int floppyd_lseek(int fd, int32_t offset, int whence)
{
- Dword errcode;
- Dword gotlen;
+ int errcode;
+ int gotlen;
Byte buf[32];
-
+
dword2byte(1, buf);
buf[4] = OP_SEEK;
-
+
dword2byte(8, buf+5);
- dword2byte(truncBytes32(offset), buf+9);
- dword2byte(whence, buf+13);
-
+ sdword2byte(offset, buf+9);
+ sdword2byte(whence, buf+13);
+
if(write(fd, buf, 17) < 17)
return AUTH_IO_ERROR;
-
+
if (read_dword(fd) != 8) {
errno = EIO;
return -1;
}
- gotlen = read_dword(fd);
- errcode = read_dword(fd);
+ gotlen = read_sdword(fd);
+ errcode = read_sdword(fd);
errno = errcode;
-
+
return gotlen;
}
-static mt_off_t floppyd_lseek64(int fd, mt_off_t offset, int whence)
+#if SIZEOF_OFF_T >= 8
+static mt_off_t floppyd_lseek64(int fd, mt_off_t offset, int whence)
{
- Dword errcode;
- Qword gotlen;
+ int errcode;
+ struct SQwordRet gotlen;
Byte buf[32];
-
+
dword2byte(1, buf);
buf[4] = OP_SEEK64;
-
+
dword2byte(12, buf+5);
- qword2byte(offset, buf+9);
- dword2byte(whence, buf+17);
-
+ qword2byte((uint32_t)offset, buf+9);
+ sdword2byte(whence, buf+17);
+
if(write(fd, buf, 21) < 21)
return AUTH_IO_ERROR;
-
+
if (read_dword(fd) != 12) {
errno = EIO;
return -1;
}
- gotlen = read_qword(fd);
- errcode = read_dword(fd);
+ gotlen = read_sqword(fd);
+ errcode = read_sdword(fd);
errno = errcode;
-
- return gotlen;
+
+ return gotlen.v;
}
+#endif
-static int floppyd_open(RemoteFile_t *This, int mode)
+static int floppyd_open(RemoteFile_t *This, int mode)
{
- Dword errcode;
- Dword gotlen;
+ int errcode;
+ int gotlen;
Byte buf[16];
-
+
if(! (This->capabilities & FLOPPYD_CAP_EXPLICIT_OPEN) ) {
/* floppyd has no "explicit seek" capabilities */
return 0;
@@ -281,68 +281,78 @@ static int floppyd_open(RemoteFile_t *This, int mode)
else
buf[4] = OP_OPRW;
dword2byte(4, buf+5);
- dword2byte(This->drive, buf+9);
+ sdword2byte(This->drive, buf+9);
if(write(This->fd, buf, 13) < 13)
return AUTH_IO_ERROR;
-
+
if (read_dword(This->fd) != 8) {
errno = EIO;
return -1;
}
- gotlen = read_dword(This->fd);
- errcode = read_dword(This->fd);
+ gotlen = read_sdword(This->fd);
+ errcode = read_sdword(This->fd);
errno = errcode;
-
+
return gotlen;
}
/* ######################################################################## */
-typedef int (*iofn) (int, char *, size_t);
+typedef ssize_t (*iofn) (int, char *, uint32_t);
-static int floppyd_io(Stream_t *Stream, char *buf, mt_off_t where, size_t len,
- iofn io)
+static ssize_t floppyd_io(Stream_t *Stream, char *buf, mt_off_t where,
+ size_t len, iofn io)
{
DeclareThis(RemoteFile_t);
- int ret;
+ ssize_t ret;
where += This->offset;
if (where != This->lastwhere ){
+#if SIZEOF_OFF_T >= 8
if(This->capabilities & FLOPPYD_CAP_LARGE_SEEK) {
if(floppyd_lseek64( This->fd, where, SEEK_SET) < 0 ){
perror("floppyd_lseek64");
- This->lastwhere = (mt_off_t) -1;
+ This->lastwhere = -1;
return -1;
}
- } else {
- if(floppyd_lseek( This->fd, where, SEEK_SET) < 0 ){
+ } else
+#endif
+ {
+ if(where > INT32_MAX || where < INT32_MIN) {
+ fprintf(stderr, "Seek position out of range\n");
+ return -1;
+ }
+ if(floppyd_lseek(This->fd, (int32_t) where, SEEK_SET) < 0 ){
perror("floppyd_lseek");
- This->lastwhere = (mt_off_t) -1;
+ This->lastwhere = -1;
return -1;
}
}
}
- ret = io(This->fd, buf, len);
+ ret = io(This->fd, buf,
+ (len > INT32_MAX) ? (uint32_t)INT32_MAX+1 : (uint32_t) len);
if ( ret == -1 ){
perror("floppyd_io");
- This->lastwhere = (mt_off_t) -1;
+ This->lastwhere = -1;
return -1;
}
This->lastwhere = where + ret;
return ret;
}
-static int floppyd_read(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
-{
+static ssize_t floppyd_pread(Stream_t *Stream, char *buf,
+ mt_off_t where, size_t len)
+{
return floppyd_io(Stream, buf, where, len, floppyd_reader);
}
-static int floppyd_write(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
+static ssize_t floppyd_pwrite(Stream_t *Stream, char *buf,
+ mt_off_t where, size_t len)
{
return floppyd_io(Stream, buf, where, len, floppyd_writer);
}
@@ -374,8 +384,8 @@ static int floppyd_flush(Stream_t *Stream)
static int floppyd_free(Stream_t *Stream)
{
Byte buf[16];
- unsigned int gotlen;
- unsigned int errcode;
+ int gotlen;
+ int errcode;
DeclareThis(RemoteFile_t);
if (This->fd > 2) {
@@ -388,10 +398,10 @@ static int floppyd_free(Stream_t *Stream)
errno = EIO;
return -1;
}
-
- gotlen = read_dword(This->fd);
- errcode = read_dword(This->fd);
-
+
+ gotlen = read_sdword(This->fd);
+ errcode = read_sdword(This->fd);
+
errno = errcode;
close(This->fd);
@@ -401,38 +411,10 @@ static int floppyd_free(Stream_t *Stream)
}
}
-static int floppyd_geom(Stream_t *Stream, struct device *dev,
- struct device *orig_dev UNUSEDP,
- int media, union bootsector *boot)
-{
- size_t tot_sectors;
- unsigned int sect_per_track;
- DeclareThis(RemoteFile_t);
- dev->ssize = 2; /* allow for init_geom to change it */
- dev->use_2m = 0x80; /* disable 2m mode to begin */
- if(media == 0xf0 || media >= 0x100){
- dev->heads = WORD(nheads);
- dev->sectors = WORD(nsect);
- tot_sectors = DWORD(bigsect);
- SET_INT(tot_sectors, WORD(psect));
- sect_per_track = dev->heads * dev->sectors;
- tot_sectors += sect_per_track - 1; /* round size up */
- dev->tracks = tot_sectors / sect_per_track;
-
- } else
- if(setDeviceFromOldDos(media, dev) < 0)
- exit(1);
-
- This->size = (mt_off_t) 512 * dev->sectors * dev->tracks * dev->heads;
-
- return 0;
-}
-
-
-static int floppyd_data(Stream_t *Stream, time_t *date, mt_size_t *size,
- int *type, int *address)
+static int floppyd_data(Stream_t *Stream, time_t *date, mt_off_t *size,
+ int *type, uint32_t *address)
{
DeclareThis(RemoteFile_t);
@@ -441,7 +423,7 @@ static int floppyd_data(Stream_t *Stream, time_t *date, mt_size_t *size,
*date = 0;
if(size)
/* the size derived from the geometry */
- *size = (mt_size_t) This->size;
+ *size = This->size;
if(type)
*type = 0; /* not a directory */
if(address)
@@ -452,11 +434,13 @@ static int floppyd_data(Stream_t *Stream, time_t *date, mt_size_t *size,
/* ######################################################################## */
static Class_t FloppydFileClass = {
- floppyd_read,
- floppyd_write,
+ 0,
+ 0,
+ floppyd_pread,
+ floppyd_pwrite,
floppyd_flush,
floppyd_free,
- floppyd_geom,
+ set_geom_noop,
floppyd_data,
0, /* pre_allocate */
0, /* get_dosConvert */
@@ -478,8 +462,8 @@ static int get_host_and_port_and_drive(const char* name, char** hostname,
p2 = p;
if (*p) p++;
*p2 = 0;
-
- *port = FLOPPYD_DEFAULT_PORT;
+
+ *port = FLOPPYD_DEFAULT_PORT;
if(*p >= '0' && *p <= '9')
*port = strtou16(p, &p, 0);
if(*p == '/')
@@ -517,18 +501,18 @@ static in_addr_t getipaddress(char *ipaddr)
if (((ip = inet_addr(ipaddr)) == INADDR_NONE) &&
(strcmp(ipaddr, "255.255.255.255") != 0)) {
-
+
if ((host = gethostbyname(ipaddr)) != NULL) {
memcpy(&ip, host->h_addr, sizeof(ip));
}
-
+
endhostent();
}
-
+
#ifdef DEBUG
fprintf(stderr, "IP lookup %s -> 0x%08lx\n", ipaddr, ip);
#endif
-
+
return (ip);
}
@@ -537,25 +521,25 @@ static in_addr_t getipaddress(char *ipaddr)
* */
static int connect_to_server(in_addr_t ip, uint16_t port)
{
-
+
struct sockaddr_in addr;
int sock;
-
+
/*
* Allocate a socket.
*/
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
return (-1);
}
-
+
/*
* Set the address to connect to.
*/
-
+
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = ip;
-
+
/*
* Connect our socket to the above address.
*/
@@ -568,36 +552,34 @@ static int connect_to_server(in_addr_t ip, uint16_t port)
*/
{
int on = 1;
- setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
+ setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
(char *)&on, sizeof(on));
}
-
+
return (sock);
}
-static int ConnectToFloppyd(RemoteFile_t *floppyd, const char* name,
+static int ConnectToFloppyd(RemoteFile_t *floppyd, const char* name,
char *errmsg);
-Stream_t *FloppydOpen(struct device *dev,
- char *name, int mode, char *errmsg,
- mt_size_t *maxSize)
+Stream_t *FloppydOpen(struct device *dev,
+ const char *name, int mode, char *errmsg,
+ mt_off_t *maxSize)
{
RemoteFile_t *This;
if (!dev || !(dev->misc_flags & FLOPPYD_FLAG))
return NULL;
-
+
This = New(RemoteFile_t);
if (!This){
printOom();
return NULL;
}
- This->Class = &FloppydFileClass;
- This->Next = 0;
+ init_head(&This->head, &FloppydFileClass, NULL);
+
This->offset = 0;
This->lastwhere = 0;
- This->refs = 1;
- This->Buffer = 0;
This->fd = ConnectToFloppyd(This, name, errmsg);
if (This->fd == -1) {
@@ -614,31 +596,31 @@ Stream_t *FloppydOpen(struct device *dev,
}
if(maxSize) {
- *maxSize =
- (This->capabilities & FLOPPYD_CAP_LARGE_SEEK) ?
- max_off_t_seek : max_off_t_31;
+ *maxSize =
+ ((This->capabilities & FLOPPYD_CAP_LARGE_SEEK) ?
+ max_off_t_seek : max_off_t_31);
}
- return (Stream_t *) This;
+ return &This->head;
}
-static int ConnectToFloppyd(RemoteFile_t *floppyd, const char* name,
- char *errmsg)
+static int ConnectToFloppyd(RemoteFile_t *floppyd, const char* name,
+ char *errmsg)
{
char* hostname;
char* display;
uint16_t port;
- int rval = get_host_and_port_and_drive(name, &hostname, &display,
+ int rval = get_host_and_port_and_drive(name, &hostname, &display,
&port, &floppyd->drive);
int sock;
unsigned int reply;
-
+
if (!rval) return -1;
floppyd->version = FLOPPYD_PROTOCOL_VERSION;
floppyd->capabilities = 0;
while(1) {
sock = connect_to_server(getipaddress(hostname), port);
-
+
if (sock == -1) {
#ifdef HAVE_SNPRINTF
snprintf(errmsg, 200,
@@ -651,7 +633,7 @@ static int ConnectToFloppyd(RemoteFile_t *floppyd, const char* name,
#endif
return -1;
}
-
+
reply = authenticate_to_floppyd(floppyd, sock, display);
if(floppyd->version == FLOPPYD_PROTOCOL_VERSION_OLD)
break;
@@ -664,7 +646,7 @@ static int ConnectToFloppyd(RemoteFile_t *floppyd, const char* name,
}
if (reply != 0) {
- fprintf(stderr,
+ fprintf(stderr,
"Permission denied, authentication failed!\n"
"%s\n", AuthErrors[reply]);
return -1;
@@ -675,4 +657,3 @@ static int ConnectToFloppyd(RemoteFile_t *floppyd, const char* name,
return sock;
}
-#endif
diff --git a/floppyd_io.h b/floppyd_io.h
index 58f763f..da15506 100644
--- a/floppyd_io.h
+++ b/floppyd_io.h
@@ -30,16 +30,16 @@ typedef uint64_t Qword;
#define DWORD_ERR ((Dword) -1)
/*extern int ConnectToFloppyd(const char* name, Class_t** ioclass);*/
-Stream_t *FloppydOpen(struct device *dev,
- char *name, int mode, char *errmsg,
- mt_size_t *maxSize);
+Stream_t *FloppydOpen(struct device *dev,
+ const char *name, int mode, char *errmsg,
+ mt_off_t *maxSize);
#define FLOPPYD_DEFAULT_PORT 5703
#define FLOPPYD_PROTOCOL_VERSION_OLD 10
#define FLOPPYD_PROTOCOL_VERSION 11
-#define FLOPPYD_CAP_EXPLICIT_OPEN 1 /* explicit open. Useful for
+#define FLOPPYD_CAP_EXPLICIT_OPEN 1 /* explicit open. Useful for
* clean signalling of readonly disks */
#define FLOPPYD_CAP_LARGE_SEEK 2 /* large seeks */
@@ -69,13 +69,13 @@ enum AuthErrorsEnum {
UNUSED(static inline void cork(int sockhandle, int on))
{
#ifdef TCP_CORK
- if(setsockopt(sockhandle, IPPROTO_TCP,
+ if(setsockopt(sockhandle, IPPROTO_TCP,
TCP_CORK, (char *)&on, sizeof(on)) < 0) {
perror("setsockopt cork");
}
#else
on = 1 ^ on;
- if(setsockopt(sockhandle, IPPROTO_TCP,
+ if(setsockopt(sockhandle, IPPROTO_TCP,
TCP_NODELAY, (char *)&on, sizeof(on)) < 0) {
perror("setsockopt nodelay");
}
diff --git a/force_io.c b/force_io.c
index 006d315..7884c22 100644
--- a/force_io.c
+++ b/force_io.c
@@ -1,4 +1,4 @@
-/* Copyright 1996,1997,1999,2001,2002,2009 Alain Knaff.
+/* Copyright 1996,1997,1999,2001,2002,2009,2021 Alain Knaff.
* This file is part of mtools.
*
* Mtools is free software: you can redistribute it and/or modify
@@ -18,7 +18,7 @@
*
* written by:
*
- * Alain L. Knaff
+ * Alain L. Knaff
* alain@knaff.lu
*
*/
@@ -27,13 +27,13 @@
#include "msdos.h"
#include "stream.h"
-static int force_io(Stream_t *Stream,
- char *buf, mt_off_t start, size_t len,
- int (*io)(Stream_t *, char *, mt_off_t, size_t))
+static ssize_t force_pio(Stream_t *Stream,
+ char *buf, mt_off_t start, size_t len,
+ ssize_t (*io)(Stream_t *, char *, mt_off_t, size_t))
{
- int ret;
+ ssize_t ret;
int done=0;
-
+
while(len){
ret = io(Stream, buf, start, len);
if ( ret <= 0 ){
@@ -42,22 +42,34 @@ static int force_io(Stream_t *Stream,
else
return ret;
}
- start += ret;
+ assert((size_t)ret <= len);
+ start += (size_t) ret;
done += ret;
- len -= ret;
+ len -= (size_t) ret;
buf += ret;
}
return done;
}
-int force_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+static ssize_t write_wrapper(Stream_t *Stream, char *buf,
+ mt_off_t start UNUSEDP, size_t len)
+{
+ return Stream->Class->write(Stream, buf, len);
+}
+
+ssize_t force_write(Stream_t *Stream, char *buf, size_t len)
+{
+ return force_pio(Stream, buf, 0, len, write_wrapper);
+}
+
+ssize_t force_pwrite(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
{
- return force_io(Stream, buf, start, len,
- Stream->Class->write);
+ return force_pio(Stream, buf, start, len,
+ Stream->Class->pwrite);
}
-int force_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+ssize_t force_pread(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
{
- return force_io(Stream, buf, start, len,
- Stream->Class->read);
+ return force_pio(Stream, buf, start, len,
+ Stream->Class->pread);
}
diff --git a/fs.h b/fs.h
index 7708c06..f856be8 100644
--- a/fs.h
+++ b/fs.h
@@ -21,23 +21,16 @@
#include "stream.h"
-typedef struct FsPublic_t {
- Class_t *Class;
- int refs;
- Stream_t *Next;
- Stream_t *Buffer;
-
- int serialized;
- unsigned long serial_number;
- unsigned int cluster_size;
- unsigned int sector_size;
-} FsPublic_t;
-
Stream_t *fs_init(char drive, int mode, int *isRop);
int fat_free(Stream_t *Dir, unsigned int fat);
int fatFreeWithDir(Stream_t *Dir, struct directory *dir);
int fat_error(Stream_t *Dir);
-int fat32RootCluster(Stream_t *Dir);
+uint32_t fat32RootCluster(Stream_t *Dir);
char getDrive(Stream_t *Stream);
+typedef struct Fs_t Fs_t;
+bool getSerialized(Fs_t *File);
+unsigned long getSerialNumber(Fs_t *File);
+uint32_t getClusterBytes(Fs_t *File);
+
#endif
diff --git a/fsP.h b/fsP.h
index 3fb88e4..d8deaea 100644
--- a/fsP.h
+++ b/fsP.h
@@ -27,63 +27,66 @@ typedef enum fatAccessMode_t {
} fatAccessMode_t;
typedef struct Fs_t {
- Class_t *Class;
- int refs;
- Stream_t *Next;
- Stream_t *Buffer;
-
+ struct Stream_t head;
+
int serialized;
unsigned long serial_number;
- unsigned int cluster_size;
- unsigned int sector_size;
+ uint8_t cluster_size;
+ uint16_t sector_size;
+
int fat_error;
unsigned int (*fat_decode)(struct Fs_t *This, unsigned int num);
void (*fat_encode)(struct Fs_t *This, unsigned int num,
unsigned int code);
- Stream_t *Direct;
int fat_dirty;
- unsigned int fat_start;
- unsigned int fat_len;
-
- unsigned int num_fat;
- unsigned int end_fat;
- unsigned int last_fat;
- int fat_bits; /* must be signed, because we use negative values
- * for special purposes */
+ uint16_t fat_start;
+ uint32_t fat_len;
+
+ uint8_t num_fat;
+ uint32_t end_fat;
+ uint32_t last_fat;
+ unsigned int fat_bits; /* When it ends up here, all negative
+ special values have been
+ eliminated */
+
struct FatMap_t *FatMap;
- unsigned int dir_start;
- unsigned int dir_len;
- unsigned int clus_start;
+ uint32_t dir_start;
+ uint16_t dir_len;
+ uint32_t clus_start;
- unsigned int num_clus;
+ uint32_t num_clus;
char drive; /* for error messages */
/* fat 32 */
- unsigned int primaryFat;
- unsigned int writeAllFats;
- unsigned int rootCluster;
- unsigned int infoSectorLoc;
- unsigned int last; /* last sector allocated, or MAX32 if unknown */
- unsigned int freeSpace; /* free space, or MAX32 if unknown */
- int preallocatedClusters;
-
- int lastFatSectorNr;
+ uint32_t primaryFat;
+ uint32_t writeAllFats;
+ uint32_t rootCluster;
+ uint32_t infoSectorLoc;
+ uint16_t backupBoot;
+ uint32_t last; /* last sector allocated, or MAX32 if unknown */
+ uint32_t freeSpace; /* free space, or MAX32 if unknown */
+ unsigned int preallocatedClusters;
+
+ uint32_t lastFatSectorNr;
unsigned char *lastFatSectorData;
fatAccessMode_t lastFatAccessMode;
- int sectorMask;
- int sectorShift;
+ unsigned int sectorMask;
+ unsigned int sectorShift;
doscp_t *cp;
} Fs_t;
+#ifndef abs
+#define abs(x) ((unsigned int)((x)>0?(x):-(x)))
+#endif
+
+mt_off_t sectorsToBytes(Fs_t *This, uint32_t off);
int fs_free(Stream_t *Stream);
-void set_fat12(Fs_t *Fs);
-void set_fat16(Fs_t *Fs);
-void set_fat32(Fs_t *Fs);
+void set_fat(Fs_t *This);
unsigned int get_next_free_cluster(Fs_t *Fs, unsigned int last);
unsigned int fatDecode(Fs_t *This, unsigned int pos);
void fatAppend(Fs_t *This, unsigned int pos, unsigned int newpos);
@@ -91,13 +94,26 @@ void fatDeallocate(Fs_t *This, unsigned int pos);
void fatAllocate(Fs_t *This, unsigned int pos, unsigned int value);
void fatEncode(Fs_t *This, unsigned int pos, unsigned int value);
-int fat_read(Fs_t *This, union bootsector *boot,
- size_t tot_sectors, int nodups);
+int fat_read(Fs_t *This, union bootsector *boot, int nodups);
void fat_write(Fs_t *This);
-int zero_fat(Fs_t *Fs, int media_descriptor);
+int zero_fat(Fs_t *Fs, uint8_t media_descriptor);
extern Class_t FsClass;
-int fsPreallocateClusters(Fs_t *Fs, long);
+int fsPreallocateClusters(Fs_t *Fs, uint32_t);
+void fsReleasePreallocateClusters(Fs_t *Fs, uint32_t);
Fs_t *getFs(Stream_t *Stream);
+int calc_fs_parameters(struct device *dev, bool fat32, uint32_t tot_sectors,
+ struct Fs_t *Fs, uint8_t *descr);
+
+/* Fs_t *makeFsForFormat(void); */
+void initFsForFormat(Fs_t *Fs);
+void setFsSectorSize(Fs_t *Fs, struct device *dev, uint16_t msize);
+
+uint32_t parseFsParams( Fs_t *This,
+ union bootsector *boot,
+ int media,
+ unsigned int cylinder_size);
+uint32_t calc_clus_start(Fs_t *Fs);
+int calc_num_clus(Fs_t *Fs, uint32_t tot_sectors);
#endif
diff --git a/hash.c b/hash.c
index 3f526aa..4e865cd 100644
--- a/hash.c
+++ b/hash.c
@@ -67,7 +67,7 @@ static int alloc_ht(T_HashTable *H, size_t size)
H->entries = NewArray(size, T_HashTableEl);
if (H->entries == NULL)
return -1; /* out of memory error */
-
+
for(ii=0; ii < size; ii++)
H->entries[ii] = &unallocated;
return 0;
@@ -80,7 +80,7 @@ int make_ht(T_HashFunc f1, T_HashFunc f2, T_ComparFunc c, size_t size,
if (*H == NULL){
return -1; /* out of memory error */
}
-
+
(*H)->f1 = f1;
(*H)->f2 = f2;
(*H)->compar = c;
@@ -134,7 +134,7 @@ static int rehash(T_HashTable *H)
size_t size,i;
T_HashTableEl *oldentries;
/* resize the table */
-
+
size = H->size;
oldentries = H->entries;
if(alloc_ht(H,((H->inuse+1)*4+H->fill)/5))
@@ -205,8 +205,7 @@ int hash_remove(T_HashTable *H,T_HashTableEl *E, size_t hint)
{
T_HashTableEl *E2;
- if (hint >=0 && hint < H->size &&
- H->entries[hint] == E){
+ if (hint < H->size && H->entries[hint] == E){
H->inuse--;
H->entries[hint] = &deleted;
return 0;
diff --git a/htable.h b/htable.h
index 0754e14..e14419a 100644
--- a/htable.h
+++ b/htable.h
@@ -19,7 +19,7 @@
typedef struct hashtable T_HashTable;
typedef void *T_HashTableEl;
-typedef size_t (*T_HashFunc)(void *);
+typedef uint32_t (*T_HashFunc)(void *);
typedef int (*T_ComparFunc)(void *, void *);
diff --git a/init.c b/init.c
index 62574f9..4b9b7e5 100644
--- a/init.c
+++ b/init.c
@@ -24,19 +24,24 @@
#include "msdos.h"
#include "stream.h"
#include "mtools.h"
+#include "device.h"
+#include "old_dos.h"
#include "fsP.h"
-#include "plain_io.h"
-#include "floppyd_io.h"
-#include "xdf_io.h"
#include "buffer.h"
#include "file_name.h"
+#include "open_image.h"
#define FULL_CYL
+mt_off_t sectorsToBytes(Fs_t *This, uint32_t off)
+{
+ return (mt_off_t) off << This->sectorShift;
+}
+
/*
* Read the boot sector. We glean the disk parameters from this sector.
*/
-static int read_boot(Stream_t *Stream, union bootsector * boot, int size)
+static int read_boot(Stream_t *Stream, union bootsector * boot, size_t size)
{
size_t boot_sector_size; /* sector size, as stored in boot sector */
@@ -46,10 +51,10 @@ static int read_boot(Stream_t *Stream, union bootsector * boot, int size)
if(size > MAX_BOOT)
size = MAX_BOOT;
- if (force_read(Stream, boot->characters, 0, size) != size)
+ if (force_pread(Stream, boot->characters, 0, size) != (ssize_t) size)
return -1;
- boot_sector_size = WORD(secsiz);
+ boot_sector_size = WORD(secsiz);
if(boot_sector_size < sizeof(boot->bytes)) {
/* zero rest of in-memory boot sector */
memset(boot->bytes+boot_sector_size, 0,
@@ -74,8 +79,10 @@ static doscp_t *get_dosConvert(Stream_t *Stream)
}
Class_t FsClass = {
- read_pass_through, /* read */
- write_pass_through, /* write */
+ 0,
+ 0,
+ pread_pass_through, /* read */
+ pwrite_pass_through, /* write */
fs_flush,
fs_free, /* free */
0, /* set geometry */
@@ -99,7 +106,7 @@ static int get_media_type(Stream_t *St, union bootsector *boot)
char temp[512];
/* old DOS disk. Media descriptor in the first FAT byte */
/* we assume 512-byte sectors here */
- if (force_read(St,temp,(mt_off_t) 512,512) == 512)
+ if (force_pread(St,temp,512,512) == 512)
media = (unsigned char) temp[0];
else
media = 0;
@@ -116,11 +123,80 @@ Stream_t *GetFs(Stream_t *Fs)
return Fs;
}
+static void boot_to_geom(struct device *dev, int media,
+ union bootsector *boot) {
+ uint32_t tot_sectors;
+ int BootP, Infp0, InfpX, InfTm;
+ int j;
+ unsigned char sum;
+ uint16_t sect_per_track;
+ struct label_blk_t *labelBlock;
+
+ dev->ssize = 2; /* allow for init_geom to change it */
+ dev->use_2m = 0x80; /* disable 2m mode to begin */
+
+ if(media == 0xf0 || media >= 0x100){
+ dev->heads = WORD(nheads);
+ dev->sectors = WORD(nsect);
+ tot_sectors = DWORD(bigsect);
+ SET_INT(tot_sectors, WORD(psect));
+ sect_per_track = dev->heads * dev->sectors;
+ if(sect_per_track == 0) {
+ if(mtools_skip_check) {
+ /* add some fake values if sect_per_track is
+ * zero. Indeed, some atari disks lack the
+ * geometry values (i.e. have zeroes in their
+ * place). In order to avoid division by zero
+ * errors later on, plug 1 everywhere
+ */
+ dev->heads = 1;
+ dev->sectors = 1;
+ sect_per_track = 1;
+ } else {
+ fprintf(stderr, "The devil is in the details: zero number of heads or sectors\n");
+ exit(1);
+ }
+ }
+ dev->tracks = tot_sectors / sect_per_track;
+ if(tot_sectors % sect_per_track)
+ /* round size up */
+ dev->tracks++;
+
+ BootP = WORD(ext.old.BootP);
+ Infp0 = WORD(ext.old.Infp0);
+ InfpX = WORD(ext.old.InfpX);
+ InfTm = WORD(ext.old.InfTm);
+
+ if(WORD(fatlen)) {
+ labelBlock = &boot->boot.ext.old.labelBlock;
+ } else {
+ labelBlock = &boot->boot.ext.fat32.labelBlock;
+ }
+
+ if (boot->boot.descr >= 0xf0 &&
+ has_BPB4 &&
+ strncmp( boot->boot.banner,"2M", 2 ) == 0 &&
+ BootP < 512 && Infp0 < 512 && InfpX < 512 && InfTm < 512 &&
+ BootP >= InfTm + 2 && InfTm >= InfpX && InfpX >= Infp0 &&
+ Infp0 >= 76 ){
+ for (sum=0, j=63; j < BootP; j++)
+ sum += boot->bytes[j];/* checksum */
+ dev->ssize = boot->bytes[InfTm];
+ if (!sum && dev->ssize <= 7){
+ dev->use_2m = 0xff;
+ dev->ssize |= 0x80; /* is set */
+ }
+ }
+ dev->sector_size = WORD(secsiz);
+ } else
+ if(setDeviceFromOldDos(media, dev) < 0)
+ exit(1);
+}
+
/**
- * Tries out all device definitions for the given drive number, until one
- * is found that is able to read from the device
+ * Tries out one device definition for the given drive number
* Parameters
- * - drive: drive letter to check
+ * - dev: device definition to try
* - mode: file open mode
* - out_dev: device parameters (geometry, etc.) are returned here
* - boot: boot sector is read from the disk into this structure
@@ -128,171 +204,218 @@ Stream_t *GetFs(Stream_t *Fs)
* - media: media byte is returned here (ored with 0x100 if there is a
* BIOS Parameter block present)
* - maxSize: maximal size supported by (physical) drive returned here
+ * - try_writable: whether to try opening it writable from the get-go,
+ * even if not specified as writable in mode (used for mlabel)
* - isRop: whether device is read-only is returned here
* Return value:
* - a Stream allowing to read from this device, must be closed by caller
+ *
+ * If a geometry change is needed, drive is re-opened RW, as geometry
+ * change ioctl needs write access. However, in such case, the lock
+ * acquired is still only a read lock.
*/
-Stream_t *find_device(char drive, int mode, struct device *out_dev,
- union bootsector *boot,
- char *name, int *media, mt_size_t *maxSize,
- int *isRop)
+static Stream_t *try_device(struct device *dev,
+ int mode, struct device *out_dev,
+ union bootsector *boot,
+ char *name, int *media, mt_off_t *maxSize,
+ int *isRop, int try_writable,
+ char *errmsg)
{
- char errmsg[200];
- Stream_t *Stream;
- struct device *dev;
- int r;
- int isRo=0;
-
- Stream = NULL;
- sprintf(errmsg, "Drive '%c:' not supported", drive);
- /* open the device */
- for (dev=devices; dev->name; dev++) {
- FREE(&Stream);
- if (dev->drive != drive)
- continue;
- *out_dev = *dev;
- expand(dev->name,name);
+ int retry_write;
+ int have_read_bootsector=0;
+ int modeFlags = mode & ~O_ACCMODE;
+ int openMode;
+ int lockMode;
+
+ *out_dev = *dev;
+ expand(dev->name,name);
#ifdef USING_NEW_VOLD
- strcpy(name, getVoldName(dev, name));
-#endif
-
- Stream = 0;
- if(out_dev->misc_flags & FLOPPYD_FLAG) {
- Stream = 0;
-#ifdef USE_FLOPPYD
- Stream = FloppydOpen(out_dev, name, mode,
- errmsg, maxSize);
-#endif
- } else {
-
-#ifdef USE_XDF
- Stream = XdfOpen(out_dev, name, mode, errmsg, 0);
- if(Stream) {
- out_dev->use_2m = 0x7f;
- if(maxSize)
- *maxSize = max_off_t_31;
- }
+ strcpy(name, getVoldName(dev, name));
#endif
-
- if (!Stream)
- Stream = SimpleFileOpen(out_dev, dev, name,
- isRop ? mode | O_RDWR: mode,
- errmsg, 0, 1, maxSize);
-
- if(Stream) {
- isRo=0;
- } else if(isRop &&
- (errno == EPERM || errno == EACCES || errno == EROFS)) {
- Stream = SimpleFileOpen(out_dev, dev, name,
- mode | O_RDONLY,
- errmsg, 0, 1, maxSize);
- if(Stream) {
- isRo=1;
+ if(try_writable) {
+ /* Caller asks up to try first read-write, and only fall back
+ * if not feasible */
+ openMode = O_RDWR | modeFlags;
+ } else {
+ openMode = mode;
+ }
+ lockMode = openMode;
+
+ for(retry_write=0; retry_write<2; retry_write++) {
+ Stream_t *Stream;
+ int r;
+ int geomFailure=0;
+
+ if(retry_write)
+ mode |= O_RDWR;
+
+ Stream = OpenImage(out_dev, dev, name, openMode, errmsg,
+ 0, lockMode,
+ maxSize, &geomFailure, NULL);
+ if(Stream == NULL) {
+ if(geomFailure && (mode & O_ACCMODE) == O_RDONLY) {
+ /* Our first attempt was to open read-only,
+ but this resulted in failure setting the
+ geometry */
+ openMode = modeFlags | O_RDWR;
+ continue;
}
- }
- }
- if( !Stream)
- continue;
-
- /* read the boot sector */
- if ((r=read_boot(Stream, boot, out_dev->blocksize)) < 0){
- sprintf(errmsg,
- "init %c: could not read boot sector",
- drive);
- continue;
+ if(try_writable &&
+ (errno == EPERM ||
+ errno == EACCES ||
+ errno == EROFS)) {
+ /* Our first attempt was to open
+ * read-write, but this resulted in a
+ * read-protection problem */
+ lockMode = openMode = modeFlags | O_RDONLY;
+ continue;
+ }
+ return NULL;
}
-
- if((*media= get_media_type(Stream, boot)) <= 0xf0 ){
- if (boot->boot.jump[2]=='L')
+ if(!have_read_bootsector) {
+ /* read the boot sector */
+ if ((r=read_boot(Stream, boot, out_dev->blocksize)) < 0){
sprintf(errmsg,
- "diskette %c: is Linux LILO, not DOS",
- drive);
- else
- sprintf(errmsg,"init %c: non DOS media", drive);
- continue;
+ "init %c: could not read boot sector",
+ dev->drive);
+ FREE(&Stream);
+ return NULL;
+ }
+
+ if((*media= get_media_type(Stream, boot)) <= 0xf0 ){
+ if (boot->boot.jump[2]=='L')
+ sprintf(errmsg,
+ "diskette %c: is Linux LILO, not DOS",
+ dev->drive);
+ else
+ sprintf(errmsg,"init %c: non DOS media", dev->drive);
+ FREE(&Stream);
+ return NULL;
+ }
+ have_read_bootsector=1;
}
/* set new parameters, if needed */
errno = 0;
- if(SET_GEOM(Stream, out_dev, dev, *media, boot)){
+ boot_to_geom(out_dev, *media, boot);
+ if(SET_GEOM(Stream, out_dev, dev)){
+ if(errno == EBADF || errno == EPERM) {
+ /* Retry with write */
+ FREE(&Stream);
+ openMode = modeFlags | O_RDWR;
+ continue;
+ }
if(errno)
#ifdef HAVE_SNPRINTF
snprintf(errmsg, 199,
- "Can't set disk parameters for %c: %s",
- drive, strerror(errno));
+ "Can't set disk parameters for %c: %s",
+ dev->drive, strerror(errno));
#else
- sprintf(errmsg,
- "Can't set disk parameters for %c: %s",
- drive, strerror(errno));
+ sprintf(errmsg,
+ "Can't set disk parameters for %c: %s",
+ drive, strerror(errno));
#endif
else
sprintf(errmsg,
"Can't set disk parameters for %c",
- drive);
- continue;
+ dev->drive);
+ FREE(&Stream);
+ return NULL;
+ }
+ if(isRop) {
+ *isRop = (openMode & O_ACCMODE) == O_RDONLY;
}
- break;
+ return Stream;
}
+ return NULL;
+}
- /* print error msg if needed */
- if ( dev->drive == 0 ){
- FREE(&Stream);
- fprintf(stderr,"%s\n",errmsg);
- return NULL;
- }
- if(isRop)
- *isRop = isRo;
- return Stream;
+uint32_t calc_clus_start(Fs_t *Fs) {
+ return Fs->fat_start + Fs->fat_len*Fs->num_fat + Fs->dir_len;
}
+/* Calculates number of clusters, and fills it in into Fs->num_clus
+ * Returns 0 if calculation could be performed, and -1 if less sectors than
+ * clus_start
+ */
+int calc_num_clus(Fs_t *Fs, uint32_t tot_sectors)
+{
+ Fs->clus_start = calc_clus_start(Fs);
+ if(tot_sectors <= Fs->clus_start)
+ return -1;
+ Fs->num_clus = (tot_sectors - Fs->clus_start) / Fs->cluster_size;
+ return 0;
+}
-Stream_t *fs_init(char drive, int mode, int *isRop)
+/**
+ * Tries out all device definitions for the given drive letter, until one
+ * is found that is able to read from the device
+ * Parameters
+ * - drive: drive letter to check
+ * - mode: file open mode
+ * - out_dev: device parameters (geometry, etc.) are returned here
+ * - boot: boot sector is read from the disk into this structure
+ * - name: "name" of device definition (returned)
+ * - media: media byte is returned here (ored with 0x100 if there is a
+ * BIOS Parameter block present)
+ * - maxSize: maximal size supported by (physical) drive returned here
+ * - isRop: whether device is read-only is returned here
+ * Return value:
+ * - a Stream allowing to read from this device, must be closed by caller
+ */
+Stream_t *find_device(char drive, int mode, struct device *out_dev,
+ union bootsector *boot,
+ char *name, int *media, mt_off_t *maxSize,
+ int *isRop)
{
- int blocksize;
- int media;
- int disk_size = 0; /* In case we don't happen to set this below */
- size_t tot_sectors;
- char name[EXPAND_BUF];
- int cylinder_size;
- struct device dev;
- mt_size_t maxSize;
+ char errmsg[200];
+ struct device *dev;
- union bootsector boot;
+ sprintf(errmsg, "Drive '%c:' not supported", drive);
+ /* open the device */
+ for (dev=devices; dev->name; dev++) {
+ Stream_t *Stream;
+ int isRo;
+ isRo=0;
+ if (dev->drive != drive)
+ continue;
- Fs_t *This;
+ Stream = try_device(dev, mode, out_dev,
+ boot,
+ name, media, maxSize,
+ &isRo, isRop != NULL,
+ errmsg);
+ if(Stream) {
+ if(isRop)
+ *isRop = isRo;
+ return Stream;
+ }
+ }
- This = New(Fs_t);
- if (!This)
- return NULL;
+ /* print error msg if needed */
+ fprintf(stderr,"%s\n",errmsg);
+ return NULL;
+}
- This->Direct = NULL;
- This->Next = NULL;
- This->refs = 1;
- This->Buffer = 0;
- This->Class = &FsClass;
- This->preallocatedClusters = 0;
- This->lastFatSectorNr = 0;
- This->lastFatAccessMode = 0;
- This->lastFatSectorData = 0;
- This->drive = drive;
- This->last = 0;
- This->Direct = find_device(drive, mode, &dev, &boot, name, &media,
- &maxSize, isRop);
- if(!This->Direct)
- return NULL;
+uint32_t parseFsParams( Fs_t *This,
+ union bootsector *boot,
+ int media,
+ unsigned int cylinder_size)
+{
+ uint32_t tot_sectors;
- cylinder_size = dev.heads * dev.sectors;
- This->serialized = 0;
if ((media & ~7) == 0xf8){
/* This bit of code is only entered if there is no BPB, or
* else result of the AND would be 0x1xx
*/
struct OldDos_t *params=getOldDosByMedia(media);
- if(params == NULL)
- return NULL;
+ if(params == NULL) {
+ fprintf(stderr, "Unknown media byte %02x\n", media);
+ return 0;
+ }
This->cluster_size = params->cluster_size;
tot_sectors = cylinder_size * params->tracks;
This->fat_start = 1;
@@ -302,24 +425,23 @@ Stream_t *fs_init(char drive, int mode, int *isRop)
This->sector_size = 512;
This->sectorShift = 9;
This->sectorMask = 511;
- This->fat_bits = 12;
} else {
struct label_blk_t *labelBlock;
- int i;
-
- This->sector_size = WORD_S(secsiz);
+ unsigned int i;
+
+ This->sector_size = WORD(secsiz);
if(This->sector_size > MAX_SECTOR){
- fprintf(stderr,"init %c: sector size too big\n", drive);
- return NULL;
+ fprintf(stderr,"init: sector size too big\n");
+ return 0;
}
i = log_2(This->sector_size);
if(i == 24) {
fprintf(stderr,
- "init %c: sector size (%d) not a small power of two\n",
- drive, This->sector_size);
- return NULL;
+ "init: sector size (%d) not a small power of two\n",
+ This->sector_size);
+ return 0;
}
This->sectorShift = i;
This->sectorMask = This->sector_size - 1;
@@ -328,20 +450,22 @@ Stream_t *fs_init(char drive, int mode, int *isRop)
* all numbers are in sectors, except num_clus
* (which is in clusters)
*/
- tot_sectors = WORD_S(psect);
+ tot_sectors = WORD(psect);
if(!tot_sectors)
- tot_sectors = DWORD_S(bigsect);
+ tot_sectors = DWORD(bigsect);
- This->cluster_size = boot.boot.clsiz;
- This->fat_start = WORD_S(nrsvsect);
- This->fat_len = WORD_S(fatlen);
- This->dir_len = WORD_S(dirents) * MDIR_SIZE / This->sector_size;
- This->num_fat = boot.boot.nfat;
+ This->cluster_size = boot->boot.clsiz;
+ This->fat_start = WORD(nrsvsect);
+ This->fat_len = WORD(fatlen);
+ This->dir_len = WORD(dirents) * MDIR_SIZE / This->sector_size;
+ This->num_fat = boot->boot.nfat;
if (This->fat_len) {
- labelBlock = &boot.boot.ext.old.labelBlock;
+ labelBlock = &boot->boot.ext.old.labelBlock;
} else {
- labelBlock = &boot.boot.ext.fat32.labelBlock;
+ labelBlock = &boot->boot.ext.fat32.labelBlock;
+ This->fat_len = DWORD(ext.fat32.bigFat);
+ This->backupBoot = WORD(ext.fat32.backupBoot);
}
if(has_BPB4) {
@@ -350,9 +474,61 @@ Stream_t *fs_init(char drive, int mode, int *isRop)
}
}
- if (tot_sectors >= (maxSize >> This->sectorShift)) {
- fprintf(stderr, "Big disks not supported on this architecture\n");
- exit(1);
+ if(calc_num_clus(This, tot_sectors) < 0)
+ /* Too few sectors */
+ return 0;
+ set_fat(This);
+
+ return tot_sectors;
+}
+
+
+Stream_t *fs_init(char drive, int mode, int *isRop)
+{
+ uint32_t blocksize;
+ int media;
+ size_t disk_size = 0; /* In case we don't happen to set this below */
+ uint32_t tot_sectors;
+ char name[EXPAND_BUF];
+ unsigned int cylinder_size;
+ struct device dev;
+ mt_off_t maxSize;
+ char errmsg[81];
+
+ union bootsector boot;
+
+ Fs_t *This;
+
+ This = New(Fs_t);
+ if (!This)
+ return NULL;
+
+ init_head(&This->head, &FsClass, NULL);
+ This->preallocatedClusters = 0;
+ This->lastFatSectorNr = 0;
+ This->lastFatAccessMode = 0;
+ This->lastFatSectorData = 0;
+ This->drive = drive;
+ This->last = 0;
+
+ This->head.Next = find_device(drive, mode, &dev, &boot, name, &media,
+ &maxSize, isRop);
+ if(!This->head.Next)
+ return NULL;
+
+ cylinder_size = dev.heads * dev.sectors;
+ This->serialized = 0;
+
+ tot_sectors = parseFsParams(This, &boot, media, cylinder_size);
+ if(tot_sectors == 0) {
+ /* Error raised by parseFsParams */
+ return NULL;
+ }
+
+ if (check_if_sectors_fit(tot_sectors, maxSize,
+ This->sector_size, errmsg) < 0) {
+ fprintf(stderr, "%s", errmsg);
+ return NULL;
}
/* full cylinder buffering */
@@ -387,33 +563,34 @@ Stream_t *fs_init(char drive, int mode, int *isRop)
blocksize = This->sector_size;
else
blocksize = dev.blocksize;
- if (disk_size)
- This->Next = buf_init(This->Direct,
- 8 * disk_size * blocksize,
- disk_size * blocksize,
- This->sector_size);
- else
- This->Next = This->Direct;
-
- if (This->Next == NULL) {
- perror("init: allocate buffer");
- This->Next = This->Direct;
+ if (disk_size) {
+ Stream_t *Buffer = buf_init(This->head.Next,
+ 8 * disk_size * blocksize,
+ disk_size * blocksize,
+ This->sector_size);
+
+ if (Buffer != NULL)
+ This->head.Next = Buffer;
+ else
+ perror("init: allocate buffer");
}
/* read the FAT sectors */
- if(fat_read(This, &boot, tot_sectors, dev.use_2m&0x7f)){
+ if(fat_read(This, &boot, dev.use_2m&0x7f)){
+ fprintf(stderr, "Error reading FAT\n");
This->num_fat = 1;
- FREE(&This->Next);
- Free(This->Next);
+ FREE(&This->head.Next);
+ Free(This->head.Next);
return NULL;
}
/* Set the codepage */
This->cp = cp_open(dev.codepage);
if(This->cp == NULL) {
+ fprintf(stderr, "Error setting code page\n");
fs_free((Stream_t *)This);
- FREE(&This->Next);
- Free(This->Next);
+ FREE(&This->head.Next);
+ Free(This->head.Next);
return NULL;
}
@@ -424,13 +601,21 @@ char getDrive(Stream_t *Stream)
{
DeclareThis(Fs_t);
- if(This->Class != &FsClass)
+ if(This->head.Class != &FsClass)
return getDrive(GetFs(Stream));
else
return This->drive;
}
-int fsPreallocateClusters(Fs_t *Fs, long size)
+/*
+ * Upper layer asks to pre-allocated more additional clusters
+ * Parameters:
+ * size: new additional clusters to pre-allocate
+ * Return:
+ * 0 if pre-allocation was granted
+ * -1 if not enough clusters could be found
+ */
+int fsPreallocateClusters(Fs_t *Fs, uint32_t size)
{
if(size > 0 && getfreeMinClusters((Stream_t *)Fs, size) != 1)
return -1;
@@ -438,3 +623,16 @@ int fsPreallocateClusters(Fs_t *Fs, long size)
Fs->preallocatedClusters += size;
return 0;
}
+
+/*
+ * Upper layer wants to release some clusters that it had
+ * pre-allocated before Usually done because they have now been really
+ * allocated, and thus pre-allocation needs to be released to prevent
+ * counting them twice.
+ * Parameters:
+ * size: new additional clusters to pre-allocate
+ */
+void fsReleasePreallocateClusters(Fs_t *Fs, uint32_t size)
+{
+ Fs->preallocatedClusters -= size;
+}
diff --git a/lba.c b/lba.c
new file mode 100644
index 0000000..37693bd
--- /dev/null
+++ b/lba.c
@@ -0,0 +1,94 @@
+/* Copyright 2021 Alain Knaff.
+ * This file is part of mtools.
+ *
+ * Mtools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * "LBA Assist" geometry
+ */
+
+#include "sysincludes.h"
+#include "mtools.h"
+#include "lba.h"
+
+int compute_lba_geom_from_tot_sectors(struct device *dev)
+{
+ unsigned int sect_per_track;
+ uint32_t tracks;
+
+ /* If already fully specified, nothing to do */
+ if(dev->heads && dev->sectors && dev->tracks)
+ return 0;
+
+ /* If tot_sectors missing, return. Hopefully size still
+ * specified somewhere that will be read at a later stage
+ * (such as mformat command line) */
+ if(dev->tot_sectors == 0) {
+ return 0;
+ }
+
+ /* Floppy sizes, allowing for non-standard sizes with slightly
+ more sectors per track than the default */
+ if(dev->tot_sectors &&
+ dev->tot_sectors <= 8640 && dev->tot_sectors % 40 == 0) {
+ if(dev->tot_sectors <= 540) {
+ /* double density 48tpi single sided */
+ dev->tracks = 40;
+ dev->heads = 1;
+ } else if(dev->tot_sectors <= 1080) {
+ /* double density 48tpi double sided or
+ 96 tpi single sided */
+
+ if(dev->heads == 1)
+ dev->tracks = 80;
+ else {
+ dev->tracks = 40;
+ dev->heads = 2;
+ }
+ } else {
+ /* double density 96tpi double sided,
+ * high density, extra density */
+ dev->tracks = 80;
+ dev->heads = 2;
+ }
+ dev->sectors =
+ (uint16_t)(dev->tot_sectors / dev->heads / dev->tracks);
+ }
+
+
+ /* Heads or sectors not known => fill them in both... */
+ if(!dev->sectors || !dev->heads) {
+ dev->sectors = 63;
+
+ if (dev->tot_sectors < 16u*dev->sectors*1024)
+ dev->heads = 16;
+ else if (dev->tot_sectors < 32u*dev->sectors*1024)
+ dev->heads = 32;
+ else if (dev->tot_sectors < 64u*dev->sectors*1024)
+ dev->heads = 64;
+ else if (dev->tot_sectors < 128u*dev->sectors*1024)
+ dev->heads = 128;
+ else
+ dev->heads = 255;
+ }
+
+ /* ... and calculate corresponding tracks */
+ if(!dev->tracks) {
+ sect_per_track = dev->heads * dev->sectors;
+ tracks = (dev->tot_sectors + sect_per_track - 1) /
+ sect_per_track;
+ dev->tracks = tracks;
+ }
+
+ return 0;
+}
diff --git a/lba.h b/lba.h
new file mode 100644
index 0000000..47a2af5
--- /dev/null
+++ b/lba.h
@@ -0,0 +1 @@
+int compute_lba_geom_from_tot_sectors(struct device *dev);
diff --git a/llong.c b/llong.c
index 95383f7..2369b68 100644
--- a/llong.c
+++ b/llong.c
@@ -17,7 +17,6 @@
#include "sysincludes.h"
#include "stream.h"
-#include "fsP.h"
#include "llong.h"
#include "mtools.h"
@@ -36,20 +35,46 @@ int fileTooBig(mt_off_t off) {
return (off & ~max_off_t_32) != 0;
}
+/* truncMtOffToOff */
off_t truncBytes32(mt_off_t off)
{
+ if (fileTooBig(off)) {
+ fprintf(stderr, "Internal error, offset too big\n");
+ exit(1);
+ }
+ return (off_t) off;
+}
+
+uint32_t truncMtOffTo32u(mt_off_t off)
+{
if (fileTooBig(off)) {
fprintf(stderr, "Internal error, offset too big\n");
exit(1);
}
- return (off_t) off;
+ return (uint32_t) off;
+}
+
+uint32_t truncSizeTo32u(size_t siz)
+{
+ if (siz > UINT32_MAX) {
+ fprintf(stderr, "Internal error, size too big\n");
+ exit(1);
+ }
+ return (uint32_t) siz;
}
-mt_off_t sectorsToBytes(Stream_t *Stream, off_t off)
+#if SIZEOF_MT_OFF_T == 4
+mt_off_t to_mt_off_t(uint32_t off)
{
- DeclareThis(Fs_t);
- return (mt_off_t) off << This->sectorShift;
+ if(off > UINT32_MAX >> 1) {
+ fprintf(stderr, "File size/pos %d too big for this platform\n",
+ off);
+ exit(1);
+ }
+ return (mt_off_t) off;
}
+#endif
+
#if defined HAVE_LLSEEK
# ifndef HAVE_LLSEEK_PROTOTYPE
@@ -63,7 +88,6 @@ extern long long lseek64 (int fd, long long offset, int origin);
# endif
#endif
-
int mt_lseek(int fd, mt_off_t where, int whence)
{
#if defined HAVE_LSEEK64
@@ -75,7 +99,7 @@ int mt_lseek(int fd, mt_off_t where, int whence)
if(llseek(fd, where, whence) >= 0)
return 0;
else
- return -1;
+ return -1;
#else
if (lseek(fd, (off_t) where, whence) >= 0)
return 0;
@@ -84,12 +108,12 @@ int mt_lseek(int fd, mt_off_t where, int whence)
#endif
}
-unsigned int log_2(int size)
+unsigned int log_2(unsigned int size)
{
unsigned int i;
for(i=0; i<24; i++) {
- if(1 << i == size)
+ if(1u << i == size)
return i;
}
return 24;
diff --git a/llong.h b/llong.h
index 8c01918..c4c3d4d 100644
--- a/llong.h
+++ b/llong.h
@@ -1,7 +1,7 @@
#ifndef MTOOLS_LLONG_H
#define MTOOLS_LLONG_H
-/* Copyright 1999,2001-2004,2007-2009 Alain Knaff.
+/* Copyright 1999,2001-2004,2007-2009,2021 Alain Knaff.
* This file is part of mtools.
*
* Mtools is free software: you can redistribute it and/or modify
@@ -21,30 +21,32 @@
#if 1
-#ifdef HAVE_OFF_T_64
+#if SIZEOF_OFF_T >= 8
/* if off_t is already 64 bits, be happy, and don't worry about the
* loff_t and llseek stuff */
# define MT_OFF_T off_t
-# if SIZEOF_SIZE_T == 4
-/* Some systems (NetBSD) apparently have 64 bit off_t, but 32 bit size_t ... */
-# define MT_SIZE_T off_t
-# else
-# define MT_SIZE_T size_t
+# define SIZEOF_MT_OFF_T SIZEOF_OFF_T
+#endif
+
+#ifndef MT_OFF_T
+# if defined(HAVE_LSEEK64) && defined (HAVE_OFF64_T)
+# define MT_OFF_T off64_t
+# define SIZEOF_MT_OFF_T 8
# endif
#endif
+
#ifndef MT_OFF_T
# if defined(HAVE_LLSEEK) || defined(HAVE_LSEEK64)
/* we have llseek. Now, what's its type called? loff_t or offset_t ? */
# ifdef HAVE_LOFF_T
# define MT_OFF_T loff_t
+# define SIZEOF_MT_OFF_T 8
/* use the same type for size. Better to get signedness wrong than width */
-# define MT_SIZE_T loff_t
# else
# ifdef HAVE_OFFSET_T
# define MT_OFF_T offset_t
-/* use the same type for size. Better to get signedness wrong than width */
-# define MT_SIZE_T offset_t
+# define SIZEOF_MT_OFF_T 8
# endif
# endif
# endif
@@ -55,21 +57,34 @@
# ifdef HAVE_LONG_LONG
/* ... first try long long ... */
# define MT_OFF_T long long
-# define MT_SIZE_T unsigned long long
+# define SIZEOF_MT_OFF_T 8
# else
-# ifdef HAVE_OFF64_T
-# define MT_OFF_T off64_t
-# define MT_SIZE_T off64_t
-# else
-/* ... and if that fails, fall back on good ole' off_t */
-# define MT_OFF_T off_t
-# define MT_SIZE_T size_t
-# endif
+/* ... and if that fails, fall back on good ole' off_t, even if that
+ * only has 32 bits */
+# define MT_OFF_T off_t
+# define SIZEOF_MT_OFF_T SIZEOF_OFF_T
# endif
#endif
typedef MT_OFF_T mt_off_t;
-typedef MT_SIZE_T mt_size_t;
+
+/* Define a common supertype of uint32_t and mt_off_t. Usually,
+ * mt_off_t is bigger, except on 32-bit architectures without large
+ * file support, where uint32_t can represent larger values. N.B. in
+ * such a setup, negative values of mt_off_t could not be handled, but
+ * we don't use any such values anyways in mtools
+ */
+#if SIZEOF_MT_OFF_T == 4
+
+typedef uint32_t smt_off_t;
+mt_off_t to_mt_off_t(uint32_t off);
+
+#else
+
+typedef mt_off_t smt_off_t;
+#define to_mt_off_t(x) (x)
+
+#endif
#else
/* testing: meant to flag dubious assignments between 32 bit length types
@@ -79,11 +94,6 @@ typedef struct {
int high;
} *mt_off_t;
-typedef struct {
- unsigned int lo;
- unsigned int high;
-} *mt_size_t;
-
#endif
#define min(a,b) ((a) < (b) ? (a) : (b))
@@ -100,11 +110,13 @@ extern const mt_off_t max_off_t_31;
extern const mt_off_t max_off_t_41;
extern const mt_off_t max_off_t_seek;
-extern off_t truncBytes32(mt_off_t off);
+extern off_t truncBytes32(mt_off_t off); /* truncMtOffToOff */
+extern uint32_t truncMtOffTo32u(mt_off_t off);
+extern uint32_t truncSizeTo32u(size_t siz);
extern int fileTooBig(mt_off_t off);
int mt_lseek(int fd, mt_off_t where, int whence);
-unsigned int log_2(int);
+unsigned int log_2(unsigned int);
#endif
diff --git a/lockdev.c b/lockdev.c
index 3a6eab9..20423c7 100644
--- a/lockdev.c
+++ b/lockdev.c
@@ -29,7 +29,7 @@
#if (defined(HAVE_FLOCK) && defined (LOCK_EX) && (defined(LOCK_NB) || defined(ALRM)))
-
+
# ifdef ALRM
# define USE_FLOCK_W
# else
@@ -45,7 +45,7 @@
# else
# define USE_LOCKF
# endif
-
+
#else /* LOCKF */
#if (defined(F_SETLK) && defined(F_WRLCK))
@@ -77,7 +77,7 @@ int lock_dev(int fd, int mode, struct device *dev)
int ret=0;
#if defined(USE_FLOCK_W) || defined(USE_LOCKF_W) || defined (USE_SETLK_W)
struct sigaction alrm_action, old_alrm_action;
- int old_alrm = alarm(0);
+ unsigned int old_alrm = alarm(0);
memset(&alrm_action, 0, sizeof(alrm_action));
alrm_action.sa_handler = alrm;
alrm_action.sa_flags = 0;
@@ -88,7 +88,7 @@ int lock_dev(int fd, int mode, struct device *dev)
#ifdef USE_FLOCK
ret = flock(fd, (mode ? LOCK_EX : LOCK_SH)|LOCK_NB);
#endif
-
+
#ifdef USE_FLOCK_W
ret = flock(fd, (mode ? LOCK_EX : LOCK_SH));
#endif
@@ -103,7 +103,7 @@ int lock_dev(int fd, int mode, struct device *dev)
else
ret = 0;
#endif
-
+
#if (defined(USE_SETLK) || defined(USE_SETLK_W))
{
struct flock flk;
@@ -119,7 +119,7 @@ int lock_dev(int fd, int mode, struct device *dev)
# endif
}
#endif
-
+
#if defined(USE_FLOCK_W) || defined(USE_LOCKF_W) || defined (USE_SETLK_W)
/* Cancel the alarm */
sigaction(SIGALRM, &old_alrm_action, NULL);
@@ -133,7 +133,7 @@ int lock_dev(int fd, int mode, struct device *dev)
return 1;
}
#endif
-
+
if(
#ifdef EWOULDBLOCK
(errno != EWOULDBLOCK)
diff --git a/m4/ax_lib_socket_nsl.m4 b/m4/ax_lib_socket_nsl.m4
new file mode 100644
index 0000000..54cad68
--- /dev/null
+++ b/m4/ax_lib_socket_nsl.m4
@@ -0,0 +1,40 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_lib_socket_nsl.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_LIB_SOCKET_NSL
+#
+# DESCRIPTION
+#
+# This macro figures out what libraries are required on this platform to
+# link sockets programs.
+#
+# The common cases are not to need any extra libraries, or to need
+# -lsocket and -lnsl. We need to avoid linking with libnsl unless we need
+# it, though, since on some OSes where it isn't necessary it will totally
+# break networking. Unisys also includes gethostbyname() in libsocket but
+# needs libnsl for socket().
+#
+# LICENSE
+#
+# Copyright (c) 2008 Russ Allbery <rra@stanford.edu>
+# Copyright (c) 2008 Stepan Kasal <kasal@ucw.cz>
+# Copyright (c) 2008 Warren Young <warren@etr-usa.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 7
+
+AU_ALIAS([LIB_SOCKET_NSL], [AX_LIB_SOCKET_NSL])
+AC_DEFUN([AX_LIB_SOCKET_NSL],
+[
+ AC_SEARCH_LIBS([gethostbyname], [nsl])
+ AC_SEARCH_LIBS([socket], [socket], [], [
+ AC_CHECK_LIB([socket], [socket], [LIBS="-lsocket -lnsl $LIBS"],
+ [], [-lnsl])])
+])
diff --git a/mainloop.c b/mainloop.c
index cfd91bf..4a0f004 100644
--- a/mainloop.c
+++ b/mainloop.c
@@ -85,7 +85,7 @@ static const char *fix_mcwd(char *ans)
return ans;
}
-int unix_dir_loop(Stream_t *Stream, MainParam_t *mp);
+int unix_dir_loop(Stream_t *Stream, MainParam_t *mp);
int unix_loop(Stream_t *Stream UNUSEDP, MainParam_t *mp, char *arg,
int follow_dir_link);
@@ -100,7 +100,7 @@ int unix_loop(Stream_t *Stream UNUSEDP, MainParam_t *mp,
{
int ret;
int isdir=0;
- int unixNameLength;
+ size_t unixNameLength;
mp->File = NULL;
mp->direntry = NULL;
@@ -142,7 +142,7 @@ int unix_loop(Stream_t *Stream UNUSEDP, MainParam_t *mp,
fprintf(stderr,
"skipping directory symlink %s\n",
arg);
- return 0;
+ return 0;
}
#endif
if(! (mp->lookupflags & ACCEPT_DIR))
@@ -168,7 +168,7 @@ int isSpecial(const char *name)
return 1;
if(!strcmp(name,".."))
return 1;
- return 0;
+ return 0;
}
#ifdef HAVE_WCHAR_H
@@ -180,7 +180,7 @@ int isSpecialW(const wchar_t *name)
return 1;
if(!wcscmp(name,L".."))
return 1;
- return 0;
+ return 0;
}
#endif
@@ -247,7 +247,7 @@ static int handle_leaf(direntry_t *direntry, MainParam_t *mp,
}
static int _dos_loop(Stream_t *Dir, MainParam_t *mp, const char *filename)
-{
+{
Stream_t *MyFile=0;
direntry_t entry;
int ret;
@@ -257,10 +257,10 @@ static int _dos_loop(Stream_t *Dir, MainParam_t *mp, const char *filename)
r=0;
initializeDirentry(&entry, Dir);
while(!got_signal &&
- (r=vfat_lookup(&entry, filename, -1,
- mp->lookupflags,
- mp->shortname.data, mp->shortname.len,
- mp->longname.data, mp->longname.len)) == 0 ){
+ (r=vfat_lookup_zt(&entry, filename,
+ mp->lookupflags,
+ mp->shortname.data, mp->shortname.len,
+ mp->longname.data, mp->longname.len)) == 0 ){
mp->File = NULL;
if(!checkForDot(mp->lookupflags,entry.name)) {
MyFile = 0;
@@ -297,7 +297,7 @@ static int recurs_dos_loop(MainParam_t *mp, const char *filename0,
/* Dir is de-allocated by the same entity which allocated it */
const char *ptr;
direntry_t entry;
- int length;
+ size_t length;
int lookupflags;
int ret;
int have_one;
@@ -338,12 +338,12 @@ static int recurs_dos_loop(MainParam_t *mp, const char *filename0,
doing_mcwd = !!filename1;
ptr = strchr(filename0, '/');
- if(!ptr) {
- length = strlen(filename0);
+ if(!ptr) {
+ length = strlen(filename0);
ptr = filename1;
filename1 = 0;
} else {
- length = ptr - filename0;
+ length = ptrdiff(ptr, filename0);
ptr++;
}
if(!ptr) {
@@ -354,7 +354,7 @@ static int recurs_dos_loop(MainParam_t *mp, const char *filename0,
mp->targetName = 0;
return ret;
}
-
+
if(!strcmp(filename0, ".") || !filename0[0]) {
return handle_leaf(getDirentry(mp->File),
mp, lookupState);
@@ -366,7 +366,7 @@ static int recurs_dos_loop(MainParam_t *mp, const char *filename0,
}
lookupflags = mp->lookupflags;
-
+
if(lookupState) {
lookupState->filename = filename0;
if(lookupState->nbContainers + lookupState->nbDirs > 0){
@@ -431,7 +431,7 @@ static int common_dos_loop(MainParam_t *mp, const char *pathname,
int ret;
mp->loop = _dos_loop;
-
+
drive='\0';
cwd = "";
if(*pathname && pathname[1] == ':') {
@@ -507,17 +507,40 @@ static int dos_target_lookup(MainParam_t *mp, const char *arg)
default:
/* too much */
fprintf(stderr, "Ambiguous %s\n", arg);
- return ERROR_ONE;
+ return ERROR_ONE;
}
}
+/*
+ * Is target a Unix directory
+ * -1 error occured
+ * 0 regular file
+ * 1 directory
+ */
+static int unix_is_dir(const char *name)
+{
+ struct stat buf;
+ if(stat(name, &buf) < 0)
+ return -1;
+ else
+ return 1 && S_ISDIR(buf.st_mode);
+}
+
static int unix_target_lookup(MainParam_t *mp, const char *arg)
{
char *ptr;
mp->unixTarget = strdup(arg);
/* try complete filename */
- if(access(mp->unixTarget, F_OK) == 0)
+ if(access(mp->unixTarget, F_OK) == 0) {
+ switch(unix_is_dir(mp->unixTarget)) {
+ case -1:
+ return ERROR_ONE;
+ case 0:
+ mp->targetName="";
+ break;
+ }
return GOT_ONE;
+ }
ptr = strrchr(mp->unixTarget, '/');
if(!ptr) {
mp->targetName = mp->unixTarget;
@@ -542,12 +565,14 @@ int main_loop(MainParam_t *mp, char **argv, int argc)
{
int i;
int ret, Bret;
-
+
Bret = 0;
if(argc != 1 && mp->targetName) {
fprintf(stderr,
"Several file names given, but last argument (%s) not a directory\n", mp->targetName);
+ FREE(&mp->targetDir);
+ return 1;
}
for (i = 0; i < argc; i++) {
@@ -565,7 +590,7 @@ int main_loop(MainParam_t *mp, char **argv, int argc)
ret = unix_loop(0, mp, argv[i], 1);
else
ret = dos_loop(mp, argv[i]);
-
+
if (! (ret & (GOT_ONE | ERROR_ONE)) ) {
/* one argument was unmatched */
fprintf(stderr, "%s: File \"%s\" not found\n",
@@ -650,13 +675,9 @@ char *mpBuildUnixFilename(MainParam_t *mp)
return 0;
strcpy(ret, mp->unixTarget);
if(*target) {
-#if 1 /* fix for 'mcopy -n x:file existingfile' -- H. Lermen 980816 */
- if(!mp->targetName && !mp->targetDir) {
- struct MT_STAT buf;
- if (!MT_STAT(ret, &buf) && !S_ISDIR(buf.st_mode))
- return ret;
- }
-#endif
+ /* fix for 'mcopy -n x:file existingfile' -- H. Lermen 980816 */
+ if(!mp->targetName && !mp->targetDir && !unix_is_dir(ret))
+ return ret;
strcat(ret, "/");
if(!strcmp(target, ".")) {
target="DOT";
@@ -664,7 +685,7 @@ char *mpBuildUnixFilename(MainParam_t *mp)
target="DOTDOT";
}
while( (tmp=strchr(target, '/')) ) {
- strncat(ret, target, tmp-target);
+ strncat(ret, target, ptrdiff(tmp,target));
strcat(ret, "\\");
target=tmp+1;
}
diff --git a/mainloop.h b/mainloop.h
index a2ff666..c611233 100644
--- a/mainloop.h
+++ b/mainloop.h
@@ -24,13 +24,13 @@
typedef struct bounded_string {
char *data; /* storage of converted string, including final null byte */
- size_t len; /* max length of converted string, including final null
+ size_t len; /* max length of converted string, including final null
* byte */
} bounded_string;
typedef struct MainParam_t {
/* stuff needing to be initialised by the caller */
- int (*loop)(Stream_t *Dir, struct MainParam_t *mp,
+ int (*loop)(Stream_t *Dir, struct MainParam_t *mp,
const char *filename);
int (*dirCallback)(direntry_t *, struct MainParam_t *);
int (*callback)(direntry_t *, struct MainParam_t *);
@@ -44,9 +44,9 @@ typedef struct MainParam_t {
int fast_quit; /* for commands manipulating multiple files, quit
* as soon as even _one_ file has a problem */
- bounded_string shortname; /* where to put the short name of the
+ bounded_string shortname; /* where to put the short name of the
* matched file */
- bounded_string longname; /* where to put the long name of the
+ bounded_string longname; /* where to put the long name of the
* matched file */
/* out parameters */
Stream_t *File;
@@ -79,7 +79,7 @@ int main_loop(MainParam_t *MainParam, char **argv, int argc);
int target_lookup(MainParam_t *mp, const char *arg);
-Stream_t *open_root_dir(unsigned char drivename, int flags, int *isRop);
+Stream_t *open_root_dir(char drivename, int flags, int *isRop);
const char *mpGetBasename(MainParam_t *mp); /* statically allocated
* string */
diff --git a/match.c b/match.c
index 8ba3b50..3fcc505 100644
--- a/match.c
+++ b/match.c
@@ -47,7 +47,7 @@ static int is_in_range(wchar_t ch, const wchar_t **p, int *reverse) {
/* Malformed pattern, range not closed */
return 0;
if(*(++(*p)) == '-') {
- last = *(++(*p));
+ last = *(++(*p));
if(last==']') {
/* Last "-" in range designates itself */
if(ch == first || ch == '-')
diff --git a/mattrib.1 b/mattrib.1
index 10984af..5ff2911 100644
--- a/mattrib.1
+++ b/mattrib.1
@@ -1,5 +1,5 @@
'\" t
-.TH mattrib 1 "28Nov20" mtools-4.0.26
+.TH mattrib 1 "08Jan22" mtools-4.0.37
.SH Name
mattrib - change MSDOS file attribute flags
'\" t
diff --git a/mattrib.c b/mattrib.c
index c684e76..0fa3e10 100644
--- a/mattrib.c
+++ b/mattrib.c
@@ -25,11 +25,10 @@
#include "mainloop.h"
typedef struct Arg_t {
- unsigned char add;
- unsigned char remove;
- struct MainParam_t mp;
int recursive;
int doPrintName;
+ unsigned char add;
+ unsigned char remove;
} Arg_t;
static int attrib_file(direntry_t *entry, MainParam_t *mp)
@@ -110,7 +109,7 @@ static int concise_view_attrib(direntry_t *entry, MainParam_t *mp)
if(IS_ARCHIVE(entry))
putchar('A');
if(IS_DIR(entry))
- putchar('D');
+ putchar('D');
if(IS_SYSTEM(entry))
putchar('S');
if(IS_HIDDEN(entry))
@@ -135,9 +134,9 @@ static int recursive_attrib(direntry_t *entry, MainParam_t *mp)
static void usage(int ret) NORETURN;
static void usage(int ret)
{
- fprintf(stderr, "Mtools version %s, dated %s\n",
+ fprintf(stderr, "Mtools version %s, dated %s\n",
mversion, mdate);
- fprintf(stderr,
+ fprintf(stderr,
"Usage: %s [-p] [-a|+a] [-h|+h] [-r|+r] [-s|+s] msdosfile [msdosfiles...]\n",
progname);
exit(ret);
@@ -163,6 +162,7 @@ void mattrib(int argc, char **argv, int type UNUSEDP) NORETURN;
void mattrib(int argc, char **argv, int type UNUSEDP)
{
Arg_t arg;
+ struct MainParam_t mp;
int view;
int c;
int concise;
@@ -230,29 +230,29 @@ void mattrib(int argc, char **argv, int type UNUSEDP)
if (optind >= argc)
usage(1);
- init_mp(&arg.mp);
+ init_mp(&mp);
if(view){
if(concise) {
- arg.mp.callback = concise_view_attrib;
+ mp.callback = concise_view_attrib;
arg.doPrintName = (argc - optind > 1 ||
arg.recursive ||
strpbrk(argv[optind], "*[?") != 0);
} else if (replay) {
- arg.mp.callback = replay_attrib;
+ mp.callback = replay_attrib;
} else
- arg.mp.callback = view_attrib;
- arg.mp.openflags = O_RDONLY;
+ mp.callback = view_attrib;
+ mp.openflags = O_RDONLY;
} else {
- arg.mp.callback = attrib_file;
- arg.mp.openflags = O_RDWR;
+ mp.callback = attrib_file;
+ mp.openflags = O_RDWR;
}
if(arg.recursive)
- arg.mp.dirCallback = recursive_attrib;
+ mp.dirCallback = recursive_attrib;
- arg.mp.arg = (void *) &arg;
- arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR;
+ mp.arg = (void *) &arg;
+ mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR;
if(arg.recursive)
- arg.mp.lookupflags |= DO_OPEN_DIRS | NO_DOTS;
- exit(main_loop(&arg.mp, argv + optind, argc - optind));
+ mp.lookupflags |= DO_OPEN_DIRS | NO_DOTS;
+ exit(main_loop(&mp, argv + optind, argc - optind));
}
diff --git a/mbadblocks.1 b/mbadblocks.1
index a4975ed..62ad593 100644
--- a/mbadblocks.1
+++ b/mbadblocks.1
@@ -1,5 +1,5 @@
'\" t
-.TH mbadblocks 1 "28Nov20" mtools-4.0.26
+.TH mbadblocks 1 "08Jan22" mtools-4.0.37
.SH Name
mbadblocks - tests a floppy disk, and marks the bad blocks in the FAT
'\" t
diff --git a/mbadblocks.c b/mbadblocks.c
index 37b4207..e1dcdfa 100644
--- a/mbadblocks.c
+++ b/mbadblocks.c
@@ -47,16 +47,16 @@ static void checkListTwice(char *filename) {
/**
* Marks given cluster as bad, but prints error instead if cluster already used
*/
-static void mark(Fs_t *Fs, long offset, unsigned int badClus) {
- unsigned int old = Fs->fat_decode((Fs_t*)Fs, offset);
+static void mark(Fs_t *Fs, uint32_t offset, uint32_t badClus) {
+ uint32_t old = Fs->fat_decode((Fs_t*)Fs, offset);
if(old == 0) {
fatEncode((Fs_t*)Fs, offset, badClus);
return;
}
if(old == badClus) {
- fprintf(stderr, "Cluster %ld already marked\n", offset);
+ fprintf(stderr, "Cluster %d already marked\n", offset);
} else {
- fprintf(stderr, "Cluster %ld is busy\n", offset);
+ fprintf(stderr, "Cluster %d is busy\n", offset);
}
}
@@ -71,24 +71,24 @@ static void progress(unsigned int i, unsigned int total) {
}
static int scan(Fs_t *Fs, Stream_t *dev,
- long cluster, unsigned int badClus,
+ uint32_t cluster, uint32_t badClus,
char *buffer, int doWrite) {
- off_t start;
+ uint32_t start;
off_t ret;
- off_t pos;
+ mt_off_t pos;
int bad=0;
if(Fs->fat_decode((Fs_t*)Fs, cluster))
/* cluster busy, or already marked */
return 0;
start = (cluster - 2) * Fs->cluster_size + Fs->clus_start;
- pos = sectorsToBytes((Stream_t*)Fs, start);
+ pos = sectorsToBytes(Fs, start);
if(doWrite) {
- ret = force_write(dev, buffer, pos, in_len);
- if(ret < (off_t) in_len )
+ ret = force_pwrite(dev, buffer, pos, in_len);
+ if(ret < 0 || (size_t) ret < in_len )
bad = 1;
} else {
- ret = force_read(dev, in_buf, pos, in_len);
+ ret = force_pread(dev, in_buf, pos, in_len);
if(ret < (off_t) in_len )
bad = 1;
else if(buffer) {
@@ -102,7 +102,7 @@ static int scan(Fs_t *Fs, Stream_t *dev,
}
if(bad) {
- printf("Bad cluster %ld found\n", cluster);
+ printf("Bad cluster %d found\n", cluster);
fatEncode((Fs_t*)Fs, cluster, badClus);
return 1;
}
@@ -140,10 +140,10 @@ void mbadblocks(int argc, char **argv, int type UNUSEDP)
sectorMode = 1;
break;
case 'S':
- startSector = atoui(optarg);
+ startSector = atoui(optarg);
break;
case 'E':
- endSector = atoui(optarg);
+ endSector = atoui(optarg);
break;
case 'w':
writeMode = 1;
@@ -185,17 +185,19 @@ void mbadblocks(int argc, char **argv, int type UNUSEDP)
}
init_random();
for(i=0; i < in_len * N_PATTERN; i++) {
- pat_buf[i] = random();
+ pat_buf[i] = (char) random();
}
}
for(i=0; i < Fs->clus_start; i++ ){
- ret = READS(Fs->Next, in_buf,
- sectorsToBytes((Stream_t*)Fs, i), Fs->sector_size);
- if( ret < 0 ){
+ ssize_t r;
+ r = PREADS(Fs->head.Next, in_buf,
+ sectorsToBytes(Fs, i), Fs->sector_size);
+ if( r < 0 ){
perror("early error");
+ ret = -1;
goto exit_0;
}
- if(ret < (signed int) Fs->sector_size){
+ if((size_t) r < Fs->sector_size){
fprintf(stderr,"end of file in file_read\n");
ret = 1;
goto exit_0;
@@ -207,7 +209,7 @@ void mbadblocks(int argc, char **argv, int type UNUSEDP)
if(startSector < 2)
startSector = 2;
- if(endSector > Fs->num_clus + 2 || endSector <= 0)
+ if(endSector > Fs->num_clus + 2 || endSector <= 0)
endSector = Fs->num_clus + 2;
if(filename) {
@@ -222,7 +224,7 @@ void mbadblocks(int argc, char **argv, int type UNUSEDP)
}
while(fgets(line, sizeof(line), f)) {
char *ptr = line + strspn(line, " \t");
- long offset = strtol(ptr, 0, 0);
+ uint32_t offset = strtou32(ptr, 0, 0);
if(sectorMode)
offset = (offset-Fs->clus_start)/Fs->cluster_size + 2;
if(offset < 2) {
@@ -236,7 +238,7 @@ void mbadblocks(int argc, char **argv, int type UNUSEDP)
}
} else {
Stream_t *dev;
- dev = Fs->Next;
+ dev = Fs->head.Next;
if(dev->Next)
dev = dev->Next;
@@ -247,7 +249,7 @@ void mbadblocks(int argc, char **argv, int type UNUSEDP)
if(got_signal)
break;
progress(i, Fs->num_clus);
- ret |= scan(Fs, dev, i, badClus,
+ ret |= scan(Fs, dev, i, badClus,
pat_buf + in_len * (i % N_PATTERN),
1);
}
@@ -262,7 +264,7 @@ void mbadblocks(int argc, char **argv, int type UNUSEDP)
if(got_signal)
break;
progress(i, Fs->num_clus);
- ret |= scan(Fs, dev, i, badClus,
+ ret |= scan(Fs, dev, i, badClus,
pat_buf + in_len * (i % N_PATTERN),
0);
}
diff --git a/mcat.1 b/mcat.1
index 630582b..79ba357 100644
--- a/mcat.1
+++ b/mcat.1
@@ -1,5 +1,5 @@
'\" t
-.TH mcat 1 "28Nov20" mtools-4.0.26
+.TH mcat 1 "08Jan22" mtools-4.0.37
.SH Name
mcat - dump raw disk image
'\" t
diff --git a/mcat.c b/mcat.c
index 60dff53..c0633e6 100644
--- a/mcat.c
+++ b/mcat.c
@@ -23,15 +23,12 @@
#include "msdos.h"
#include "mtools.h"
#include "mainloop.h"
-#include "fsP.h"
-#include "xdf_io.h"
-#include "floppyd_io.h"
-#include "plain_io.h"
+#include "open_image.h"
static void usage(void) NORETURN;
-static void usage(void)
+static void usage(void)
{
- fprintf(stderr, "Mtools version %s, dated %s\n",
+ fprintf(stderr, "Mtools version %s, dated %s\n",
mversion, mdate);
fprintf(stderr, "Usage: mcat [-V] [-w] device\n");
fprintf(stderr, " -w write on device else read\n");
@@ -44,12 +41,12 @@ static void usage(void)
#define BUF_SIZE 16000u
#endif
-static size_t bufLen(size_t blocksize, mt_size_t totalSize, mt_off_t address)
+static size_t bufLen(size_t blocksize, mt_off_t totalSize, mt_off_t address)
{
if(totalSize == 0)
return blocksize;
- if(address + blocksize > totalSize)
- return totalSize - address;
+ if((mt_off_t) blocksize > totalSize - address)
+ return (size_t) (totalSize - address);
return blocksize;
}
@@ -64,10 +61,10 @@ void mcat(int argc, char **argv, int type UNUSEDP)
char buf[BUF_SIZE];
mt_off_t address = 0;
+ mt_off_t maxSize = 0;
char mode = O_RDONLY;
- int optindex = 1;
- size_t len;
+ int c;
noPrivileges = 1;
@@ -75,27 +72,31 @@ void mcat(int argc, char **argv, int type UNUSEDP)
usage();
}
- if (argv[1][0] == '-') {
- if (argv[1][1] != 'w') {
+ while ((c = getopt(argc,argv, "wi:"))!= EOF) {
+ switch (c) {
+ case 'w':
+ mode = O_WRONLY;
+ break;
+ case 'i':
+ set_cmd_line_image(optarg);
+ break;
+ default:
usage();
}
- mode = O_WRONLY;
- optindex++;
}
- if (argc - optindex < 1)
- usage();
-
-
- if (!argv[optindex][0] || argv[optindex][1] != ':'
- || argv[optindex][2]) {
+ if (argc - optind > 1)
usage();
+ if(argc - optind == 1) {
+ if(!argv[optind][0] || argv[optind][1] != ':')
+ usage();
+ drive = ch_toupper(argv[argc -1][0]);
+ } else {
+ drive = get_default_drive();
}
- drive = ch_toupper(argv[optindex][0]);
-
- /* check out a drive whose letter and parameters match */
- sprintf(errmsg, "Drive '%c:' not supported", drive);
+ /* check out a drive whose letter and parameters match */
+ sprintf(errmsg, "Drive '%c:' not supported", drive);
Stream = NULL;
for (dev=devices; dev->name; dev++) {
FREE(&Stream);
@@ -107,58 +108,47 @@ void mcat(int argc, char **argv, int type UNUSEDP)
strcpy(name, getVoldName(dev, name));
#endif
- Stream = 0;
-#ifdef USE_XDF
- Stream = XdfOpen(&out_dev, name, mode, errmsg, 0);
- if(Stream)
- out_dev.use_2m = 0x7f;
-
-#endif
-
-#ifdef USE_FLOPPYD
- if(!Stream)
- Stream = FloppydOpen(&out_dev, name,
- mode, errmsg, NULL);
-#endif
-
-
- if (!Stream)
- Stream = SimpleFileOpen(&out_dev, dev, name, mode,
- errmsg, 0, 1, 0);
-
+ Stream = OpenImage(&out_dev, dev, name, mode,
+ errmsg, ALWAYS_GET_GEOMETRY, mode, &maxSize,
+ NULL, NULL);
if( !Stream)
continue;
break;
}
- /* print error msg if needed */
- if ( dev->drive == 0 ){
- FREE(&Stream);
- fprintf(stderr,"%s\n",errmsg);
- exit(1);
- }
-
+ /* print error msg if needed */
+ if ( dev->drive == 0 )
+ goto exit_1;
if (mode == O_WRONLY) {
- mt_size_t size=0;
- size = out_dev.sectors * out_dev.heads * out_dev.tracks;
- size *= 512;
+ size_t len;
+ mt_off_t size=0;
+ if(chs_to_totsectors(&out_dev, errmsg) < 0 ||
+ check_if_sectors_fit(out_dev.tot_sectors,
+ maxSize, 512, errmsg))
+ goto exit_1;
+ size = 512 * (mt_off_t) out_dev.tot_sectors;
while ((len = fread(buf, 1,
bufLen(BUF_SIZE, size, address),
- stdin)) > 0) {
- int r = WRITES(Stream, buf, address, len);
+ stdin)) > 0) {
+ ssize_t r = PWRITES(Stream, buf, address, len);
fprintf(stderr, "Wrote to %d\n", (int) address);
if(r < 0)
break;
address += len;
}
} else {
- while ((len = READS(Stream, buf, address, BUF_SIZE)) > 0) {
- fwrite(buf, 1, len, stdout);
- address += len;
+ ssize_t len;
+ while ((len = PREADS(Stream, buf, address, BUF_SIZE)) > 0) {
+ fwrite(buf, 1, (size_t) len, stdout);
+ address += (size_t) len;
}
}
FREE(&Stream);
exit(0);
+exit_1:
+ FREE(&Stream);
+ fprintf(stderr,"%s\n",errmsg);
+ exit(1);
}
diff --git a/mcd.1 b/mcd.1
index 24528e8..13b7dc0 100644
--- a/mcd.1
+++ b/mcd.1
@@ -1,5 +1,5 @@
'\" t
-.TH mcd 1 "28Nov20" mtools-4.0.26
+.TH mcd 1 "08Jan22" mtools-4.0.37
.SH Name
mcd - change MSDOS directory
'\" t
diff --git a/mcd.c b/mcd.c
index a11909b..81e4eb6 100644
--- a/mcd.c
+++ b/mcd.c
@@ -32,32 +32,51 @@ static int mcd_callback(direntry_t *entry, MainParam_t *mp UNUSEDP)
fprintf(stderr,"mcd: Can't open mcwd .file for writing\n");
return ERROR_ONE;
}
-
+
fprintPwd(fp, entry,0);
fprintf(fp, "\n");
fclose(fp);
return GOT_ONE | STOP_NOW;
}
+static void usage(int ret) NORETURN;
+static void usage(int ret)
+{
+ fprintf(stderr, "Mtools version %s, dated %s\n",
+ mversion, mdate);
+ fprintf(stderr, "Usage: %s: [-V] [-i image] msdosdirectory\n",
+ progname);
+ exit(ret);
+}
+
void mcd(int argc, char **argv, int type UNUSEDP) NORETURN;
void mcd(int argc, char **argv, int type UNUSEDP)
{
struct MainParam_t mp;
-
- if (argc > 2) {
- fprintf(stderr, "Mtools version %s, dated %s\n",
- mversion, mdate);
- fprintf(stderr, "Usage: %s: [-V] msdosdirectory\n", argv[0]);
- exit(1);
+ int c;
+
+ while ((c = getopt(argc, argv, "i:")) != EOF) {
+ switch(c) {
+ case 'i':
+ set_cmd_line_image(optarg);
+ break;
+ case 'h':
+ usage(0);
+ default:
+ usage(1);
+ }
}
+ if (argc > optind + 1)
+ usage(1);
+
init_mp(&mp);
mp.lookupflags = ACCEPT_DIR | NO_DOTS;
mp.dirCallback = mcd_callback;
if (argc == 1) {
printf("%s\n", mp.mcwd);
exit(0);
- } else
- exit(main_loop(&mp, argv + 1, 1));
+ } else
+ exit(main_loop(&mp, argv + optind, 1));
}
diff --git a/mclasserase.1 b/mclasserase.1
deleted file mode 100644
index 1ca4328..0000000
--- a/mclasserase.1
+++ /dev/null
@@ -1,112 +0,0 @@
-'\" t
-.TH mclasserase 1 "28Nov20" mtools-4.0.26
-.SH Name
-mclasserase - erase memory cards
-'\" t
-.de TQ
-.br
-.ns
-.TP \\$1
-..
-
-.tr \(is'
-.tr \(if`
-.tr \(pd"
-
-.SH Note\ of\ warning
-This manpage has been automatically generated from mtools's texinfo
-documentation, and may not be entirely accurate or complete. See the
-end of this man page for details.
-.PP
-.SH Description
-.PP
-The \fR\&\f(CWmclasserase\fR command is used to wipe memory cards by
-overwriting it three times: first with \fR\&\f(CW0xff\fR, then with
-\&\fR\&\f(CW0x00\fR, then with \fR\&\f(CW0xff\fR again. The command uses the following
-syntax:
-.PP
-
-.nf
-.ft 3
-.in +0.3i
-\&\fR\&\f(CWmclasserase [\fR\&\f(CW-d] \fImsdosdrive\fR\&\f(CW
-.fi
-.in -0.3i
-.ft R
-.PP
-
-\&\fR
-.PP
-MS-DOS drive is optional, if none is specified, use \fR\&\f(CWA:\fR. If more than
-one drive are specified, all but the last are ignored.
-.PP
-\&\fR\&\f(CWMclasserase\fR accepts the following command line options:
-.TP
-\&\fR\&\f(CWd\fR\
-Stop after each erase cycle, for testing purposes
-.TP
-\&\fR\&\f(CWp\fR\
-Not yet implemented
-.PP
-\&\fR\&\f(CWMclasserase\fR returns 0 on success or -1 on failure.
-.PP
-.SH See\ Also
-Mtools' texinfo doc
-.SH Viewing\ the\ texi\ doc
-This manpage has been automatically generated from mtools's texinfo
-documentation. However, this process is only approximative, and some
-items, such as crossreferences, footnotes and indices are lost in this
-translation process. Indeed, these items have no appropriate
-representation in the manpage format. Moreover, not all information has
-been translated into the manpage version. Thus I strongly advise you to
-use the original texinfo doc. See the end of this manpage for
-instructions how to view the texinfo doc.
-.TP
-* \ \
-To generate a printable copy from the texinfo doc, run the following
-commands:
-
-.nf
-.ft 3
-.in +0.3i
- ./configure; make dvi; dvips mtools.dvi
-.fi
-.in -0.3i
-.ft R
-.PP
-
-\&\fR
-.TP
-* \ \
-To generate a html copy, run:
-
-.nf
-.ft 3
-.in +0.3i
- ./configure; make html
-.fi
-.in -0.3i
-.ft R
-.PP
-
-\&\fRA premade html can be found at
-\&\fR\&\f(CW\(ifhttp://www.gnu.org/software/mtools/manual/mtools.html\(is\fR
-.TP
-* \ \
-To generate an info copy (browsable using emacs' info mode), run:
-
-.nf
-.ft 3
-.in +0.3i
- ./configure; make info
-.fi
-.in -0.3i
-.ft R
-.PP
-
-\&\fR
-.PP
-The texinfo doc looks most pretty when printed or as html. Indeed, in
-the info version certain examples are difficult to read due to the
-quoting conventions used in info.
-.PP
diff --git a/mclasserase.c b/mclasserase.c
deleted file mode 100644
index 8e71e3b..0000000
--- a/mclasserase.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/* Copyright 2003 Stefan Feuz, Lukas Meyer, Thomas Locher
- * Copyright 2004,2006,2007,2009 Alain Knaff.
- * This file is part of mtools.
- *
- * Mtools is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Mtools is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
- *
- * Filename:
- * mclasserase.c
- *
- * Original Creation Date:
- * 05.III.2003
- *
- * Copyright:
- * GPL
- *
- * Programmer:
- * Stefan Feuz, Lukas Meyer, Thomas Locher
- */
-
-#include "sysincludes.h"
-#include "msdos.h"
-#include "mtools.h"
-#include "vfat.h"
-#include "mainloop.h"
-#include "fsP.h"
-
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-
-#include "file.h"
-
-#include <unistd.h>
-#include <stdio.h>
-
-/**
- * Prints the Usage Message to STDOUT<br>
- *
- * @author stefan feuz<br>
- * stefan.feuz@ruag.com
- *
- * @param n.a.
- *
- * @returns n.a.
- *
- */
-static void usage(int ret) NORETURN;
-static void usage(int ret)
-{
- fprintf(stderr, "Mtools version %s, dated %s\n", mversion, mdate);
- fprintf(stderr, "Usage: %s [-d] drive:\n", progname);
- exit(ret);
-}
-
-/**
- * Delete all files on a Drive.<br>
- *
- * @author Lukas Meyer<br>
- * lukas.meyer@ruag.com
- * @version 0.4, 11.12.2003
- *
- * @param drive the drive to erase
- * @param debug 1: stop after each erase cycle, 0: normal mode
- *
- * @returns n.a.
- *
- */
-static void do_mclasserase(char drive,int debug) NORETURN;
-static void do_mclasserase(char drive,int debug)
-{
- struct device dev; /* Device information structure */
- union bootsector boot;
-
- int media; /* Just used to enter some in find_device */
- char name[EXPAND_BUF];
- Stream_t *Stream;
- struct label_blk_t *labelBlock;
-
- FILE * fDevice; /* Stores device's file descriptor */
-
- char cCardType[12];
-
- char drivel[3]; /* Stores the drive letter */
-
-
- int i = 0;
-
- /* FILE *forf; */
-
- char dummy[2]; /* dummy input for debugging purposes.. */
- int icount=0;
- int iTotalErase = 0;
-
-/* How many times we'll overwrite the media: */
-#define CYCLES 3
- unsigned char odat[CYCLES]; /* Data for each overwrite procedure */
-
- /* Creating values for overwrite */
- odat[0]=0xff;
- odat[1]=0x00;
- odat[2]=0xff;
-
-
- if (debug == 1)
- printf("cycles: %i, odats: %i,%i,%i\n",CYCLES,odat[0],odat[1],odat[2]);
-
-
-
- /* Reading parameters from card. Exit with -1 if failed. */
- if(! (Stream = find_device(drive, O_RDONLY, &dev, &boot,
- name, &media, 0, NULL)))
- exit(1);
-
- FREE(&Stream);
-
- /* Determine the FAT - type */
-#if 0
- if(WORD(fatlen)) {
- labelBlock = &bbelBlock = &boot->ext.old.labelBlock;
- } else {
- labelBlock = &boot->ext.fat32.labelBlock;
- }
-#endif
-
- /* we use only FAT12/16 ...*/
- labelBlock = &boot.boot.ext.old.labelBlock;
-
- /* store card type */
- sprintf(cCardType, "%11.11s", labelBlock->label);
-
- if (debug == 1)
- {
- printf("Using Device: %s\n",name);
- printf("Card-Type detected: %s\n",cCardType);
- }
-
- /* Forming cat command to overwrite the medias content. */
- sprintf( drivel, "%c:", ch_tolower(drive) );
-
-#if 0
- media_sectors = dev.tracks * dev.sectors;
- sector_size = WORD(secsiz) * dev.heads;
-
-
- printf(mcat);
- printf("\n%d\n", media_sectors);
- printf("%d\n", sector_size);
-#endif
-
- /*
- * Overwrite device
- */
- for( i=0; i < CYCLES; i++){
-
- if (debug==1)
- {
- printf("Erase Cycle %i, writing data: 0x%2.2x...\n",i+1,odat[i]);
- }
-
- fDevice = fopen(name,"ab+");
-
- if (fDevice == 0)
- {
- perror("Error opening device");
- exit(-1);
- }
-
-
- if (debug==1)
- {
- printf("Open successful...\n");
- printf("Flushing device after 32 kBytes of data...\n");
- printf("Erasing:");
- fflush( stdout );
- }
-
- /* iTotalErase = 0; */
-
- /*
- * overwrite the whole device
- */
- while ((feof(fDevice)==0) && (ferror(fDevice)==0))
- {
-
- fputc(odat[i],fDevice);
-
- icount++;
- if (icount > (32 * 1024))
- {
- /* flush device every 32KB of data...*/
- fflush( fDevice );
-
- iTotalErase += icount;
- if (debug == 1)
- {
- printf(".");
- fflush( stdout );
- }
- icount=0;
- }
- }
-
- if (debug==1)
- {
- printf("\nPress <ENTER> to continue\n");
- printf("Press <x> and <ENTER> to abort\n");
-
- if(scanf("%c",dummy) < 1)
- printf("Input error\n");
- fflush( stdin );
-
- if (strcmp(dummy,"x") == 0)
- {
- printf("exiting.\n");
- exit(0);
- }
- }
-
- fclose(fDevice);
-
- }
-
-
- /*
- * Format device using shell script
- */
- if (debug == 0)
- {
- /* redirect STDERR and STDOUT to the black hole... */
- if (dup2(open("/dev/null", O_WRONLY), STDERR_FILENO) != STDERR_FILENO)
- printf("Error with dup2() stdout\n");
- if (dup2(open("/dev/null", O_WRONLY), STDOUT_FILENO) != STDOUT_FILENO)
- printf("Error with dup2() stdout\n");
- }
-
- if (debug == 1)
- printf("Calling amuFormat.sh with args: %s,%s\n",cCardType,drivel);
-
- execlp("amuFormat.sh","",cCardType,drivel,NULL);
-
- /* we never come back...(we shouldn't come back ...) */
- exit(-1);
-
-}
-
-
-/**
- * Total Erase of Data on a Disk. After using mclasserase there won't
- * be ANY bits of old files on the disk.<br>
- * </b>
- * @author stefan feuz<br>
- * thomas locher<br>
- * stefan.feuz@ruag.com
- * thomas.locher@ruag.com
- * @version 0.3, 02.12.2003
- *
- * @param argc generated automatically by operating systems
- * @param **argv1 generated automatically by operating systems
- * @param type generated automatically by operating systems
- *
- * @param -d stop after each erase cycle, for testing purposes
- *
- * @returns int 0 if all is well done<br>
- * int -1 if there is something wrong
- *
- * @info mclasserase [-p tempFilePath] [-d] drive:
- *
- *
- */
-void mclasserase(int argc, char **argv, int type UNUSEDP) NORETURN;
-void mclasserase(int argc, char **argv, int type UNUSEDP)
-{
- /* declaration of all variables */
- int c;
- int debug=0;
- /* char* tempFilePath=NULL; */
- char drive='a';
-
- extern int optind;
-
- destroy_privs();
-
- /* check and read command line arguments */
-#ifdef DEBUG
- printf("mclasserase: argc = %i\n",argc);
-#endif
- /* check num of arguments */
- if(helpFlag(argc, argv))
- usage(0);
- if ( (argc != 2) & (argc != 3) & (argc != 4))
- { /* wrong num of arguments */
- printf ("mclasserase: wrong num of args\n");
- usage(1);
- }
- else
- { /* correct num of arguments */
- while ((c = getopt(argc, argv, "+p:dh")) != EOF)
- {
- switch (c)
- {
-
- case 'd':
-
- printf("=============\n");
- printf("Debug Mode...\n");
- printf("=============\n");
- debug = 1;
- break;
- case 'p':
- printf("option -p not implemented yet\n");
- break;
- case 'h':
- usage(0);
- case '?':
- usage(1);
- default:
- break;
- }
- }
-#ifdef DEBUG
- printf("mclasserase: optind = %i\n",optind);
- /* look for the drive to erase */
- printf("mclasserase: searching drive\n");
-#endif
- for(; optind < argc; optind++)
- {
- if(!argv[optind][0] || argv[optind][1] != ':')
- {
- usage(1);
- }
- drive = ch_toupper(argv[optind][0]);
- }
- }
-#ifdef DEBUG
- printf("mclasserase: found drive %c\n", drive);
-#endif
- /* remove all data on drive, you never come back if drive does
- * not exist */
-
- do_mclasserase(drive,debug);
-}
diff --git a/mcopy.1 b/mcopy.1
index 9ce0804..41d39f7 100644
--- a/mcopy.1
+++ b/mcopy.1
@@ -1,5 +1,5 @@
'\" t
-.TH mcopy 1 "28Nov20" mtools-4.0.26
+.TH mcopy 1 "08Jan22" mtools-4.0.37
.SH Name
mcopy - copy MSDOS files to/from Unix
'\" t
diff --git a/mcopy.c b/mcopy.c
index c9a8900..c96089c 100644
--- a/mcopy.c
+++ b/mcopy.c
@@ -1,5 +1,5 @@
/* Copyright 1986-1992 Emmet P. Gray.
- * Copyright 1994,1996-2002,2007-2009 Alain Knaff.
+ * Copyright 1994,1996-2002,2007-2009,2021 Alain Knaff.
* This file is part of mtools.
*
* Mtools is free software: you can redistribute it and/or modify
@@ -40,12 +40,12 @@ static void set_mtime(const char *target, time_t mtime)
{
if (target && strcmp(target, "-") && mtime != 0L) {
#ifdef HAVE_UTIMES
- struct timeval tv[2];
+ struct timeval tv[2];
tv[0].tv_sec = mtime;
tv[0].tv_usec = 0;
tv[1].tv_sec = mtime;
tv[1].tv_usec = 0;
- utimes((char *)target, tv);
+ utimes(target, tv);
#else
#ifdef HAVE_UTIME
struct utimbuf utbuf;
@@ -107,7 +107,6 @@ static int _unix_write(MainParam_t *mp, int needfilter, const char *unixFile)
Stream_t *File=mp->File;
Stream_t *Target, *Source;
struct MT_STAT stbuf;
- int ret;
char errmsg[80];
File->Class->get_data(File, &mtime, 0, 0, 0);
@@ -130,16 +129,14 @@ static int _unix_write(MainParam_t *mp, int needfilter, const char *unixFile)
if(!S_ISREG(stbuf.st_mode)) {
fprintf(stderr,"\"%s\" is not a regular file\n",
unixFile);
-
+
return ERROR_ONE;
}
sFd = get_fd(File);
if(sFd == -1) {
- fprintf(stderr, "Not ok Unix file ==> good\n");
- }
- if((!MT_FSTAT(sFd, &srcStbuf)) &&
- stbuf.st_dev == srcStbuf.st_dev &&
- stbuf.st_ino == srcStbuf.st_ino) {
+ } else if((!MT_FSTAT(sFd, &srcStbuf)) &&
+ stbuf.st_dev == srcStbuf.st_dev &&
+ stbuf.st_ino == srcStbuf.st_ino) {
fprintf(stderr, "Attempt to copy file on itself\n");
return ERROR_ONE;
}
@@ -149,7 +146,7 @@ static int _unix_write(MainParam_t *mp, int needfilter, const char *unixFile)
unixFile)) {
return ERROR_ONE;
}
-
+
}
}
@@ -158,7 +155,7 @@ static int _unix_write(MainParam_t *mp, int needfilter, const char *unixFile)
mpPrintFilename(stderr,mp);
fprintf(stderr,"\n");
}
-
+
if(got_signal) {
return ERROR_ONE;
}
@@ -166,19 +163,18 @@ static int _unix_write(MainParam_t *mp, int needfilter, const char *unixFile)
if ((Target = SimpleFileOpen(0, 0, unixFile,
O_WRONLY | O_CREAT | O_TRUNC,
errmsg, 0, 0, 0))) {
- ret = 0;
- if(needfilter && arg->textmode){
- Source = open_filter(COPY(File),arg->convertCharset);
- if (!Source)
- ret = -1;
- } else
- Source = COPY(File);
-
- if (ret == 0 )
+ mt_off_t ret;
+ Source = COPY(File);
+ if(needfilter && arg->textmode)
+ Source = open_dos2unix(Source,arg->convertCharset);
+
+ if (Source)
ret = copyfile(Source, Target);
+ else
+ ret = -1;
FREE(&Source);
FREE(&Target);
- if(ret <= -1){
+ if(ret < 0){
if(!arg->type)
unlink(unixFile);
return ERROR_ONE;
@@ -223,7 +219,7 @@ static int unix_copydir(direntry_t *entry, MainParam_t *mp)
if (!arg->recursive && mp->basenameHasWildcard)
return 0;
- File->Class->get_data(File, &mtime, 0, 0, 0);
+ File->Class->get_data(File, &mtime, 0, 0, 0);
if (!arg->preserveTime)
mtime = 0L;
if(!arg->type && arg->verbose) {
@@ -250,11 +246,11 @@ static int unix_copydir(direntry_t *entry, MainParam_t *mp)
ret = mp->loop(File, &newArg.mp, "*");
set_mtime(unixFile, mtime);
free(unixFile);
- return ret | GOT_ONE;
+ return ret | GOT_ONE;
} else {
perror("mkdir");
- fprintf(stderr,
- "Failure to make directory %s\n",
+ fprintf(stderr,
+ "Failure to make directory %s\n",
unixFile);
free(unixFile);
return ERROR_ONE;
@@ -289,15 +285,16 @@ static int writeit(struct dos_name_t *dosname,
{
Stream_t *Target;
time_t now;
- int type, fat, ret;
+ int type;
+ mt_off_t ret;
+ uint32_t fat;
time_t date;
- mt_size_t filesize, newsize;
+ mt_off_t filesize;
Arg_t *arg = (Arg_t *) arg0;
+ Stream_t *Source = COPY(arg->mp.File);
-
-
- if (arg->mp.File->Class->get_data(arg->mp.File,
- & date, &filesize, &type, 0) < 0 ){
+ if (Source->Class->get_data(Source, &date, &filesize,
+ &type, 0) < 0 ){
fprintf(stderr, "Can't stat source file\n");
return -1;
}
@@ -322,7 +319,7 @@ static int writeit(struct dos_name_t *dosname,
/* will it fit? */
if (!getfreeMinBytes(arg->mp.targetDir, filesize))
return -1;
-
+
/* preserve mod time? */
if (arg->preserveTime)
now = date;
@@ -336,22 +333,19 @@ static int writeit(struct dos_name_t *dosname,
fprintf(stderr,"Could not open Target\n");
exit(1);
}
- if (arg->needfilter & arg->textmode)
- Target = open_filter(Target,arg->convertCharset);
-
-
-
- ret = copyfile(arg->mp.File, Target);
- GET_DATA(Target, 0, &newsize, 0, &fat);
+ if (arg->needfilter & arg->textmode) {
+ Source = open_unix2dos(Source,arg->convertCharset);
+ }
+
+ ret = copyfile(Source, Target);
+ GET_DATA(Target, 0, 0, 0, &fat);
+ FREE(&Source);
FREE(&Target);
- if (arg->needfilter & arg->textmode)
- newsize++; /* ugly hack: we gathered the size before the Ctrl-Z
- * was written. Increment it manually */
if(ret < 0 ){
fat_free(arg->mp.targetDir, fat);
return -1;
} else {
- mk_entry(dosname, arg->attr, fat, truncBytes32(newsize),
+ mk_entry(dosname, arg->attr, fat, (uint32_t)ret,
now, &entry->dir);
return 0;
}
@@ -392,7 +386,7 @@ static Stream_t *subDir(Stream_t *parent, const char *filename)
direntry_t entry;
initializeDirentry(&entry, parent);
- switch(vfat_lookup(&entry, filename, -1, ACCEPT_DIR, 0, 0, 0, 0)) {
+ switch(vfat_lookup_zt(&entry, filename, ACCEPT_DIR, 0, 0, 0, 0)) {
case 0:
return OpenFileByDirentry(&entry);
case -1:
@@ -460,9 +454,9 @@ static int dos_copydir(direntry_t *entry, MainParam_t *mp)
/* maybe the directory already exist. Use it */
newArg.mp.targetDir = subDir(mp->targetDir, targetName);
if(!newArg.mp.targetDir)
- newArg.mp.targetDir = createDir(mp->targetDir,
+ newArg.mp.targetDir = createDir(mp->targetDir,
targetName,
- &arg->ch, arg->attr,
+ &arg->ch, arg->attr,
now);
} else
newArg.mp.targetDir = mp->targetDir;
@@ -495,7 +489,7 @@ static void usage(int ret)
fprintf(stderr,
"Usage: %s [-spatnmQVBT] [-D clash_option] sourcefile targetfile\n", progname);
fprintf(stderr,
- " %s [-spatnmQVBT] [-D clash_option] sourcefile [sourcefiles...] targetdirectory\n",
+ " %s [-spatnmQVBT] [-D clash_option] sourcefile [sourcefiles...] targetdirectory\n",
progname);
exit(ret);
}
@@ -505,7 +499,7 @@ void mcopy(int argc, char **argv, int mtype)
{
Arg_t arg;
int c, fastquit;
-
+
/* get command line options */
@@ -537,6 +531,7 @@ void mcopy(int argc, char **argv, int mtype)
break;
case 'T':
arg.convertCharset = 1;
+ /*-fallthrough*/
case 'a':
case 't':
arg.textmode = 1;
@@ -558,7 +553,7 @@ void mcopy(int argc, char **argv, int mtype)
batchmode = 1;
break;
case 'o':
- handle_clash_options(&arg.ch, c);
+ handle_clash_options(&arg.ch, (char) c);
break;
case 'D':
if(handle_clash_options(&arg.ch, *optarg))
@@ -570,6 +565,7 @@ void mcopy(int argc, char **argv, int mtype)
usage(1);
default:
break;
+
}
}
@@ -595,7 +591,7 @@ void mcopy(int argc, char **argv, int mtype)
arg.mp.unixTarget = strdup("");
arg.mp.callback = dos_to_unix;
arg.mp.dirCallback = unix_copydir;
- arg.mp.unixcallback = unix_to_unix;
+ arg.mp.unixcallback = unix_to_unix;
} else {
const char *target;
if (argc - optind == 1) {
diff --git a/mdel.1 b/mdel.1
index ea8dcd4..2ece0c8 100644
--- a/mdel.1
+++ b/mdel.1
@@ -1,5 +1,5 @@
'\" t
-.TH mdel 1 "28Nov20" mtools-4.0.26
+.TH mdel 1 "08Jan22" mtools-4.0.37
.SH Name
mdel - delete an MSDOS file
'\" t
diff --git a/mdel.c b/mdel.c
index e650d71..4f0de7b 100644
--- a/mdel.c
+++ b/mdel.c
@@ -80,7 +80,7 @@ static int del_entry(direntry_t *entry, MainParam_t *mp)
progname, tmp))
return ERROR_ONE;
}
- if (fatFreeWithDirentry(entry))
+ if (fatFreeWithDirentry(entry))
return ERROR_ONE;
wipeEntry(entry);
@@ -95,14 +95,14 @@ static int del_file(direntry_t *entry, MainParam_t *mp)
Arg_t *arg = (Arg_t *) mp->arg;
MainParam_t sonmp;
int ret;
- int r;
+ int r;
sonmp = *mp;
sonmp.arg = mp->arg;
r = 0;
if (IS_DIR(entry)){
- /* a directory */
+ /* a directory */
SubDir = OpenFileByDirentry(entry);
initializeDirentry(&subEntry, SubDir);
ret = 0;
@@ -143,9 +143,9 @@ static int del_file(direntry_t *entry, MainParam_t *mp)
static void usage(int ret) NORETURN;
static void usage(int ret)
{
- fprintf(stderr,
+ fprintf(stderr,
"Mtools version %s, dated %s\n", mversion, mdate);
- fprintf(stderr,
+ fprintf(stderr,
"Usage: %s [-v] msdosfile [msdosfiles...]\n", progname);
exit(ret);
}
@@ -205,6 +205,6 @@ void mdel(int argc, char **argv, int deltype)
if(l > 1 && argv[i][b+l-1] == '/')
argv[i][b+l-1] = '\0';
}
-
+
exit(main_loop(&mp, argv + optind, argc - optind));
}
diff --git a/mdeltree.1 b/mdeltree.1
index 8707f73..30d661d 100644
--- a/mdeltree.1
+++ b/mdeltree.1
@@ -1,5 +1,5 @@
'\" t
-.TH mdeltree 1 "28Nov20" mtools-4.0.26
+.TH mdeltree 1 "08Jan22" mtools-4.0.37
.SH Name
mdeltree - recursively delete an MSDOS directory and its contents
'\" t
diff --git a/mdir.1 b/mdir.1
index 40f607a..2d87122 100644
--- a/mdir.1
+++ b/mdir.1
@@ -1,5 +1,5 @@
'\" t
-.TH mdir 1 "28Nov20" mtools-4.0.26
+.TH mdir 1 "08Jan22" mtools-4.0.37
.SH Name
mdir - display an MSDOS directory
'\" t
diff --git a/mdir.c b/mdir.c
index 788ef5a..b1d4685 100644
--- a/mdir.c
+++ b/mdir.c
@@ -48,14 +48,14 @@ static Stream_t *currentDir;
static int filesInDir; /* files in current dir */
static int filesOnDrive; /* files on drive */
-
+
static int dirsOnDrive; /* number of listed directories on this drive */
static int debug = 0; /* debug mode */
-static mt_size_t bytesInDir;
-static mt_size_t bytesOnDrive;
-static Stream_t *RootDir;
+static mt_off_t bytesInDir;
+static mt_off_t bytesOnDrive;
+static Stream_t *RootDir;
static char mdir_shortname[4*12+1];
@@ -105,7 +105,7 @@ static __inline__ void print_time(struct directory *dir)
{
char am_pm;
int hour = DOS_HOUR(dir);
-
+
if(!mtools_twenty_four_hour_clock) {
am_pm = (hour >= 12) ? 'p' : 'a';
if (hour > 12)
@@ -121,11 +121,11 @@ static __inline__ void print_time(struct directory *dir)
/*
* Return a number in dotted notation
*/
-static const char *dotted_num(mt_size_t num, int width, char **buf)
+static const char *dotted_num(mt_off_t num, size_t width, char **buf)
{
size_t len;
register char *srcp, *dstp;
- int size;
+ size_t size;
unsigned long numlo;
unsigned long numhi;
@@ -135,18 +135,18 @@ static const char *dotted_num(mt_size_t num, int width, char **buf)
if (*buf == NULL)
return "";
-
+
/* Create the number in maximum width; make sure that the string
* length is not exceeded (in %6ld, the result can be longer than 6!)
*/
numlo = num % 1000000000;
- numhi = num / 1000000000;
+ numhi = (unsigned long) (num / 1000000000);
if(numhi && size > 9) {
- sprintf(*buf, "%.*lu%09lu", size-9, numhi, numlo);
+ sprintf(*buf, "%.*lu%09lu", (int)(size-9), numhi, numlo);
} else {
- sprintf(*buf, "%.*lu", size, numlo);
+ sprintf(*buf, "%.*lu", (int) size, numlo);
}
for (srcp=*buf; srcp[1] != '\0'; ++srcp)
@@ -154,7 +154,7 @@ static const char *dotted_num(mt_size_t num, int width, char **buf)
srcp[0] = ' ';
else
break;
-
+
len = strlen(*buf);
srcp = (*buf)+len;
dstp = (*buf)+len+1;
@@ -172,7 +172,7 @@ static const char *dotted_num(mt_size_t num, int width, char **buf)
if (dstp + 3 < (*buf) + len)
/* use spaces instead of dots: they please both
* Americans and Europeans */
- dstp[3] = ' ';
+ dstp[3] = ' ';
srcp += 3;
dstp += 4;
}
@@ -184,7 +184,7 @@ static __inline__ int print_volume_label(Stream_t *Dir, char drive)
{
Stream_t *Stream = GetFs(Dir);
direntry_t entry;
- DeclareThis(FsPublic_t);
+ DeclareThis(Fs_t);
char shortname[13];
char longname[VBUFSIZE];
int r;
@@ -192,7 +192,7 @@ static __inline__ int print_volume_label(Stream_t *Dir, char drive)
RootDir = OpenRoot(Stream);
if(concise)
return 0;
-
+
/* find the volume label */
initializeDirentry(&entry, RootDir);
@@ -210,19 +210,21 @@ static __inline__ int print_volume_label(Stream_t *Dir, char drive)
else
printf(" Volume in drive %c is %s",
drive, shortname);
- if(This->serialized)
+ if(getSerialized(This)) {
+ unsigned long serial_number = getSerialNumber(This);
printf("\n Volume Serial Number is %04lX-%04lX",
- (This->serial_number >> 16) & 0xffff,
- This->serial_number & 0xffff);
+ (serial_number >> 16) & 0xffff,
+ serial_number & 0xffff);
+ }
return 0;
}
-static void printSummary(int files, mt_size_t bytes)
+static void printSummary(int files, mt_off_t bytes)
{
if(!filesInDir)
printf("No files\n");
- else {
+ else {
char *s1 = NULL;
printf(" %3d file", files);
if(files == 1)
@@ -279,10 +281,10 @@ static int enterDrive(Stream_t *Dir, char drive)
int r;
if(currentDrive == drive)
return 0; /* still the same */
-
+
leaveDrive(0);
currentDrive = drive;
-
+
r = print_volume_label(Dir, drive);
if (r)
return r;
@@ -306,7 +308,7 @@ static void leaveDirectory(int haveError)
free(dynDirPath);
if(wide)
putchar('\n');
-
+
if(!concise)
printSummary(filesInDir, bytesInDir);
}
@@ -372,21 +374,21 @@ static int list_file(direntry_t *entry, MainParam_t *mp UNUSEDP)
return ERROR_ONE;
if (wide) {
if(filesInDir % 5)
- putchar(' ');
+ putchar(' ');
else
putchar('\n');
}
-
+
if(IS_DIR(entry)){
size = 0;
} else
size = FILE_SIZE(&entry->dir);
-
+
Case = entry->dir.Case;
- if(!(Case & (BASECASE | EXTCASE)) &&
+ if(!(Case & (BASECASE | EXTCASE)) &&
mtools_ignore_short_case)
Case |= BASECASE | EXTCASE;
-
+
cp = GET_DOSCONVERT(entry->Dir);
dos_to_wchar(cp, entry->dir.ext, ext, 3);
if(Case & EXTCASE){
@@ -411,13 +413,13 @@ static int list_file(direntry_t *entry, MainParam_t *mp UNUSEDP)
(int) (15 - 2 - strlen(mdir_shortname)), "");
else
printf("%-15s", mdir_shortname);
- } else if(!concise) {
+ } else if(!concise) {
char tmpBasename[4*8+1];
char tmpExt[4*3+1];
WCHAR_TO_NATIVE(name,tmpBasename,8);
WCHAR_TO_NATIVE(ext,tmpExt,3);
- if (name[0] == ' ')
+ if (name[0] == ' ')
printf(" ");
else if(mtools_dotted_dir)
printf("%-12s ", mdir_shortname);
@@ -435,7 +437,7 @@ static int list_file(direntry_t *entry, MainParam_t *mp UNUSEDP)
if(debug)
printf(" %s %d ", tmpBasename, START(&entry->dir));
-
+
if(*mdir_longname)
printf(" %s", mdir_longname);
printf("\n");
@@ -453,8 +455,8 @@ static int list_file(direntry_t *entry, MainParam_t *mp UNUSEDP)
filesOnDrive++;
filesInDir++;
- bytesOnDrive += (mt_size_t) size;
- bytesInDir += (mt_size_t) size;
+ bytesOnDrive += size;
+ bytesInDir += size;
return GOT_ONE;
}
@@ -499,7 +501,7 @@ static int list_recurs_directory(direntry_t *entry UNUSEDP,
/* then list subdirectories */
subMp = *mp;
subMp.lookupflags = ACCEPT_DIR | NO_DOTS | NO_MSG | DO_OPEN;
- return ret | mp->loop(mp->File, &subMp, "*");
+ return ret | mp->loop(mp->File, &subMp, "*") | GOT_ONE;
}
#if 0
@@ -600,11 +602,12 @@ void mdir(int argc, char **argv, int type UNUSEDP)
if (testmode) {
mp.lookupflags = ACCEPT_DIR | NO_DOTS;
mp.dirCallback = test_directory;
- } else
+ } else
#endif
- if(recursive) {
- mp.lookupflags = ACCEPT_DIR | DO_OPEN_DIRS | NO_DOTS;
+ if(recursive) {
+ mp.lookupflags = ACCEPT_DIR | ACCEPT_PLAIN | DO_OPEN_DIRS | NO_DOTS;
mp.dirCallback = list_recurs_directory;
+ mp.callback = list_file;
} else {
mp.lookupflags = ACCEPT_DIR | ACCEPT_PLAIN | DO_OPEN_DIRS;
mp.dirCallback = list_non_recurs_directory;
diff --git a/mdoctorfat.c b/mdoctorfat.c
index 5cbe06c..8ff3893 100644
--- a/mdoctorfat.c
+++ b/mdoctorfat.c
@@ -37,7 +37,7 @@ typedef struct Arg_t {
uint32_t fat;
int markbad;
int setsize;
- unsigned long size;
+ uint32_t size;
Fs_t *Fs;
} Arg_t;
@@ -45,16 +45,16 @@ static int dos_doctorfat(direntry_t *entry, MainParam_t *mp)
{
Fs_t *Fs = getFs(mp->File);
Arg_t *arg=(Arg_t *) mp->arg;
-
+
if(!arg->markbad && entry->entry != -3) {
/* if not root directory, change it */
set_word(entry->dir.start, arg->fat & 0xffff);
set_word(entry->dir.startHi, arg->fat >> 16);
if(arg->setsize)
set_dword(entry->dir.size, arg->size);
- dir_write(entry);
+ dir_write(entry);
}
- arg->Fs = Fs;
+ arg->Fs = Fs;
return GOT_ONE;
}
@@ -84,7 +84,7 @@ void mdoctorfat(int argc, char **argv, int mtype UNUSEDP)
char *number, *eptr;
int i;
unsigned int offset;
-
+
/* get command line options */
init_clash_handling(& arg.ch);
@@ -112,14 +112,14 @@ void mdoctorfat(int argc, char **argv, int mtype UNUSEDP)
break;
case 's':
arg.setsize=1;
- arg.size = strtoul(optarg,&endptr,0);
+ arg.size = strtou32(optarg,&endptr,0);
break;
case 'h':
usage(0);
case '?':
usage(1);
}
- check_number_parse_errno(c, optarg, endptr);
+ check_number_parse_errno((char)c, optarg, endptr);
}
if (argc - optind < 2)
@@ -129,10 +129,10 @@ void mdoctorfat(int argc, char **argv, int mtype UNUSEDP)
/* only 1 file to copy... */
init_mp(&arg.mp);
arg.mp.arg = (void *) &arg;
-
+
arg.mp.callback = dos_doctorfat;
arg.mp.unixcallback = unix_doctorfat;
-
+
arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR | DO_OPEN;
arg.mp.openflags = O_RDWR;
arg.fat = strtoui(argv[optind+1], 0, 0) + offset;
diff --git a/mdu.1 b/mdu.1
index 564d9e4..057d3c5 100644
--- a/mdu.1
+++ b/mdu.1
@@ -1,5 +1,5 @@
'\" t
-.TH mdu 1 "28Nov20" mtools-4.0.26
+.TH mdu 1 "08Jan22" mtools-4.0.37
.SH Name
mdu - display the amount of space occupied by an MSDOS directory
'\" t
diff --git a/mdu.c b/mdu.c
index b6a7523..b17f46d 100644
--- a/mdu.c
+++ b/mdu.c
@@ -69,7 +69,7 @@ static int dir_mdu(direntry_t *entry, MainParam_t *mp)
Arg_t *parentArg = (Arg_t *) (mp->arg);
Arg_t arg;
int ret;
-
+
arg = *parentArg;
arg.mp.arg = (void *) &arg;
arg.parent = parentArg;
diff --git a/mformat.1 b/mformat.1
index 89fd43a..045ca48 100644
--- a/mformat.1
+++ b/mformat.1
@@ -1,5 +1,5 @@
'\" t
-.TH mformat 1 "28Nov20" mtools-4.0.26
+.TH mformat 1 "08Jan22" mtools-4.0.37
.SH Name
mformat - add an MSDOS filesystem to a low-level formatted floppy disk
'\" t
diff --git a/mformat.c b/mformat.c
index cd2e5f3..75cc926 100644
--- a/mformat.c
+++ b/mformat.c
@@ -24,40 +24,32 @@
#include "msdos.h"
#include "mtools.h"
#include "mainloop.h"
+#include "device.h"
+#include "old_dos.h"
#include "fsP.h"
#include "file.h"
#include "plain_io.h"
-#include "floppyd_io.h"
#include "nameclash.h"
#include "buffer.h"
#ifdef HAVE_ASSERT_H
#include <assert.h>
#endif
-#ifdef USE_XDF
-#include "xdf_io.h"
-#endif
+#include "stream.h"
#include "partition.h"
+#include "open_image.h"
#include "file_name.h"
-
-#ifndef abs
-#define abs(x) ((x)>0?(x):-(x))
-#endif
+#include "lba.h"
#ifdef OS_linux
#include "linux/hdreg.h"
-
-#define _LINUX_STRING_H_
-#define kdev_t int
#include "linux/fs.h"
-#undef _LINUX_STRING_H_
#endif
-
-static int init_geometry_boot(union bootsector *boot, struct device *dev,
- uint8_t sectors0,
- uint8_t rate_0, uint8_t rate_any,
- unsigned long *tot_sectors, int keepBoot)
+static uint16_t init_geometry_boot(union bootsector *boot, struct device *dev,
+ uint8_t sectors0,
+ uint8_t rate_0, uint8_t rate_any,
+ uint32_t *tot_sectors, int keepBoot)
{
int nb_renum;
int sector2;
@@ -70,19 +62,18 @@ static int init_geometry_boot(union bootsector *boot, struct device *dev,
assert(*tot_sectors != 0);
#endif
- if (*tot_sectors <= UINT16_MAX){
+ if (*tot_sectors <= UINT16_MAX && dev->hidden <= UINT16_MAX){
set_word(boot->boot.psect, (uint16_t) *tot_sectors);
set_dword(boot->boot.bigsect, 0);
- } else if(*tot_sectors <= UINT32_MAX){
+ set_word(boot->boot.nhs, (uint16_t) dev->hidden);
+ } else {
set_word(boot->boot.psect, 0);
set_dword(boot->boot.bigsect, (uint32_t) *tot_sectors);
- } else {
- fprintf(stderr, "Too many sectors %ld\n", *tot_sectors);
- exit(1);
+ set_dword(boot->boot.nhs, dev->hidden);
}
if (dev->use_2m & 0x7f){
- int bootOffset;
+ uint16_t bootOffset;
uint8_t j;
uint8_t size2;
uint16_t i;
@@ -122,7 +113,7 @@ static int init_geometry_boot(union bootsector *boot, struct device *dev,
boot->bytes[i++] = size2;
sector2 -= (1 << size2) >> 2;
}
- boot->bytes[nb_renum] = ( i - nb_renum - 1 ) / 3;
+ boot->bytes[nb_renum] = (uint8_t)(( i - nb_renum - 1 )/3);
set_word(boot->boot.ext.old.InfTm, i);
@@ -141,7 +132,7 @@ static int init_geometry_boot(union bootsector *boot, struct device *dev,
/* checksum */
for (sum=0, j=64; j<i; j++)
sum += boot->bytes[j];/* checksum */
- boot->boot.ext.old.CheckSum=-sum;
+ boot->boot.ext.old.CheckSum=(unsigned char)-sum;
return bootOffset;
} else {
if(!keepBoot) {
@@ -158,133 +149,31 @@ static int init_geometry_boot(union bootsector *boot, struct device *dev,
}
}
+static unsigned char bootprog[]=
+{0xfa, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xc0, 0xfc, 0xb9, 0x00, 0x01,
+ 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x80, 0xf3, 0xa5, 0xea, 0x00, 0x00,
+ 0x00, 0x08, 0xb8, 0x01, 0x02, 0xbb, 0x00, 0x7c, 0xba, 0x80, 0x00,
+ 0xb9, 0x01, 0x00, 0xcd, 0x13, 0x72, 0x05, 0xea, 0x00, 0x7c, 0x00,
+ 0x00, 0xcd, 0x19};
-static int comp_fat_bits(Fs_t *Fs, int estimate,
- unsigned long tot_sectors, int fat32)
-{
- int needed_fat_bits;
-
- needed_fat_bits = 12;
-
-#define MAX_DISK_SIZE(bits,clusters) \
- TOTAL_DISK_SIZE((bits), Fs->sector_size, (clusters), \
- Fs->num_fat, MAX_BYTES_PER_CLUSTER/Fs->sector_size)
-
- if(tot_sectors > MAX_DISK_SIZE(12, FAT12-1))
- needed_fat_bits = 16;
- if(fat32 || tot_sectors > MAX_DISK_SIZE(16, FAT16-1))
- needed_fat_bits = 32;
-
-#undef MAX_DISK_SIZE
-
- if(abs(estimate) && abs(estimate) < needed_fat_bits) {
- if(fat32) {
- fprintf(stderr,
- "Contradiction between FAT size on command line and FAT size in conf file\n");
- exit(1);
- }
- fprintf(stderr,
- "Device too big for a %d bit FAT\n",
- estimate);
- exit(1);
- }
-
- if(!estimate) {
- unsigned int min_fat16_size;
-
- if(needed_fat_bits > 12)
- return needed_fat_bits;
- min_fat16_size = DISK_SIZE(16, Fs->sector_size, FAT12,
- Fs->num_fat, 1);
- if(tot_sectors < min_fat16_size)
- return 12;
- else if(Fs->cluster_size == 0 &&
- tot_sectors >= 2* min_fat16_size)
- return 16; /* heuristics */
- }
-
- return estimate;
-}
-
-
-/*
- * According to Microsoft "Hardware White Paper", "Microsoft
- * Extensible Formware Initiative", "FAT32 File System Specification",
- * Version 1.03, December 6, 2000:
- * If (CountofClusters < 4085) { // 0x0ff5
- * // Volume is FAT12
- * } else if (CountofClusters < 65525) { // 0xfff5
- * // Volume is FAT16
- * } else {
- * //Volume is FAT32
- * }
- *
- * This document can be found at the following URL:
- * https://staff.washington.edu/dittrich/misc/fatgen103.pdf
- * The relevant passus is on page 15.
- *
- * Actually, experimentations with Windows NT 4 show that the
- * cutoff is 4087 rather than 4085... This is Microsoft after all.
- * Not sure what the other Microsoft OS'es do though...
- */
-static void calc_fat_bits2(Fs_t *Fs, unsigned long tot_sectors, int fat_bits,
- int may_change_cluster_size,
- int may_change_root_size)
+static __inline__ void inst_boot_prg(union bootsector *boot, uint16_t offset)
{
- unsigned long rem_sect;
-
- /*
- * the "remaining sectors" after directory and boot
- * hasve been accounted for.
- */
- rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
- switch(abs(fat_bits)) {
- case 0:
-
-#define MY_DISK_SIZE(bits,clusters) \
- DISK_SIZE( (bits), Fs->sector_size, (clusters), \
- Fs->num_fat, Fs->cluster_size)
-
- if(rem_sect >= MY_DISK_SIZE(16, FAT12+2))
- /* big enough for FAT16
- * We take a margin of 2, because NT4
- * misbehaves, and starts considering a disk
- * as FAT16 only if it is larger than 4086
- * sectors, rather than 4084 as it should
- */
- set_fat16(Fs);
- else if(rem_sect <= MY_DISK_SIZE(12, FAT12-1))
- /* small enough for FAT12 */
- set_fat12(Fs);
- else {
- /* "between two chairs",
- * augment cluster size, and
- * settle it */
- if(may_change_cluster_size &&
- Fs->cluster_size * Fs->sector_size * 2
- <= MAX_BYTES_PER_CLUSTER)
- Fs->cluster_size <<= 1;
- else if(may_change_root_size) {
- Fs->dir_len +=
- rem_sect - MY_DISK_SIZE(12, FAT12-1);
- }
- set_fat12(Fs);
- }
- break;
-#undef MY_DISK_SIZE
-
- case 12:
- set_fat12(Fs);
- break;
- case 16:
- set_fat16(Fs);
- break;
- case 32:
- set_fat32(Fs);
- break;
+ memcpy(boot->bytes + offset, bootprog, sizeof(bootprog));
+ if(offset - 2 < 0x80) {
+ /* short jump */
+ boot->boot.jump[0] = 0xeb;
+ boot->boot.jump[1] = (uint8_t) (offset -2);
+ boot->boot.jump[2] = 0x90;
+ } else {
+ /* long jump, if offset is too large */
+ boot->boot.jump[0] = 0xe9;
+ boot->boot.jump[1] = (uint8_t) (offset - 3);
+ boot->boot.jump[2] = (uint8_t) ( (offset - 3) >> 8);
}
+ set_word(boot->boot.jump + offset + 20, offset + 24);
}
+/* Set up the root directory */
static __inline__ void format_root(Fs_t *Fs, char *label, union bootsector *boot)
{
Stream_t *RootDir;
@@ -314,8 +203,8 @@ static __inline__ void format_root(Fs_t *Fs, char *label, union bootsector *boot
} else
dirlen = Fs->dir_len;
for (i = 0; i < dirlen; i++)
- WRITES(RootDir, buf, sectorsToBytes((Stream_t*)Fs, i),
- Fs->sector_size);
+ PWRITES(RootDir, buf, sectorsToBytes(Fs, i),
+ Fs->sector_size);
ch.ignore_entry = 1;
if(label[0])
@@ -325,375 +214,610 @@ static __inline__ void format_root(Fs_t *Fs, char *label, union bootsector *boot
if(Fs->fat_bits == 32)
set_word(boot->boot.dirents, 0);
else
- set_word(boot->boot.dirents, Fs->dir_len * (Fs->sector_size / 32));
+ set_word(boot->boot.dirents,
+ (uint16_t) (Fs->dir_len * (Fs->sector_size / 32)));
free(buf);
}
-
-#ifdef USE_XDF
-static void xdf_calc_fat_size(Fs_t *Fs, unsigned long tot_sectors,
- int fat_bits)
-{
- unsigned int rem_sect;
-
- rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start - 2 * Fs->fat_len;
-
- if(Fs->fat_len) {
- /* an XDF disk, we know the fat_size and have to find
- * out the rest. We start with a cluster size of 1 and
- * keep doubling until everything fits into the
- * FAT. This will occur eventually, as our FAT has a
- * minimal size of 1 */
- for(Fs->cluster_size = 1; 1 ; Fs->cluster_size <<= 1) {
- Fs->num_clus = rem_sect / Fs->cluster_size;
- if(abs(fat_bits) == 16 || Fs->num_clus >= FAT12)
- set_fat16(Fs);
- else
- set_fat12(Fs);
- if (Fs->fat_len >= NEEDED_FAT_SIZE(Fs))
- return;
- }
- }
- fprintf(stderr,"Internal error while calculating Xdf fat size\n");
- exit(1);
-}
-#endif
-
-static void calc_fat_size(Fs_t *Fs, unsigned long tot_sectors)
+/*
+ * Calculate length of one FAT, in sectors, given the number of total sectors
+ * Returns
+ * -2: if there are less total sectors than even clus_start
+ * 0: if a length was successfully calculated. (in that case, it is filled
+ * into Fs->fat_len)
+ * 1: if the specified number of FAT bits cannot accomodate that many
+ * sectors => caller should raise FAT bits
+ */
+static int calc_fat_len(Fs_t *Fs, uint32_t tot_sectors)
{
- unsigned long rem_sect;
- unsigned long real_rem_sect;
- unsigned long numerator;
- unsigned long denominator;
+ uint32_t rem_sect;
+ uint32_t numerator;
+ uint32_t denominator;
+ uint32_t corr=0; /* correct numeric overflow */
+ uint32_t clus_start;
unsigned int fat_nybbles;
- unsigned int slack;
- int printGrowMsg=1; /* Should we print "growing FAT" messages ?*/
+
+#ifdef HAVE_ASSERT_H
+ assert(Fs->fat_bits != 0);
+#endif
#ifdef DEBUG
fprintf(stderr, "Fat start=%d\n", Fs->fat_start);
fprintf(stderr, "tot_sectors=%lu\n", tot_sectors);
fprintf(stderr, "dir_len=%d\n", Fs->dir_len);
#endif
- real_rem_sect = rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
+ Fs->fat_len = 0;
+ clus_start = calc_clus_start(Fs);
+ if(tot_sectors < clus_start)
+ return -2;
+ rem_sect = tot_sectors - clus_start;
/* Cheat a little bit to address the _really_ common case of
odd number of remaining sectors while both nfat and cluster size
are even... */
- if(rem_sect %2 == 1 &&
- Fs->num_fat %2 == 0 &&
- Fs->cluster_size %2 == 0)
+ if(rem_sect % 2 == 1 &&
+ Fs->num_fat % 2 == 0 &&
+ Fs->cluster_size % 2 == 0)
rem_sect--;
#ifdef DEBUG
fprintf(stderr, "Rem sect=%lu\n", rem_sect);
#endif
- if(Fs->fat_bits == 0) {
- fprintf(stderr, "Weird, fat bits = 0\n");
- exit(1);
- }
-
-
/* See fat_size_calculation.tex or
- (http://ftp.gnu.org/software/mtools/manual/fat_size_calculation.pdf)
+ (https://www.gnu.org/gnu/mtools/manual/fat_size_calculation.pdf)
for an explantation about why the stuff below works...
*/
fat_nybbles = Fs->fat_bits / 4;
numerator = rem_sect+2*Fs->cluster_size;
+ /* Might overflow, but will be cancelled out below. As the
+ operation is unsigned, a posteriori fixup is allowable, as
+ wrap-around is part of the spec. For *signed* quantities,
+ this hack would be incorrect, as it would be "undefined
+ behavior" */
+
+ /* Initial denominator is nybbles consumed by one cluster, both in
+ * FAT and in cluster space */
denominator =
Fs->cluster_size * Fs->sector_size * 2 +
Fs->num_fat * fat_nybbles;
- if(fat_nybbles == 3)
+ if(fat_nybbles == 3) {
+ /* We need to do this test here, or multiplying rem_sect with
+ * fat_nybbles might overflow */
+ if(rem_sect > 256 * FAT12)
+ return 1;
numerator *= fat_nybbles;
- else
+ } else
/* Avoid numerical overflows, divide the denominator
* rather than multiplying the numerator */
denominator = denominator / fat_nybbles;
+ /* Substract denominator from numerator to "cancel out" an
+ unsigned integer overflow which might have happened with
+ total number of sectors very near maximum (2^32-1) and huge
+ cluster size. This substraction removes 1 from the result
+ of the following division, so we will add 1 again after the
+ division. However, we only do this if (original) numerator
+ is bigger than denominator though, as otherwise we risk the
+ inverse problem of going below 0 on small disks */
+ if(rem_sect > denominator) {
+ numerator -= denominator;
+ corr++;
+ }
+
#ifdef DEBUG
fprintf(stderr, "Numerator=%lu denominator=%lu\n",
numerator, denominator);
#endif
- Fs->fat_len = (numerator-1)/denominator+1;
- Fs->num_clus = (rem_sect-(Fs->fat_len*Fs->num_fat))/Fs->cluster_size;
+ Fs->fat_len = (numerator-1)/denominator+1+corr;
+ return 0;
+}
- /* Apply upper bounds for FAT bits */
- if(Fs->fat_bits == 16 && Fs->num_clus >= FAT16)
- Fs->num_clus = FAT16-1;
- if(Fs->fat_bits == 12 && Fs->num_clus >= FAT12)
- Fs->num_clus = FAT12-1;
+/* Is there enough space in the FAT for the descriptors for all clusters.
+ * This only works if we assume that it is already clear that Fs->num_clus is
+ * less than FAT32, or else it might overflow */
+static inline bool clusters_fit_into_fat(Fs_t *Fs) {
+ return ((Fs->num_clus+2) * (Fs->fat_bits/4) - 1) / (Fs->sector_size*2) <
+ Fs->fat_len;
+}
+
+/*
+ * Assert that FAT param calculation has been performed correctly, and
+ * set_fat
+ */
+static void check_fs_params_and_set_fat(Fs_t *Fs, uint32_t tot_sectors)
+{
+ unsigned int provisional_fat_bits;
- /* A safety, if above math is correct, this should not be happen...*/
- if(Fs->num_clus > (Fs->fat_len * Fs->sector_size * 2 /
- fat_nybbles - 2)) {
- fprintf(stderr,
- "Fat size miscalculation, shrinking num_clus from %d ",
- Fs->num_clus);
- Fs->num_clus = (Fs->fat_len * Fs->sector_size * 2 /
- fat_nybbles - 2);
- fprintf(stderr, " to %d\n", Fs->num_clus);
- }
#ifdef DEBUG
fprintf(stderr, "Num_clus=%d fat_len=%d nybbles=%d\n",
Fs->num_clus, Fs->fat_len, fat_nybbles);
#endif
- if ( Fs->num_clus < FAT16 && Fs->fat_bits > 16 ){
- fprintf(stderr,"Too few clusters for this fat size."
- " Please choose a 16-bit fat in your /etc/mtools.conf"
- " or .mtoolsrc file\n");
- exit(1);
- }
-
- /* As the number of clusters is specified nowhere in the boot sector,
- * it will be calculated by removing everything else from total number
- * of sectors. This means that if we reduced the number of clusters
- * above, we will have to grow the FAT in order to take up any excess
- * sectors... */
#ifdef HAVE_ASSERT_H
- assert(rem_sect >= Fs->num_clus * Fs->cluster_size +
- Fs->fat_len * Fs->num_fat);
-#endif
- slack = rem_sect -
- Fs->num_clus * Fs->cluster_size -
- Fs->fat_len * Fs->num_fat;
- if(slack >= Fs->cluster_size) {
- /* This can happen under two circumstances:
- 1. We had to reduce num_clus because we reached maximum
- number of cluster for FAT12 or FAT16
- */
- if(printGrowMsg) {
- fprintf(stderr, "Slack=%d\n", slack);
- fprintf(stderr, "Growing fat size from %d",
- Fs->fat_len);
- }
- Fs->fat_len +=
- (slack - Fs->cluster_size) / Fs->num_fat + 1;
- if(printGrowMsg) {
- fprintf(stderr,
- " to %d in order to take up excess cluster area\n",
- Fs->fat_len);
- }
- Fs->num_clus = (rem_sect-(Fs->fat_len*Fs->num_fat))/
- Fs->cluster_size;
-
- }
+ /* if FAT bits is 32, dir_len must be zero, otherwise it must be
+ * non-zero */
+ assert(Fs->fat_bits == 32 ? (Fs->dir_len == 0) : (Fs->dir_len != 0));
+
+ /* Clusters must fill disk up entirely, except for small amount of
+ * slack smaller than one sector */
+ assert(tot_sectors >=
+ Fs->clus_start + Fs->num_clus * Fs->cluster_size);
+ assert(tot_sectors <=
+ Fs->clus_start + Fs->num_clus * Fs->cluster_size +
+ Fs->cluster_size - 1);
-#ifdef HAVE_ASSERT_H
/* Fat must be big enough for all clusters */
- assert( ((Fs->num_clus+2) * fat_nybbles) <=
- (Fs->fat_len*Fs->sector_size*2));
-
- /* num_clus must be big enough to cover rest of disk, or else further
- * users of the filesystem will assume a bigger num_clus, which might
- * be too big for fat_len */
- assert(Fs->num_clus ==
- (real_rem_sect - Fs->num_fat * Fs->fat_len) / Fs->cluster_size);
+ assert(clusters_fit_into_fat(Fs));
+#endif
+ provisional_fat_bits = Fs->fat_bits;
+ set_fat(Fs);
+#ifdef HAVE_ASSERT_H
+ assert(provisional_fat_bits == Fs->fat_bits);
#endif
}
+static void fat32_specific_init(Fs_t *Fs) {
+ Fs->primaryFat = 0;
+ Fs->writeAllFats = 1;
+ if(!Fs->backupBoot) {
+ if(Fs->fat_start <= 6)
+ Fs->backupBoot = Fs->fat_start - 1;
+ else
+ Fs->backupBoot=6;
+ }
-static unsigned char bootprog[]=
-{0xfa, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xc0, 0xfc, 0xb9, 0x00, 0x01,
- 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x80, 0xf3, 0xa5, 0xea, 0x00, 0x00,
- 0x00, 0x08, 0xb8, 0x01, 0x02, 0xbb, 0x00, 0x7c, 0xba, 0x80, 0x00,
- 0xb9, 0x01, 0x00, 0xcd, 0x13, 0x72, 0x05, 0xea, 0x00, 0x7c, 0x00,
- 0x00, 0xcd, 0x19};
+ if(Fs->fat_start < 3) {
+ fprintf(stderr,
+ "For FAT 32, reserved sectors need to be at least 3\n");
+ exit(1);
+ }
-static __inline__ void inst_boot_prg(union bootsector *boot, int offset)
-{
- memcpy((char *) boot->boot.jump + offset,
- (char *) bootprog, sizeof(bootprog) /sizeof(bootprog[0]));
- if(offset - 2 < 0x80) {
- /* short jump */
- boot->boot.jump[0] = 0xeb;
- boot->boot.jump[1] = offset -2;
- boot->boot.jump[2] = 0x90;
- } else {
- /* long jump, if offset is too large */
- boot->boot.jump[0] = 0xe9;
- boot->boot.jump[1] = offset -3;
- boot->boot.jump[2] = 0x00;
+ if(Fs->fat_start <= Fs->backupBoot) {
+ fprintf(stderr,
+ "Reserved sectors (%d) must be more than backupBoot (%d)\n", Fs->fat_start, Fs->backupBoot);
+ Fs->backupBoot = 0;
}
- set_word(boot->boot.jump + offset + 20, offset + 24);
}
-static void calc_cluster_size(struct Fs_t *Fs, unsigned long tot_sectors,
- int fat_bits)
-
+/* Try given cluster- and fat_size (and other parameters), and say whether
+ * cluster_size/fat_bits should be increased, decreased, or is fine as is.
+ * Parameters
+ * Fs the file system object
+ * tot_sectors size of file system, in sectors
+ * may_change_boot_size try_cluster_size may increase number of boot
+ * (reserved) sectors to make everything fit
+ * may_change_fat_len try_cluster_size may change (compute) FAT length
+ * may_change_root_size try_cluster_size may increase root directory size
+ * to make everything fit
+ * may_pad if there are (slightly) too many clusters,
+ * try_cluster_size may artificially inflate number of
+ * boot sectors, fat length or root_size to take up
+ * space in order to reduce number clusters below limit
+ *
+ * Return values
+ * -2 Too few sectors to contain even the header (reserved sectors, minimal
+ * FAT and root directory), or other internal error
+ * -1 This cluster size leads to too few clusters for the FAT size.
+ * Caller should either reduce cluster size or FAT size, and try again
+ * 0 Everything fits
+ * 1 This cluster size leads to too many clusters for the FAT
+ * size. Caller should either increase cluster size or FAT size, and
+ * try again
+ * 2 Fat length is set, and there are too many clusters to fit into
+ * that Fat length. Caller should either increase cluster size, or
+ * decrease FAT size, and try again
+ *
+ */
+static int try_cluster_size(Fs_t *Fs,
+ uint32_t tot_sectors,
+ bool may_change_boot_size,
+ bool may_change_fat_len,
+ bool may_change_root_size,
+ bool may_pad)
{
- unsigned int max_clusters; /* maximal possible number of sectors for
- * this FAT entry length (12/16/32) */
- unsigned int max_fat_size; /* maximal size of the FAT for this FAT
- * entry length (12/16/32) */
- unsigned int rem_sect; /* remaining sectors after we accounted for
- * the root directory and boot sector(s) */
-
- switch(abs(fat_bits)) {
- case 12:
- max_clusters = FAT12-1;
- max_fat_size = Fs->num_fat *
- FAT_SIZE(12, Fs->sector_size, max_clusters);
- break;
- case 16:
- case 0: /* still hesititating between 12 and 16 */
- max_clusters = FAT16-1;
- max_fat_size = Fs->num_fat *
- FAT_SIZE(16, Fs->sector_size, max_clusters);
- break;
- case 32:
- /*
- FAT32 cluster sizes for disks with 512 block size
- according to Microsoft specification fatgen103.doc:
-
- 32.5 MB - 260 MB cluster_size = 1
- 260 MB - 8 GB cluster_size = 8
- 8 GB - 16 GB cluster_size = 16
- 16 GB - 32 GB cluster_size = 32
- 32 GB - 2 TB cluster_size = 64
-
- Below calculation is generalized and does not depend
- on 512 block size.
- */
- Fs->cluster_size = tot_sectors > 32*1024*1024*2 ? 64 :
- tot_sectors > 16*1024*1024*2 ? 32 :
- tot_sectors > 8*1024*1024*2 ? 16 :
- tot_sectors > 260*1024*2 ? 8 : 1;
- return;
- default:
- fprintf(stderr,"Bad fat size\n");
- exit(1);
+ uint32_t maxClus;
+ uint32_t minClus;
+
+ switch(Fs->fat_bits) {
+ case 12:
+ minClus = 1;
+ maxClus = FAT12;
+ break;
+ case 16:
+ minClus = 4096;
+ maxClus = FAT16;
+ break;
+ case 32:
+ minClus = FAT16;
+ maxClus = FAT32;
+ break;
+ default:
+#ifdef HAVE_ASSERT_H
+ assert(false && "Bad number of FAT bits");
+#endif
+ return -2;
}
- if(tot_sectors <= Fs->fat_start + Fs->num_fat + Fs->dir_len) {
- /* we need at least enough sectors to fit boot, fat and root
- * dir */
- fprintf(stderr, "Not enough sectors\n");
- exit(1);
+ if(getenv("MTOOLS_DEBUG_FAT")) {
+ fprintf(stderr, "FAT=%d Cluster=%d%s\n",
+ Fs->fat_bits, Fs->cluster_size,
+ may_pad ? " may_pad" : "");
}
- rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
+ if(may_change_fat_len) {
+ int fit=calc_fat_len(Fs, tot_sectors);
+ if(fit != 0)
+ return fit;
+ }
- /* double the cluster size until we can fill up the disk with
- * the maximal number of sectors of this size */
- while(Fs->cluster_size * max_clusters + max_fat_size < rem_sect) {
- if(Fs->cluster_size > 64) {
- /* bigger than 64. Should fit */
- fprintf(stderr,
- "Internal error while calculating cluster size\n");
- exit(1);
+ while(true) {
+ uint32_t bwaste; /* How many sectors we need to "waste" */
+ uint16_t waste;
+ uint16_t dir_grow=0;
+
+ if(calc_num_clus(Fs, tot_sectors) < 0)
+ return -2;
+ if(Fs->num_clus < minClus)
+ return -1; /* Not enough clusters => loop
+ * should shrink FAT bits again */
+
+ if(!may_change_fat_len) {
+ /* If fat_len has been explicitly specified by
+ * user, make sure that number of clusters
+ * fit within that fat_len */
+ if(Fs->num_clus >= FAT32 || !clusters_fit_into_fat(Fs))
+ return 2; /* Caller should should pick a
+ * bigger cluster size, but not a
+ * higher FAT bits */
}
- Fs->cluster_size <<= 1;
- }
-}
+ if(Fs->num_clus < maxClus)
+ break;
+ if(!may_pad)
+ return 1;
+
+ /* "Pad" fat by artifically adding sectors to boot sectors,
+ FAT or root directory to diminish number of clusters */
+
+ /* This is needed when a size of a FAT fs somehow is
+ * "in between" 2 fat bits: too large for FAT12, too small
+ * for FAT16.
+
+ * This happens because if there slightly too may
+ * clusters for FAT12, the system passes to
+ * FAT16. However, this makes the space taken up by
+ * the descriptor of each sector in the FAT larger,
+ * making the FAT larger overall, leaving less space
+ * for the clusters themselves, i.e. less
+ * clusters. Sometimes this is enough to push the
+ * number of clusters *below* the minimum for FAT12.
+
+ * a similar situation happens when switching from
+ * FAT16 to FAT32.
+
+ * if this happens, we switch back to the lower FAT
+ * bits, and allow "padding", i.e. artificially
+ * "wasting" space by adding more reserved (boot)
+ * sectors, adding "useless" extra sectors to the FAT,
+ * or allowing more root directory entries.
+
+ */
+ bwaste = tot_sectors - Fs->clus_start -
+ maxClus * Fs->cluster_size + 1;
+#ifdef HAVE_ASSERT_H
+ assert(bwaste <= UINT16_MAX);
+#endif
+ waste = (uint16_t) bwaste;
-static int old_dos_size_to_geom(size_t size,
- unsigned int *cyls,
- unsigned short *heads,
- unsigned short *sects)
-{
- struct OldDos_t *params = getOldDosBySize(size);
- if(params != NULL) {
- *cyls = params->tracks;
- *heads = params->heads;
- *sects = params->sectors;
- return 0;
- } else
- return 1;
-}
+ if(may_change_root_size) {
+ dir_grow = 32 - Fs->dir_len;
+ if(dir_grow > waste)
+ dir_grow = waste;
+ waste -= dir_grow;
+ }
+ if(may_change_fat_len &&
+ (!may_change_boot_size || Fs->fat_bits == 12)) {
+ uint16_t fat_grow =
+ (waste + Fs->num_fat - 1) / Fs->num_fat;
+ uint16_t dir_shrink = 0;
+ Fs->fat_len += fat_grow;
+
+ /* Shrink directory again, but at most as by as much
+ * as we grew it earlyer */
+ dir_shrink = waste - fat_grow * Fs->num_fat;
+ if(dir_shrink > dir_grow)
+ dir_shrink = dir_grow;
+ dir_grow -= dir_shrink;
+ } else if(may_change_boot_size) {
+ Fs->fat_start += waste;
+ }
+ Fs->dir_len += dir_grow;
+ /* If padding once failed, no point in keeping on retrying */
+ may_pad=false;
+ }
+#ifdef HAVE_ASSERT_H
+ /* number of clusters must be within allowable range for fat
+ bits */
+ assert(Fs->num_clus >= minClus);
+ assert(Fs->num_clus < maxClus);
+#endif
+ return 0;
+}
-static void calc_fs_parameters(struct device *dev, unsigned long tot_sectors,
- struct Fs_t *Fs, union bootsector *boot)
+/* Finds a set of filesystem parameters, given the device size, and
+ * any presets specified by user
+ * On return, Fs will be initialized, or one of the following error codes
+ * will be returned:
+ * -1 Not enough sectors for any kind of FAT filesystem
+ * -2 Not enough clusters for given number of FAT bits
+ * -3 Too many clusters for given number of FAT bits
+ * -4 Too many clusters for chosen FAT length
+ */
+int calc_fs_parameters(struct device *dev, bool fat32,
+ uint32_t tot_sectors,
+ struct Fs_t *Fs, uint8_t *descr)
{
+ bool may_change_boot_size = (Fs->fat_start == 0);
+ bool may_change_fat_bits = (dev->fat_bits == 0) && !fat32;
+ bool may_change_cluster_size = (Fs->cluster_size == 0);
+ bool may_change_root_size = (Fs->dir_len == 0);
+ bool may_change_fat_len = (Fs->fat_len == 0);
+ bool may_pad = false;
+ uint16_t saved_dir_len;
+
struct OldDos_t *params=NULL;
- if(dev->fat_bits == 0 || abs(dev->fat_bits) == 12)
+ Fs->infoSectorLoc = 0;
+ if( (may_change_fat_bits || abs(dev->fat_bits) == 12) &&
+ (may_change_boot_size || Fs->fat_start == 1) )
params = getOldDosByParams(dev->tracks,dev->heads,dev->sectors,
Fs->dir_len, Fs->cluster_size);
if(params != NULL) {
- boot->boot.descr = params->media;
+ int num_clus_valid;
+ *descr = params->media;
+ Fs->fat_start = 1;
Fs->cluster_size = params->cluster_size;
Fs->dir_len = params->dir_len;
Fs->fat_len = params->fat_len;
Fs->fat_bits = 12;
- } else {
- int may_change_cluster_size = (Fs->cluster_size == 0);
- int may_change_root_size = (Fs->dir_len == 0);
+ num_clus_valid = calc_num_clus(Fs, tot_sectors);
+#ifdef HAVE_ASSERT_H
+ assert(num_clus_valid >= 0);
+#endif
+ check_fs_params_and_set_fat(Fs, tot_sectors);
+ return 0;
+ }
- /* a non-standard format */
- if(DWORD(nhs) || tot_sectors % (dev->sectors * dev->heads))
- boot->boot.descr = 0xf8;
+ /* a format described by BPB */
+ if(dev->hidden || tot_sectors % (dev->sectors * dev->heads))
+ *descr = 0xf8;
+ else
+ *descr = 0xf0;
+
+ Fs->fat_bits = abs(dev->fat_bits);
+ if(Fs->fat_bits == 0)
+ /* If fat_bits not specified by device, start with a 12-bit
+ * FAT, unless 32 bit specified on command line */
+ Fs->fat_bits = fat32 ? 32 : 12;
+ if(!Fs->cluster_size) {
+ if(tot_sectors < 2400 && dev->heads == 2)
+ /* double sided double density floppies */
+ Fs->cluster_size = 2;
+ else if(may_change_fat_len && Fs->fat_bits == 32)
+ /* FAT32 => start with 8 */
+ Fs->cluster_size = 8;
else
- boot->boot.descr = 0xf0;
-
+ /* In all other cases, start with 1 */
+ Fs->cluster_size = 1;
+ }
- if(!Fs->cluster_size) {
+ if(!Fs->dir_len) {
+ if(tot_sectors < 1200) {
+ /* Double density floppies */
if (dev->heads == 1)
- Fs->cluster_size = 1;
- else {
- Fs->cluster_size = (tot_sectors > 2000 ) ? 1:2;
- if (dev->use_2m & 0x7f)
+ Fs->dir_len = 4;
+ else
+ Fs->dir_len = 7;
+ } else if(tot_sectors <= 3840)
+ /* High density floppies */
+ Fs->dir_len = 14;
+ else if(tot_sectors <= 7680)
+ /* extra density floppies */
+ Fs->dir_len = 15;
+ else
+ Fs->dir_len = 32;
+ }
+ saved_dir_len = Fs->dir_len;
+
+ while(true) {
+ int fit;
+ if(may_change_boot_size) {
+ if(Fs->fat_bits == 32)
+ Fs->fat_start = 32;
+ else
+ Fs->fat_start = 1;
+ }
+
+ if(Fs->fat_bits == 32)
+ Fs->dir_len = 0;
+ else if(Fs->dir_len == 0)
+ Fs->dir_len = saved_dir_len;
+
+ if(Fs->fat_bits == 32 &&
+ may_change_cluster_size && may_change_fat_len) {
+ /*
+ FAT32 cluster sizes for disks with 512 block size
+ according to Microsoft specification fatgen103.doc:
+
+ ...
+ - 8 GB cluster_size = 8
+ 8 GB - 16 GB cluster_size = 16
+ 16 GB - 32 GB cluster_size = 32
+ 32 GB - 2 TB cluster_size = 64
+
+ Below calculation is generalized and does not depend
+ on 512 block size.
+ */
+ Fs->cluster_size = tot_sectors >= 32*1024*1024*2 ? 64 :
+ tot_sectors >= 16*1024*1024*2 ? 32 :
+ tot_sectors >= 8*1024*1024*2 ? 16 :
+ Fs->cluster_size;
+ }
+
+ fit=try_cluster_size(Fs,
+ tot_sectors,
+ may_change_boot_size,
+ may_change_fat_len,
+ may_change_root_size,
+ may_pad);
+
+ if(getenv("MTOOLS_DEBUG_FAT")) {
+ fprintf(stderr, " fit=%d\n", fit);
+ }
+ if(fit == 0)
+ break;
+ if(fit == -2)
+ return -1;
+
+#ifdef HAVE_ASSERT_H
+ assert(fit != 2 || !may_change_fat_len);
+#endif
+ if(fit < 0) {
+ if(may_change_cluster_size &&
+ may_change_fat_len &&
+ Fs->cluster_size > 1) {
+ Fs->cluster_size = Fs->cluster_size / 2;
+ continue;
+ }
+
+ /* Somehow we ended up with too few sectors
+ * for FAT size. This can only happen if
+ * cluster size is not adjustable, and if we
+ * had *barely* more clusters than allowed by
+ * previous fat bits. After raising fat bits,
+ * fat_len grew larger (due to each individual
+ * FAT entry now being larger), pushing the
+ * number of clusters *below* new limit. =>
+ * we lower fat bits again */
+ if(!may_change_fat_bits || Fs->fat_bits == 12)
+ return -2;
+
+ switch(Fs->fat_bits) {
+ case 16:
+ Fs->fat_bits=12;
+ break;
+ case 32:
+ Fs->fat_bits=16;
+ break;
+ }
+ may_pad=true;
+ continue;
+ }
+
+ if(fit == 1 && may_change_fat_bits && !may_pad) {
+ /* If cluster_size reached
+ * "maximum" for fat_bits,
+ * switch over to next
+ */
+ if(Fs->fat_bits == 12 &&
+ (!may_change_cluster_size ||
+ Fs->cluster_size >= 8)) {
+ Fs->fat_bits = 16;
+ if(may_change_cluster_size)
Fs->cluster_size = 1;
+ continue;
+ }
+
+ if(Fs->fat_bits == 16 &&
+ (!may_change_cluster_size ||
+ Fs->cluster_size >= 64)) {
+ Fs->fat_bits = 32;
+ if(may_change_cluster_size)
+ Fs->cluster_size =
+ may_change_fat_len ? 8 : 1;
+ continue;
}
}
- if(!Fs->dir_len) {
- if (dev->heads == 1)
- Fs->dir_len = 4;
- else
- Fs->dir_len = (tot_sectors > 2000) ? 32 : 7;
+ if(may_change_cluster_size && Fs->cluster_size < 128) {
+ /* Double cluster size, and try again */
+ Fs->cluster_size = 2 * Fs->cluster_size;
+ continue;
}
- calc_cluster_size(Fs, tot_sectors, dev->fat_bits);
-#ifdef USE_XDF
- if(Fs->fat_len)
- xdf_calc_fat_size(Fs, tot_sectors, dev->fat_bits);
- else
-#endif
- {
- calc_fat_bits2(Fs, tot_sectors, dev->fat_bits,
- may_change_cluster_size,
- may_change_root_size);
- calc_fat_size(Fs, tot_sectors);
+ if(fit == 2 && may_change_fat_bits &&
+ may_change_root_size &&
+ Fs->fat_bits == 16) {
+ Fs->fat_bits=12;
+ may_pad=true;
+ continue;
}
+
+ /* Still too many clusters? */
+ return (fit == 2) ? -4 : -3;
}
- set_word(boot->boot.fatlen, Fs->fat_len);
+ if(getenv("MTOOLS_DEBUG_FAT") || getenv("MTOOLS_DEBUG_FAT_SUMMARY")) {
+ fprintf(stderr,
+ " FAT%d Cluster_size=%d %d clusters FAT_LEN=%d\n",
+ Fs->fat_bits,
+ Fs->cluster_size,
+ Fs->num_clus,
+ Fs->fat_len);
+ }
+ check_fs_params_and_set_fat(Fs, tot_sectors);
+ if(Fs->fat_bits == 32)
+ fat32_specific_init(Fs);
+ return 0;
}
-
-
-static void calc_fs_parameters_32(unsigned long tot_sectors,
- struct Fs_t *Fs, union bootsector *boot)
+void initFsForFormat(Fs_t *Fs)
{
- unsigned long num_clus;
- if(DWORD(nhs))
- boot->boot.descr = 0xf8;
- else
- boot->boot.descr = 0xf0;
+ memset(Fs, 0, sizeof(*Fs));
+ init_head(&Fs->head, &FsClass, NULL);
- if(!Fs->cluster_size)
- calc_cluster_size(Fs, tot_sectors, 32);
+ Fs->cluster_size = 0;
Fs->dir_len = 0;
- num_clus = tot_sectors / Fs->cluster_size;
- /* Maximal number of clusters on FAT32 is 0xffffff6 */
- if (num_clus > 0xffffff6) {
- fprintf(stderr, "Too many clusters\n");
- exit(1);
- }
- Fs->num_clus = (unsigned int) num_clus;
- set_fat32(Fs);
- calc_fat_size(Fs, tot_sectors);
- set_word(boot->boot.fatlen, 0);
- set_dword(boot->boot.ext.fat32.bigFat, Fs->fat_len);
+ Fs->fat_len = 0;
+ Fs->num_fat = 2;
+ Fs->backupBoot = 0;
}
+void setFsSectorSize(Fs_t *Fs, struct device *dev, uint16_t msize) {
+ unsigned int j;
+ Fs->sector_size = 512;
+ if( !(dev->use_2m & 0x7f)) {
+ Fs->sector_size = (uint16_t) (128u << (dev->ssize & 0x7f));
+ }
+ SET_INT(Fs->sector_size, msize);
+ for(j = 0; j < 31; j++) {
+ if (Fs->sector_size == (unsigned int) (1 << j)) {
+ Fs->sectorShift = j;
+ break;
+ }
+ }
+ Fs->sectorMask = Fs->sector_size - 1;
+}
+static int old_dos_size_to_geom(size_t size,
+ unsigned int *cyls,
+ unsigned short *heads,
+ unsigned short *sects)
+{
+ struct OldDos_t *params = getOldDosBySize(size);
+ if(params != NULL) {
+ *cyls = params->tracks;
+ *heads = params->heads;
+ *sects = params->sectors;
+ return 0;
+ } else
+ return 1;
+}
static void usage(int ret) NORETURN;
static void usage(int ret)
@@ -716,165 +840,11 @@ static void usage(int ret)
exit(ret);
}
-#ifdef OS_linux
-static int get_sector_size(int fd, char *errmsg) {
- int sec_size;
- if (ioctl(fd, BLKSSZGET, &sec_size) != 0 || sec_size <= 0) {
- sprintf(errmsg, "Could not get sector size of device (%s)",
- strerror(errno));
- return -1;
- }
-
- /* Cap sector size at 4096 */
- if(sec_size > 4096)
- sec_size = 4096;
- return sec_size;
-}
-
-static int get_block_geom(int fd, struct device *dev, char *errmsg) {
- struct hd_geometry geom;
- int sec_size;
- long size;
- uint16_t heads=dev->heads;
- uint16_t sectors=dev->sectors;
- unsigned int sect_per_track;
-
- if (ioctl(fd, HDIO_GETGEO, &geom) < 0) {
- sprintf(errmsg, "Could not get geometry of device (%s)",
- strerror(errno));
- return -1;
- }
-
- if (ioctl(fd, BLKGETSIZE, &size) < 0) {
- sprintf(errmsg, "Could not get size of device (%s)",
- strerror(errno));
- return -1;
- }
-
- sec_size = get_sector_size(fd, errmsg);
- if(sec_size < 0)
- return -1;
-
- dev->ssize = 0;
- while (dev->ssize < 0x7F && (128 << dev->ssize) < sec_size)
- dev->ssize++;
-
- if(!heads)
- heads = geom.heads;
- if(!sectors)
- sectors = geom.sectors;
-
- sect_per_track = heads * sectors;
- if(!dev->hidden) {
- unsigned long hidden;
- hidden = geom.start % sect_per_track;
- if(hidden && hidden != sectors) {
- sprintf(errmsg,
- "Hidden (%ld) does not match sectors (%d)\n",
- hidden, sectors);
- return -1;
- }
- dev->hidden = hidden;
- }
- dev->heads = heads;
- dev->sectors = sectors;
- if(!dev->tracks)
- dev->tracks = (size + dev->hidden % sect_per_track) / sect_per_track;
- return 0;
-}
-#endif
-
-static int get_lba_geom(Stream_t *Direct, unsigned long tot_sectors, struct device *dev, char *errmsg) {
- int sect_per_track;
- unsigned long tracks;
-
- /* if one value is already specified we do not want to overwrite it */
- if (dev->heads || dev->sectors || dev->tracks) {
- sprintf(errmsg, "Number of heads or sectors or tracks was already specified");
- return -1;
- }
-
- if (!tot_sectors) {
-#ifdef OS_linux
- int fd;
- int sec_size;
- long size;
- struct MT_STAT stbuf;
-
- fd = get_fd(Direct);
- if (MT_FSTAT(fd, &stbuf) < 0) {
- sprintf(errmsg, "Could not stat file (%s)", strerror(errno));
- return -1;
- }
-
- if (S_ISBLK(stbuf.st_mode)) {
- if (ioctl(fd, BLKGETSIZE, &size) != 0) {
- sprintf(errmsg, "Could not get size of device (%s)",
- strerror(errno));
- return -1;
- }
- sec_size = get_sector_size(fd, errmsg);
- if(sec_size < 0)
- return -1;
-
- if (!(dev->ssize & 0x80)) {
- dev->ssize = 0;
- while (dev->ssize < 0x7F && (128 << dev->ssize) < sec_size)
- dev->ssize++;
- }
- if ((dev->ssize & 0x7f) > 2)
- tot_sectors = size >> ((dev->ssize & 0x7f) - 2);
- else
- tot_sectors = size << (2 - (dev->ssize & 0x7f));
- } else if (S_ISREG(stbuf.st_mode)) {
- tot_sectors = stbuf.st_size >> ((dev->ssize & 0x7f) + 7);
- } else {
- sprintf(errmsg, "Could not get size of device (%s)",
- "No method available");
- return -1;
- }
-#else
- mt_size_t size;
- GET_DATA(Direct, 0, &size, 0, 0);
- if (size == 0) {
- sprintf(errmsg, "Could not get size of device (%s)",
- "No method available");
- return -1;
- }
- tot_sectors = size >> ((dev->ssize & 0x7f) + 7);
-#endif
- }
-
- dev->sectors = 63;
-
- if (tot_sectors < 16*63*1024)
- dev->heads = 16;
- else if (tot_sectors < 32*63*1024)
- dev->heads = 32;
- else if (tot_sectors < 64*63*1024)
- dev->heads = 64;
- else if (tot_sectors < 128*63*1024)
- dev->heads = 128;
- else
- dev->heads = 255;
-
- sect_per_track = dev->heads * dev->sectors;
- tracks = (tot_sectors + dev->hidden % sect_per_track) / sect_per_track;
- if (tracks > 0xFFFFFFFF) {
- sprintf(errmsg, "Device is too big, it has too many tracks");
- return -1;
- }
-
- dev->tracks = (uint32_t) tracks;
-
- return 0;
-}
-
void mformat(int argc, char **argv, int dummy UNUSEDP) NORETURN;
void mformat(int argc, char **argv, int dummy UNUSEDP)
{
int r; /* generic return value */
- Fs_t Fs;
+ Fs_t *Fs;
unsigned int hs;
int hs_set;
unsigned int arguse_2m = 0;
@@ -883,10 +853,10 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
uint8_t rate_0, rate_any;
int mangled;
uint8_t argssize=0; /* sector size */
- int msize=0;
+ uint16_t msize=0;
int fat32 = 0;
struct label_blk_t *labelBlock;
- int bootOffset;
+ size_t bootOffset;
#ifdef USE_XDF
unsigned int i;
@@ -900,8 +870,8 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
struct device used_dev;
unsigned int argtracks;
uint16_t argheads, argsectors;
- unsigned long tot_sectors=0;
- int blocksize;
+ uint32_t tot_sectors=0;
+ uint32_t blocksize;
char drive, name[EXPAND_BUF];
@@ -913,18 +883,14 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
uint32_t serial;
int serial_set;
- int fsVersion;
- int mediaDesc=-1;
+ uint16_t fsVersion;
+ uint8_t mediaDesc=0;
+ bool haveMediaDesc=false;
- mt_size_t maxSize;
+ mt_off_t maxSize;
int Atari = 0; /* should we add an Atari-style serial number ? */
- unsigned int backupBoot = 6;
- int backupBootSet = 0;
-
- unsigned int resvSects = 0;
-
char *endptr;
hs = hs_set = 0;
@@ -938,22 +904,22 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
serial = 0;
fsVersion = 0;
- Fs.cluster_size = 0;
- Fs.refs = 1;
- Fs.dir_len = 0;
+ Fs = New(Fs_t);
+ if (!Fs) {
+ fprintf(stderr, "Out of memory\n");
+ exit(1);
+ }
+ initFsForFormat(Fs);
if(getenv("MTOOLS_DIR_LEN")) {
- Fs.dir_len = atoui(getenv("MTOOLS_DIR_LEN"));
- if(Fs.dir_len <= 0)
- Fs.dir_len=0;
+ Fs->dir_len = atou16(getenv("MTOOLS_DIR_LEN"));
+ if(Fs->dir_len <= 0)
+ Fs->dir_len=0;
}
- Fs.fat_len = 0;
- Fs.num_fat = 2;
if(getenv("MTOOLS_NFATS")) {
- Fs.num_fat = atoui(getenv("MTOOLS_NFATS"));
- if(Fs.num_fat <= 0)
- Fs.num_fat=2;
+ Fs->num_fat = atou8(getenv("MTOOLS_NFATS"));
+ if(Fs->num_fat <= 0)
+ Fs->num_fat=2;
}
- Fs.Class = &FsClass;
rate_0 = mtools_rate_0;
rate_any = mtools_rate_any;
@@ -997,7 +963,7 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
break;
case 'T':
- tot_sectors = atoui(optarg);
+ tot_sectors = parseSize(optarg);
break;
case 'n': /*non-standard*/
@@ -1060,7 +1026,7 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
break;
case 'M':
- msize = atoi(optarg);
+ msize = atou16(optarg);
if(msize != 512 &&
msize != 1024 &&
msize != 2048 &&
@@ -1088,21 +1054,20 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
break;
case 'I':
- fsVersion = strtoi(optarg,&endptr,0);
+ fsVersion = strtou16(optarg,&endptr,0);
break;
case 'c':
- Fs.cluster_size = atoui(optarg);
+ Fs->cluster_size = atou8(optarg);
break;
case 'r':
- Fs.dir_len = strtoui(optarg,&endptr,0);
+ Fs->dir_len = strtou16(optarg,&endptr,0);
break;
case 'L':
- Fs.fat_len = strtoui(optarg,&endptr,0);
+ Fs->fat_len = strtoui(optarg,&endptr,0);
break;
-
case 'B':
bootSector = optarg;
break;
@@ -1110,31 +1075,35 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
keepBoot = 1;
break;
case 'K':
- backupBoot = atoui(optarg);
- backupBootSet=1;
- if(backupBoot < 2) {
+ Fs->backupBoot = atou16(optarg);
+ if(Fs->backupBoot < 2) {
fprintf(stderr, "Backupboot must be greater than 2\n");
exit(1);
}
break;
case 'R':
- resvSects = atoui(optarg);
+ Fs->fat_start = atou8(optarg);
break;
case 'h':
argheads = atou16(optarg);
break;
case 'd':
- Fs.num_fat = atoui(optarg);
+ Fs->num_fat = atou8(optarg);
break;
case 'm':
- mediaDesc = strtoi(optarg,&endptr,0);
+ mediaDesc = strtou8(optarg,&endptr,0);
if(*endptr)
- mediaDesc = strtoi(optarg,&endptr,16);
+ mediaDesc = strtou8(optarg,&endptr,16);
+ if(optarg == endptr || *endptr) {
+ fprintf(stderr, "Bad mediadesc %s\n", optarg);
+ exit(1);
+ }
+ haveMediaDesc=true;
break;
default:
usage(1);
}
- check_number_parse_errno(c, optarg, endptr);
+ check_number_parse_errno((char)c, optarg, endptr);
}
if (argc - optind > 1)
@@ -1167,10 +1136,9 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
/* check out a drive whose letter and parameters match */
sprintf(errmsg, "Drive '%c:' not supported", drive);
- Fs.Direct = NULL;
blocksize = 0;
for(dev=devices;dev->drive;dev++) {
- FREE(&(Fs.Direct));
+ FREE(&(Fs->head.Next));
/* drive letter */
if (dev->drive != drive)
continue;
@@ -1190,108 +1158,64 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
#endif
#ifdef USE_XDF
- if(!format_xdf) {
-#endif
- Fs.Direct = 0;
-#ifdef USE_FLOPPYD
- Fs.Direct = FloppydOpen(&used_dev, name,
- O_RDWR | create,
- errmsg, &maxSize);
+ if(format_xdf)
+ used_dev.misc_flags |= USE_XDF_FLAG;
+ info.FatSize=0;
#endif
- if(!Fs.Direct) {
- Fs.Direct = SimpleFileOpen(&used_dev, dev, name,
- O_RDWR | create,
- errmsg, 0, 1,
- &maxSize);
- }
+ if(tot_sectors)
+ used_dev.tot_sectors = tot_sectors;
+ Fs->head.Next = OpenImage(&used_dev, dev, name,
+ O_RDWR|create, errmsg,
+ ALWAYS_GET_GEOMETRY,
+ O_RDWR,
+ &maxSize, NULL,
#ifdef USE_XDF
- } else {
- used_dev.misc_flags |= USE_XDF_FLAG;
- Fs.Direct = XdfOpen(&used_dev, name, O_RDWR,
- errmsg, &info);
- if(Fs.Direct && !Fs.fat_len)
- Fs.fat_len = info.FatSize;
- if(Fs.Direct && !Fs.dir_len)
- Fs.dir_len = info.RootDirSize;
- }
+ &info
+#else
+ NULL
#endif
+ );
- if (!Fs.Direct)
- continue;
-
-#ifdef OS_linux
- if ((!used_dev.tracks || !used_dev.heads || !used_dev.sectors) &&
- (!IS_SCSI(dev))) {
- int fd= get_fd(Fs.Direct);
- struct MT_STAT stbuf;
-
- if (MT_FSTAT(fd, &stbuf) < 0) {
- sprintf(errmsg, "Could not stat file (%s)", strerror(errno));
- continue;
- }
-
- if (S_ISBLK(stbuf.st_mode))
- /* If the following get_block_geom fails, do not
- * continue to next drive description, but allow
- * get_lba_geom to kick in
- */
- get_block_geom(fd, &used_dev, errmsg);
+#ifdef USE_XDF
+ if(Fs->head.Next && info.FatSize) {
+ if(!Fs->fat_len)
+ Fs->fat_len = info.FatSize;
+ if(!Fs->dir_len)
+ Fs->dir_len = info.RootDirSize;
}
#endif
- if ((!used_dev.tracks && !tot_sectors) ||
- !used_dev.heads || !used_dev.sectors){
- if (get_lba_geom(Fs.Direct, tot_sectors, &used_dev,
- errmsg) < 0) {
- sprintf(errmsg, "%s: "
- "Complete geometry of the disk "
- "was not specified, \n"
- "neither in /etc/mtools.conf nor "
- "on the command line. \n"
- "LBA Assist Translation for "
- "calculating CHS geometry "
- "of the disk failed.\n", argv[0]);
- continue;
- }
- }
-
-#if 0
- /* set parameters, if needed */
- if(SET_GEOM(Fs.Direct, &used_dev, 0xf0, boot)){
- sprintf(errmsg,"Can't set disk parameters: %s",
- strerror(errno));
+ if (!Fs->head.Next)
continue;
- }
-#endif
- Fs.sector_size = 512;
- if( !(used_dev.use_2m & 0x7f)) {
- Fs.sector_size = 128 << (used_dev.ssize & 0x7f);
- }
- SET_INT(Fs.sector_size, msize);
- {
- unsigned int j;
- for(j = 0; j < 31; j++) {
- if (Fs.sector_size == (unsigned int) (1 << j)) {
- Fs.sectorShift = j;
- break;
- }
- }
- Fs.sectorMask = Fs.sector_size - 1;
- }
+ if(tot_sectors)
+ used_dev.tot_sectors = tot_sectors;
+
+ setFsSectorSize(Fs, &used_dev, msize);
- if(!used_dev.blocksize || used_dev.blocksize < Fs.sector_size)
- blocksize = Fs.sector_size;
+ if(!used_dev.blocksize || used_dev.blocksize < Fs->sector_size)
+ blocksize = Fs->sector_size;
else
blocksize = used_dev.blocksize;
if(blocksize > MAX_SECTOR)
blocksize = MAX_SECTOR;
+ if(chs_to_totsectors(&used_dev, errmsg) < 0 ||
+ check_if_sectors_fit(dev->tot_sectors, maxSize, blocksize,
+ errmsg) < 0) {
+ FREE(&Fs->head.Next);
+ continue;
+ }
+
+ if(!tot_sectors)
+ tot_sectors = used_dev.tot_sectors;
+
/* do a "test" read */
if (!create &&
- READS(Fs.Direct, &boot.characters, 0, Fs.sector_size) !=
- (signed int) Fs.sector_size) {
+ PREADS(Fs->head.Next,
+ &boot.characters, 0, Fs->sector_size) !=
+ (signed int) Fs->sector_size) {
#ifdef HAVE_SNPRINTF
snprintf(errmsg, sizeof(errmsg)-1,
"Error reading from '%s', wrong parameters?",
@@ -1301,47 +1225,43 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
"Error reading from '%s', wrong parameters?",
name);
#endif
+ FREE(&Fs->head.Next);
continue;
}
break;
}
-
/* print error msg if needed */
if ( dev->drive == 0 ){
- FREE(&Fs.Direct);
+ FREE(&Fs->head.Next);
fprintf(stderr,"%s: %s\n", argv[0],errmsg);
exit(1);
}
- /* calculate the total number of sectors */
if(tot_sectors == 0) {
- unsigned long sect_per_track = used_dev.heads*used_dev.sectors;
- tot_sectors = used_dev.tracks*sect_per_track - used_dev.hidden%sect_per_track;
- /* Number of sectors must fit into 32bit value */
- if (tot_sectors > 0xFFFFFFFF) {
- fprintf(stderr, "Too many sectors\n");
- exit(1);
- }
+ fprintf(stderr, "Number of sectors not known\n");
+ exit(1);
}
/* create the image file if needed */
if (create) {
- WRITES(Fs.Direct, &boot.characters,
- sectorsToBytes((Stream_t*)&Fs, tot_sectors-1),
- Fs.sector_size);
+ PWRITES(Fs->head.Next, &boot.characters,
+ sectorsToBytes(Fs, tot_sectors-1),
+ Fs->sector_size);
}
/* the boot sector */
if(bootSector) {
int fd;
+ ssize_t ret;
fd = open(bootSector, O_RDONLY | O_BINARY | O_LARGEFILE);
if(fd < 0) {
perror("open boot sector");
exit(1);
}
- if(read(fd, &boot.bytes, blocksize) < blocksize) {
+ ret=read(fd, &boot.bytes, blocksize);
+ if(ret < 0 || (size_t) ret < blocksize) {
perror("short read on boot sector");
exit(1);
}
@@ -1349,16 +1269,14 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
close(fd);
}
if(!keepBoot && !(used_dev.use_2m & 0x7f))
- memset(boot.characters, '\0', Fs.sector_size);
- set_dword(boot.boot.nhs, used_dev.hidden);
+ memset(boot.characters, '\0', Fs->sector_size);
- Fs.Next = buf_init(Fs.Direct,
- blocksize * used_dev.heads * used_dev.sectors,
- blocksize * used_dev.heads * used_dev.sectors,
- blocksize);
- Fs.Buffer = 0;
+ Fs->head.Next = buf_init(Fs->head.Next,
+ blocksize * used_dev.heads * used_dev.sectors,
+ blocksize * used_dev.heads * used_dev.sectors,
+ blocksize);
- boot.boot.nfat = Fs.num_fat;
+ boot.boot.nfat = Fs->num_fat;
if(!keepBoot)
set_word(&boot.bytes[510], 0xaa55);
@@ -1366,7 +1284,24 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
set_word(boot.boot.nsect, used_dev.sectors);
set_word(boot.boot.nheads, used_dev.heads);
- used_dev.fat_bits = comp_fat_bits(&Fs,used_dev.fat_bits, tot_sectors, fat32);
+ switch(calc_fs_parameters(&used_dev, fat32, tot_sectors, Fs,
+ &boot.boot.descr)) {
+ case -1:
+ fprintf(stderr, "Too few sectors\n");
+ exit(1);
+ case -2:
+ fprintf(stderr, "Too few clusters for %d bit fat\n",
+ Fs->fat_bits);
+ exit(1);
+ case -3:
+ fprintf(stderr, "Too many clusters for %d bit FAT\n",
+ Fs->fat_bits);
+ exit(1);
+ case -4:
+ fprintf(stderr, "Too many clusters for fat length %d\n",
+ Fs->fat_len);
+ exit(1);
+ }
if(!keepBoot && !(used_dev.use_2m & 0x7f)) {
if(!used_dev.partition) {
@@ -1376,37 +1311,17 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
setBeginEnd(&partTable[1], 0,
used_dev.heads * used_dev.sectors *
used_dev.tracks,
- used_dev.heads, used_dev.sectors, 1, 0,
- used_dev.fat_bits);
+ (uint8_t) used_dev.heads,
+ (uint8_t) used_dev.sectors, 1, 0,
+ Fs->fat_bits);
}
}
- if(used_dev.fat_bits == 32) {
- Fs.primaryFat = 0;
- Fs.writeAllFats = 1;
- if(resvSects) {
- if(resvSects < 3) {
- fprintf(stderr,
- "For FAT 32, reserved sectors need to be at least 3\n");
- resvSects = 32;
- }
-
- if(resvSects <= backupBoot && !backupBootSet)
- backupBoot = resvSects - 1;
- Fs.fat_start = resvSects;
- } else
- Fs.fat_start = 32;
-
- if(Fs.fat_start <= backupBoot) {
- fprintf(stderr,
- "Reserved sectors (%d) must be more than backupBoot (%d)\n", Fs.fat_start, backupBoot);
- backupBoot = 6;
- Fs.fat_start = 32;
- }
-
- calc_fs_parameters_32(tot_sectors, &Fs, &boot);
+ if(Fs->fat_bits == 32) {
+ set_word(boot.boot.fatlen, 0);
+ set_dword(boot.boot.ext.fat32.bigFat, Fs->fat_len);
- Fs.clus_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
+ Fs->clus_start = Fs->num_fat * Fs->fat_len + Fs->fat_start;
/* extension flags: mirror fats, and use #0 as primary */
set_word(boot.boot.ext.fat32.extFlags,0);
@@ -1415,37 +1330,26 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
set_word(boot.boot.ext.fat32.fsVersion,fsVersion);
/* root directory */
- set_dword(boot.boot.ext.fat32.rootCluster, Fs.rootCluster = 2);
+ set_dword(boot.boot.ext.fat32.rootCluster, Fs->rootCluster = 2);
/* info sector */
- set_word(boot.boot.ext.fat32.infoSector, Fs.infoSectorLoc = 1);
- Fs.infoSectorLoc = 1;
+ set_word(boot.boot.ext.fat32.infoSector, Fs->infoSectorLoc = 1);
+ Fs->infoSectorLoc = 1;
/* no backup boot sector */
- set_word(boot.boot.ext.fat32.backupBoot, backupBoot);
+ set_word(boot.boot.ext.fat32.backupBoot, Fs->backupBoot);
labelBlock = & boot.boot.ext.fat32.labelBlock;
} else {
- Fs.infoSectorLoc = 0;
- if(resvSects) {
- if(resvSects < 1) {
- fprintf(stderr,
- "Reserved sectors need to be at least 1\n");
- resvSects = 1;
- }
- Fs.fat_start = resvSects;
- } else
- Fs.fat_start = 1;
- calc_fs_parameters(&used_dev, tot_sectors, &Fs, &boot);
- Fs.dir_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
- Fs.clus_start = Fs.dir_start + Fs.dir_len;
+ set_word(boot.boot.fatlen, (uint16_t) Fs->fat_len);
+ Fs->dir_start = Fs->num_fat * Fs->fat_len + Fs->fat_start;
+ Fs->clus_start = Fs->dir_start + Fs->dir_len;
labelBlock = & boot.boot.ext.old.labelBlock;
-
}
/* Set the codepage */
- Fs.cp = cp_open(used_dev.codepage);
- if(Fs.cp == NULL)
+ Fs->cp = cp_open(used_dev.codepage);
+ if(Fs->cp == NULL)
exit(1);
if (!keepBoot)
@@ -1460,23 +1364,23 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
if (!serial_set)
serial=(uint32_t) random();
set_dword(labelBlock->serial, serial);
- label_name_pc(GET_DOSCONVERT((Stream_t *)&Fs),
+ label_name_pc(GET_DOSCONVERT((Stream_t *)Fs),
label[0] ? label : "NO NAME ", 0,
&mangled, &shortlabel);
strncpy(labelBlock->label, shortlabel.base, 8);
strncpy(labelBlock->label+8, shortlabel.ext, 3);
- sprintf(labelBlock->fat_type, "FAT%2.2d ", Fs.fat_bits);
+ sprintf(labelBlock->fat_type, "FAT%2.2d ", Fs->fat_bits);
labelBlock->fat_type[7] = ' ';
- set_word(boot.boot.secsiz, Fs.sector_size);
- boot.boot.clsiz = (unsigned char) Fs.cluster_size;
- set_word(boot.boot.nrsvsect, Fs.fat_start);
+ set_word(boot.boot.secsiz, Fs->sector_size);
+ boot.boot.clsiz = (unsigned char) Fs->cluster_size;
+ set_word(boot.boot.nrsvsect, Fs->fat_start);
bootOffset = init_geometry_boot(&boot, &used_dev, sectors0,
rate_0, rate_any,
&tot_sectors, keepBoot);
if(!bootOffset) {
- bootOffset = ((unsigned char *) labelBlock) - boot.bytes +
+ bootOffset = ptrdiff((char *) labelBlock, (char*)boot.bytes) +
sizeof(struct label_blk_t);
}
if(Atari) {
@@ -1486,8 +1390,8 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
boot.boot.banner[7] = (char) random();
}
- if(!keepBoot)
- inst_boot_prg(&boot, bootOffset);
+ if(!keepBoot && bootOffset <= UINT16_MAX)
+ inst_boot_prg(&boot, (uint16_t)bootOffset);
/* Mimic 3.8 behavior, else 2m disk do not work (???)
* luferbu@fluidsignal.com (Luis Bustamante), Fri, 14 Jun 2002
*/
@@ -1497,42 +1401,39 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
boot.boot.jump[2] = 0x90;
}
if(used_dev.use_2m & 0x7f)
- Fs.num_fat = 1;
- if(mediaDesc != -1)
+ Fs->num_fat = 1;
+ if(haveMediaDesc)
boot.boot.descr=mediaDesc;
- Fs.lastFatSectorNr = 0;
- Fs.lastFatSectorData = 0;
- zero_fat(&Fs, boot.boot.descr);
- Fs.freeSpace = Fs.num_clus;
- Fs.last = 2;
+ Fs->lastFatSectorNr = 0;
+ Fs->lastFatSectorData = 0;
+ zero_fat(Fs, boot.boot.descr);
+ Fs->freeSpace = Fs->num_clus;
+ Fs->last = 2;
#ifdef USE_XDF
- if(format_xdf)
+ if(used_dev.misc_flags & USE_XDF_FLAG)
for(i=0;
- i < (info.BadSectors+Fs.cluster_size-1)/Fs.cluster_size;
+ i < (info.BadSectors+Fs->cluster_size-1)/Fs->cluster_size;
i++)
- fatEncode(&Fs, i+2, 0xfff7);
+ fatEncode(Fs, i+2, 0xfff7);
#endif
- format_root(&Fs, label, &boot);
- WRITES((Stream_t *)&Fs, boot.characters,
- (mt_off_t) 0, Fs.sector_size);
-
- if(used_dev.fat_bits == 32) {
- WRITES((Stream_t *)&Fs, boot.characters,
- (mt_off_t) backupBoot * Fs.sector_size, Fs.sector_size);
+ format_root(Fs, label, &boot);
+ if(PWRITES((Stream_t *)Fs, boot.characters, 0, Fs->sector_size) < 0) {
+ fprintf(stderr, "Error writing boot sector\n");
+ exit(1);
}
- if(Fs.fat_bits == 32 && WORD_S(ext.fat32.backupBoot) != MAX16) {
- WRITES((Stream_t *)&Fs, boot.characters,
- sectorsToBytes((Stream_t*)&Fs,
- WORD_S(ext.fat32.backupBoot)),
- Fs.sector_size);
+ if(Fs->fat_bits == 32 && WORD_S(ext.fat32.backupBoot) != MAX16) {
+ if(PWRITES((Stream_t *)Fs, boot.characters,
+ sectorsToBytes(Fs, WORD_S(ext.fat32.backupBoot)),
+ Fs->sector_size) < 0) {
+ fprintf(stderr, "Error writing backup boot sector\n");
+ exit(1);
+ }
}
- FLUSH((Stream_t *)&Fs); /* flushes Fs.
- * This triggers the writing of the FAT */
- FREE(&Fs.Next);
- Fs.Class->freeFunc((Stream_t *)&Fs);
+
+ FREE((Stream_t **)&Fs);
#ifdef USE_XDF
if(format_xdf && isatty(0) && !getenv("MTOOLS_USE_XDF"))
fprintf(stderr,
diff --git a/minfo.1 b/minfo.1
index 5d8fecd..8cc4035 100644
--- a/minfo.1
+++ b/minfo.1
@@ -1,5 +1,5 @@
'\" t
-.TH minfo 1 "28Nov20" mtools-4.0.26
+.TH minfo 1 "08Jan22" mtools-4.0.37
.SH Name
minfo - print the parameters of a MSDOS filesystem
'\" t
diff --git a/minfo.c b/minfo.c
index 05c4e9d..07a1773 100644
--- a/minfo.c
+++ b/minfo.c
@@ -24,13 +24,14 @@
#include "vfat.h"
#include "mtools.h"
#include "nameclash.h"
+#include "fsP.h"
static void usage(int ret) NORETURN;
static void usage(int ret)
{
- fprintf(stderr,
+ fprintf(stderr,
"Mtools version %s, dated %s\n", mversion, mdate);
- fprintf(stderr,
+ fprintf(stderr,
"Usage: %s [-v] drive\n", progname);
exit(ret);
}
@@ -44,9 +45,9 @@ static void displayInfosector(Stream_t *Stream, union bootsector *boot)
return;
infosec = (InfoSector_t *) safe_malloc(WORD(secsiz));
- force_read(Stream, (char *) infosec,
- (mt_off_t) WORD(secsiz) * WORD(ext.fat32.infoSector),
- WORD(secsiz));
+ force_pread(Stream, (char *) infosec,
+ (mt_off_t) WORD(secsiz) * WORD(ext.fat32.infoSector),
+ WORD(secsiz));
printf("\nInfosector:\n");
printf("signature=0x%08x\n", _DWORD(infosec->signature1));
if(_DWORD(infosec->count) != MAX32)
@@ -55,6 +56,12 @@ static void displayInfosector(Stream_t *Stream, union bootsector *boot)
printf("last allocated cluster=%u\n", _DWORD(infosec->pos));
}
+/*
+ * Number of hidden sector is only a 4 byte quantity if number of sectors is
+ */
+static uint32_t getHidden(union bootsector *boot) {
+ return WORD(psect) ? WORD(nhs) : DWORD(nhs);
+}
static void displayBPB(Stream_t *Stream, union bootsector *boot) {
struct label_blk_t *labelBlock;
@@ -66,15 +73,16 @@ static void displayBPB(Stream_t *Stream, union bootsector *boot) {
printf("cluster size: %d sectors\n", boot->boot.clsiz);
printf("reserved (boot) sectors: %d\n", WORD(nrsvsect));
printf("fats: %d\n", boot->boot.nfat);
- printf("max available root directory slots: %d\n",
+ printf("max available root directory slots: %d\n",
WORD(dirents));
printf("small size: %d sectors\n", WORD(psect));
printf("media descriptor byte: 0x%x\n", boot->boot.descr);
printf("sectors per fat: %d\n", WORD(fatlen));
printf("sectors per track: %d\n", WORD(nsect));
printf("heads: %d\n", WORD(nheads));
- printf("hidden sectors: %d\n", DWORD(nhs));
- printf("big size: %d sectors\n", DWORD(bigsect));
+ printf("hidden sectors: %d\n", getHidden(boot));
+ if(!WORD(psect))
+ printf("big size: %u sectors\n", DWORD(bigsect));
if(WORD(fatlen)) {
labelBlock = &boot->boot.ext.old.labelBlock;
@@ -83,20 +91,20 @@ static void displayBPB(Stream_t *Stream, union bootsector *boot) {
}
if(has_BPB4) {
- printf("physical drive id: 0x%x\n",
+ printf("physical drive id: 0x%x\n",
labelBlock->physdrive);
- printf("reserved=0x%x\n",
+ printf("reserved=0x%x\n",
labelBlock->reserved);
- printf("dos4=0x%x\n",
+ printf("dos4=0x%x\n",
labelBlock->dos4);
- printf("serial number: %08X\n",
+ printf("serial number: %08X\n",
_DWORD(labelBlock->serial));
- printf("disk label=\"%11.11s\"\n",
+ printf("disk label=\"%11.11s\"\n",
labelBlock->label);
- printf("disk type=\"%8.8s\"\n",
+ printf("disk type=\"%8.8s\"\n",
labelBlock->fat_type);
}
-
+
if(!WORD(fatlen)){
printf("Big fatlen=%u\n",
DWORD(ext.fat32.bigFat));
@@ -116,27 +124,144 @@ static void displayBPB(Stream_t *Stream, union bootsector *boot) {
}
}
+static int try(uint32_t tot_sectors, Fs_t *masterFs, Fs_t *tryFs,
+ struct device *master_dev, struct device *try_dev,
+ uint8_t *bootDescr) {
+ *tryFs = *masterFs;
+ *try_dev = *master_dev;
+ return calc_fs_parameters(try_dev, 0, tot_sectors,
+ tryFs, bootDescr);
+}
+
+static void print_mformat_commandline(const char *imgFile,
+ char drive,
+ struct device *dev,
+ union bootsector *boot,
+ int media,
+ int haveBPB) {
+ uint8_t size_code;
+ uint32_t sect_per_track;
+ uint32_t hidden;
+ uint32_t tot_sectors;
+ int tracks_match=0;
+ Fs_t masterFs, tryFs, actual;
+ struct device used_dev;
+ uint8_t tryMedia;
+ int bad;
+
+ sect_per_track = dev->sectors * dev->heads;
+ if(sect_per_track == 0)
+ return;
+
+ tot_sectors = parseFsParams(&actual, boot,
+ media | (haveBPB ? 0x100:0),
+ sect_per_track);
+ if(tot_sectors == 0)
+ return;
+
+ printf("mformat command line:\n mformat ");
+
+ if(haveBPB) {
+ if(media == 0xf0)
+ hidden = getHidden(boot);
+ else
+ hidden = 0;
+ size_code = (uint8_t) actual.sectorShift-7;
+ } else {
+ size_code=2;
+ hidden = 0;
+ }
+
+ if(tot_sectors ==
+ dev->tracks * sect_per_track - hidden % sect_per_track) {
+ tracks_match=1;
+ printf("-t %d ", dev->tracks);
+ } else {
+ printf("-T %d ", tot_sectors);
+ }
+ printf ("-h %d -s %d ", dev->heads, dev->sectors);
+ if(haveBPB && (hidden || !tracks_match))
+ printf("-H %d ", hidden);
+ used_dev=*dev;
+ if(size_code != 2) {
+ printf("-S %d ",size_code);
+ used_dev.ssize = size_code;
+ }
+
+ initFsForFormat(&masterFs);
+ setFsSectorSize(&masterFs, &used_dev, 0);
+
+ if(actual.num_fat != 2) {
+ masterFs.num_fat = actual.num_fat;
+ printf("-d %d ", actual.num_fat);
+ }
+
+ bad=try(tot_sectors, &masterFs, &tryFs, dev , &used_dev, &tryMedia);
+
+ if(bad || actual.dir_len != tryFs.dir_len) {
+ masterFs.dir_len = actual.dir_len;
+ printf("-r %d ", actual.dir_len);
+ bad = try(tot_sectors,
+ &masterFs, &tryFs, dev , &used_dev,
+ &tryMedia);
+ }
+
+ if(bad || actual.cluster_size != tryFs.cluster_size) {
+ masterFs.cluster_size = actual.cluster_size;
+ printf("-c %d ", actual.cluster_size);
+ bad = try(tot_sectors,
+ &masterFs, &tryFs, dev , &used_dev,
+ &tryMedia);
+ }
+
+ if(bad || actual.fat_start != tryFs.fat_start) {
+ masterFs.fat_start = actual.fat_start;
+ printf("-R %d ", actual.fat_start);
+ bad = try(tot_sectors,
+ &masterFs, &tryFs, dev , &used_dev,
+ &tryMedia);
+ }
+
+ if(bad || actual.fat_len != tryFs.fat_len) {
+ masterFs.fat_len = actual.fat_len;
+ printf("-L %d ", actual.fat_len);
+ bad = try(tot_sectors,
+ &masterFs, &tryFs, dev , &used_dev,
+ &tryMedia);
+ }
+#ifdef HAVE_ASSERT_H
+ assert(!bad);
+#endif
+ if((media & 0xff) != (tryMedia & 0xff))
+ printf("-m %d ", (media & 0xff));
+
+ if(actual.fat_bits == 32) {
+ if(actual.backupBoot != tryFs.backupBoot)
+ printf("-K %d ", actual.backupBoot);
+ }
+
+ if(imgFile != NULL)
+ printf("-i \"%s\" ", imgFile);
+ printf("%c:\n", ch_tolower(drive));
+ printf("\n");
+}
+
+
void minfo(int argc, char **argv, int type UNUSEDP) NORETURN;
void minfo(int argc, char **argv, int type UNUSEDP)
{
union bootsector boot;
char name[EXPAND_BUF];
- int media;
- int haveBPB;
- int size_code;
- int i;
struct device dev;
char drive;
int verbose=0;
int c;
Stream_t *Stream;
int have_drive = 0;
-
- unsigned long sect_per_track;
-
+ int ex=0;
char *imgFile=NULL;
-
+
if(helpFlag(argc, argv))
usage(0);
while ((c = getopt(argc, argv, "i:vh")) != EOF) {
@@ -156,6 +281,9 @@ void minfo(int argc, char **argv, int type UNUSEDP)
}
for(;optind <= argc; optind++) {
+ int media;
+ int haveBPB;
+
if(optind == argc) {
if(have_drive)
break;
@@ -167,13 +295,16 @@ void minfo(int argc, char **argv, int type UNUSEDP)
}
have_drive = 1;
- if(! (Stream = find_device(drive, O_RDONLY, &dev, &boot,
- name, &media, 0, NULL)))
- exit(1);
+ if(! (Stream = find_device(drive, O_RDONLY, &dev, &boot,
+ name, &media, 0, NULL))) {
+ fprintf(stderr, "Could not open drive %c:\n", drive);
+ ex=1;
+ continue;
+ }
haveBPB = media >= 0x100;
media = media & 0xff;
-
+
printf("device information:\n");
printf("===================\n");
printf("filename=\"%s\"\n", name);
@@ -182,78 +313,35 @@ void minfo(int argc, char **argv, int type UNUSEDP)
printf("cylinders: %d\n\n", dev.tracks);
printf("media byte: %02x\n\n", media & 0xff);
- sect_per_track = dev.sectors * dev.heads;
- if(sect_per_track != 0) {
- unsigned int hidden;
- unsigned long tot_sectors;
- int tracks_match=0;
- printf("mformat command line: mformat ");
-
- if(haveBPB) {
- int sector_size;
- tot_sectors = DWORD_S(bigsect);
- SET_INT(tot_sectors, WORD_S(psect));
- sector_size = WORD_S(secsiz);
- size_code=2;
- for(i=0; i<7; i++) {
- if(sector_size == 128 << i) {
- size_code = i;
- break;
- }
- }
- if(media == 0xf0)
- hidden = DWORD_S(nhs);
- else
- hidden = 0;
- } else {
- tot_sectors = dev.tracks * sect_per_track;
- size_code=2;
- hidden = 0;
- }
-
- if(tot_sectors ==
- dev.tracks * sect_per_track - hidden % sect_per_track) {
- tracks_match=1;
- printf("-t %d ", dev.tracks);
- } else {
- printf("-T %ld ", tot_sectors);
- }
- printf ("-h %d -s %d ", dev.heads, dev.sectors);
- if(haveBPB && (hidden || !tracks_match))
- printf("-H %d ", hidden);
- if(size_code != 2)
- printf("-S %d ",size_code);
- if(imgFile != NULL)
- printf("-i \"%s\" ", imgFile);
- printf("%c:\n", ch_tolower(drive));
- printf("\n");
- }
+ print_mformat_commandline(imgFile, drive,
+ &dev, &boot, media, haveBPB);
if(haveBPB || verbose)
displayBPB(Stream, &boot);
if(verbose) {
- int size;
+ uint16_t size;
+ ssize_t ssize;
unsigned char *buf;
printf("\n");
size = WORD_S(secsiz);
-
+
buf = (unsigned char *) malloc(size);
if(!buf) {
fprintf(stderr, "Out of memory error\n");
exit(1);
}
- size = READS(Stream, buf, (mt_off_t) 0, size);
- if(size < 0) {
+ ssize = PREADS(Stream, buf, 0, size);
+ if(ssize < 0) {
perror("read boot sector");
exit(1);
}
- print_sector("Boot sector hexdump", buf, size);
+ print_sector("Boot sector hexdump", buf, (uint16_t)ssize);
}
}
FREE(&Stream);
- exit(0);
+ exit(ex);
}
diff --git a/misc.c b/misc.c
index 21796d1..690f370 100644
--- a/misc.c
+++ b/misc.c
@@ -36,29 +36,29 @@ char *get_homedir(void)
uid_t uid;
char *homedir;
char *username;
-
- homedir = getenv ("HOME");
- /*
- * first we call getlogin.
- * There might be several accounts sharing one uid
+
+ homedir = getenv ("HOME");
+ /*
+ * first we call getlogin.
+ * There might be several accounts sharing one uid
*/
if ( homedir )
return homedir;
-
+
pw = 0;
-
+
username = getenv("LOGNAME");
if ( !username )
username = getlogin();
if ( username )
pw = getpwnam( username);
-
+
if ( pw == 0 ){
/* if we can't getlogin, look up the pwent by uid */
uid = geteuid();
pw = getpwuid(uid);
}
-
+
/* we might still get no entry */
if ( pw )
return pw->pw_dir;
@@ -100,7 +100,7 @@ FILE *open_mcwd(const char *mode)
struct MT_STAT sbuf;
char file[MAXPATHLEN+1];
time_t now;
-
+
get_mcwd_file_name(file);
if (*mode == 'r'){
if (MT_STAT(file, &sbuf) < 0)
@@ -117,10 +117,10 @@ FILE *open_mcwd(const char *mode)
return NULL;
}
}
-
+
return fopen(file, mode);
}
-
+
void *safe_malloc(size_t size)
@@ -141,10 +141,10 @@ void print_sector(const char *message, unsigned char *data, int size)
int row;
printf("%s:\n", message);
-
+
for(row = 0; row * 16 < size; row++){
printf("%03x ", row * 16);
- for(col = 0; col < 16; col++)
+ for(col = 0; col < 16; col++)
printf("%02x ", data [row*16+col]);
for(col = 0; col < 16; col++) {
if(isprint(data [row*16+col]))
@@ -193,7 +193,7 @@ time_t getTimeNow(time_t *now)
}
}
}
-
+
if(!haveTime) {
time(&sharedNow);
haveTime = 1;
@@ -206,31 +206,65 @@ time_t getTimeNow(time_t *now)
/* Convert a string to an offset. The string should be a number,
optionally followed by S (sectors), K (K-Bytes), M (Megabytes), G
(Gigabytes) */
-off_t str_to_offset(char *str) {
- char s, *endp = NULL;
+off_t str_to_offset_with_end(const char *str, char **endp) {
+ char s;
off_t ofs;
- ofs = strtol(str, &endp, 0);
+ *endp = NULL;
+ ofs = strtol(str, endp, 0);
+ s = **endp;
+ /* trailing char, see if it is a size specifier */
+ if (s == 's' || s == 'S') /* sector */
+ ofs <<= 9;
+ else if (s == 'k' || s == 'K') /* kb */
+ ofs <<= 10;
+ else if (s == 'm' || s == 'M') /* Mb */
+ ofs <<= 20;
+ else if (s == 'g' || s == 'G') /* Gb */
+ ofs <<= 30;
+ else
+ return ofs; /* invalid character */
+ (*endp)++;
+ return ofs;
+}
+
+/* Convert a string to a size. The string should be a number,
+ optionally followed by S (sectors), K (K-Bytes), M (Megabytes), G
+ (Gigabytes) */
+mt_off_t str_to_off_with_end(const char *str, char **endp) {
+ char s;
+ mt_off_t siz;
+
+ *endp = NULL;
+ siz = strtol(str, endp, 0);
+ s = **endp;
+ /* trailing char, see if it is a size specifier */
+ if (s == 's' || s == 'S') /* sector */
+ siz <<= 9;
+ else if (s == 'k' || s == 'K') /* kb */
+ siz <<= 10;
+ else if (s == 'm' || s == 'M') /* Mb */
+ siz <<= 20;
+ else if (s == 'g' || s == 'G') /* Gb */
+ siz <<= 30;
+ else
+ return siz; /* invalid character */
+ (*endp)++;
+ return siz;
+}
+
+off_t str_to_offset(char *str) {
+ char *end;
+ off_t ofs = str_to_offset_with_end(str, &end);
if (ofs <= 0)
return 0; /* invalid or missing offset */
- s = *endp++;
- if (s) { /* trailing char, see if it is a size specifier */
- if (s == 's' || s == 'S') /* sector */
- ofs <<= 9;
- else if (s == 'k' || s == 'K') /* kb */
- ofs <<= 10;
- else if (s == 'm' || s == 'M') /* Mb */
- ofs <<= 20;
- else if (s == 'g' || s == 'G') /* Gb */
- ofs <<= 30;
- else
- return 0; /* invalid character */
- if (*endp)
- return 0; /* extra char, invalid */
- }
+ if (*end)
+ return 0; /* extra char, invalid */
return ofs;
}
+
+
#if 0
#undef free
diff --git a/missFuncs.c b/missFuncs.c
index 271fe0b..c774bd7 100644
--- a/missFuncs.c
+++ b/missFuncs.c
@@ -123,7 +123,7 @@ char * strchr (const char* s, int c)
{
if (!s) return NULL;
while (*s && *s != c) s++;
- if (*s)
+ if (*s)
return (char*) s;
else
return NULL;
@@ -133,7 +133,7 @@ char * strchr (const char* s, int c)
#ifndef HAVE_STRRCHR
-char * strrchr (const char* s1, int c)
+char * strrchr (const char* s1, int c)
{
char* s = (char*) s1;
char* start = (char*) s;
@@ -175,7 +175,7 @@ char *strpbrk(const char *string, const char *brkset)
static int getdigit(char a, int max)
{
int dig;
-
+
if(a < '0')
return -1;
if(a <= '9') {
@@ -412,7 +412,7 @@ static exitCallback_t *callback = 0;
int atexit(void (*function) (void))
{
exitCallback_t *newCallback;
-
+
newCallback = New(exitCallback_t);
if(!newCallback) {
printOom();
diff --git a/mk_direntry.c b/mk_direntry.c
index 37015ea..da1c105 100644
--- a/mk_direntry.c
+++ b/mk_direntry.c
@@ -36,7 +36,7 @@
/**
* Converts input to shortname
* @param un unix name (in Unix charset)
- *
+ *
* @return 1 if name had to be mangled
*/
static __inline__ int convert_to_shortname(doscp_t *cp, ClashHandling_t *ch,
@@ -54,7 +54,7 @@ static __inline__ int convert_to_shortname(doscp_t *cp, ClashHandling_t *ch,
static __inline__ void chomp(char *line)
{
- int l = strlen(line);
+ size_t l = strlen(line);
while(l > 0 && (line[l-1] == '\n' || line[l-1] == '\r')) {
line[--l] = '\0';
}
@@ -70,7 +70,7 @@ static __inline__ int ask_rename(doscp_t *cp, ClashHandling_t *ch,
{
int mangled;
- /* TODO: Would be nice to suggest "autorenamed" version of name, press
+ /* TODO: Would be nice to suggest "autorenamed" version of name, press
* <Return> to get it.
*/
#if 0
@@ -92,7 +92,7 @@ static __inline__ int ask_rename(doscp_t *cp, ClashHandling_t *ch,
if (isprimary)
strcpy(longname, tname);
else
- mangled = convert_to_shortname(cp,
+ mangled = convert_to_shortname(cp,
ch, tname, shortname);
} while (mangled & 1);
return 1;
@@ -107,7 +107,7 @@ static __inline__ int ask_rename(doscp_t *cp, ClashHandling_t *ch,
static __inline__ clash_action ask_namematch(doscp_t *cp,
dos_name_t *dosname,
char *longname,
- int isprimary,
+ int isprimary,
ClashHandling_t *ch,
int no_overwrite,
int reason)
@@ -178,12 +178,12 @@ static __inline__ clash_action ask_namematch(doscp_t *cp,
fflush(opentty(1));
if (mtools_raw_tty) {
int rep;
- rep = fgetc(opentty(1));
+ rep = fgetc(opentty(1));
fputs("\n", stderr);
if(rep == EOF)
ans[0] = 'q';
else
- ans[0] = rep;
+ ans[0] = (char) rep;
} else {
if(fgets(ans, 9, opentty(0)) == NULL)
ans[0] = 'q';
@@ -299,9 +299,13 @@ static __inline__ clash_action process_namematch(doscp_t *cp,
return NAMEMATCH_SKIP;
else
return NAMEMATCH_OVERWRITE;
- default:
+ case NAMEMATCH_NONE:
+ case NAMEMATCH_ERROR:
+ case NAMEMATCH_SUCCESS:
+ case NAMEMATCH_GREW:
return NAMEMATCH_NONE;
}
+ return action;
}
static int contains_illegals(const char *string, const char *illegals,
@@ -332,7 +336,7 @@ static int is_reserved(char *ans, int islong)
((islong && !ans[4]) ||
(!islong && !strncmp(ans+4," ",4))))
return 1;
-
+
return 0;
}
@@ -384,18 +388,18 @@ static __inline__ clash_action get_slots(Stream_t *Dir,
ch->use_longname)) {
case -1:
return NAMEMATCH_ERROR;
-
+
case 0:
return NAMEMATCH_SKIP;
/* Single-file error error or skip request */
-
+
case 5:
return NAMEMATCH_GREW;
/* Grew directory, try again */
-
+
case 6:
return NAMEMATCH_SUCCESS; /* Success */
- }
+ }
match_pos = -2;
if (ssp->longmatch > -1) {
/* Primary Long Name Match */
@@ -403,7 +407,7 @@ static __inline__ clash_action get_slots(Stream_t *Dir,
fprintf(stderr,
"Got longmatch=%d for name %s.\n",
longmatch, longname);
-#endif
+#endif
match_pos = ssp->longmatch;
isprimary = 1;
} else if ((ch->use_longname & 1) && (ssp->shortmatch != -1)) {
@@ -439,7 +443,7 @@ static __inline__ clash_action get_slots(Stream_t *Dir,
}
ret = process_namematch(cp, dosname, longname,
isprimary, ch, no_overwrite, reason);
-
+
if (ret == NAMEMATCH_OVERWRITE && match_pos > -1){
if((entry.dir.attr & 0x5) &&
(ask_confirmation("file is read only, overwrite anyway (y/n) ? ")))
@@ -447,7 +451,7 @@ static __inline__ clash_action get_slots(Stream_t *Dir,
/* Free up the file to be overwritten */
if(fatFreeWithDirentry(&entry))
return NAMEMATCH_ERROR;
-
+
#if 0
if(isprimary &&
match_pos - ssp->match_free + 1 >= ssp->size_needed){
@@ -587,7 +591,7 @@ static int _mwrite_one(Stream_t *Dir,
case NAMEMATCH_ERROR:
return -1; /* Non-file-specific error,
* quit */
-
+
case NAMEMATCH_SKIP:
return -1; /* Skip file (user request or
* error) */
@@ -613,7 +617,7 @@ static int _mwrite_one(Stream_t *Dir,
return -1;
}
expanded = 1;
-
+
if (dir_grow(Dir, scan.max_entry))
return -1;
continue;
@@ -622,7 +626,9 @@ static int _mwrite_one(Stream_t *Dir,
return write_slots(Dir, &dosname, longname,
&scan, cb, arg,
ch->use_longname);
- default:
+ case NAMEMATCH_NONE:
+ case NAMEMATCH_AUTORENAME:
+ case NAMEMATCH_QUIT:
fprintf(stderr,
"Internal error: clash_action=%d\n",
ret);
diff --git a/mkmanifest.1 b/mkmanifest.1
index 4f398fb..5fa70c6 100644
--- a/mkmanifest.1
+++ b/mkmanifest.1
@@ -1,5 +1,5 @@
'\" t
-.TH mkmanifest 1 "28Nov20" mtools-4.0.26
+.TH mkmanifest 1 "08Jan22" mtools-4.0.37
.SH Name
mkmanifest - makes list of file names and their DOS 8+3 equivalent
'\" t
diff --git a/mkmanifest.c b/mkmanifest.c
index 1ccf37f..d950669 100644
--- a/mkmanifest.c
+++ b/mkmanifest.c
@@ -59,7 +59,7 @@ int main(int argc, char **argv)
static char *dos_name2(const char *name)
{
- static const char *dev[9] = {"con", "aux", "com1", "com2", "lpt1",
+ static const char *dev[9] = {"con", "aux", "com1", "com2", "lpt1",
"prn", "lpt2", "lpt3", "nul"};
char *s;
char *ext,*temp;
@@ -72,7 +72,7 @@ static char *dos_name2(const char *name)
/* separate the name from extension */
ext = 0;
dot = 0;
- for (i=strlen(buf)-1; i>=0; i--) {
+ for (i=(int)strlen(buf)-1; i>=0; i--) {
if (buf[i] == '.' && !dot) {
dot = 1;
buf[i] = '\0';
@@ -87,7 +87,7 @@ static char *dos_name2(const char *name)
else {
/* if name is a device */
for (i=0; i<9; i++) {
- if (!strcasecmp(temp, dev[i]))
+ if (!strcasecmp(temp, dev[i]))
*temp = 'x';
}
/* name too long? */
@@ -101,7 +101,7 @@ static char *dos_name2(const char *name)
*s = 'x';
while (ext && (s = strpbrk(ext, "^+=/[]:',?*\\<>|\". ")))
- *s = 'x';
+ *s = 'x';
strncpy(ans, temp, 12);
ans[12] = '\0';
}
diff --git a/mkmanpages b/mkmanpages
index cc10eb1..f543514 100755
--- a/mkmanpages
+++ b/mkmanpages
@@ -95,7 +95,6 @@ echo floppyd_installtest
echo mattrib
echo mbadblocks
echo mcd
-echo mclasserase
echo mcopy
echo mdel
echo mdeltree
diff --git a/mlabel.1 b/mlabel.1
index 6f24f7a..bc92d50 100644
--- a/mlabel.1
+++ b/mlabel.1
@@ -1,5 +1,5 @@
'\" t
-.TH mlabel 1 "28Nov20" mtools-4.0.26
+.TH mlabel 1 "08Jan22" mtools-4.0.37
.SH Name
mlabel - make an MSDOS volume label
'\" t
diff --git a/mlabel.c b/mlabel.c
index c90c722..4b08791 100644
--- a/mlabel.c
+++ b/mlabel.c
@@ -30,8 +30,8 @@
static void _label_name(doscp_t *cp, const char *filename, int verbose UNUSEDP,
int *mangled, dos_name_t *ans, int preserve_case)
{
- int len;
- int i;
+ size_t len;
+ size_t i;
int have_lower, have_upper;
wchar_t wbuffer[12];
@@ -159,7 +159,7 @@ void mlabel(int argc, char **argv, int type UNUSEDP)
case 'n':
set_serial = SER_RANDOM;
init_random();
- serial=random();
+ serial=(uint32_t) random();
break;
case 'N':
set_serial = SER_SET;
@@ -171,7 +171,7 @@ void mlabel(int argc, char **argv, int type UNUSEDP)
optarg);
exit(1);
}
- check_number_parse_errno(c, optarg, eptr);
+ check_number_parse_errno((char)c, optarg, eptr);
break;
case 'h':
usage(0);
@@ -208,12 +208,12 @@ void mlabel(int argc, char **argv, int type UNUSEDP)
fprintf(stderr, "Both clear and new label specified\n");
FREE(&RootDir);
exit(1);
- }
+ }
RootDir = open_root_dir(drive, isRop ? 0 : O_RDWR, isRop);
if(isRo) {
show = 1;
interactive = 0;
- }
+ }
if(!RootDir) {
fprintf(stderr, "%s: Cannot initialize drive\n", argv[0]);
exit(1);
@@ -241,7 +241,7 @@ void mlabel(int argc, char **argv, int type UNUSEDP)
/* ask for new label */
if(interactive){
- saved_sig_state ss;
+ saved_sig_state ss;
newLabel = longname;
allow_interrupts(&ss);
fprintf(stderr,"Enter the new volume label : ");
@@ -283,7 +283,7 @@ void mlabel(int argc, char **argv, int type UNUSEDP)
have_boot = 0;
if( (!show || newLabel[0]) || set_serial != SER_NONE) {
Fs = GetFs(RootDir);
- have_boot = (force_read(Fs,boot.characters,0,sizeof(boot)) ==
+ have_boot = (force_pread(Fs,boot.characters,0,sizeof(boot)) ==
sizeof(boot));
}
@@ -314,19 +314,19 @@ void mlabel(int argc, char **argv, int type UNUSEDP)
if((set_serial != SER_NONE) & have_boot) {
if(have_boot && boot.boot.descr >= 0xf0 && has_BPB4) {
- set_dword(labelBlock->serial, serial);
+ set_dword(labelBlock->serial, serial);
need_write_boot = 1;
}
}
if(need_write_boot) {
- force_write(Fs, (char *)&boot, 0, sizeof(boot));
+ force_pwrite(Fs, (char *)&boot, 0, sizeof(boot));
/* If this is fat 32, write backup boot sector too */
if(!WORD_S(fatlen)) {
int backupBoot = WORD_S(ext.fat32.backupBoot);
- force_write(Fs, (char *)&boot,
- backupBoot * WORD_S(secsiz),
- sizeof(boot));
+ force_pwrite(Fs, (char *)&boot,
+ backupBoot * WORD_S(secsiz),
+ sizeof(boot));
}
}
diff --git a/mmd.1 b/mmd.1
index 37063f5..60e6973 100644
--- a/mmd.1
+++ b/mmd.1
@@ -1,5 +1,5 @@
'\" t
-.TH mmd 1 "28Nov20" mtools-4.0.26
+.TH mmd 1 "08Jan22" mtools-4.0.37
.SH Name
mmd - make an MSDOS subdirectory
'\" t
diff --git a/mmd.c b/mmd.c
index c6b34eb..b252a27 100644
--- a/mmd.c
+++ b/mmd.c
@@ -63,13 +63,13 @@ static int makeit(dos_name_t *dosname,
{
Stream_t *Target;
CreateArg_t *arg = (CreateArg_t *) arg0;
- int fat;
- direntry_t subEntry;
+ uint32_t fat;
+ direntry_t subEntry;
/* will it fit? At least one cluster must be free */
if (!getfreeMinClusters(targetEntry->Dir, 1))
return -1;
-
+
mk_entry(dosname, ATTR_DIR, 1, 0, arg->mtime, &targetEntry->dir);
Target = OpenFileByDirentry(targetEntry);
if(!Target){
@@ -89,7 +89,7 @@ static int makeit(dos_name_t *dosname,
mk_entry_from_base(".. ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir);
dir_write(&subEntry);
- FLUSH((Stream_t *) Target);
+ FLUSH(Target);
subEntry.entry = 0;
GET_DATA(Target, 0, 0, 0, &fat);
mk_entry_from_base(". ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir);
@@ -148,7 +148,7 @@ static int createDirCallback(direntry_t *entry UNUSEDP, MainParam_t *mp)
FREE(&ret);
return GOT_ONE;
}
-
+
}
void mmd(int argc, char **argv, int type UNUSEDP) NORETURN;
diff --git a/mmount.1 b/mmount.1
index 90b983a..37a1b1c 100644
--- a/mmount.1
+++ b/mmount.1
@@ -1,5 +1,5 @@
'\" t
-.TH mmount 1 "28Nov20" mtools-4.0.26
+.TH mmount 1 "08Jan22" mtools-4.0.37
.SH Name
mmount - mount an MSDOS disk
'\" t
diff --git a/mmount.c b/mmount.c
index aee0330..3499824 100644
--- a/mmount.c
+++ b/mmount.c
@@ -18,7 +18,7 @@
*
* written by:
*
- * Alain L. Knaff
+ * Alain L. Knaff
* alain@knaff.lu
*
*/
@@ -43,7 +43,7 @@ void mmount(int argc, char **argv, int type UNUSEDP)
int media;
union bootsector boot;
Stream_t *Stream;
-
+
if (argc<2 || !argv[1][0] || argv[1][1] != ':' || argv[1][2]){
fprintf(stderr,"Usage: %s -V drive:\n", argv[0]);
exit(1);
@@ -59,7 +59,7 @@ void mmount(int argc, char **argv, int type UNUSEDP)
if ( dev.partition ) {
char part_name[4];
sprintf(part_name, "%d", dev.partition %1000);
- strcat(name, part_name);
+ strcat(name, part_name);
}
/* and finally mount it */
@@ -79,7 +79,7 @@ void mmount(int argc, char **argv, int type UNUSEDP)
exit(1);
default:
while ( wait(&status) != pid );
- }
+ }
if ( WEXITSTATUS(status) == 0 )
exit(0);
argv[0] = strdup("mount");
@@ -99,7 +99,7 @@ void mmount(int argc, char **argv, int type UNUSEDP)
#include "msdos.h"
-void mmount(int argc, char **argv, int type)
+void mmount(int argc UNUSEDP, char **argv UNUSEDP, int type UNUSEDP)
{
fprintf(stderr,"This command is only available for LINUX \n");
exit(1);
diff --git a/mmove.1 b/mmove.1
index 08082d3..51ac207 100644
--- a/mmove.1
+++ b/mmove.1
@@ -1,5 +1,5 @@
'\" t
-.TH mmove 1 "28Nov20" mtools-4.0.26
+.TH mmove 1 "08Jan22" mtools-4.0.37
.SH Name
mmove - move or rename an MSDOS file or subdirectory
'\" t
diff --git a/mmove.c b/mmove.c
index d9221cf..def0d0f 100644
--- a/mmove.c
+++ b/mmove.c
@@ -54,7 +54,7 @@ static int renameit(dos_name_t *dosname,
direntry_t *targetEntry)
{
Arg_t *arg = (Arg_t *) arg0;
- int fat;
+ uint32_t fat;
targetEntry->dir = arg->entry->dir;
dosnameToDirentry(dosname, &targetEntry->dir);
@@ -65,7 +65,7 @@ static int renameit(dos_name_t *dosname,
/* get old direntry. It is important that we do this
* on the actual direntry which is stored in the file,
* and not on a copy, because we will modify it, and the
- * modification should be visible at file
+ * modification should be visible at file
* de-allocation time */
movedEntry = getDirentry(arg->mp.File);
if(movedEntry->Dir != targetEntry->Dir) {
@@ -73,7 +73,7 @@ static int renameit(dos_name_t *dosname,
direntry_t subEntry;
Stream_t *oldDir;
/* we have a directory here. Change its parent link */
-
+
initializeDirentry(&subEntry, arg->mp.File);
switch(vfat_lookup(&subEntry, "..", 2, ACCEPT_DIR,
@@ -101,7 +101,7 @@ static int renameit(dos_name_t *dosname,
}
wipeEntry(movedEntry);
-
+
/* free the old parent, allocate the new one. */
oldDir = movedEntry->Dir;
*movedEntry = *targetEntry;
@@ -174,7 +174,7 @@ static int rename_directory(direntry_t *entry, MainParam_t *mp)
ret = rename_file(entry, mp);
if(ret & ERROR_ONE)
return ret;
-
+
return ret;
}
@@ -220,7 +220,7 @@ static void usage(int ret)
fprintf(stderr,
"Usage: %s [-vV] [-D clash_option] file targetfile\n", progname);
fprintf(stderr,
- " %s [-vV] [-D clash_option] file [files...] target_directory\n",
+ " %s [-vV] [-D clash_option] file [files...] target_directory\n",
progname);
exit(ret);
}
@@ -252,7 +252,7 @@ void mmove(int argc, char **argv, int oldsyntax)
arg.verbose = 1;
break;
case 'o':
- handle_clash_options(&arg.ch, c);
+ handle_clash_options(&arg.ch, (char)c);
break;
case 'D':
if(handle_clash_options(&arg.ch, *optarg))
@@ -270,7 +270,7 @@ void mmove(int argc, char **argv, int oldsyntax)
if (argc - optind < 2)
usage(1);
- init_mp(&arg.mp);
+ init_mp(&arg.mp);
arg.mp.arg = (void *) &arg;
arg.mp.openflags = O_RDWR;
diff --git a/mpartition.1 b/mpartition.1
index 4c3b9a7..a87ee77 100644
--- a/mpartition.1
+++ b/mpartition.1
@@ -1,5 +1,5 @@
'\" t
-.TH mpartition 1 "28Nov20" mtools-4.0.26
+.TH mpartition 1 "08Jan22" mtools-4.0.37
.SH Name
mpartition - partition an MSDOS hard disk
'\" t
diff --git a/mpartition.c b/mpartition.c
index 1c50ef3..efc5d40 100644
--- a/mpartition.c
+++ b/mpartition.c
@@ -27,32 +27,20 @@
#include "plain_io.h"
#include "nameclash.h"
#include "buffer.h"
-#include "scsi.h"
#include "partition.h"
+#include "open_image.h"
+#include "lba.h"
#ifdef OS_linux
#include "linux/hdreg.h"
-
-#define _LINUX_STRING_H_
-#define kdev_t int
#include "linux/fs.h"
-#undef _LINUX_STRING_H_
-
#endif
-#define tolinear(x) \
-(sector(x)-1+(head(x)+cyl(x)*used_dev->heads)*used_dev->sectors)
-
-
-static __inline__ void print_hsc(hsc *h)
-{
- printf(" h=%d s=%d c=%d\n",
- head(*h), sector(*h), cyl(*h));
-}
-
-static void set_offset(hsc *h, unsigned long offset, int heads, int sectors)
+static void set_offset(hsc *h, unsigned long offset,
+ uint16_t heads, uint16_t sectors)
{
- int head, sector, cyl;
+ uint16_t head, sector;
+ unsigned int cyl;
if(! heads || !sectors)
head = sector = cyl = 0; /* linear mode */
@@ -61,20 +49,43 @@ static void set_offset(hsc *h, unsigned long offset, int heads, int sectors)
offset = offset / sectors;
head = offset % heads;
- cyl = offset / heads;
- if(cyl > 1023) cyl = 1023;
+ offset = offset / heads;
+ if(offset > 1023)
+ cyl = 1023;
+ else
+ cyl = (uint16_t) offset;
}
-
- h->head = head;
+ if(head > UINT8_MAX) {
+ /* sector or head out of range => linear mode */
+ head = sector = cyl = 0;
+ }
+ h->head = (uint8_t) head;
h->sector = ((sector+1) & 0x3f) | ((cyl & 0x300)>>2);
h->cyl = cyl & 0xff;
}
void setBeginEnd(struct partition *partTable,
- unsigned long begin, unsigned long end,
- unsigned int heads, unsigned int sectors,
- int activate, int type, int fat_bits)
+ uint32_t begin, uint32_t end,
+ uint16_t iheads, uint16_t isectors,
+ int activate, uint8_t type, unsigned int fat_bits)
{
+ uint8_t heads, sectors;
+
+ if(iheads > UINT8_MAX) {
+ fprintf(stderr,
+ "Too many heads for partition: %d\n",
+ iheads);
+ exit(1);
+ }
+ heads=(uint8_t) iheads;
+ if(isectors > UINT8_MAX) {
+ fprintf(stderr,
+ "Too many sectors for partition: %d\n",
+ isectors);
+ exit(1);
+ }
+ sectors=(uint8_t) isectors;
+
set_offset(&partTable->start, begin, heads, sectors);
set_offset(&partTable->end, end-1, heads, sectors);
set_dword(partTable->start_sect, begin);
@@ -125,7 +136,7 @@ void setBeginEnd(struct partition *partTable,
else if (fat_bits == 16)
/* FAT 16 partition */
type = 0x04; /* DOS FAT16, CHS */
- } else if (end < sectors * heads * 1024)
+ } else if (end < sectors * heads * 1024u)
/* FAT 12 or FAT16 partition above the 32M
* mark but below the 1024 cylinder mark.
* Indeed, there can be no CHS partition
@@ -137,83 +148,6 @@ void setBeginEnd(struct partition *partTable,
partTable->sys_ind = type;
}
-int consistencyCheck(struct partition *partTable, int doprint, int verbose,
- int *has_activated, unsigned int *last_end,
- unsigned int *j,
- struct device *used_dev, int target_partition)
-{
- int i;
- unsigned int inconsistency;
-
- *j = 0;
- *last_end = 1;
-
- /* quick consistency check */
- inconsistency = 0;
- *has_activated = 0;
- for(i=1; i<5; i++){
- if(!partTable[i].sys_ind)
- continue;
- if(partTable[i].boot_ind)
- (*has_activated)++;
- if((used_dev &&
- (used_dev->heads != head(partTable[i].end)+1 ||
- used_dev->sectors != sector(partTable[i].end))) ||
- sector(partTable[i].start) != 1){
- fprintf(stderr,
- "Partition %d is not aligned\n",
- i);
- inconsistency=1;
- }
-
- if(*j &&
- *last_end > BEGIN(partTable[i])) {
- fprintf(stderr,
- "Partitions %d and %d badly ordered or overlapping\n",
- *j,i);
- inconsistency=1;
- }
-
- *last_end = END(partTable[i]);
- *j = i;
-
- if(used_dev &&
- cyl(partTable[i].start) != 1023 &&
- tolinear(partTable[i].start) != BEGIN(partTable[i])) {
- fprintf(stderr,
- "Start position mismatch for partition %d\n",
- i);
- inconsistency=1;
- }
- if(used_dev &&
- cyl(partTable[i].end) != 1023 &&
- tolinear(partTable[i].end)+1 != END(partTable[i])) {
- fprintf(stderr,
- "End position mismatch for partition %d\n",
- i);
- inconsistency=1;
- }
-
- if(doprint && verbose) {
- if(i==target_partition)
- putchar('*');
- else
- putchar(' ');
- printf("Partition %d\n",i);
-
- printf(" active=%x\n", partTable[i].boot_ind);
- printf(" start:");
- print_hsc(&partTable[i].start);
- printf(" type=0x%x\n", partTable[i].sys_ind);
- printf(" end:");
- print_hsc(&partTable[i].end);
- printf(" start=%d\n", BEGIN(partTable[i]));
- printf(" nr=%d\n", _DWORD(partTable[i].nr_sects));
- printf("\n");
- }
- }
- return inconsistency;
-}
/* setsize function. Determines scsicam mapping if this cannot be inferred from
* any existing partitions. Shamelessly snarfed from the Linux kernel ;-) */
@@ -254,7 +188,7 @@ int consistencyCheck(struct partition *partTable, int doprint, int verbose,
static int setsize(unsigned long capacity,unsigned int *cyls,
uint16_t *hds, uint16_t *secs) {
- unsigned int rv = 0;
+ int rv = 0;
unsigned long heads, sectors, cylinders, temp;
cylinders = 1024L; /* Set number of cylinders to max */
@@ -273,15 +207,15 @@ static int setsize(unsigned long capacity,unsigned int *cyls,
cylinders = capacity / temp;/* Compute number of cylinders */
}
}
- if (cylinders == 0) rv=(unsigned)-1;/* Give error if 0 cylinders */
+ if (cylinders == 0) rv=-1;/* Give error if 0 cylinders */
*cyls = (unsigned int) cylinders; /* Stuff return values */
- *secs = (unsigned int) sectors;
- *hds = (unsigned int) heads;
+ *secs = (uint16_t) sectors;
+ *hds = (uint16_t) heads;
return(rv);
}
-static void setsize0(unsigned long capacity,unsigned int *cyls,
+static void setsize0(uint32_t capacity,unsigned int *cyls,
uint16_t *hds, uint16_t *secs)
{
int r;
@@ -325,9 +259,9 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
Stream_t *Stream;
unsigned int dummy2;
- unsigned int i,j;
+ unsigned int i;
- int sec_per_cyl;
+ uint16_t sec_per_cyl;
int doprint = 0;
int verbose = 0;
int create = 0;
@@ -335,24 +269,26 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
unsigned int length = 0;
int do_remove = 0;
int initialize = 0;
- unsigned int tot_sectors=0;
- int type = 0;
+
+ uint32_t tot_sectors=0;
+ /* Needs to be long due to BLKGETSIZE ioctl */
+
+ uint8_t type = 0;
int begin_set = 0;
int size_set = 0;
int end_set = 0;
- unsigned int last_end = 0;
int activate = 0;
int has_activated = 0;
int inconsistency=0;
unsigned int begin=0;
unsigned int end=0;
- int sizetest=0;
int dirty = 0;
- int open2flags = NO_OFFSET;
+ int open2flags = 0;
int c;
struct device used_dev;
- int argtracks, argheads, argsectors;
+ unsigned int argtracks;
+ uint16_t argheads, argsectors;
char drive, name[EXPAND_BUF];
unsigned char buf[512];
@@ -360,6 +296,7 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
struct device *dev;
char errmsg[2100];
char *bootSector=0;
+ struct partition *tpartition;
argtracks = 0;
argheads = 0;
@@ -413,17 +350,17 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
/* could be abused to "manually" create
* extended partitions */
open2flags |= NO_PRIV;
- type = strtoi(optarg, &endptr, 0);
+ type = strtou8(optarg, &endptr, 0);
break;
case 't':
- argtracks = atoi(optarg);
+ argtracks = atoui(optarg);
break;
case 'h':
- argheads = atoi(optarg);
+ argheads = atou16(optarg);
break;
case 's':
- argsectors = atoi(optarg);
+ argsectors = atou16(optarg);
break;
case 'f':
@@ -436,28 +373,19 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
case 'v':
verbose++;
break;
- case 'S':
- /* testing only */
- /* could be abused to create partitions
- * extending beyond the actual size of the
- * device */
- open2flags |= NO_PRIV;
- tot_sectors = strtoui(optarg, &endptr, 0);
- sizetest = 1;
- break;
case 'b':
begin_set = 1;
begin = strtoui(optarg, &endptr, 0);
break;
case 'l':
size_set = 1;
- length = strtoui(optarg, &endptr, 0);
+ length = parseSize(optarg);
break;
default:
usage(1);
}
- check_number_parse_errno(c, optarg, endptr);
+ check_number_parse_errno((char)c, optarg, endptr);
}
if (argc - optind != 1 ||
@@ -497,8 +425,9 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
#ifdef USING_NEW_VOLD
strcpy(name, getVoldName(dev, name));
#endif
- Stream = SimpleFileOpen(&used_dev, dev, name, mode,
- errmsg, open2flags, 1, 0);
+ Stream = OpenImage(&used_dev, dev, name, mode, errmsg,
+ open2flags | SKIP_PARTITION | ALWAYS_GET_GEOMETRY,
+ mode, NULL, NULL, NULL);
if (!Stream) {
#ifdef HAVE_SNPRINTF
@@ -510,36 +439,10 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
continue;
}
-
- /* try to find out the size */
- if(!sizetest)
- tot_sectors = 0;
- if(IS_SCSI(dev)) {
- unsigned char cmd[10];
- unsigned char data[10];
- cmd[0] = SCSI_READ_CAPACITY;
- memset ((void *) &cmd[2], 0, 8);
- memset ((void *) &data[0], 137, 10);
- scsi_cmd(get_fd(Stream), cmd, 10, SCSI_IO_READ,
- data, 10, get_extra_data(Stream));
-
- tot_sectors = 1 +
- (data[0] << 24) +
- (data[1] << 16) +
- (data[2] << 8) +
- (data[3] );
- if(verbose)
- printf("%d sectors in total\n", tot_sectors);
- }
-
-#ifdef OS_linux
- if (tot_sectors == 0) {
- ioctl(get_fd(Stream), BLKGETSIZE, &tot_sectors);
- }
-#endif
+ tot_sectors = used_dev.tot_sectors;
/* read the partition table */
- if (READS(Stream, (char *) buf, 0, 512) != 512 && !initialize){
+ if (PREADS(Stream, (char *) buf, 0, 512) != 512 && !initialize){
#ifdef HAVE_SNPRINTF
snprintf(errmsg, sizeof(errmsg)-1,
"Error reading from '%s', wrong parameters?",
@@ -595,12 +498,13 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
inconsistency = 1;
}
+ tpartition=&partTable[dev->partition];
if(do_remove){
- if(!partTable[dev->partition].sys_ind)
+ if(!tpartition->sys_ind)
fprintf(stderr,
"Partition for drive %c: does not exist\n",
drive);
- if((partTable[dev->partition].sys_ind & 0x3f) == 5) {
+ if((tpartition->sys_ind & 0x3f) == 5) {
fprintf(stderr,
"Partition for drive %c: may be an extended partition\n",
drive);
@@ -608,69 +512,59 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
"Use the -f flag to remove it anyways\n");
inconsistency = 1;
}
- memset(&partTable[dev->partition], 0, sizeof(*partTable));
+ memset(tpartition, 0, sizeof(*tpartition));
}
- if(create && partTable[dev->partition].sys_ind) {
+ if(create && tpartition->sys_ind) {
fprintf(stderr,
"Partition for drive %c: already exists\n", drive);
fprintf(stderr,
"Use the -r flag to remove it before attempting to recreate it\n");
}
+ /* if number of heads and sectors not known yet, set "reasonable"
+ * defaults */
+ compute_lba_geom_from_tot_sectors(&used_dev);
- /* find out number of heads and sectors, and whether there is
- * any activated partition */
+ /* find out whether there is any activated partition. Moreover
+ * if no offset of a partition to be created have been
+ * specificed, find out whether it may be placed between the
+ * preceding and following partition already existing */
has_activated = 0;
for(i=1; i<5; i++){
- if(!partTable[i].sys_ind)
+ struct partition *partition=&partTable[i];
+ if(!partition->sys_ind)
continue;
- if(partTable[i].boot_ind)
+ if(partition->boot_ind)
has_activated++;
- /* set geometry from entry */
- if (!used_dev.heads)
- used_dev.heads = head(partTable[i].end)+1;
- if(!used_dev.sectors)
- used_dev.sectors = sector(partTable[i].end);
if(i<dev->partition && !begin_set)
- begin = END(partTable[i]);
+ begin = END(partition);
if(i>dev->partition && !end_set && !size_set) {
- end = BEGIN(partTable[i]);
+ end = BEGIN(partition);
end_set = 1;
}
}
-#ifdef OS_linux
- if(!used_dev.sectors && !used_dev.heads) {
- if(!IS_SCSI(dev)) {
- struct hd_geometry geom;
- if(ioctl(get_fd(Stream), HDIO_GETGEO, &geom) == 0) {
- used_dev.heads = geom.heads;
- used_dev.sectors = geom.sectors;
- }
- }
- }
-#endif
-
if(!used_dev.sectors && !used_dev.heads) {
- if(tot_sectors)
- setsize0(tot_sectors,&dummy2,&used_dev.heads,
+ if(tot_sectors) {
+ setsize0((uint32_t)tot_sectors,&dummy2,&used_dev.heads,
&used_dev.sectors);
- else {
+ } else {
used_dev.heads = 64;
used_dev.sectors = 32;
}
}
if(verbose)
- fprintf(stderr,"sectors: %d heads: %d %d\n",
+ fprintf(stderr,"sectors: %d heads: %d %u\n",
used_dev.sectors, used_dev.heads, tot_sectors);
sec_per_cyl = used_dev.sectors * used_dev.heads;
if(create) {
- if(!end_set && tot_sectors) {
+ unsigned int overlap;
+ if(!end_set && !size_set && tot_sectors) {
end = tot_sectors - tot_sectors % sec_per_cyl;
end_set = 1;
}
@@ -679,79 +573,61 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
* the disk, keep one track unused to allow place for
* the master boot record */
if(!begin && !begin_set)
- begin = used_dev.sectors;
- if(!size_set && used_dev.tracks) {
- size_set = 2;
- length = sec_per_cyl * used_dev.tracks;
-
- /* round the size in order to take
- * into account any "hidden" sectors */
-
- /* do we anchor this at the beginning ?*/
- if(begin_set || dev->partition <= 2 || !end_set)
- length -= begin % sec_per_cyl;
- else if(end - length < begin)
- /* truncate any overlap */
- length = end - begin;
- }
+ begin = used_dev.sectors ? used_dev.sectors : 2048;
+
+ /* Do not try to align partitions (other than first) on track
+ * boundaries here: apparently this was a thing of the past */
+
if(size_set) {
- if(!begin_set && dev->partition >2 && end_set)
- begin = end - length;
- else
- end = begin + length;
+ end = begin + length;
} else if(!end_set) {
fprintf(stderr,"Unknown size\n");
exit(1);
}
- setBeginEnd(&partTable[dev->partition], begin, end,
+ /* Make sure partition boundaries are correctly ordered
+ * (end > begin) */
+ if(begin >= end) {
+ fprintf(stderr, "Begin larger than end\n");
+ exit(1);
+ }
+
+ /* Check whether new partition doesn't overlap with
+ * any of those already in place */
+ if((overlap=findOverlap(partTable, 4, begin, end))) {
+ fprintf(stderr,
+ "Partition would overlap with partition %d\n",
+ overlap);
+ exit(1);
+ }
+
+ setBeginEnd(tpartition, begin, end,
used_dev.heads, used_dev.sectors,
!has_activated, type,
- dev->fat_bits);
+ abs(dev->fat_bits));
}
if(activate) {
- if(!partTable[dev->partition].sys_ind) {
+ if(!tpartition->sys_ind) {
fprintf(stderr,
"Partition for drive %c: does not exist\n",
drive);
} else {
switch(activate) {
case 1:
- partTable[dev->partition].boot_ind=0x80;
+ tpartition->boot_ind=0x80;
break;
case -1:
- partTable[dev->partition].boot_ind=0x00;
+ tpartition->boot_ind=0x00;
break;
}
}
}
-
inconsistency |= consistencyCheck(partTable, doprint, verbose,
- &has_activated, &last_end, &j,
+ &has_activated, tot_sectors,
&used_dev, dev->partition);
- if(doprint && !inconsistency && partTable[dev->partition].sys_ind) {
- printf("The following command will recreate the partition for drive %c:\n",
- drive);
- used_dev.tracks =
- (_DWORD(partTable[dev->partition].nr_sects) +
- (BEGIN(partTable[dev->partition]) % sec_per_cyl)) /
- sec_per_cyl;
- printf("mpartition -c -t %d -h %d -s %d -b %u %c:\n",
- used_dev.tracks, used_dev.heads, used_dev.sectors,
- BEGIN(partTable[dev->partition]), drive);
- }
-
- if(tot_sectors && last_end >tot_sectors) {
- fprintf(stderr,
- "Partition %d exceeds beyond end of disk\n",
- j);
- exit(1);
- }
-
-
switch(has_activated) {
case 0:
fprintf(stderr,
@@ -771,17 +647,31 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
if(inconsistency && !force) {
fprintf(stderr,
"inconsistency detected!\n" );
- if(dirty)
+ if(dirty) {
fprintf(stderr,
"Retry with the -f switch to go ahead anyways\n");
- exit(1);
+ exit(1);
+ }
+ }
+
+ if(doprint && tpartition->sys_ind) {
+ printf("The following command will recreate the partition for drive %c:\n",
+ drive);
+ used_dev.tracks =
+ (_DWORD(tpartition->nr_sects) +
+ (BEGIN(tpartition) % sec_per_cyl)) /
+ sec_per_cyl;
+ printf("mpartition -c -b %d -l %d -t %d -h %d -s %d -b %u %c:\n",
+ BEGIN(tpartition), PART_SIZE(tpartition),
+ used_dev.tracks, used_dev.heads, used_dev.sectors,
+ BEGIN(tpartition), drive);
}
if(dirty) {
/* write data back to the disk */
if(verbose>=2)
print_sector("Writing sector", buf, 512);
- if (WRITES(Stream, (char *) buf, 0, 512) != 512) {
+ if (PWRITES(Stream, (char *) buf, 0, 512) != 512) {
fprintf(stderr,"Error writing partition table");
exit(1);
}
diff --git a/mrd.1 b/mrd.1
index 215cace..7f8c8ff 100644
--- a/mrd.1
+++ b/mrd.1
@@ -1,5 +1,5 @@
'\" t
-.TH mrd 1 "28Nov20" mtools-4.0.26
+.TH mrd 1 "08Jan22" mtools-4.0.37
.SH Name
mrd - remove an MSDOS subdirectory
'\" t
diff --git a/mren.1 b/mren.1
index e89a4b5..70c40e9 100644
--- a/mren.1
+++ b/mren.1
@@ -1,5 +1,5 @@
'\" t
-.TH mren 1 "28Nov20" mtools-4.0.26
+.TH mren 1 "08Jan22" mtools-4.0.37
.SH Name
mren - rename an existing MSDOS file
'\" t
diff --git a/msdos.h b/msdos.h
index 192228b..8aed16b 100644
--- a/msdos.h
+++ b/msdos.h
@@ -141,7 +141,7 @@ struct fat32_t {
unsigned char infoSector[2]; /* 48 changeable global info */
unsigned char backupBoot[2]; /* 50 back up boot sector */
unsigned char reserved[6]; /* 52 ? */
- unsigned char reserved2[6]; /* 52 ? */
+ unsigned char reserved2[6]; /* 58 ? */
struct label_blk_t labelBlock;
}; /* ends at 58 */
@@ -202,17 +202,18 @@ union bootsector {
#define OFFSET(x) (((char *) (boot->x)) - ((char *)(boot->jump)))
/* max FAT12/FAT16 sizes, according to
-
+
https://staff.washington.edu/dittrich/misc/fatgen103.pdf
https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/fatgen103.doc
- interestingly enough, another Microsoft document
+ interestingly enough, another Microsoft document
[http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b67321]
gives different values, but the first seems to be more sure about
itself, so we believe that one ;-)
*/
#define FAT12 0x0ff5 /* max. number + 1 of clusters described by a 12 bit FAT */
#define FAT16 0xfff5 /* max number + 1 of clusters for a 16 bit FAT */
+#define FAT32 0xffffff5 /* max number + 1 of clusters for a 32 bit FAT */
#define ATTR_ARCHIVE 0x20
#define ATTR_DIR 0x10
@@ -248,8 +249,6 @@ union bootsector {
((n) * FAT_SIZE(bits, sec_siz, clusters) + \
(clusters) * (cluster_size))
-#define TOTAL_DISK_SIZE(bits, sec_siz, clusters, n, cluster_size) \
- (DISK_SIZE(bits, sec_siz, clusters, n, cluster_size) + 2)
/* approx. total disk size: assume 1 boot sector and one directory sector */
extern const char *mversion;
diff --git a/mshortname.1 b/mshortname.1
index 35901f7..98d0f74 100644
--- a/mshortname.1
+++ b/mshortname.1
@@ -1,5 +1,5 @@
'\" t
-.TH mshortname 1 "28Nov20" mtools-4.0.26
+.TH mshortname 1 "08Jan22" mtools-4.0.37
.SH Name
mshortname - shows short name of a file
'\" t
diff --git a/mshortname.c b/mshortname.c
index 495cef5..1e3aa96 100644
--- a/mshortname.c
+++ b/mshortname.c
@@ -34,9 +34,9 @@ static int print_short_name(direntry_t *entry, MainParam_t *mp UNUSEDP)
static void usage(int ret) NORETURN;
static void usage(int ret)
{
- fprintf(stderr, "Mtools version %s, dated %s\n",
+ fprintf(stderr, "Mtools version %s, dated %s\n",
mversion, mdate);
- fprintf(stderr,
+ fprintf(stderr,
"Usage: %s msdosfile [msdosfiles...]\n",
progname);
exit(ret);
diff --git a/mshowfat.1 b/mshowfat.1
index 04a0179..11e6c40 100644
--- a/mshowfat.1
+++ b/mshowfat.1
@@ -1,5 +1,5 @@
'\" t
-.TH mshowfat 1 "28Nov20" mtools-4.0.26
+.TH mshowfat 1 "08Jan22" mtools-4.0.37
.SH Name
mshowfat - shows FAT clusters allocated to file
'\" t
diff --git a/mshowfat.c b/mshowfat.c
index b04c6e6..d4919c4 100644
--- a/mshowfat.c
+++ b/mshowfat.c
@@ -72,7 +72,7 @@ void mshowfat(int argc, char **argv, int mtype UNUSEDP)
{
Arg_t arg;
int c, ret;
-
+
/* get command line options */
if(helpFlag(argc, argv))
usage(0);
diff --git a/mtools.1 b/mtools.1
index b9a127a..49d9e07 100644
--- a/mtools.1
+++ b/mtools.1
@@ -1,5 +1,5 @@
'\" t
-.TH mtools 1 "28Nov20" mtools-4.0.26
+.TH mtools 1 "26Dec21" mtools-4.0.37
.SH Name
mtools - utilities to access DOS disks in Unix.
'\" t
@@ -36,7 +36,7 @@ Mtools can be found at the following places (and their mirrors):
.nf
.ft 3
.in +0.3i
-http://ftp.gnu.org/gnu/mtools/mtools-4.0.26.tar.gz
+http://ftp.gnu.org/gnu/mtools/mtools-4.0.37.tar.gz
.fi
.in -0.3i
.ft R
@@ -82,13 +82,17 @@ All options use the \fR\&\f(CW-\fR (minus) as their first character, not
Most mtools commands allow multiple filename parameters, which
doesn't follow MS-DOS conventions, but which is more user-friendly.
.PP
-Most mtools commands allow options that instruct them how to handle file
-name clashes. See section name clashes, for more details on these. All
-commands accept the \fR\&\f(CW-V\fR flags which prints the version, and most
-accept the \fR\&\f(CW-v\fR flag, which switches on verbose mode. In verbose
-mode, these commands print out the name of the MS-DOS files upon which
-they act, unless stated otherwise. See section Commands, for a description of
-the options which are specific to each command.
+Most mtools commands allow options that instruct them how to handle
+file name clashes. See section name clashes, for more details on these.
+.PP
+All commands accept the \fR\&\f(CW-i\fR flag which allows to specify an
+image file (See section drive letters).
+.PP
+All commands accept the \fR\&\f(CW-V\fR flag which prints the version, and
+most accept the \fR\&\f(CW-v\fR flag, which switches on verbose mode. In
+verbose mode, these commands print out the name of the MS-DOS files
+upon which they act, unless stated otherwise. See section Commands, for a
+description of the options which are specific to each command.
.PP
.SS Drive\ letters
.PP
@@ -479,7 +483,6 @@ floppyd_installtest
mattrib
mbadblocks
mcd
-mclasserase
mcopy
mdel
mdeltree
diff --git a/mtools.5 b/mtools.5
index ef5f95e..74f5d43 100644
--- a/mtools.5
+++ b/mtools.5
@@ -1,5 +1,5 @@
'\" t
-.TH mtools 5 "28Nov20" MTOOLS MTOOLS
+.TH mtools 5 "26Dec21" MTOOLS MTOOLS
.SH Name
mtools.conf - mtools configuration files
'\" t
@@ -13,7 +13,7 @@ mtools.conf - mtools configuration files
.tr \(if`
.tr \(pd"
-.ds St Mtools\ 4.0.26
+.ds St Mtools\ 4.0.37
.PP
.SH Description
.PP
@@ -339,6 +339,34 @@ for all drives by using the global \fR\&\f(CWdefault_codepage\fR parameter
(outside of any drive description). This parameters exists starting at
version 4.0.0
.TP
+\&\fR\&\f(CWdata_map\fR\
+Remaps data from image file. This is useful for image files which
+might need additional zero-filled sectors to be inserted. Such is the
+case for instance for IBM 3174 floppy images. These images represent
+floppy disks with fewer sectors on their first cylinder. These missing
+sectors are not stored in the image, but are still counted in the
+filesystem layout. The data_map allows to fake these missing sectors
+for the upper layers of mtools. A data_map is a comma-separated
+sequence of source type and size. Source type may be \fR\&\f(CWzero\fR for
+zero-filled sectors created by map, \fR\&\f(CWskip\fR for data in raw image
+to be ignored (skipped), and nothing for data to be used as is
+(copied) from the raw image. Datamap is automatically complemented by
+an implicit last element of data to be used as is from current offset
+to end of file. Each size is a number followed by a unit: \fR\&\f(CWs\fR for
+a 512 byte sector, \fR\&\f(CWK\fR for Kbytes, \fR\&\f(CWM\fR for megabytes,
+\&\fR\&\f(CWG\fR for gigabytes, and nothing for single bytes.
+.IP
+Example:
+.IP
+\&\fR\&\f(CWdata_map=1s,zero31s,28s,skip1s\fR would be a map for use with IBM
+3174 floppy images. First sector (\fR\&\f(CW1s\fR, boot sector) is used as
+is. Then follow 31 fake zero-filled sectors (\fR\&\f(CWzero31s\fR), then the
+next 28 sectors from image (\fR\&\f(CW28s\fR) are used as is (they contain
+FAT and root directory), then one sector from image is skipped
+(\fR\&\f(CWskip1s\fR), and finally the rest of image is used as is
+(implicit)
+.IP
+.TP
\&\fR\&\f(CWprecmd\fR\
On some variants of Solaris, it is necessary to call 'volcheck -v'
before opening a floppy device, in order for the system to notice that
diff --git a/mtools.c b/mtools.c
index ffac8bb..a6401ae 100644
--- a/mtools.c
+++ b/mtools.c
@@ -32,7 +32,6 @@ static const struct dispatch {
{"mbadblocks",mbadblocks, 0},
{"mcat",mcat, 0},
{"mcd",mcd, 0},
- {"mclasserase",mclasserase, 0},
{"mcopy",mcopy, 0},
{"mdel",mdel, 0},
{"mdeltree",mdel, 2},
@@ -78,10 +77,10 @@ int main(int argc,char **argv)
/*#define PRIV_TEST*/
#ifdef PRIV_TEST
- {
+ {
int euid;
char command[100];
-
+
printf("INIT: %d %d\n", getuid(), geteuid());
drop_privs();
printf("DROP: %d %d\n", getuid(), geteuid());
@@ -105,7 +104,7 @@ int main(int argc,char **argv)
#ifdef __EMX__
_wildcard(&argc,&argv);
-#endif
+#endif
/* check whether the compiler lays out structures in a sane way */
@@ -132,7 +131,7 @@ int main(int argc,char **argv)
** Mainly done for the BeOS, which doesn't support links yet.
*/
- if(argc >= 3 &&
+ if(argc >= 3 &&
!strcmp(argv[1], "-c") &&
!strcmp(name, "mtools")) {
argc-=2;
@@ -143,9 +142,9 @@ int main(int argc,char **argv)
/* print the version */
- if(argc >= 2 &&
+ if(argc >= 2 &&
(strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") ==0)) {
- printf("%s (GNU mtools) %s\n",
+ printf("%s (GNU mtools) %s\n",
name, mversion);
printf("configured with the following options: ");
#ifdef USE_XDF
diff --git a/mtools.h b/mtools.h
index 6959a44..b3fd3c8 100644
--- a/mtools.h
+++ b/mtools.h
@@ -17,88 +17,16 @@
* along with Mtools. If not, see <http://www.gnu.org/licenses/>.
*/
#include "msdos.h"
-
+#include "llong.h"
typedef struct dos_name_t dos_name_t;
#if defined(OS_sco3)
#define MAXPATHLEN 1024
#include <signal.h>
extern int lockf(int, int, off_t); /* SCO has no proper include file for lockf */
-#endif
-
-#define SCSI_FLAG 0x001u
-#define PRIV_FLAG 0x002u
-#define NOLOCK_FLAG 0x004u
-#define USE_XDF_FLAG 0x008u
-#define MFORMAT_ONLY_FLAG 0x010u
-#define VOLD_FLAG 0x020u
-#define FLOPPYD_FLAG 0x040u
-#define FILTER_FLAG 0x080u
-#define SWAP_FLAG 0x100u
-
-#define IS_SCSI(x) ((x) && ((x)->misc_flags & SCSI_FLAG))
-#define IS_PRIVILEGED(x) ((x) && ((x)->misc_flags & PRIV_FLAG))
-#define IS_NOLOCK(x) ((x) && ((x)->misc_flags & NOLOCK_FLAG))
-#define IS_MFORMAT_ONLY(x) ((x) && ((x)->misc_flags & MFORMAT_ONLY_FLAG))
-#define SHOULD_USE_VOLD(x) ((x)&& ((x)->misc_flags & VOLD_FLAG))
-#define SHOULD_USE_XDF(x) ((x)&& ((x)->misc_flags & USE_XDF_FLAG))
-#define DO_SWAP(x) ((x) && ((x)->misc_flags & SWAP_FLAG))
-
-typedef struct device {
- const char *name; /* full path to device */
-
- char drive; /* the drive letter */
- int fat_bits; /* FAT encoding scheme */
-
- int mode; /* any special open() flags */
- unsigned int tracks; /* tracks */
- uint16_t heads; /* heads */
- uint16_t sectors; /* sectors */
- unsigned int hidden; /* number of hidden sectors. Used for
- * mformatting partitioned devices */
-
- off_t offset; /* skip this many bytes */
-
- unsigned int partition;
-
- unsigned int misc_flags;
-
- /* Linux only stuff */
- uint8_t ssize;
- unsigned int use_2m;
-
- char *precmd; /* command to be executed before opening
- * the drive */
-
- /* internal variables */
- int file_nr; /* used during parsing */
- unsigned int blocksize; /* size of disk block in bytes */
-
- int codepage; /* codepage for shortname encoding */
-
- const char *cfg_filename; /* used for debugging purposes */
-} device_t;
-
-struct OldDos_t {
- unsigned int tracks;
- uint16_t sectors;
- uint16_t heads;
-
- unsigned int dir_len;
- unsigned int cluster_size;
- unsigned int fat_len;
-
- uint8_t media;
-};
-
-extern struct OldDos_t *getOldDosBySize(size_t size);
-extern struct OldDos_t *getOldDosByMedia(int media);
-extern struct OldDos_t *getOldDosByParams(unsigned int tracks,
- unsigned int heads,
- unsigned int sectors,
- unsigned int dir_len,
- unsigned int cluster_size);
-int setDeviceFromOldDos(int media, struct device *dev);
+#endif
+
+
#ifndef OS_linux
@@ -120,72 +48,62 @@ extern const char *short_illegals, *long_illegals;
} \
} while(0)
-#define smaximize(target, max) do { \
- if(max < 0) { \
- if(target > 0) \
- target = 0; \
- } else if(target > max) { \
- target = max; \
- } \
-} while(0)
-
#define sizemaximize(target, max) do { \
if(max < 0) { \
if(target > 0) \
target = 0; \
} else if(target > (size_t) max) { \
- target = max; \
+ target = (size_t) max; \
} \
} while(0)
#define minimize(target, min) do { \
if(target < min) \
target = min; \
-} while(0)
+} while(0)
-int init_geom(int fd, struct device *dev, struct device *orig_dev,
- struct MT_STAT *statbuf);
+#ifdef OS_linux
+int get_sector_size(int fd);
+#endif
int readwrite_sectors(int fd, /* file descriptor */
int *drive,
int rate,
int seektrack,
int track, int head, int sector, int size, /* address */
- char *data,
+ char *data,
int bytes,
int direction,
int retries);
-int lock_dev(int fd, int mode, struct device *dev);
-
char *unix_normalize (doscp_t *cp, char *ans, struct dos_name_t *dn,
size_t ans_size);
void dos_name(doscp_t *cp, const char *filename, int verbose, int *mangled,
struct dos_name_t *);
struct directory *mk_entry(const dos_name_t *filename, unsigned char attr,
- unsigned int fat, size_t size, time_t date,
+ unsigned int fat, uint32_t size, time_t date,
struct directory *ndir);
struct directory *mk_entry_from_base(const char *base, unsigned char attr,
- unsigned int fat, size_t size, time_t date,
+ unsigned int fat, uint32_t size, time_t date,
struct directory *ndir);
-int copyfile(Stream_t *Source, Stream_t *Target);
-int getfreeMinClusters(Stream_t *Stream, size_t ref);
+mt_off_t copyfile(Stream_t *Source, Stream_t *Target);
+int getfreeMinClusters(Stream_t *Stream, uint32_t ref);
FILE *opentty(int mode);
int is_dir(Stream_t *Dir, char *path);
-void bufferize(Stream_t **Dir);
int dir_grow(Stream_t *Dir, int size);
int match(const wchar_t *, const wchar_t *, wchar_t *, int, int);
wchar_t *unix_name(doscp_t *fromDos,
- const char *base, const char *ext, char Case,
+ const char *base, const char *ext, uint8_t Case,
wchar_t *answer);
void *safe_malloc(size_t size);
-Stream_t *open_filter(Stream_t *Next,int convertCharset);
+Stream_t *open_dos2unix(Stream_t *Next,int convertCharset);
+Stream_t *open_unix2dos(Stream_t *Next,int convertCharset);
extern int got_signal;
/* int do_gotsignal(char *, int);
@@ -204,11 +122,7 @@ void restore_interrupts(saved_sig_state *ss);
#define SET_INT(target, source) \
if(source)target=source
-
-UNUSED(static __inline__ int compare (long ref, long testee))
-{
- return (ref && ref != testee);
-}
+#define compare(ref,testee) ((ref) && (ref) != (testee))
UNUSED(static __inline__ char ch_toupper(char ch))
{
@@ -235,13 +149,17 @@ UNUSED(static __inline__ void init_random(void))
srandom((unsigned int)time (0));
}
+UNUSED(static __inline__ size_t ptrdiff (const char *end, const char *begin))
+{
+ return (size_t) (end-begin);
+}
Stream_t *GetFs(Stream_t *Fs);
-void label_name_uc(doscp_t *cp, const char *filename, int verbose,
+void label_name_uc(doscp_t *cp, const char *filename, int verbose,
int *mangled, dos_name_t *ans);
-void label_name_pc(doscp_t *cp, const char *filename, int verbose,
+void label_name_pc(doscp_t *cp, const char *filename, int verbose,
int *mangled, dos_name_t *ans);
/* environmental variables */
@@ -264,7 +182,10 @@ char get_default_drive(void);
void set_cmd_line_image(char *img);
void check_number_parse_errno(char c, const char *optarg, char *endptr);
void read_config(void);
+off_t str_to_offset_with_end(const char *str, char **endp);
+mt_off_t str_to_off_with_end(const char *str, char **endp);
off_t str_to_offset(char *str);
+uint32_t parseSize(char *sizeStr);
unsigned int strtoui(const char *nptr, char **endptr, int base);
unsigned int atoui(const char *nptr);
#ifndef HAVE_STRTOI
@@ -278,20 +199,15 @@ uint16_t atou16(const char *str);
uint32_t strtou32(const char *nptr, char **endptr, int base);
uint32_t atou32(const char *str);
-extern struct device *devices;
-extern struct device const_devices[];
-extern const unsigned int nr_const_devices;
-
#define New(type) ((type*)(calloc(1,sizeof(type))))
#define Grow(adr,n,type) ((type*)(realloc((char *)adr,n*sizeof(type))))
-#define Free(adr) (free((char *)adr));
+#define Free(adr) (free((char *)adr))
#define NewArray(size,type) ((type*)(calloc((size),sizeof(type))))
void mattrib(int argc, char **argv, int type);
void mbadblocks(int argc, char **argv, int type);
void mcat(int argc, char **argv, int type);
void mcd(int argc, char **argv, int type);
-void mclasserase(int argc, char **argv, int type);
void mcopy(int argc, char **argv, int type);
void mdel(int argc, char **argv, int type);
void mdir(int argc, char **argv, int type);
@@ -319,8 +235,6 @@ void closeExec(int fd);
extern const char *progname;
-void precmd(struct device *dev);
-
void print_sector(const char *message, unsigned char *data, int size);
time_t getTimeNow(time_t *now);
@@ -330,7 +244,7 @@ char *getVoldName(struct device *dev, char *name);
Stream_t *OpenDir(const char *filename);
-/* int unix_dir_loop(Stream_t *Stream, MainParam_t *mp);
+/* int unix_dir_loop(Stream_t *Stream, MainParam_t *mp);
int unix_loop(MainParam_t *mp, char *arg); */
struct dirCache_t **getDirCacheP(Stream_t *Stream);
diff --git a/mtools.info b/mtools.info
index e43a18d..44ecf44 100644
--- a/mtools.info
+++ b/mtools.info
@@ -1,6 +1,6 @@
-This is mtools.info, produced by makeinfo version 6.5 from mtools.texi.
+This is mtools.info, produced by makeinfo version 6.7 from mtools.texi.
-This manual is for Mtools (version 4.0.26, November 2020), which is a
+This manual is for Mtools (version 4.0.37, January 2022), which is a
collection of tools to allow Unix systems to manipulate MS-DOS files.
Copyright (C) 2007, 2009 Free Software Foundation, Inc. Copyright
@@ -53,7 +53,7 @@ preliminary mounting or initialization (assuming the default
'/etc/mtools.conf' works on your machine). With mtools, one can change
floppies too without unmounting and mounting.
- This manual is for Mtools (version 4.0.26, November 2020), which is a
+ This manual is for Mtools (version 4.0.37, January 2022), which is a
collection of tools to allow Unix systems to manipulate MS-DOS files.
Copyright (C) 2007, 2009 Free Software Foundation, Inc. Copyright
@@ -87,7 +87,7 @@ File: mtools.info, Node: Location, Next: Common features, Prev: Top, Up: Top
*********************
Mtools can be found at the following places (and their mirrors):
- http://ftp.gnu.org/gnu/mtools/mtools-4.0.26.tar.gz
+ http://ftp.gnu.org/gnu/mtools/mtools-4.0.37.tar.gz
These patches are named 'mtools-'VERSION'-'DDMM'.taz', where version
stands for the base version, DD for the day and MM for the month. Due
@@ -149,7 +149,11 @@ doesn't follow MS-DOS conventions, but which is more user-friendly.
Most mtools commands allow options that instruct them how to handle
file name clashes. *Note name clashes::, for more details on these.
-All commands accept the '-V' flags which prints the version, and most
+
+ All commands accept the '-i' flag which allows to specify an image
+file (*Note drive letters::).
+
+ All commands accept the '-V' flag which prints the version, and most
accept the '-v' flag, which switches on verbose mode. In verbose mode,
these commands print out the name of the MS-DOS files upon which they
act, unless stated otherwise. *Note Commands::, for a description of
@@ -848,6 +852,34 @@ integer (all others)
specify a global code page for all drives by using the global
'default_codepage' parameter (outside of any drive description).
This parameters exists starting at version 4.0.0
+
+'data_map'
+ Remaps data from image file. This is useful for image files which
+ might need additional zero-filled sectors to be inserted. Such is
+ the case for instance for IBM 3174 floppy images. These images
+ represent floppy disks with fewer sectors on their first cylinder.
+ These missing sectors are not stored in the image, but are still
+ counted in the filesystem layout. The data_map allows to fake
+ these missing sectors for the upper layers of mtools. A data_map
+ is a comma-separated sequence of source type and size. Source type
+ may be 'zero' for zero-filled sectors created by map, 'skip' for
+ data in raw image to be ignored (skipped), and nothing for data to
+ be used as is (copied) from the raw image. Datamap is
+ automatically complemented by an implicit last element of data to
+ be used as is from current offset to end of file. Each size is a
+ number followed by a unit: 's' for a 512 byte sector, 'K' for
+ Kbytes, 'M' for megabytes, 'G' for gigabytes, and nothing for
+ single bytes.
+
+ Example:
+
+ 'data_map=1s,zero31s,28s,skip1s' would be a map for use with IBM
+ 3174 floppy images. First sector ('1s', boot sector) is used as
+ is. Then follow 31 fake zero-filled sectors ('zero31s'), then the
+ next 28 sectors from image ('28s') are used as is (they contain FAT
+ and root directory), then one sector from image is skipped
+ ('skip1s'), and finally the rest of image is used as is (implicit)
+
'precmd'
On some variants of Solaris, it is necessary to call 'volcheck -v'
before opening a floppy device, in order for the system to notice
@@ -1045,7 +1077,6 @@ description of those.
* mbadblocks:: tests a floppy disk, and marks the bad blocks in the FAT
* mcat:: same as cat. Only useful with floppyd.
* mcd:: change MS-DOS directory
-* mclasserase:: erase memory card
* mcopy:: copy MS-DOS files to/from Unix
* mdel:: delete an MS-DOS file
* mdeltree:: recursively delete an MS-DOS directory
@@ -1312,7 +1343,7 @@ the low-level nature of this command, it will happily destroy any data
written before on the disk without warning!

-File: mtools.info, Node: mcd, Next: mclasserase, Prev: mcat, Up: Commands
+File: mtools.info, Node: mcd, Next: mcopy, Prev: mcat, Up: Commands
4.6 Mcd
=======
@@ -1337,33 +1368,9 @@ the file is more than 6 hours old.
another device. It may be wise to remove old '.mcwd' files at logout.

-File: mtools.info, Node: mclasserase, Next: mcopy, Prev: mcd, Up: Commands
-
-4.7 Mclasserase
-===============
-
-The 'mclasserase' command is used to wipe memory cards by overwriting it
-three times: first with '0xff', then with '0x00', then with '0xff'
-again. The command uses the following syntax:
-
- mclasserase [-d] MSDOSDRIVE
-
- MS-DOS drive is optional, if none is specified, use 'A:'. If more
-than one drive are specified, all but the last are ignored.
-
- 'Mclasserase' accepts the following command line options:
-
-'d'
- Stop after each erase cycle, for testing purposes
-'p'
- Not yet implemented
-
- 'Mclasserase' returns 0 on success or -1 on failure.
-
-
-File: mtools.info, Node: mcopy, Next: mdel, Prev: mclasserase, Up: Commands
+File: mtools.info, Node: mcopy, Next: mdel, Prev: mcd, Up: Commands
-4.8 Mcopy
+4.7 Mcopy
=========
The 'mcopy' command is used to copy MS-DOS files to and from Unix. It
@@ -1427,7 +1434,7 @@ depending on its position on the command line.
'v'
Verbose. Displays the name of each file as it is copied.
-4.8.1 Bugs
+4.7.1 Bugs
----------
Unlike MS-DOS, the '+' operator (append) from MS-DOS is not supported.
@@ -1438,7 +1445,7 @@ However, you may use 'mtype' to produce the same effect:

File: mtools.info, Node: mdel, Next: mdeltree, Prev: mcopy, Up: Commands
-4.9 Mdel
+4.8 Mdel
========
The 'mdel' command is used to delete an MS-DOS file. Its syntax is:
@@ -1452,8 +1459,8 @@ The 'mdel' command is used to delete an MS-DOS file. Its syntax is:

File: mtools.info, Node: mdeltree, Next: mdir, Prev: mdel, Up: Commands
-4.10 Mdeltree
-=============
+4.9 Mdeltree
+============
The 'mdeltree' command is used to delete an MS-DOS file. Its syntax is:
@@ -1466,7 +1473,7 @@ directory to be removed does not exist.

File: mtools.info, Node: mdir, Next: mdu, Prev: mdeltree, Up: Commands
-4.11 Mdir
+4.10 Mdir
=========
The 'mdir' command is used to display an MS-DOS directory. Its syntax
@@ -1503,7 +1510,7 @@ for some MS-DOS files.

File: mtools.info, Node: mdu, Next: mformat, Prev: mdir, Up: Commands
-4.12 Mdu
+4.11 Mdu
========
'Mdu' is used to list the space occupied by a directory, its
@@ -1522,7 +1529,7 @@ the cluster size.

File: mtools.info, Node: mformat, Next: mkmanifest, Prev: mdu, Up: Commands
-4.13 Mformat
+4.12 Mformat
============
The 'mformat' command is used to add an MS-DOS file system to a
@@ -1714,7 +1721,7 @@ the default.
It doesn't record bad block information to the Fat, use 'mbadblocks'
for that.
-4.13.1 Number of sectors per cluster
+4.12.1 Number of sectors per cluster
------------------------------------
If the user indicates no cluster size, mformat figures out a default
@@ -1749,7 +1756,7 @@ sectors.

File: mtools.info, Node: mkmanifest, Next: minfo, Prev: mformat, Up: Commands
-4.14 Mkmanifest
+4.13 Mkmanifest
===============
The 'mkmanifest' command is used to create a shell script (packing list)
@@ -1767,7 +1774,7 @@ arc,' and 'mtools' to change perfectly good Unix filenames to fit the
MS-DOS restrictions. This command is only useful if the target system
which will read the diskette cannot handle VFAT long names.
-4.14.1 Example
+4.13.1 Example
--------------
You want to copy the following Unix files to a MS-DOS diskette (using
@@ -1806,7 +1813,7 @@ system, and I now want the files back to their original names. If the
file "manifest" (the output captured above) was sent along with those
files, it could be used to convert the filenames.
-4.14.2 Bugs
+4.13.2 Bugs
-----------
The short names generated by 'mkmanifest' follow the old convention
@@ -1815,7 +1822,7 @@ The short names generated by 'mkmanifest' follow the old convention

File: mtools.info, Node: minfo, Next: mlabel, Prev: mkmanifest, Up: Commands
-4.15 Minfo
+4.14 Minfo
==========
The 'minfo' command prints the parameters of a MS-DOS file system, such
@@ -1833,7 +1840,7 @@ with MS-DOS 1.0 file systems

File: mtools.info, Node: mlabel, Next: mmd, Prev: minfo, Up: Commands
-4.16 Mlabel
+4.15 Mlabel
===========
The 'mlabel' command adds a volume label to a disk. Its syntax is:
@@ -1866,7 +1873,7 @@ success or 1 on failure.

File: mtools.info, Node: mmd, Next: mmount, Prev: mlabel, Up: Commands
-4.17 Mmd
+4.16 Mmd
========
The 'mmd' command is used to make an MS-DOS subdirectory. Its syntax
@@ -1880,7 +1887,7 @@ occurs if the directory already exists.

File: mtools.info, Node: mmount, Next: mmove, Prev: mmd, Up: Commands
-4.18 Mmount
+4.17 Mmount
===========
The 'mmount' command is used to mount an MS-DOS disk. It is only
@@ -1897,7 +1904,7 @@ the disk is write protected, it is automatically mounted read only.

File: mtools.info, Node: mmove, Next: mpartition, Prev: mmount, Up: Commands
-4.19 Mmove
+4.18 Mmove
==========
The 'mmove' command is used to move or rename an existing MS-DOS file or
@@ -1915,7 +1922,7 @@ parameters, drive a: is assumed by default.

File: mtools.info, Node: mpartition, Next: mrd, Prev: mmove, Up: Commands
-4.20 Mpartition
+4.19 Mpartition
===============
The 'mpartition' command is used to create MS-DOS file systems as
@@ -2000,7 +2007,7 @@ partition table:
'B BOOTSECTOR'
Reads the template master boot record from file BOOTSECTOR.
-4.20.1 Choice of partition type
+4.19.1 Choice of partition type
-------------------------------
Mpartition proceeds as follows to pick a type for the partition:
@@ -2043,7 +2050,7 @@ with two notable differences:

File: mtools.info, Node: mrd, Next: mren, Prev: mpartition, Up: Commands
-4.21 Mrd
+4.20 Mrd
========
The 'mrd' command is used to remove an MS-DOS subdirectory. Its syntax
@@ -2057,7 +2064,7 @@ occurs if the directory does not exist or is not empty.

File: mtools.info, Node: mren, Next: mshortname, Prev: mrd, Up: Commands
-4.22 Mren
+4.21 Mren
=========
The 'mren' command is used to rename or move an existing MS-DOS file or
@@ -2079,7 +2086,7 @@ version of 'REN', 'mren' can be used to rename directories.

File: mtools.info, Node: mshortname, Next: mshowfat, Prev: mren, Up: Commands
-4.23 Mshortname
+4.22 Mshortname
===============
The 'mshortname' command is used to display the short name of a file.
@@ -2093,7 +2100,7 @@ without any character set conversion.

File: mtools.info, Node: mshowfat, Next: mtoolstest, Prev: mshortname, Up: Commands
-4.24 Mshowfat
+4.23 Mshowfat
=============
The 'mshowfat' command is used to display the FAT entries for a file.
@@ -2108,7 +2115,7 @@ containing that offset is printed.

File: mtools.info, Node: mtoolstest, Next: mtype, Prev: mshowfat, Up: Commands
-4.25 Mtoolstest
+4.24 Mtoolstest
===============
The 'mtoolstest' command is used to tests the mtools configuration
@@ -2122,7 +2129,7 @@ files into new style configuration files.

File: mtools.info, Node: mtype, Next: mzip, Prev: mtoolstest, Up: Commands
-4.26 Mtype
+4.25 Mtype
==========
The 'mtype' command is used to display contents of an MS-DOS file. Its
@@ -2153,7 +2160,7 @@ arguments.

File: mtools.info, Node: mzip, Prev: mtype, Up: Commands
-4.27 Mzip
+4.26 Mzip
=========
The 'mzip' command is used to issue ZIP disk specific commands on Linux,
@@ -2198,7 +2205,7 @@ in a Mac. On a PC, the Mac file system appears as a hidden file named
'partishn.mac'. You may erase it to reclaim the 50 Megs of space taken
up by the Mac file system.
-4.27.1 Bugs
+4.26.1 Bugs
-----------
This command is a big kludge. A proper implementation would take a
@@ -2454,12 +2461,12 @@ Concept index
* Bad blocks: mbadblocks. (line 6)
* bigger sectors: bigger sectors. (line 6)
* blocksize: miscellaneous variables.
- (line 32)
+ (line 60)
* bugs: Location. (line 6)
* Case sensitivity: case sensitivity. (line 6)
* Changing file attributes: mattrib. (line 6)
* character devices: miscellaneous variables.
- (line 32)
+ (line 60)
* Checking configuration file: mtoolstest. (line 6)
* Clusters of a file: mshowfat. (line 6)
* Command list: Commands. (line 6)
@@ -2516,7 +2523,7 @@ Concept index
* erasing MS-DOS files: mdel. (line 6)
* exclusive access to a drive: open flags. (line 6)
* Executing commands before opening the device: miscellaneous variables.
- (line 26)
+ (line 54)
* Fat: mshowfat. (line 6)
* fdformat: more sectors. (line 6)
* File name of device node: location information. (line 10)
@@ -2567,14 +2574,12 @@ Concept index
* mcat: mcat. (line 9)
* mcd: mcd. (line 6)
* mcd (introduction): directory. (line 6)
-* mclasserase: mclasserase. (line 6)
* mcopy: mcopy. (line 6)
* Mcwd file: mcd. (line 6)
* mdel: mdel. (line 6)
* mdeltree: mdeltree. (line 6)
* mdir: mdir. (line 6)
* mdu: mdu. (line 6)
-* Memory Card: mclasserase. (line 6)
* mformat: mformat. (line 6)
* mformat (geometry used for): geometry description. (line 6)
* mformat parameters: minfo. (line 6)
@@ -2615,14 +2620,13 @@ Concept index
* partitions (creating): mpartition. (line 6)
* password protected Zip disks: mzip. (line 6)
* patches: Location. (line 6)
-* Physically erase: mclasserase. (line 6)
* plain floppy: device xxx busy: miscellaneous flags. (line 11)
* Porting: Porting mtools. (line 6)
* Primary file name (long names): long names. (line 6)
* Primary file name (name clashes): name clashes. (line 6)
* Ram disk: location information. (line 28)
* raw device: miscellaneous variables.
- (line 32)
+ (line 60)
* Read errors: mbadblocks. (line 6)
* Read-only files (changing the attribute): mattrib. (line 6)
* Read-only files (listing them): mdir. (line 6)
@@ -2648,7 +2652,7 @@ Concept index
* Solaris (Raw access to SCSI devices such as Zip & Jaz): miscellaneous flags.
(line 17)
* Solaris (volcheck): miscellaneous variables.
- (line 26)
+ (line 54)
* Solaris (vold): miscellaneous flags. (line 57)
* Space occupied by directories and files: mdu. (line 6)
* Special formats: high capacity formats.
@@ -2695,71 +2699,75 @@ Concept index

Tag Table:
-Node: Top872
-Node: Location3129
-Node: Common features4067
-Node: arguments4831
-Node: drive letters6492
-Node: directory7846
-Node: long names8292
-Node: name clashes10838
-Node: case sensitivity13122
-Node: high capacity formats14359
-Node: more sectors15404
-Node: bigger sectors16459
-Node: 2m17188
-Node: XDF18374
-Node: exit codes19717
-Node: bugs20355
-Node: Configuration20888
-Node: configuration file location22177
-Node: general syntax22630
-Node: default values23461
-Node: global variables23989
-Node: per drive variables26182
-Node: general information27017
-Node: location information27459
-Node: geometry description28988
-Node: open flags32849
-Node: miscellaneous variables33449
-Node: miscellaneous flags35525
-Node: multiple descriptions39155
-Node: parsing order40829
-Node: old style configuration41860
-Node: Commands42559
-Node: floppyd44481
-Node: floppyd_installtest49274
-Node: mattrib49905
-Node: mbadblocks51700
-Node: mcat52994
-Node: mcd53808
-Node: mclasserase54669
-Node: mcopy55345
-Node: mdel58363
-Node: mdeltree58702
-Node: mdir59121
-Node: mdu60397
-Node: mformat60903
-Node: mkmanifest69414
-Node: minfo71388
-Node: mlabel71958
-Node: mmd73111
-Node: mmount73460
-Node: mmove74063
-Node: mpartition74868
-Node: mrd80394
-Node: mren80752
-Node: mshortname81501
-Node: mshowfat81831
-Node: mtoolstest82240
-Node: mtype82812
-Node: mzip83663
-Ref: mzip-Footnote-185688
-Ref: mzip-Footnote-285769
-Node: Compiling mtools86056
-Node: Porting mtools87155
-Node: Command Index93063
-Node: Variable Index93191
-Node: Concept Index95014
+Node: Top871
+Node: Location3127
+Node: Common features4065
+Node: arguments4829
+Node: drive letters6594
+Node: directory7948
+Node: long names8394
+Node: name clashes10940
+Node: case sensitivity13224
+Node: high capacity formats14461
+Node: more sectors15506
+Node: bigger sectors16561
+Node: 2m17290
+Node: XDF18476
+Node: exit codes19819
+Node: bugs20457
+Node: Configuration20990
+Node: configuration file location22279
+Node: general syntax22732
+Node: default values23563
+Node: global variables24091
+Node: per drive variables26284
+Node: general information27119
+Node: location information27561
+Node: geometry description29090
+Node: open flags32951
+Node: miscellaneous variables33551
+Node: miscellaneous flags37141
+Node: multiple descriptions40771
+Node: parsing order42445
+Node: old style configuration43476
+Node: Commands44175
+Node: floppyd46057
+Node: floppyd_installtest50850
+Node: mattrib51481
+Node: mbadblocks53276
+Node: mcat54570
+Node: mcd55384
+Node: mcopy56239
+Node: mdel59249
+Node: mdeltree59588
+Node: mdir60005
+Node: mdu61281
+Node: mformat61787
+Node: mkmanifest70298
+Node: minfo72272
+Node: mlabel72842
+Node: mmd73995
+Node: mmount74344
+Node: mmove74947
+Node: mpartition75752
+Node: mrd81278
+Node: mren81636
+Node: mshortname82385
+Node: mshowfat82715
+Node: mtoolstest83124
+Node: mtype83696
+Node: mzip84547
+Ref: mzip-Footnote-186572
+Ref: mzip-Footnote-286653
+Node: Compiling mtools86940
+Node: Porting mtools88039
+Node: Command Index93947
+Node: Variable Index94075
+Node: Concept Index95898

End Tag Table
+
+
+Local Variables:
+coding: utf-8
+End:
diff --git a/mtools.spec b/mtools.spec
index 82b31c1..ac0248f 100644
--- a/mtools.spec
+++ b/mtools.spec
@@ -1,7 +1,7 @@
%define _binary_payload w9.gzdio
Name: mtools
Summary: mtools, read/write/list/format DOS disks under Unix
-Version: 4.0.26
+Version: 4.0.37
Release: 1
License: GPLv3+
Group: Utilities/System
@@ -49,7 +49,6 @@ rm %{buildroot}%{_infodir}/dir
%{_mandir}/man1/mbadblocks.1*
%{_mandir}/man1/mcat.1*
%{_mandir}/man1/mcd.1*
-%{_mandir}/man1/mclasserase.1*
%{_mandir}/man1/mcopy.1*
%{_mandir}/man1/mdel.1*
%{_mandir}/man1/mdeltree.1*
@@ -77,7 +76,6 @@ rm %{buildroot}%{_infodir}/dir
%{_bindir}/mbadblocks
%{_bindir}/mcat
%{_bindir}/mcd
-%{_bindir}/mclasserase
%{_bindir}/mcopy
%{_bindir}/mdel
%{_bindir}/mdeltree
@@ -135,6 +133,92 @@ if [ -f %{_bindir}/install-info ] ; then
fi
%changelog
+* Sun Dec 26 2021 Alain Knaff <alain@knaff.lu>
+- Removed mclasserase commands, which doesn't fit the coding
+ structure of the rest of mtools
+- Add support to -i option to mcd
+- Document -i in mtools.1
+- Fix a missing commad error in floppyd_io.c
+* Sun Nov 21 2021 Alain Knaff <alain@knaff.lu>
+- Fix error status of recursive listing of empty root directory
+- If recursive listing, also show matched files at level one
+- Use "seekless" reads & write internally, where possible
+- Text mode conversion refactoring
+- Misc refactoring
+* Fri Aug 06 2021 Alain Knaff <alain@knaff.lu>
+- Fix cluster padding at end of file in batch mode, and add comments about what
+ happens here
+* Fri Jul 23 2021 Alain Knaff <alain@knaff.lu>
+- Fix mcopy -s issue
+* Sat Jul 17 2021 Alain Knaff <alain@knaff.lu>
+- Fix support for partitions (broken in 4.0.30)
+- Portability fixes for Solaris 10 and 11
+- General simplification of configure script, and largefile handling
+- Tested and fixed for platforms *without* largefile support
+- In cases where lseek works with 32-bit offsets, prefer lseek64 over llseek
+- Fixed floppy sector size handling on platforms that are not Linux
+- Added support for image files on command line to mcat
+* Sat Jul 10 2021 Alain Knaff <alain@knaff.lu>
+- Simplify algorithm that choses filesystem parameters for
+ format, and align it more closely with what Win7 does
+- Fix mformatting XDF when XDF not explicitly specified on
+ mformat command line
+- easier way to enter sizes on mformat command line (mformat -C -T 1440K)
+- For small sizes, mformat assumes floppy geometries (heads 1 or 2,
+ tracks 40 or 80)
+- Handle attempts to mformat too small filesystems more gracefully
+- Enable minfo to print out additional mformat command line
+ parameters, if the present filesystem uses non-default values for
+ these
+- minfo no longer prints bigsect if smallsect is set
+- for remap filter, error when trying to write non-zero data to
+unmapped sectors
+- Fix misc compilation warnings occuring when disabling certain
+features (largefiles, raw-term)
+
+* Sat Jun 19 2021 Alain Knaff <alain@knaff.lu>
+- Move Linux-specific block device sizing code into
+ linux-specific section of devices.c
+- Error messages for all failure cases on fs_init failure
+- Fix compilation without XDF support (OpenImage signature)
+- Fix polarity of format_xdf command-line parameter of mformat
+- In XDF_IO retry enough times to actually succeed, even if
+ FDC was in a bad state before
+- Remove useless buffer flushing triggered when giving up a
+ reference to a stream node that is still referenced
+ elsewhere.
+- Clearer error message if neither size nor geometry of drive
+ to be mformatted is known
+- In mformat, make Fs dynamically allocated rather than
+ on-stack, so as to be able to use utilities supplied by
+ stream.c
+- Remove duplicate writing of backup boot sector
+- Allow to infer geometry if only size is specified
+- Protect against attempt to create zero-sized buffer
+- Code simplification in mattrib
+- Remove dead code in mpartition
+
+* Thu Jun 17 2021 Alain Knaff <alain@knaff.lu>
+- Fixed XDF floppy disk access
+- Fixed faulty behavior at end of image in mcat
+- Device/Image size handling refactoring
+- allow remap to write to zero-backed sectors (may happen if
+ buffer is flushed, and is not an error in that case)
+- Raise an error when trying to mcopy multiple source files
+ over a single destination file (rather than directory)
+- fix handling of "hidden" sectors (is a 2 byte quantity on
+ small disks, not 4 byte as previously assumed)
+- Modernize partition support. Tuned consistency check to
+ actually check about important issues (such as overlapping
+ partitions) rather than stuff nobody else cares about
+ (alignment on entire cylinder boundaries)
+- Move various "filter" options (partition, offset, swap,
+ scsi) into separate classes, rather than leaving almost
+ everything in plain_io
+- Simplify and centralize geometry handling and LBA code
+- Fix some more more compiler warnings
+* Mon May 31 2021 Alain Knaff <alain@knaff.lu>
+-Fix bug in cluster preallocation, which was accidentally introduced by compiler warning "fixes" from v4_0_28
* Sat Nov 28 2020 Alain Knaff <alain@knaff.lu>
- Fix compilation on Macintosh
- Ignore image file locking errors if we are performing a read-only access anyways
diff --git a/mtools.texi b/mtools.texi
index fdcd2bb..7b3dca5 100644
--- a/mtools.texi
+++ b/mtools.texi
@@ -165,14 +165,17 @@ All options use the @code{-} (minus) as their first character, not
Most mtools commands allow multiple filename parameters, which
doesn't follow MS-DOS conventions, but which is more user-friendly.
-Most mtools commands allow options that instruct them how to handle file
-name clashes. @xref{name clashes}, for more details on these. All
-commands accept the @code{-V} flags which prints the version, and most
-accept the @code{-v} flag, which switches on verbose mode. In verbose
-mode, these commands print out the name of the MS-DOS files upon which
-they act, unless stated otherwise. @xref{Commands}, for a description of
-the options which are specific to each command.
+Most mtools commands allow options that instruct them how to handle
+file name clashes. @xref{name clashes}, for more details on these.
+All commands accept the @code{-i} flag which allows to specify an
+image file (@xref{drive letters}).
+
+All commands accept the @code{-V} flag which prints the version, and
+most accept the @code{-v} flag, which switches on verbose mode. In
+verbose mode, these commands print out the name of the MS-DOS files
+upon which they act, unless stated otherwise. @xref{Commands}, for a
+description of the options which are specific to each command.
@node drive letters, directory, arguments, Common features
@section Drive letters
@@ -946,6 +949,35 @@ also available in ISO-Latin-1. You may also specify a global code page
for all drives by using the global @code{default_codepage} parameter
(outside of any drive description). This parameters exists starting at
version 4.0.0
+
+@item data_map
+Remaps data from image file. This is useful for image files which
+might need additional zero-filled sectors to be inserted. Such is the
+case for instance for IBM 3174 floppy images. These images represent
+floppy disks with fewer sectors on their first cylinder. These missing
+sectors are not stored in the image, but are still counted in the
+filesystem layout. The data_map allows to fake these missing sectors
+for the upper layers of mtools. A data_map is a comma-separated
+sequence of source type and size. Source type may be @code{zero} for
+zero-filled sectors created by map, @code{skip} for data in raw image
+to be ignored (skipped), and nothing for data to be used as is
+(copied) from the raw image. Datamap is automatically complemented by
+an implicit last element of data to be used as is from current offset
+to end of file. Each size is a number followed by a unit: @code{s} for
+a 512 byte sector, @code{K} for Kbytes, @code{M} for megabytes,
+@code{G} for gigabytes, and nothing for single bytes.
+
+Example:
+
+@code{data_map=1s,zero31s,28s,skip1s} would be a map for use with IBM
+3174 floppy images. First sector (@code{1s}, boot sector) is used as
+is. Then follow 31 fake zero-filled sectors (@code{zero31s}), then the
+next 28 sectors from image (@code{28s}) are used as is (they contain
+FAT and root directory), then one sector from image is skipped
+(@code{skip1s}), and finally the rest of image is used as is
+(implicit)
+
+
@item precmd
@cindex Solaris (volcheck)
@cindex Executing commands before opening the device
@@ -1188,7 +1220,6 @@ description of those.
* mbadblocks:: tests a floppy disk, and marks the bad blocks in the FAT
* mcat:: same as cat. Only useful with floppyd.
* mcd:: change MS-DOS directory
-* mclasserase:: erase memory card
* mcopy:: copy MS-DOS files to/from Unix
* mdel:: delete an MS-DOS file
* mdeltree:: recursively delete an MS-DOS directory
@@ -1480,7 +1511,7 @@ stdin and writes it to the given device.
command, it will happily destroy any data written before on the
disk without warning!
-@node mcd, mclasserase, mcat, Commands
+@node mcd, mcopy, mcat, Commands
@section Mcd
@pindex mcd
@cindex Directory (changing)
@@ -1510,38 +1541,7 @@ if the file is more than 6 hours old.
Unlike MS-DOS versions of @code{CD}, @code{mcd} can be used to change to
another device. It may be wise to remove old @file{.mcwd} files at logout.
-@node mclasserase, mcopy, mcd, Commands
-@section Mclasserase
-@pindex mclasserase
-@cindex Memory Card
-@cindex Physically erase
-
-The @code{mclasserase} command is used to wipe memory cards by
-overwriting it three times: first with @code{0xff}, then with
-@code{0x00}, then with @code{0xff} again. The command uses the following
-syntax:
-
-@example
-@code{mclasserase} [@code{-d}] @var{msdosdrive}
-@end example
-
-MS-DOS drive is optional, if none is specified, use @code{A:}. If more than
-one drive are specified, all but the last are ignored.
-
-@code{Mclasserase} accepts the following command line options:
-
-@table @code
-@item d
-Stop after each erase cycle, for testing purposes
-@item p
-Not yet implemented
-@end table
-
-
-@code{Mclasserase} returns 0 on success or -1 on failure.
-
-
-@node mcopy, mdel, mclasserase, Commands
+@node mcopy, mdel, mcd, Commands
@section Mcopy
@pindex mcopy
@cindex Reading MS-DOS files
diff --git a/mtools.tmpl.1 b/mtools.tmpl.1
index 7676937..2e80714 100644
--- a/mtools.tmpl.1
+++ b/mtools.tmpl.1
@@ -1,5 +1,5 @@
'\" t
-.TH mtools 1 "28Nov20" mtools-4.0.26
+.TH mtools 1 "08Jan22" mtools-4.0.37
.SH Name
mtools - utilities to access DOS disks in Unix.
'\" t
@@ -36,7 +36,7 @@ Mtools can be found at the following places (and their mirrors):
.nf
.ft 3
.in +0.3i
-http://ftp.gnu.org/gnu/mtools/mtools-4.0.26.tar.gz
+http://ftp.gnu.org/gnu/mtools/mtools-4.0.37.tar.gz
.fi
.in -0.3i
.ft R
@@ -82,13 +82,17 @@ All options use the \fR\&\f(CW-\fR (minus) as their first character, not
Most mtools commands allow multiple filename parameters, which
doesn't follow MS-DOS conventions, but which is more user-friendly.
.PP
-Most mtools commands allow options that instruct them how to handle file
-name clashes. See section name clashes, for more details on these. All
-commands accept the \fR\&\f(CW-V\fR flags which prints the version, and most
-accept the \fR\&\f(CW-v\fR flag, which switches on verbose mode. In verbose
-mode, these commands print out the name of the MS-DOS files upon which
-they act, unless stated otherwise. See section Commands, for a description of
-the options which are specific to each command.
+Most mtools commands allow options that instruct them how to handle
+file name clashes. See section name clashes, for more details on these.
+.PP
+All commands accept the \fR\&\f(CW-i\fR flag which allows to specify an
+image file (See section drive letters).
+.PP
+All commands accept the \fR\&\f(CW-V\fR flag which prints the version, and
+most accept the \fR\&\f(CW-v\fR flag, which switches on verbose mode. In
+verbose mode, these commands print out the name of the MS-DOS files
+upon which they act, unless stated otherwise. See section Commands, for a
+description of the options which are specific to each command.
.PP
.SS Drive\ letters
.PP
@@ -479,7 +483,6 @@ floppyd_installtest
mattrib
mbadblocks
mcd
-mclasserase
mcopy
mdel
mdeltree
diff --git a/mtools.tmpl.5 b/mtools.tmpl.5
index e58d13d..d9c4d35 100644
--- a/mtools.tmpl.5
+++ b/mtools.tmpl.5
@@ -1,5 +1,5 @@
'\" t
-.TH mtools 5 "28Nov20" MTOOLS MTOOLS
+.TH mtools 5 "08Jan22" MTOOLS MTOOLS
.SH Name
mtools.conf - mtools configuration files
'\" t
@@ -13,7 +13,7 @@ mtools.conf - mtools configuration files
.tr \(if`
.tr \(pd"
-.ds St Mtools\ 4.0.26
+.ds St Mtools\ 4.0.37
.PP
.SH Description
.PP
@@ -339,6 +339,34 @@ for all drives by using the global \fR\&\f(CWdefault_codepage\fR parameter
(outside of any drive description). This parameters exists starting at
version 4.0.0
.TP
+\&\fR\&\f(CWdata_map\fR\
+Remaps data from image file. This is useful for image files which
+might need additional zero-filled sectors to be inserted. Such is the
+case for instance for IBM 3174 floppy images. These images represent
+floppy disks with fewer sectors on their first cylinder. These missing
+sectors are not stored in the image, but are still counted in the
+filesystem layout. The data_map allows to fake these missing sectors
+for the upper layers of mtools. A data_map is a comma-separated
+sequence of source type and size. Source type may be \fR\&\f(CWzero\fR for
+zero-filled sectors created by map, \fR\&\f(CWskip\fR for data in raw image
+to be ignored (skipped), and nothing for data to be used as is
+(copied) from the raw image. Datamap is automatically complemented by
+an implicit last element of data to be used as is from current offset
+to end of file. Each size is a number followed by a unit: \fR\&\f(CWs\fR for
+a 512 byte sector, \fR\&\f(CWK\fR for Kbytes, \fR\&\f(CWM\fR for megabytes,
+\&\fR\&\f(CWG\fR for gigabytes, and nothing for single bytes.
+.IP
+Example:
+.IP
+\&\fR\&\f(CWdata_map=1s,zero31s,28s,skip1s\fR would be a map for use with IBM
+3174 floppy images. First sector (\fR\&\f(CW1s\fR, boot sector) is used as
+is. Then follow 31 fake zero-filled sectors (\fR\&\f(CWzero31s\fR), then the
+next 28 sectors from image (\fR\&\f(CW28s\fR) are used as is (they contain
+FAT and root directory), then one sector from image is skipped
+(\fR\&\f(CWskip1s\fR), and finally the rest of image is used as is
+(implicit)
+.IP
+.TP
\&\fR\&\f(CWprecmd\fR\
On some variants of Solaris, it is necessary to call 'volcheck -v'
before opening a floppy device, in order for the system to notice that
diff --git a/mtoolsDirentry.h b/mtoolsDirentry.h
index 2ad0c29..4c3960b 100644
--- a/mtoolsDirentry.h
+++ b/mtoolsDirentry.h
@@ -21,11 +21,15 @@
typedef struct direntry_t {
struct Stream_t *Dir;
- /* struct direntry_t *parent; parent level */
- int entry; /* slot in parent directory (-3 if root) */
- struct directory dir; /* descriptor in parent directory (random if
+ /* struct direntry_t *parent; parent level */
+ int entry; /* slot in parent directory */
+ /* Negative values have the following meanings:
+ -1 not initialized
+ -2 entry searched for, but not found
+ -3 root directory */
+ struct directory dir; /* descriptor in parent directory (random if
* root)*/
- wchar_t name[MAX_VNAMELEN+1]; /* name in its parent directory, or
+ wchar_t name[MAX_VNAMELEN+1]; /* name in its parent directory, or
* NULL if root */
int beginSlot; /* begin and end slot, for delete */
int endSlot;
@@ -33,10 +37,17 @@ typedef struct direntry_t {
#include "stream.h"
-int vfat_lookup(direntry_t *entry, const char *filename, int length, int flags,
+int vfat_lookup(direntry_t *entry, const char *filename, size_t length,
+ int flags,
char *shortname, size_t shortname_len,
char *longname, size_t longname_len);
+int vfat_lookup_zt(direntry_t *entry, const char *filename,
+ int flags,
+ char *shortname, size_t shortname_len,
+ char *longname, size_t longname_len);
+
+
struct directory *dir_read(direntry_t *entry, int *error);
void initializeDirentry(direntry_t *entry, struct Stream_t *Dir);
@@ -54,7 +65,7 @@ int isSubdirOf(Stream_t *inside, Stream_t *outside);
char *getPwd(direntry_t *entry);
void fprintPwd(FILE *f, direntry_t *entry, int escape);
void fprintShortPwd(FILE *f, direntry_t *entry);
-int write_vfat(Stream_t *, dos_name_t *, char *, int, direntry_t *);
+int write_vfat(Stream_t *, dos_name_t *, char *, unsigned int, direntry_t *);
void wipeEntry(struct direntry_t *entry);
@@ -64,7 +75,7 @@ int lookupForInsert(Stream_t *Dir,
direntry_t *direntry,
struct dos_name_t *dosname,
char *longname,
- struct scan_state *ssp,
+ struct scan_state *ssp,
int ignore_entry,
int source_entry,
int pessimisticShortRename,
diff --git a/mtoolstest.1 b/mtoolstest.1
index 7fd1292..1057cfa 100644
--- a/mtoolstest.1
+++ b/mtoolstest.1
@@ -1,5 +1,5 @@
'\" t
-.TH mtoolstest 1 "28Nov20" mtools-4.0.26
+.TH mtoolstest 1 "08Jan22" mtools-4.0.37
.SH Name
mtoolstest - tests and displays the configuration
'\" t
diff --git a/mtype.1 b/mtype.1
index 5ef1c22..835c67f 100644
--- a/mtype.1
+++ b/mtype.1
@@ -1,5 +1,5 @@
'\" t
-.TH mtype 1 "28Nov20" mtools-4.0.26
+.TH mtype 1 "08Jan22" mtools-4.0.37
.SH Name
mtype - display contents of an MSDOS file
'\" t
diff --git a/mzip.1 b/mzip.1
index 4087aee..a141fff 100644
--- a/mzip.1
+++ b/mzip.1
@@ -1,5 +1,5 @@
'\" t
-.TH mzip 1 "28Nov20" mtools-4.0.26
+.TH mzip 1 "08Jan22" mtools-4.0.37
.SH Name
mzip - change protection mode and eject disk on Zip/Jaz drive
'\" t
diff --git a/mzip.c b/mzip.c
index 8721910..1148fa3 100644
--- a/mzip.c
+++ b/mzip.c
@@ -55,8 +55,8 @@
#endif
-static int zip_cmd(int priv, int fd, unsigned char cdb[6], int clen,
- scsi_io_mode_t mode, void *data, size_t len,
+static int zip_cmd(int priv, int fd, unsigned char cdb[6], uint8_t clen,
+ scsi_io_mode_t mode, void *data, uint32_t len,
void *extra_data)
{
int r;
@@ -69,7 +69,7 @@ static int zip_cmd(int priv, int fd, unsigned char cdb[6], int clen,
return r;
}
-static int test_mounted ( char *dev )
+static int test_mounted ( char *dev UNUSEDP)
{
#ifdef HAVE_MNTENT_H
struct mntent *mnt;
@@ -79,14 +79,14 @@ static int test_mounted ( char *dev )
* Now check if any partition of this device is already mounted (this
* includes checking if the device is mounted under a different name).
*/
-
+
if (MT_STAT (dev, &st_dev)) {
fprintf (stderr, "%s: stat(%s) failed: %s.\n",
progname, dev, strerror (errno));
exit(1);
}
-
- if (!S_ISBLK (st_dev.st_mode)) /* not a block device, cannot
+
+ if (!S_ISBLK (st_dev.st_mode)) /* not a block device, cannot
* be mounted */
return 0;
@@ -99,7 +99,7 @@ static int test_mounted ( char *dev )
progname, _PATH_MOUNTED);
exit(1);
}
-
+
while ( ( mnt = getmntent (mtab) ) ) {
if (!mnt->mnt_fsname
@@ -120,7 +120,7 @@ static int test_mounted ( char *dev )
if (MT_STAT (mnt->mnt_fsname, &st_mnt)) {
continue;
}
-
+
if (S_ISBLK (st_mnt.st_mode)) {
#ifdef OS_linux
/* on Linux, warn also if the device is on the same
@@ -128,10 +128,10 @@ static int test_mounted ( char *dev )
if (MAJOR(st_mnt.st_rdev) == MAJOR(st_dev.st_rdev) &&
MINOR(st_mnt.st_rdev) >= MINOR(st_dev.st_rdev) &&
MINOR(st_mnt.st_rdev) <= MINOR(st_dev.st_rdev)+15){
- fprintf (stderr,
- "Device %s%d is mounted on %s.\n",
- dev,
- MINOR(st_mnt.st_rdev) -
+ fprintf (stderr,
+ "Device %s%d is mounted on %s.\n",
+ dev,
+ MINOR(st_mnt.st_rdev) -
MINOR(st_dev.st_rdev),
mnt->mnt_dir);
#else
@@ -154,10 +154,10 @@ static int test_mounted ( char *dev )
static void usage(int ret) NORETURN;
static void usage(int ret)
{
- fprintf(stderr,
- "Mtools version %s, dated %s\n",
+ fprintf(stderr,
+ "Mtools version %s, dated %s\n",
mversion, mdate);
- fprintf(stderr,
+ fprintf(stderr,
"Usage: %s [-V] [-q] [-e] [-u] [-r|-w|-p|-x] [drive:]\n"
"\t-q print status\n"
"\t-e eject disk\n"
@@ -166,26 +166,23 @@ static void usage(int ret)
"\t-w not write-protected (read-write)\n"
"\t-p password write protected\n"
"\t-x password protected\n"
- "\t-u unprotect till disk ejecting\n",
+ "\t-u unprotect till disk ejecting\n",
progname);
exit(ret);
}
+#define ZIP_RW (0)
+#define ZIP_RO (2)
+#define ZIP_RO_PW (3)
+#define ZIP_PW (5)
+#define ZIP_UNLOCK_TIL_EJECT (8)
-enum mode_t {
- ZIP_RW = 0,
- ZIP_RO = 2,
- ZIP_RO_PW = 3,
- ZIP_PW = 5,
- ZIP_UNLOCK_TIL_EJECT = 8
-};
-
-static enum mode_t get_zip_status(int priv, int fd, void *extra_data)
+static uint8_t get_zip_status(int priv, int fd, void *extra_data)
{
unsigned char status[128];
unsigned char cdb[6] = { 0x06, 0, 0x02, 0, sizeof status, 0 };
-
- if (zip_cmd(priv, fd, cdb, 6, SCSI_IO_READ,
+
+ if (zip_cmd(priv, fd, cdb, 6, SCSI_IO_READ,
status, sizeof status, extra_data) == -1) {
perror("status: ");
exit(1);
@@ -194,29 +191,32 @@ static enum mode_t get_zip_status(int priv, int fd, void *extra_data)
}
-static int short_command(int priv, int fd, int cmd1, int cmd2,
- int cmd3, const char *data, void *extra_data)
+static int short_command(int priv, int fd, uint8_t cmd1, uint8_t cmd2,
+ uint8_t cmd3, const char *data, void *extra_data)
{
- unsigned char cdb[6] = { 0, 0, 0, 0, 0, 0 };
+ uint8_t cdb[6] = { 0, 0, 0, 0, 0, 0 };
cdb[0] = cmd1;
cdb[1] = cmd2;
cdb[4] = cmd3;
- return zip_cmd(priv, fd, cdb, 6, SCSI_IO_WRITE,
- (char *) data, data ? strlen(data) : 0, extra_data);
+ return zip_cmd(priv, fd, cdb, 6, SCSI_IO_WRITE,
+ (char *) data, data ? (uint32_t) strlen(data) : 0,
+ extra_data);
}
-static int iomega_command(int priv, int fd, int mode, const char *data,
+static int iomega_command(int priv, int fd, uint8_t mode, const char *data,
void *extra_data)
{
- return short_command(priv, fd,
- SCSI_IOMEGA, mode, data ? strlen(data) : 0,
+ return short_command(priv, fd,
+ SCSI_IOMEGA, mode,
+ /* Do we really need strlen(data) in here? */
+ data ? (uint8_t) strlen(data) : 0,
data, extra_data);
}
-static int door_command(int priv, int fd, int cmd1, int cmd2,
+static int door_command(int priv, int fd, uint8_t cmd1, uint8_t cmd2,
void *extra_data)
{
return short_command(priv, fd, cmd1, 0, cmd2, 0, extra_data);
@@ -231,22 +231,22 @@ void mzip(int argc, char **argv, int type UNUSEDP)
device_t *dev;
int fd = -1;
char name[EXPAND_BUF];
- enum { ZIP_NIX = 0,
- ZIP_STATUS = 1 << 0,
- ZIP_EJECT = 1 << 1,
- ZIP_MODE_CHANGE = 1 << 2,
- ZIP_FORCE = 1 << 3
- } request = ZIP_NIX;
+#define ZIP_NIX (0)
+#define ZIP_STATUS (1 << 0)
+#define ZIP_EJECT (1 << 1)
+#define ZIP_MODE_CHANGE (1 << 2)
+#define ZIP_FORCE (1 << 3)
+ int request = ZIP_NIX;
- enum mode_t newMode = ZIP_RW;
- enum mode_t oldMode = ZIP_RW;
+ uint8_t newMode = ZIP_RW;
+ uint8_t oldMode = ZIP_RW;
#define setMode(x) \
if(request & ZIP_MODE_CHANGE) usage(1); \
request |= ZIP_MODE_CHANGE; \
newMode = x; \
- break;
-
+ break
+
/* get command line options */
if(helpFlag(argc, argv))
usage(0);
@@ -257,7 +257,7 @@ void mzip(int argc, char **argv, int type UNUSEDP)
break;
case 'f':
if (get_real_uid()) {
- fprintf(stderr,
+ fprintf(stderr,
"Only root can use force. Sorry.\n");
exit(1);
}
@@ -279,24 +279,24 @@ void mzip(int argc, char **argv, int type UNUSEDP)
case 'x': /* password protected */
setMode(ZIP_PW);
case 'u': /* password protected */
- setMode(ZIP_UNLOCK_TIL_EJECT)
+ setMode(ZIP_UNLOCK_TIL_EJECT);
case 'h':
usage(0);
default: /* unrecognized */
usage(1);
-
+
}
}
-
+
if (request == ZIP_NIX) request = ZIP_STATUS; /* default action */
- if (argc - optind > 1 ||
+ if (argc - optind > 1 ||
(argc - optind == 1 &&
(!argv[optind][0] || argv[optind][1] != ':')))
usage(1);
-
+
drive = ch_toupper(argc - optind == 1 ? argv[argc - 1][0] : ':');
-
+
for (dev = devices; dev->name; dev++) {
unsigned char cdb[6] = { 0, 0, 0, 0, 0, 0 };
struct {
@@ -314,13 +314,13 @@ void mzip(int argc, char **argv, int type UNUSEDP)
reserved2[40];
} inq_data;
- if (dev->drive != drive)
+ if (dev->drive != drive)
continue;
expand(dev->name, name);
if ((request & (ZIP_MODE_CHANGE | ZIP_EJECT)) &&
!(request & ZIP_FORCE) &&
test_mounted(name)) {
- fprintf(stderr,
+ fprintf(stderr,
"Can\'t change status of/eject mounted device\n");
exit(1);
}
@@ -339,8 +339,8 @@ void mzip(int argc, char **argv, int type UNUSEDP)
/* need readonly, else we can't
* open the drive on Solaris if
- * write-protected */
- if (fd == -1)
+ * write-protected */
+ if (fd == -1)
continue;
closeExec(fd);
@@ -352,12 +352,12 @@ void mzip(int argc, char **argv, int type UNUSEDP)
cdb[0] = SCSI_INQUIRY;
cdb[4] = sizeof inq_data;
- if (zip_cmd(IS_PRIVILEGED(dev), fd, cdb, 6, SCSI_IO_READ,
+ if (zip_cmd(IS_PRIVILEGED(dev), fd, cdb, 6, SCSI_IO_READ,
&inq_data, sizeof inq_data, extra_data) != 0) {
close(fd);
continue;
}
-
+
#ifdef DEBUG
fprintf(stderr, "device: %s\n\tvendor: %.8s\n\tproduct: %.16s\n"
"\trevision: %.4s\n", name, inq_data.vendor,
@@ -381,10 +381,10 @@ void mzip(int argc, char **argv, int type UNUSEDP)
/* debugging */
fprintf(stderr,"Skipping drive with vendor='");
- fwrite(inq_data.vendor,1, sizeof(inq_data.vendor),
+ fwrite(inq_data.vendor,1, sizeof(inq_data.vendor),
stderr);
fprintf(stderr,"' product='");
- fwrite(inq_data.product,1, sizeof(inq_data.product),
+ fwrite(inq_data.product,1, sizeof(inq_data.product),
stderr);
fprintf(stderr,"'\n");
/* end debugging */
@@ -417,7 +417,7 @@ void mzip(int argc, char **argv, int type UNUSEDP)
if (request & ZIP_MODE_CHANGE) {
int ret;
- enum mode_t unlockMode, unlockMask;
+ uint8_t unlockMode, unlockMask;
const char *passwd;
char dummy[1];
@@ -433,34 +433,34 @@ void mzip(int argc, char **argv, int type UNUSEDP)
char *s;
passwd = "APlaceForYourStuff";
if ((s = strchr(passwd, '\n'))) *s = '\0'; /* chomp */
- iomega_command(IS_PRIVILEGED(dev), fd, unlockMode,
+ iomega_command(IS_PRIVILEGED(dev), fd, unlockMode,
passwd, extra_data);
}
-
- if ((get_zip_status(IS_PRIVILEGED(dev), fd, extra_data) &
+
+ if ((get_zip_status(IS_PRIVILEGED(dev), fd, extra_data) &
unlockMask) == 1) {
/* unlock first */
char *s;
passwd = getpass("Password: ");
if ((s = strchr(passwd, '\n'))) *s = '\0'; /* chomp */
- if((ret=iomega_command(IS_PRIVILEGED(dev), fd,
- unlockMode, passwd,
+ if((ret=iomega_command(IS_PRIVILEGED(dev), fd,
+ unlockMode, passwd,
extra_data))){
if (ret == -1) perror("passwd: ");
else fprintf(stderr, "wrong password\n");
exit(1);
}
- if((get_zip_status(IS_PRIVILEGED(dev),
- fd, extra_data) &
+ if((get_zip_status(IS_PRIVILEGED(dev),
+ fd, extra_data) &
unlockMask) == 1) {
fprintf(stderr, "wrong password\n");
exit(1);
}
}
-
+
if (newMode & 0x1) {
char first_try[_PASSWORD_LEN+1];
-
+
passwd = getpass("Enter new password:");
strncpy(first_try, passwd,_PASSWORD_LEN);
passwd = getpass("Re-type new password:");
@@ -477,7 +477,7 @@ void mzip(int argc, char **argv, int type UNUSEDP)
if(newMode == ZIP_UNLOCK_TIL_EJECT)
newMode |= oldMode;
- if((ret=iomega_command(IS_PRIVILEGED(dev), fd,
+ if((ret=iomega_command(IS_PRIVILEGED(dev), fd,
newMode, passwd, extra_data))){
if (ret == -1) perror("set passwd: ");
else fprintf(stderr, "password not changed\n");
@@ -489,16 +489,16 @@ void mzip(int argc, char **argv, int type UNUSEDP)
status has changed */
#endif
}
-
+
if (request & ZIP_STATUS) {
const char *unlocked;
if(oldMode & 8)
unlocked = " and unlocked until eject";
else
- unlocked = "";
+ unlocked = "";
switch (oldMode & ~8) {
- case ZIP_RW:
+ case ZIP_RW:
printf("Drive '%c:' is not write-protected\n",
drive);
break;
@@ -506,49 +506,49 @@ void mzip(int argc, char **argv, int type UNUSEDP)
printf("Drive '%c:' is write-protected%s\n",
drive, unlocked);
break;
- case ZIP_RO_PW:
- printf("Drive '%c:' is password write-protected%s\n",
+ case ZIP_RO_PW:
+ printf("Drive '%c:' is password write-protected%s\n",
drive, unlocked);
break;
- case ZIP_PW:
- printf("Drive '%c:' is password protected%s\n",
+ case ZIP_PW:
+ printf("Drive '%c:' is password protected%s\n",
drive, unlocked);
break;
- default:
+ default:
printf("Unknown protection mode %d of drive '%c:'\n",
oldMode, drive);
- break;
- }
+ break;
+ }
}
-
+
if (request & ZIP_EJECT) {
if(request & ZIP_FORCE)
- if(door_command(IS_PRIVILEGED(dev), fd,
+ if(door_command(IS_PRIVILEGED(dev), fd,
SCSI_ALLOW_MEDIUM_REMOVAL, 0,
extra_data) < 0) {
perror("door unlock: ");
exit(1);
}
- if(door_command(IS_PRIVILEGED(dev), fd,
+ if(door_command(IS_PRIVILEGED(dev), fd,
SCSI_START_STOP, 1,
extra_data) < 0) {
perror("stop motor: ");
exit(1);
}
- if(door_command(IS_PRIVILEGED(dev), fd,
+ if(door_command(IS_PRIVILEGED(dev), fd,
SCSI_START_STOP, 2, extra_data) < 0) {
perror("eject: ");
exit(1);
}
- if(door_command(IS_PRIVILEGED(dev), fd,
+ if(door_command(IS_PRIVILEGED(dev), fd,
SCSI_START_STOP, 2, extra_data) < 0) {
perror("second eject: ");
exit(1);
}
}
-
+
close(fd);
exit(0);
}
diff --git a/nameclash.h b/nameclash.h
index 7c69706..5f3bdc6 100644
--- a/nameclash.h
+++ b/nameclash.h
@@ -37,7 +37,7 @@ typedef enum clash_action {
typedef struct ClashHandling_t {
clash_action action[2];
clash_action namematch_default[2];
-
+
int nowarn; /* Don't ask, just do default action if name collision*/
int got_slots;
int mod_time;
@@ -49,10 +49,10 @@ typedef struct ClashHandling_t {
int use_longname;
int ignore_entry;
int source; /* to prevent the source from overwriting itself */
- int source_entry; /* to account for the space freed up by the original
- * name */
+ int source_entry; /* to account for the space freed up by the original
+ * name */
void (*name_converter)(doscp_t *cp,
- const char *filename, int verbose,
+ const char *filename, int verbose,
int *mangled, dos_name_t *ans);
int is_label;
} ClashHandling_t;
diff --git a/offset.c b/offset.c
new file mode 100644
index 0000000..e8be549
--- /dev/null
+++ b/offset.c
@@ -0,0 +1,90 @@
+/* Copyright 2021 Alain Knaff.
+ * This file is part of mtools.
+ *
+ * Mtools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * filter to support filesystems stored at an offset into their image
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "offset.h"
+
+typedef struct Offset_t {
+ struct Stream_t head;
+
+ mt_off_t offset;
+} Offset_t;
+
+static ssize_t offset_pread(Stream_t *Stream, char *buf,
+ mt_off_t start, size_t len)
+{
+ DeclareThis(Offset_t);
+ return PREADS(This->head.Next, buf, start+This->offset, len);
+}
+
+static ssize_t offset_pwrite(Stream_t *Stream, char *buf,
+ mt_off_t start, size_t len)
+{
+ DeclareThis(Offset_t);
+ return PWRITES(This->head.Next, buf, start+This->offset, len);
+}
+
+static Class_t OffsetClass = {
+ 0,
+ 0,
+ offset_pread,
+ offset_pwrite,
+ 0, /* flush */
+ 0, /* free */
+ set_geom_pass_through, /* set_geom */
+ 0, /* get_data */
+ 0, /* pre-allocate */
+ get_dosConvert_pass_through, /* dos convert */
+ 0, /* discard */
+};
+
+Stream_t *OpenOffset(Stream_t *Next, struct device *dev, off_t offset,
+ char *errmsg, mt_off_t *maxSize) {
+ Offset_t *This;
+
+ This = New(Offset_t);
+ if (!This){
+ printOom();
+ return 0;
+ }
+ memset((void*)This, 0, sizeof(Offset_t));
+ init_head(&This->head, &OffsetClass, Next);
+
+ This->offset = offset;
+
+ if(maxSize) {
+ if(This->offset > *maxSize) {
+ if(errmsg)
+ sprintf(errmsg,"init: Big disks not supported");
+ goto exit_0;
+ }
+
+ *maxSize -= This->offset;
+ }
+
+ if(adjust_tot_sectors(dev, This->offset, errmsg) < 0)
+ goto exit_0;
+
+ return &This->head;
+ exit_0:
+ Free(This);
+ return NULL;
+}
diff --git a/offset.h b/offset.h
new file mode 100644
index 0000000..a344399
--- /dev/null
+++ b/offset.h
@@ -0,0 +1,2 @@
+Stream_t *OpenOffset(Stream_t *Next, struct device *dev, off_t offset,
+ char *errmsg, mt_off_t *maxSize);
diff --git a/old_dos.c b/old_dos.c
index b5e146b..057b055 100644
--- a/old_dos.c
+++ b/old_dos.c
@@ -1,5 +1,5 @@
#include "sysincludes.h"
-#include "mtools.h"
+#include "old_dos.h"
static struct OldDos_t old_dos[]={
{ 40, 9, 1, 4, 1, 2, 0xfc }, /* 180 KB */
diff --git a/old_dos.h b/old_dos.h
new file mode 100644
index 0000000..2461807
--- /dev/null
+++ b/old_dos.h
@@ -0,0 +1,43 @@
+#ifndef MTOOLS_OLDDOS_H
+#define MTOOLS_OLDDOS_H
+/* Copyright 2021 Alain Knaff.
+ * This file is part of mtools.
+ *
+ * Mtools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "device.h"
+
+struct OldDos_t {
+ unsigned int tracks;
+ uint16_t sectors;
+ uint16_t heads;
+
+ uint16_t dir_len;
+ uint8_t cluster_size;
+ uint32_t fat_len;
+
+ uint8_t media;
+};
+
+extern struct OldDos_t *getOldDosBySize(size_t size);
+extern struct OldDos_t *getOldDosByMedia(int media);
+extern struct OldDos_t *getOldDosByParams(unsigned int tracks,
+ unsigned int heads,
+ unsigned int sectors,
+ unsigned int dir_len,
+ unsigned int cluster_size);
+int setDeviceFromOldDos(int media, struct device *dev);
+
+#endif
diff --git a/open_image.c b/open_image.c
new file mode 100644
index 0000000..4dfef5a
--- /dev/null
+++ b/open_image.c
@@ -0,0 +1,143 @@
+/* Copyright 2021 Alain Knaff.
+ * This file is part of mtools.
+ *
+ * Mtools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Open filesystem image or device, and push any remapping and/or partitioning layers on it
+Buffer read/write module
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "lba.h"
+
+#include "open_image.h"
+
+#include "plain_io.h"
+#include "floppyd_io.h"
+#include "xdf_io.h"
+#include "scsi_io.h"
+#include "remap.h"
+#include "partition.h"
+#include "offset.h"
+#include "swap.h"
+
+/*
+ * Open filesystem image
+ * out_dev: device descriptor, adapted to current media and context
+ * dev: initial template device descriptor (not modified)
+ * name: file name (if applicable)
+ * maxSize: if set, max size will be returned here
+ * geomFailureP: if set, geometry failure will be returned here. This means
+ * that caller should retry again opening the same image read/write
+ * skip: a bitmask of intermediary layers to skip
+ * errmsg: any error messages will be returned here
+ */
+Stream_t *OpenImage(struct device *out_dev, struct device *dev,
+ const char *name, int mode, char *errmsg,
+ int flags, int lockMode,
+ mt_off_t *maxSize, int *geomFailureP,
+#ifdef USE_XDF
+ struct xdf_info *xdf_info
+#else
+ void *dummy UNUSEDP
+#endif
+ )
+{
+ Stream_t *Stream=NULL;
+ int geomFailure=0;
+ if(out_dev->misc_flags & FLOPPYD_FLAG) {
+#ifdef USE_FLOPPYD
+ Stream = FloppydOpen(out_dev, name, mode,
+ errmsg, maxSize);
+#endif
+ } else {
+
+#ifdef USE_XDF
+ Stream = XdfOpen(out_dev, name, mode, errmsg, xdf_info);
+ if(Stream) {
+ out_dev->use_2m = 0x7f;
+ if(maxSize)
+ *maxSize = max_off_t_31;
+ }
+#endif
+
+ if (!Stream) {
+ Stream = OpenScsi(out_dev, name,
+ mode,
+ errmsg, flags, 0,
+ lockMode,
+ maxSize);
+ }
+
+ if (!Stream) {
+ Stream = SimpleFileOpenWithLm(out_dev, dev, name,
+ mode,
+ errmsg, flags, 0,
+ lockMode,
+ maxSize,
+ &geomFailure);
+ }
+
+ if(geomFailure) {
+ if(*geomFailureP)
+ *geomFailureP=geomFailure;
+ return NULL;
+ }
+ }
+
+ if( !Stream)
+ return NULL;
+
+ if(dev->data_map) {
+ Stream_t *Remapped = Remap(Stream, out_dev, errmsg);
+ if(Remapped == NULL)
+ goto exit_0;
+ Stream = Remapped;
+ }
+
+ if(dev->offset) {
+ Stream_t *Offset = OpenOffset(Stream, out_dev, dev->offset,
+ errmsg, maxSize);
+ if(Offset == NULL)
+ goto exit_0;
+ Stream = Offset;
+ }
+
+ if(DO_SWAP(dev)) {
+ Stream_t *Swap = OpenSwap(Stream);
+ if(Swap == NULL)
+ goto exit_0;
+ Stream = Swap;
+ }
+
+ if((flags & ALWAYS_GET_GEOMETRY) &&
+ compute_lba_geom_from_tot_sectors(out_dev) < 0)
+ goto exit_0;
+
+ if(dev->partition && !(flags & SKIP_PARTITION)) {
+ Stream_t *Partition = OpenPartition(Stream, out_dev,
+ errmsg, maxSize);
+ if(Partition == NULL)
+ goto exit_0;
+ Stream = Partition;
+ }
+
+ return Stream;
+ exit_0:
+ FREE(&Stream);
+ return NULL;
+}
+
diff --git a/open_image.h b/open_image.h
new file mode 100644
index 0000000..cfd7a80
--- /dev/null
+++ b/open_image.h
@@ -0,0 +1,17 @@
+#include "xdf_io.h"
+
+/* plain io */
+#define NO_PRIV 1
+#define SKIP_PARTITION 2
+#define ALWAYS_GET_GEOMETRY 4
+
+Stream_t *OpenImage(struct device *out_dev, struct device *dev,
+ const char *name, int mode, char *errmsg,
+ int flags, int lockMode,
+ mt_off_t *maxSize, int *geomFailureP,
+#ifdef USE_XDF
+ struct xdf_info *xdf_info
+#else
+ void *dummy
+#endif
+ );
diff --git a/partition.c b/partition.c
new file mode 100644
index 0000000..240f0f5
--- /dev/null
+++ b/partition.c
@@ -0,0 +1,281 @@
+/* Copyright 2021 Alain Knaff.
+ * This file is part of mtools.
+ *
+ * Mtools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Buffer read/write module
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "partition.h"
+
+typedef struct Partition_t {
+ struct Stream_t head;
+
+ mt_off_t offset; /* Offset, in bytes */
+ mt_off_t size; /* size, in bytes */
+ uint32_t nbSect; /* size, in sectors */
+
+ uint8_t pos;
+
+ uint8_t sectors;
+ uint8_t heads;
+ uint16_t cyclinders;
+} Partition_t;
+
+static __inline__ void print_hsc(hsc *h)
+{
+ printf(" h=%d s=%d c=%d\n",
+ head(*h), sector(*h), cyl(*h));
+}
+
+/*
+ * Make sure range [ start, end ] does not overlap with partition i
+ */
+static int overlapCheck(struct partition *partTable, unsigned int i,
+ uint32_t start, uint32_t end) {
+ struct partition *partition = &partTable[i];
+ if(!partition->sys_ind)
+ return 0; /* Partition not allocated => ok */
+ if(end > BEGIN(partition) &&
+ (start < END(partition) || END(partition) < BEGIN(partition)))
+ /* overlap */
+ return -1;
+ return 0;
+}
+
+unsigned int findOverlap(struct partition *partTable, unsigned int until,
+ uint32_t start, uint32_t end)
+{
+ unsigned int i;
+ for(i=1; i <= until; i++)
+ if(overlapCheck(partTable, i, start, end))
+ return i;
+ return 0;
+}
+
+
+int consistencyCheck(struct partition *partTable, int doprint,
+ int verbose,
+ int *has_activated, uint32_t tot_sectors,
+ struct device *used_dev UNUSEDP,
+ unsigned int target_partition)
+{
+ unsigned int i;
+ bool inconsistency;
+
+ /* quick consistency check */
+ inconsistency = 0;
+ *has_activated = 0;
+ for(i=1; i<=4; i++){
+ unsigned int j;
+ struct partition *partition = &partTable[i];
+ if(!partition->sys_ind)
+ continue;
+ if(partition->boot_ind)
+ (*has_activated)++;
+
+ if(END(partition) < BEGIN(partition)) {
+ fprintf(stderr,
+ "End of partition %d before its begin\n",
+ i);
+ }
+
+ if((j = findOverlap(partTable, i-1,
+ BEGIN(partition), END(partition)))) {
+ fprintf(stderr,
+ "Partitions %d and %d overlap\n",
+ j, i);
+ inconsistency=1;
+ }
+
+ if(tot_sectors && END(partition) >tot_sectors) {
+ fprintf(stderr,
+ "Partition %d extends beyond end of disk\n", i);
+ }
+
+ if(doprint && verbose) {
+ if(i==target_partition)
+ putchar('*');
+ else
+ putchar(' ');
+ printf("Partition %d\n",i);
+
+ printf(" active=%x\n", partition->boot_ind);
+ printf(" start:");
+ print_hsc(&partition->start);
+ printf(" type=0x%x\n", partition->sys_ind);
+ printf(" end:");
+ print_hsc(&partition->end);
+ printf(" start=%d\n", BEGIN(partition));
+ printf(" nr=%d\n", _DWORD(partition->nr_sects));
+ printf("\n");
+ }
+ }
+ return inconsistency;
+}
+
+
+static int limit_size(Partition_t *This, mt_off_t start, size_t *len)
+{
+ if(start > This->size)
+ return -1;
+ limitSizeToOffT(len, This->size - start);
+ return 0;
+}
+
+static ssize_t partition_pread(Stream_t *Stream, char *buf,
+ mt_off_t start, size_t len)
+{
+ DeclareThis(Partition_t);
+ if(limit_size(This, start, &len) < 0)
+ return -1;
+ return PREADS(This->head.Next, buf, start+This->offset, len);
+}
+
+static ssize_t partition_pwrite(Stream_t *Stream, char *buf,
+ mt_off_t start, size_t len)
+{
+ DeclareThis(Partition_t);
+ if(limit_size(This, start, &len) < 0)
+ return -1;
+ return PWRITES(This->head.Next, buf, start+This->offset, len);
+}
+
+static int partition_data(Stream_t *Stream, time_t *date, mt_off_t *size,
+ int *type, uint32_t *address)
+{
+ DeclareThis(Partition_t);
+
+ if(date || type || address) {
+ int ret = GET_DATA(This->head.Next, date, NULL, type, address);
+ if(ret < 0)
+ return ret;
+ }
+ if(size)
+ *size = This->size * 512;
+ return 0;
+}
+
+
+static int partition_geom(Stream_t *Stream, struct device *dev,
+ UNUSEDP struct device *orig_dev)
+{
+ DeclareThis(Partition_t);
+
+ if(!dev->tot_sectors)
+ dev->tot_sectors = This->nbSect;
+
+ return 0;
+}
+
+static Class_t PartitionClass = {
+ 0,
+ 0,
+ partition_pread,
+ partition_pwrite,
+ 0, /* flush */
+ 0, /* free */
+ partition_geom, /* set_geom */
+ partition_data, /* get_data */
+ 0, /* pre-allocate */
+ get_dosConvert_pass_through, /* dos convert */
+ 0, /* discard */
+};
+
+Stream_t *OpenPartition(Stream_t *Next, struct device *dev,
+ char *errmsg, mt_off_t *maxSize) {
+ Partition_t *This;
+ int has_activated;
+ unsigned char buf[2048];
+ struct partition *partTable=(struct partition *)(buf+ 0x1ae);
+ uint32_t partOff;
+ struct partition *partition;
+
+ if(!dev || (dev->partition > 4) || (dev->partition <= 0)) {
+ fprintf(stderr,
+ "Invalid partition %d (must be between 1 and 4), ignoring it\n",
+ dev->partition);
+ return NULL;
+ }
+
+ This = New(Partition_t);
+ if (!This){
+ printOom();
+ return 0;
+ }
+ memset((void*)This, 0, sizeof(Partition_t));
+ init_head(&This->head, &PartitionClass, Next);
+
+
+ /* read the first sector, or part of it */
+ if (force_pread(This->head.Next, (char*) buf, 0, 512) != 512)
+ goto exit_0;
+ if( _WORD(buf+510) != 0xaa55) {
+ /* Not a partition table */
+ if(errmsg)
+ sprintf(errmsg,
+ "Device does not have a BIOS partition table\n");
+ goto exit_0;
+ }
+ partition = &partTable[dev->partition];
+ if(!partition->sys_ind) {
+ if(errmsg)
+ sprintf(errmsg,
+ "Partition %d does not exist\n",
+ dev->partition);
+ goto exit_0;
+ }
+
+ partOff = BEGIN(partition);
+ if (maxSize) {
+ if (partOff > (smt_off_t)(*maxSize >> 9)) {
+ if(errmsg)
+ sprintf(errmsg,"init: Big disks not supported");
+ goto exit_0;
+ }
+ *maxSize -= partOff << 9;
+ maximize(*maxSize, ((mt_off_t)PART_SIZE(partition)) << 9);
+ }
+
+ This->offset = (mt_off_t) partOff << 9;
+
+ if(!mtools_skip_check &&
+ consistencyCheck((struct partition *)(buf+0x1ae), 0, 0,
+ &has_activated, dev->tot_sectors, dev, 0)) {
+ fprintf(stderr,
+ "Warning: inconsistent partition table\n");
+ fprintf(stderr,
+ "Possibly unpartitioned device\n");
+ fprintf(stderr,
+ "\n*** Maybe try without partition=%d in "
+ "device definition ***\n\n",
+ dev->partition);
+ fprintf(stderr,
+ "If this is a PCMCIA card, or a disk "
+ "partitioned on another computer, this "
+ "message may be in error: add "
+ "mtools_skip_check=1 to your .mtoolsrc "
+ "file to suppress this warning\n");
+ }
+ dev->tot_sectors = This->nbSect = PART_SIZE(partition);
+ This->size = (mt_off_t) This->nbSect << 9;
+ return &This->head;
+ exit_0:
+ Free(This);
+ return NULL;
+}
+
diff --git a/partition.h b/partition.h
index 7d9aa7b..1e0345f 100644
--- a/partition.h
+++ b/partition.h
@@ -22,12 +22,13 @@ typedef struct hsc {
unsigned char cyl; /* starting cylinder */
} hsc;
-#define head(x) ((unsigned int)((x).head))
-#define sector(x) ((unsigned int)((x).sector & 0x3f))
-#define cyl(x) ((unsigned int)((x).cyl | (((x).sector & 0xc0)<<2)))
+#define head(x) ((uint8_t)((x).head))
+#define sector(x) ((uint8_t)((x).sector & 0x3f))
+#define cyl(x) ((uint16_t)((x).cyl | (((x).sector & 0xc0)<<2)))
-#define BEGIN(p) _DWORD((p).start_sect)
-#define END(p) (_DWORD((p).start_sect)+(_DWORD((p).nr_sects)))
+#define BEGIN(p) _DWORD((p)->start_sect)
+#define END(p) (_DWORD((p)->start_sect)+(_DWORD((p)->nr_sects)))
+#define PART_SIZE(p) (_DWORD((p)->nr_sects))
struct partition {
@@ -41,11 +42,16 @@ struct partition {
#define sys_ind end.byte0
int consistencyCheck(struct partition *partTable, int doprint, int verbose,
- int *has_activated, unsigned int *last_end,
- unsigned int *j,
- struct device *used_dev, int target_partition);
+ int *has_activated, uint32_t tot_sectors,
+ struct device *used_dev, unsigned int target_partition);
void setBeginEnd(struct partition *partTable,
- unsigned long begin, unsigned long end,
- unsigned int heads, unsigned int sector,
- int activate, int type, int fat_bits);
+ uint32_t begin, uint32_t end,
+ uint16_t iheads, uint16_t isectors,
+ int activate, uint8_t type, unsigned int fat_bits);
+
+Stream_t *OpenPartition(Stream_t *Next, struct device *dev,
+ char *errmsg, mt_off_t *maxSize);
+
+unsigned int findOverlap(struct partition *partTable, unsigned int until,
+ uint32_t start, uint32_t end);
diff --git a/patchlevel.c b/patchlevel.c
index b9fd39e..db4b905 100644
--- a/patchlevel.c
+++ b/patchlevel.c
@@ -18,10 +18,10 @@
#include "sysincludes.h"
#include "msdos.h"
-const char *mversion="4.0.26";
+const char *mversion="4.0.37";
/* Multiple releases on same day should be marked with (b), (cd), (d) after
* date string below */
-const char *mdate = "November 28th, 2020";
+const char *mdate = "January 8th, 2022";
-const char *mformat_banner = "MTOO4026";
+const char *mformat_banner = "MTOO4037";
diff --git a/plain_io.c b/plain_io.c
index 10eb0ce..9a40e12 100644
--- a/plain_io.c
+++ b/plain_io.c
@@ -18,7 +18,7 @@
*
* written by:
*
- * Alain L. Knaff
+ * Alain L. Knaff
* alain@knaff.lu
*
*/
@@ -27,9 +27,9 @@
#include "stream.h"
#include "mtools.h"
#include "msdos.h"
+#include "open_image.h"
+#include "devices.h"
#include "plain_io.h"
-#include "scsi.h"
-#include "partition.h"
#include "llong.h"
#ifdef HAVE_LINUX_FS_H
@@ -37,55 +37,36 @@
#endif
typedef struct SimpleFile_t {
- Class_t *Class;
- int refs;
- Stream_t *Next;
- Stream_t *Buffer;
+ struct Stream_t head;
+
struct MT_STAT statbuf;
int fd;
- mt_off_t offset;
mt_off_t lastwhere;
int seekable;
int privileged;
#ifdef OS_hpux
int size_limited;
#endif
- int scsi_sector_size;
- void *extra_data; /* extra system dependent information for scsi */
- int swap; /* do the word swapping */
} SimpleFile_t;
#include "lockdev.h"
-typedef int (*iofn) (int, char *, int);
-
+typedef ssize_t (*iofn) (int, void *, size_t);
-static void swap_buffer(char *buf, size_t len)
+static ssize_t file_io(SimpleFile_t *This, char *buf,
+ mt_off_t where, size_t len,
+ iofn io)
{
- unsigned int i;
- for (i=0; i<len; i+=2) {
- char temp = buf[i];
- buf[i] = buf[i+1];
- buf[i+1] = temp;
- }
-}
-
-
-static int file_io(Stream_t *Stream, char *buf, mt_off_t where, int len,
- iofn io)
-{
- DeclareThis(SimpleFile_t);
- int ret;
-
- where += This->offset;
+ ssize_t ret;
if (This->seekable && where != This->lastwhere ){
if(mt_lseek( This->fd, where, SEEK_SET) < 0 ){
perror("seek");
- This->lastwhere = (mt_off_t) -1;
- return -1;
+ return -1; /* If seek failed, lastwhere did
+ not change */
}
+ This->lastwhere = where;
}
#ifdef OS_hpux
@@ -100,7 +81,7 @@ static int file_io(Stream_t *Stream, char *buf, mt_off_t where, int len,
ret = io(This->fd, buf, len);
#ifdef OS_hpux
- if (ret == -1 &&
+ if (ret == -1 &&
errno == EINVAL && /* if we got EINVAL */
len > MAX_SCSI_LEN) {
This->size_limited = 1;
@@ -111,43 +92,36 @@ static int file_io(Stream_t *Stream, char *buf, mt_off_t where, int len,
if ( ret == -1 ){
perror("plain_io");
- This->lastwhere = (mt_off_t) -1;
return -1;
}
This->lastwhere = where + ret;
return ret;
}
-
-
-static int file_read(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
+static ssize_t file_read(Stream_t *Stream, char *buf, size_t len)
{
DeclareThis(SimpleFile_t);
-
- int result = file_io(Stream, buf, where, len, (iofn) read);
-
- if ( This->swap )
- swap_buffer( buf, len );
- return result;
+ return file_io(This, buf, This->lastwhere, len, read);
}
-static int file_write(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
+static ssize_t file_write(Stream_t *Stream, char *buf, size_t len)
{
DeclareThis(SimpleFile_t);
+ return file_io(This, buf, This->lastwhere, len, (iofn) write);
+}
- if ( !This->swap )
- return file_io(Stream, buf, where, len, (iofn) write);
- else {
- int result;
- char *swapping = malloc( len );
- memcpy( swapping, buf, len );
- swap_buffer( swapping, len );
-
- result = file_io(Stream, swapping, where, len, (iofn) write);
+static ssize_t file_pread(Stream_t *Stream, char *buf,
+ mt_off_t where, size_t len)
+{
+ DeclareThis(SimpleFile_t);
+ return file_io(This, buf, where, len, read);
+}
- free(swapping);
- return result;
- }
+static ssize_t file_pwrite(Stream_t *Stream, char *buf,
+ mt_off_t where, size_t len)
+{
+ DeclareThis(SimpleFile_t);
+ return file_io(This, buf, where, len, (iofn) write);
}
static int file_flush(Stream_t *Stream UNUSEDP)
@@ -170,86 +144,52 @@ static int file_free(Stream_t *Stream)
return 0;
}
-static int file_geom(Stream_t *Stream, struct device *dev,
- struct device *orig_dev,
- int media, union bootsector *boot)
+static int init_geom_with_reg(int fd, struct device *dev,
+ struct device *orig_dev,
+ struct MT_STAT *statbuf) {
+ if(S_ISREG(statbuf->st_mode)) {
+ /* Regular file (image file) */
+ mt_off_t sectors;
+ if(statbuf->st_size == 0) {
+ /* zero sized image => newly created.
+ Size not actually known...
+ */
+ return 0;
+ }
+ sectors = statbuf->st_size /
+ (mt_off_t)(dev->sector_size ? dev->sector_size : 512);
+ dev->tot_sectors =
+ ((smt_off_t) sectors > UINT32_MAX)
+ ? UINT32_MAX
+ : (uint32_t) sectors;
+ return 0;
+ } else {
+ /* All the rest (devices, etc.) */
+ return init_geom(fd, dev, orig_dev, statbuf);
+ }
+}
+
+static int file_geom(Stream_t *Stream, struct device *dev,
+ struct device *orig_dev)
{
int ret;
DeclareThis(SimpleFile_t);
- size_t tot_sectors;
- int BootP, Infp0, InfpX, InfTm;
- int sectors, j;
- unsigned char sum;
- int sect_per_track;
- struct label_blk_t *labelBlock;
-
- dev->ssize = 2; /* allow for init_geom to change it */
- dev->use_2m = 0x80; /* disable 2m mode to begin */
-
- if(media == 0xf0 || media >= 0x100){
- dev->heads = WORD(nheads);
- dev->sectors = WORD(nsect);
- tot_sectors = DWORD(bigsect);
- SET_INT(tot_sectors, WORD(psect));
- sect_per_track = dev->heads * dev->sectors;
- if(sect_per_track == 0) {
- if(mtools_skip_check) {
- /* add some fake values if sect_per_track is
- * zero. Indeed, some atari disks lack the
- * geometry values (i.e. have zeroes in their
- * place). In order to avoid division by zero
- * errors later on, plug 1 everywhere
- */
- dev->heads = 1;
- dev->sectors = 1;
- sect_per_track = 1;
- } else {
- fprintf(stderr, "The devil is in the details: zero number of heads or sectors\n");
- exit(1);
- }
- }
- tot_sectors += sect_per_track - 1; /* round size up */
- dev->tracks = tot_sectors / sect_per_track;
-
- BootP = WORD(ext.old.BootP);
- Infp0 = WORD(ext.old.Infp0);
- InfpX = WORD(ext.old.InfpX);
- InfTm = WORD(ext.old.InfTm);
-
- if(WORD(fatlen)) {
- labelBlock = &boot->boot.ext.old.labelBlock;
- } else {
- labelBlock = &boot->boot.ext.fat32.labelBlock;
- }
- if (boot->boot.descr >= 0xf0 &&
- has_BPB4 &&
- strncmp( boot->boot.banner,"2M", 2 ) == 0 &&
- BootP < 512 && Infp0 < 512 && InfpX < 512 && InfTm < 512 &&
- BootP >= InfTm + 2 && InfTm >= InfpX && InfpX >= Infp0 &&
- Infp0 >= 76 ){
- for (sum=0, j=63; j < BootP; j++)
- sum += boot->bytes[j];/* checksum */
- dev->ssize = boot->bytes[InfTm];
- if (!sum && dev->ssize <= 7){
- dev->use_2m = 0xff;
- dev->ssize |= 0x80; /* is set */
- }
- }
- } else
- if(setDeviceFromOldDos(media, dev) < 0)
- exit(1);
-
- sectors = dev->sectors;
- dev->sectors = dev->sectors * WORD(secsiz) / 512;
+ if(dev->sector_size && dev->sector_size != 512) {
+ dev->sectors =
+ (uint16_t) (dev->sectors * dev->sector_size / 512);
+ }
#ifdef JPD
printf("file_geom:media=%0X=>cyl=%d,heads=%d,sects=%d,ssize=%d,use2m=%X\n",
media, dev->tracks, dev->heads, dev->sectors, dev->ssize,
dev->use_2m);
#endif
- ret = init_geom(This->fd,dev, orig_dev, &This->statbuf);
- dev->sectors = sectors;
+ ret = init_geom_with_reg(This->fd,dev, orig_dev, &This->statbuf);
+ if(dev->sector_size && dev->sector_size != 512) {
+ dev->sectors =
+ (uint16_t) (dev->sectors * 512 / dev->sector_size);
+ }
#ifdef JPD
printf("f_geom: after init_geom(), sects=%d\n", dev->sectors);
#endif
@@ -257,8 +197,8 @@ static int file_geom(Stream_t *Stream, struct device *dev,
}
-static int file_data(Stream_t *Stream, time_t *date, mt_size_t *size,
- int *type, int *address)
+static int file_data(Stream_t *Stream, time_t *date, mt_off_t *size,
+ int *type, uint32_t *address)
{
DeclareThis(SimpleFile_t);
@@ -273,7 +213,7 @@ static int file_data(Stream_t *Stream, time_t *date, mt_size_t *size,
return 0;
}
-static int file_discard(Stream_t *Stream)
+static int file_discard(Stream_t *Stream UNUSEDP)
{
#ifdef BLKFLSBUF
int ret;
@@ -287,191 +227,11 @@ static int file_discard(Stream_t *Stream)
#endif
}
-/* ZIP or other scsi device on Solaris or SunOS system.
- Since Sun won't accept a non-Sun label on a scsi disk, we must
- bypass Sun's disk interface and use low-level SCSI commands to read
- or write the ZIP drive. We thus replace the file_read and file_write
- routines with our own scsi_read and scsi_write routines, that use the
- uscsi ioctl interface. By James Dugal, jpd@usl.edu, 11-96. Tested
- under Solaris 2.5 and SunOS 4.3.1_u1 using GCC.
-
- Note: the mtools.conf entry for a ZIP drive would look like this:
-(solaris) drive C: file="/dev/rdsk/c0t5d0s2" partition=4 FAT=16 nodelay exclusive scsi=&
-(sunos) drive C: file="/dev/rsd5c" partition=4 FAT=16 nodelay exclusive scsi=1
-
- Note 2: Sol 2.5 wants mtools to be suid-root, to use the ioctl. SunOS is
- happy if we just have access to the device, so making mtools sgid to a
- group called, say, "ziprw" which has rw permission on /dev/rsd5c, is fine.
- */
-
-static void scsi_init(SimpleFile_t *This)
-{
- int fd = This->fd;
- unsigned char cdb[10],buf[8];
-
- memset(cdb, 0, sizeof cdb);
- memset(buf,0, sizeof(buf));
- cdb[0]=SCSI_READ_CAPACITY;
- if (scsi_cmd(fd, (unsigned char *)cdb,
- sizeof(cdb), SCSI_IO_READ, buf, sizeof(buf), This->extra_data)==0)
- {
- This->scsi_sector_size=
- ((unsigned)buf[5]<<16)|((unsigned)buf[6]<<8)|(unsigned)buf[7];
- if (This->scsi_sector_size != 512)
- fprintf(stderr," (scsi_sector_size=%d)\n",This->scsi_sector_size);
- }
-}
-
-static int scsi_io(Stream_t *Stream, char *buf,
- mt_off_t where, size_t len, int rwcmd)
-{
- unsigned int firstblock, nsect;
- int clen,r;
- size_t max;
- off_t offset;
- unsigned char cdb[10];
- DeclareThis(SimpleFile_t);
-
- firstblock=truncBytes32((where + This->offset)/This->scsi_sector_size);
- /* 512,1024,2048,... bytes/sector supported */
- offset=truncBytes32(where + This->offset -
- firstblock*This->scsi_sector_size);
- nsect=(offset+len+This->scsi_sector_size-1)/ This->scsi_sector_size;
-#if defined(OS_sun) && defined(OS_i386)
- if (This->scsi_sector_size>512)
- firstblock*=This->scsi_sector_size/512; /* work around a uscsi bug */
-#endif /* sun && i386 */
-
- if (len>512) {
- /* avoid buffer overruns. The transfer MUST be smaller or
- * equal to the requested size! */
- while (nsect*This->scsi_sector_size>len)
- --nsect;
- if(!nsect) {
- fprintf(stderr,"Scsi buffer too small\n");
- exit(1);
- }
- if(rwcmd == SCSI_IO_WRITE && offset) {
- /* there seems to be no memmove before a write */
- fprintf(stderr,"Unaligned write\n");
- exit(1);
- }
- /* a better implementation should use bounce buffers.
- * However, in normal operation no buffer overruns or
- * unaligned writes should happen anyways, as the logical
- * sector size is (hopefully!) equal to the physical one
- */
- }
-
-
- max = scsi_max_length();
-
- if (nsect > max)
- nsect=max;
-
- /* set up SCSI READ/WRITE command */
- memset(cdb, 0, sizeof cdb);
-
- switch(rwcmd) {
- case SCSI_IO_READ:
- cdb[0] = SCSI_READ;
- break;
- case SCSI_IO_WRITE:
- cdb[0] = SCSI_WRITE;
- break;
- }
-
- cdb[1] = 0;
-
- if (firstblock > 0x1fffff || nsect > 0xff) {
- /* I suspect that the ZIP drive also understands Group 1
- * commands. If that is indeed true, we may chose Group 1
- * more aggressively in the future */
-
- cdb[0] |= SCSI_GROUP1;
- clen=10; /* SCSI Group 1 cmd */
-
- /* this is one of the rare case where explicit coding is
- * more portable than macros... The meaning of scsi command
- * bytes is standardised, whereas the preprocessor macros
- * handling it might be not... */
-
- cdb[2] = (unsigned char) (firstblock >> 24) & 0xff;
- cdb[3] = (unsigned char) (firstblock >> 16) & 0xff;
- cdb[4] = (unsigned char) (firstblock >> 8) & 0xff;
- cdb[5] = (unsigned char) firstblock & 0xff;
- cdb[6] = 0;
- cdb[7] = (unsigned char) (nsect >> 8) & 0xff;
- cdb[8] = (unsigned char) nsect & 0xff;
- cdb[9] = 0;
- } else {
- clen = 6; /* SCSI Group 0 cmd */
- cdb[1] |= (unsigned char) ((firstblock >> 16) & 0x1f);
- cdb[2] = (unsigned char) ((firstblock >> 8) & 0xff);
- cdb[3] = (unsigned char) firstblock & 0xff;
- cdb[4] = (unsigned char) nsect;
- cdb[5] = 0;
- }
-
- if(This->privileged)
- reclaim_privs();
-
- r=scsi_cmd(This->fd, (unsigned char *)cdb, clen, rwcmd, buf,
- nsect*This->scsi_sector_size, This->extra_data);
-
- if(This->privileged)
- drop_privs();
-
- if(r) {
- perror(rwcmd == SCSI_IO_READ ? "SCMD_READ" : "SCMD_WRITE");
- return -1;
- }
-#ifdef JPD
- printf("finished %u for %u\n", firstblock, nsect);
-#endif
-
-#ifdef JPD
- printf("zip: read or write OK\n");
-#endif
- if (offset>0) memmove(buf,buf+offset,nsect*This->scsi_sector_size-offset);
- if (len==256) return 256;
- else if (len==512) return 512;
- else return nsect*This->scsi_sector_size-offset;
-}
-
-static int scsi_read(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
-{
-
-#ifdef JPD
- printf("zip: to read %d bytes at %d\n", len, where);
-#endif
- return scsi_io(Stream, buf, where, len, SCSI_IO_READ);
-}
-
-static int scsi_write(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
-{
-#ifdef JPD
- Printf("zip: to write %d bytes at %d\n", len, where);
-#endif
- return scsi_io(Stream, buf, where, len, SCSI_IO_WRITE);
-}
-
-static Class_t ScsiClass = {
- scsi_read,
- scsi_write,
- file_flush,
- file_free,
- file_geom,
- file_data,
- 0, /* pre-allocate */
- 0, /* dos-convert */
- file_discard
-};
-
-
static Class_t SimpleFileClass = {
- file_read,
+ file_read,
file_write,
+ file_pread,
+ file_pwrite,
file_flush,
file_free,
file_geom,
@@ -482,9 +242,53 @@ static Class_t SimpleFileClass = {
};
+int LockDevice(int fd, struct device *dev,
+ int locked, int lockMode,
+ char *errmsg)
+{
+#ifndef __EMX__
+#ifndef __CYGWIN__
+#ifndef OS_mingw32msvc
+ /* lock the device on writes */
+ if (locked && lock_dev(fd, (lockMode&O_ACCMODE) == O_RDWR, dev)) {
+ if(errmsg)
+#ifdef HAVE_SNPRINTF
+ snprintf(errmsg,199,
+ "plain floppy: device \"%s\" busy (%s):",
+ dev ? dev->name : "unknown", strerror(errno));
+#else
+ sprintf(errmsg,
+ "plain floppy: device \"%s\" busy (%s):",
+ (dev && strlen(dev->name) < 50) ?
+ dev->name : "unknown", strerror(errno));
+#endif
+
+ if(errno != EOPNOTSUPP || (lockMode&O_ACCMODE) == O_RDWR) {
+ /* If error is "not supported", and we're only
+ * reading from the device anyways, then ignore. Some
+ * OS'es don't support locks on read-only devices, even
+ * if they are shared (read-only) locks */
+ return -1;
+ }
+ }
+#endif
+#endif
+#endif
+ return 0;
+}
+
Stream_t *SimpleFileOpen(struct device *dev, struct device *orig_dev,
- const char *name, int mode, char *errmsg,
- int mode2, int locked, mt_size_t *maxSize)
+ const char *name, int mode, char *errmsg,
+ int mode2, int locked, mt_off_t *maxSize) {
+ return SimpleFileOpenWithLm(dev, orig_dev, name, mode,
+ errmsg, mode2, locked, mode, maxSize,
+ NULL);
+}
+
+Stream_t *SimpleFileOpenWithLm(struct device *dev, struct device *orig_dev,
+ const char *name, int mode, char *errmsg,
+ int mode2, int locked, int lockMode,
+ mt_off_t *maxSize, int *geomFailure)
{
SimpleFile_t *This;
#ifdef __EMX__
@@ -492,44 +296,42 @@ HFILE FileHandle;
ULONG Action;
APIRET rc;
#endif
+ if (IS_SCSI(dev))
+ return NULL;
This = New(SimpleFile_t);
if (!This){
printOom();
return 0;
}
memset((void*)This, 0, sizeof(SimpleFile_t));
- This->scsi_sector_size = 512;
This->seekable = 1;
#ifdef OS_hpux
This->size_limited = 0;
#endif
- This->Class = &SimpleFileClass;
+ init_head(&This->head, &SimpleFileClass, NULL);
if (!name || strcmp(name,"-") == 0 ){
if (mode == O_RDONLY)
This->fd = 0;
else
This->fd = 1;
This->seekable = 0;
- This->refs = 1;
- This->Next = 0;
- This->Buffer = 0;
if (MT_FSTAT(This->fd, &This->statbuf) < 0) {
Free(This);
if(errmsg)
#ifdef HAVE_SNPRINTF
- snprintf(errmsg,199,"Can't stat -: %s",
- strerror(errno));
+ snprintf(errmsg,199,"Can't stat -: %s",
+ strerror(errno));
#else
- sprintf(errmsg,"Can't stat -: %s",
+ sprintf(errmsg,"Can't stat -: %s",
strerror(errno));
#endif
return NULL;
}
- return (Stream_t *) This;
+ return &This->head;
}
-
+
if(dev) {
if(!(mode2 & NO_PRIV))
This->privileged = IS_PRIVILEGED(dev);
@@ -568,20 +370,15 @@ APIRET rc;
} else
#endif
{
- if (IS_SCSI(dev))
- This->fd = scsi_open(name, mode, IS_NOLOCK(dev)?0444:0666,
- &This->extra_data);
- else
- This->fd = open(name, mode | O_LARGEFILE | O_BINARY,
+ This->fd = open(name, mode | O_LARGEFILE | O_BINARY,
IS_NOLOCK(dev)?0444:0666);
}
if(IS_PRIVILEGED(dev) && !(mode2 & NO_PRIV))
drop_privs();
-
+
if (This->fd < 0) {
- Free(This);
- if(errmsg)
+ if(errmsg) {
#ifdef HAVE_SNPRINTF
snprintf(errmsg, 199, "Can't open %s: %s",
name, strerror(errno));
@@ -589,7 +386,8 @@ APIRET rc;
sprintf(errmsg, "Can't open %s: %s",
name, strerror(errno));
#endif
- return NULL;
+ }
+ goto exit_1;
}
if(IS_PRIVILEGED(dev) && !(mode2 & NO_PRIV))
@@ -603,201 +401,62 @@ APIRET rc;
&& strncmp(name, "\\\\.\\", 4) != 0
#endif
) {
- Free(This);
if(errmsg) {
#ifdef HAVE_SNPRINTF
- snprintf(errmsg,199,"Can't stat %s: %s",
+ snprintf(errmsg,199,"Can't stat %s: %s",
name, strerror(errno));
#else
if(strlen(name) > 50) {
- sprintf(errmsg,"Can't stat file: %s",
+ sprintf(errmsg,"Can't stat file: %s",
strerror(errno));
} else {
- sprintf(errmsg,"Can't stat %s: %s",
+ sprintf(errmsg,"Can't stat %s: %s",
name, strerror(errno));
}
#endif
}
- return NULL;
+ goto exit_0;
}
-#ifndef __EMX__
-#ifndef __CYGWIN__
-#ifndef OS_mingw32msvc
- /* lock the device on writes */
- if (locked && lock_dev(This->fd, mode == O_RDWR, dev)) {
- if(errmsg)
-#ifdef HAVE_SNPRINTF
- snprintf(errmsg,199,
- "plain floppy: device \"%s\" busy (%s):",
- dev ? dev->name : "unknown", strerror(errno));
-#else
- sprintf(errmsg,
- "plain floppy: device \"%s\" busy (%s):",
- (dev && strlen(dev->name) < 50) ?
- dev->name : "unknown", strerror(errno));
-#endif
- if(errno != EOPNOTSUPP || mode == O_RDWR) {
- /* If error is "not supported", and we're only
- * reading from the device anyways, then ignore. Some
- * OS'es don't support locks on read-only devices, even
- * if they are shared (read-only) locks */
- close(This->fd);
- Free(This);
- return NULL;
- }
- }
-#endif
-#endif
-#endif
+ if(LockDevice(This->fd, dev, locked, lockMode, errmsg) < 0)
+ goto exit_0;
+
/* set default parameters, if needed */
- if (dev){
- if ((!IS_MFORMAT_ONLY(dev) && dev->tracks) &&
- init_geom(This->fd, dev, orig_dev, &This->statbuf)){
- close(This->fd);
- Free(This);
- if(errmsg)
+ if (dev){
+ errno=0;
+ if (((!IS_MFORMAT_ONLY(dev) && dev->tracks) ||
+ mode2 & ALWAYS_GET_GEOMETRY) &&
+ init_geom_with_reg(This->fd, dev, orig_dev,
+ &This->statbuf)){
+ if(geomFailure && (errno==EBADF || errno==EPERM)) {
+ *geomFailure=1;
+ return NULL;
+ } else if(errmsg)
sprintf(errmsg,"init: set default params");
- return NULL;
- }
- This->offset = (mt_off_t) dev->offset;
- } else
- This->offset = 0;
-
- This->refs = 1;
- This->Next = 0;
- This->Buffer = 0;
-
- if(maxSize) {
- if (IS_SCSI(dev)) {
- *maxSize = MAX_OFF_T_B(31+log_2(This->scsi_sector_size));
- } else {
- *maxSize = max_off_t_seek;
+ goto exit_0;
}
- if(This->offset > (mt_off_t) *maxSize) {
- close(This->fd);
- Free(This);
- if(errmsg)
- sprintf(errmsg,"init: Big disks not supported");
- return NULL;
- }
-
- *maxSize -= This->offset;
- }
- /* partitioned drive */
-
- /* jpd@usl.edu: assume a partitioned drive on these 2 systems is a ZIP*/
- /* or similar drive that must be accessed by low-level scsi commands */
- /* AK: introduce new "scsi=1" statement to specifically set
- * this option. Indeed, there could conceivably be partitioned
- * devices where low level scsi commands will not be needed */
- if(IS_SCSI(dev)) {
- This->Class = &ScsiClass;
- if(This->privileged)
- reclaim_privs();
- scsi_init(This);
- if(This->privileged)
- drop_privs();
}
- This->swap = DO_SWAP( dev );
-
- if(!(mode2 & NO_OFFSET) &&
- dev && (dev->partition > 4))
- fprintf(stderr,
- "Invalid partition %d (must be between 0 and 4), ignoring it\n",
- dev->partition);
-
- while(!(mode2 & NO_OFFSET) &&
- dev && dev->partition && dev->partition <= 4) {
- int has_activated;
- unsigned int last_end, j;
- unsigned char buf[2048];
- struct partition *partTable=(struct partition *)(buf+ 0x1ae);
- size_t partOff;
-
- /* read the first sector, or part of it */
- if (force_read((Stream_t *)This, (char*) buf, 0, 512) != 512)
- break;
- if( _WORD(buf+510) != 0xaa55)
- break;
-
- partOff = BEGIN(partTable[dev->partition]);
- if (maxSize) {
- if (partOff > *maxSize >> 9) {
- close(This->fd);
- Free(This);
- if(errmsg)
- sprintf(errmsg,"init: Big disks not supported");
- return NULL;
- }
- *maxSize -= (mt_off_t) partOff << 9;
- }
-
- This->offset += (mt_off_t) partOff << 9;
- if(!partTable[dev->partition].sys_ind) {
- if(errmsg)
- sprintf(errmsg,
- "init: non-existant partition");
- close(This->fd);
- Free(This);
- return NULL;
- }
-
- if(!dev->tracks) {
- dev->heads = head(partTable[dev->partition].end)+1;
- dev->sectors = sector(partTable[dev->partition].end);
- dev->tracks = cyl(partTable[dev->partition].end) -
- cyl(partTable[dev->partition].start)+1;
- }
- dev->hidden=
- dev->sectors*head(partTable[dev->partition].start) +
- sector(partTable[dev->partition].start)-1;
- if(!mtools_skip_check &&
- consistencyCheck((struct partition *)(buf+0x1ae), 0, 0,
- &has_activated, &last_end, &j, dev, 0)) {
- fprintf(stderr,
- "Warning: inconsistent partition table\n");
- fprintf(stderr,
- "Possibly unpartitioned device\n");
- fprintf(stderr,
- "\n*** Maybe try without partition=%d in "
- "device definition ***\n\n",
- dev->partition);
- fprintf(stderr,
- "If this is a PCMCIA card, or a disk "
- "partitioned on another computer, this "
- "message may be in error: add "
- "mtools_skip_check=1 to your .mtoolsrc "
- "file to suppress this warning\n");
-
- }
- break;
- /* NOTREACHED */
- }
+ if(maxSize)
+ *maxSize = max_off_t_seek;
- This->lastwhere = -This->offset;
- /* provoke a seek on those devices that don't start on a partition
- * boundary */
+ This->lastwhere = 0;
- return (Stream_t *) This;
+ return &This->head;
+ exit_0:
+ close(This->fd);
+ exit_1:
+ Free(This);
+ return NULL;
}
int get_fd(Stream_t *Stream)
{
Class_t *clazz;
DeclareThis(SimpleFile_t);
- clazz = This->Class;
- if(clazz != &ScsiClass &&
- clazz != &SimpleFileClass)
+ clazz = This->head.Class;
+ if(clazz != &SimpleFileClass)
return -1;
else
return This->fd;
}
-
-void *get_extra_data(Stream_t *Stream)
-{
- DeclareThis(SimpleFile_t);
-
- return This->extra_data;
-}
diff --git a/plain_io.h b/plain_io.h
index 5abb90c..ab4f3f2 100644
--- a/plain_io.h
+++ b/plain_io.h
@@ -24,15 +24,20 @@
#include <io.h>
#endif
-/* plain io */
-#define NO_PRIV 1
-#define NO_OFFSET 2
Stream_t *SimpleFileOpen(struct device *dev, struct device *orig_dev,
const char *name, int mode, char *errmsg, int mode2,
- int locked, mt_size_t *maxSize);
+ int locked, mt_off_t *maxSize);
+Stream_t *SimpleFileOpenWithLm(struct device *dev, struct device *orig_dev,
+ const char *name, int mode, char *errmsg,
+ int mode2, int locked, int lockMode,
+ mt_off_t *maxSize, int *geomFailure);
int check_parameters(struct device *ref, struct device *testee);
int get_fd(Stream_t *Stream);
void *get_extra_data(Stream_t *Stream);
+
+int LockDevice(int fd, struct device *dev,
+ int locked, int lockMode,
+ char *errmsg);
#endif
diff --git a/precmd.c b/precmd.c
index d31aa01..7660237 100644
--- a/precmd.c
+++ b/precmd.c
@@ -28,7 +28,7 @@ void precmd(struct device *dev)
if(!dev || !dev->precmd)
return;
-
+
switch((pid=fork())){
case -1:
perror("Could not fork");
@@ -42,4 +42,4 @@ void precmd(struct device *dev)
}
#endif
}
-
+
diff --git a/privileges.c b/privileges.c
index 71de4c1..b055003 100644
--- a/privileges.c
+++ b/privileges.c
@@ -200,7 +200,7 @@ void init_privs(void)
#endif
#endif
}
-
+
drop_privs();
print_privs("after init, real should be 0, effective should not ");
}
diff --git a/read_dword.h b/read_dword.h
index e7150c0..499fd1d 100644
--- a/read_dword.h
+++ b/read_dword.h
@@ -18,24 +18,40 @@
* along with Mtools. If not, see <http://www.gnu.org/licenses/>.
*/
-static Dword read_dword(int handle)
+static Dword read_dword(int handle)
{
Byte val[4];
-
+
if(read(handle, (char *)val, 4) < 4)
return (Dword) -1;
return byte2dword(val);
}
-UNUSED(static Qword read_qword(int handle) )
+UNUSED(static int32_t read_sdword(int handle))
+{
+ Byte val[4];
+
+ if(read(handle, (char *)val, 4) < 4)
+ return (int32_t) -1;
+
+ return byte2sdword(val);
+}
+
+
+struct SQwordRet { int64_t v; int err; };
+UNUSED(static struct SQwordRet read_sqword(int handle) )
{
Byte val[8];
-
- if(read(handle, (char *)val, 8) < 8)
- return -1;
+ struct SQwordRet ret;
- return byte2qword(val);
+ if(read(handle, (char *)val, 8) < 8) {
+ ret.err=-1;
+ } else {
+ ret.v = (int64_t) byte2qword(val);
+ ret.err = 0;
+ }
+ return ret;
}
#endif
diff --git a/remap.c b/remap.c
new file mode 100644
index 0000000..ab96d04
--- /dev/null
+++ b/remap.c
@@ -0,0 +1,219 @@
+/* Copyright 2021 Alain Knaff.
+ * This file is part of mtools.
+ *
+ * Mtools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Remapping shim
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "remap.h"
+
+enum map_type_t {
+ DATA,
+ ZERO,
+ SKIP,
+ POS
+};
+
+struct map {
+ mt_off_t orig;
+ mt_off_t remapped;
+ enum map_type_t type;
+};
+
+typedef struct Remap_t {
+ struct Stream_t head;
+
+ struct map *map;
+ int mapSize;
+
+ mt_off_t net_offset;
+} Remap_t;
+
+static enum map_type_t remap(Remap_t *This, mt_off_t *start, size_t *len) {
+ int i;
+ for(i=0; i < This->mapSize - 1; i++)
+ if(*start < This->map[i+1].remapped) {
+ limitSizeToOffT(len, This->map[i+1].remapped - *start);
+ break;
+ }
+ *start = *start - This->map[i].remapped + This->map[i].orig;
+ return This->map[i].type;
+}
+
+static ssize_t remap_pread(Stream_t *Stream, char *buf,
+ mt_off_t start, size_t len)
+{
+ DeclareThis(Remap_t);
+ if(remap(This, &start, &len)==DATA)
+ return PREADS(This->head.Next, buf, start, len);
+ else {
+ memset(buf, 0, len);
+ return (ssize_t) len;
+ }
+}
+
+static ssize_t remap_pwrite(Stream_t *Stream, char *buf,
+ mt_off_t start, size_t len)
+{
+ DeclareThis(Remap_t);
+ if(remap(This, &start, &len)==DATA)
+ return PWRITES(This->head.Next, buf, start, len);
+ else {
+ unsigned int i;
+ /* When writing to a "zero" sector, make sure that we
+ indeed only write zeroes back to there. Helps catch
+ putting filesystems with parameters unsuitable to
+ the particular mapping */
+ for(i=0; i<len; i++) {
+ if(buf[i]) {
+ fprintf(stderr, "Bad data written to unmapped sectors\n");
+ errno = EFAULT;
+ return -1;
+ }
+ }
+ return (ssize_t) len;
+ }
+}
+
+static int remap_free(Stream_t *Stream)
+{
+ DeclareThis(Remap_t);
+ if(This->map)
+ free(This->map);
+ return 0;
+}
+
+static Class_t RemapClass = {
+ 0,
+ 0,
+ remap_pread,
+ remap_pwrite,
+ 0, /* flush */
+ remap_free, /* free */
+ set_geom_pass_through, /* set_geom */
+ 0, /* get_data */
+ 0, /* pre-allocate */
+ get_dosConvert_pass_through, /* dos convert */
+ 0, /* discard */
+};
+
+static int process_map(Remap_t *This, const char *ptr,
+ int countOnly, char *errmsg) {
+ mt_off_t orig=0;
+ mt_off_t remapped=0;
+ int count=0;
+ int atEnd=0;
+ char *eptr;
+ while(!atEnd) {
+ mt_off_t len;
+ enum map_type_t type;
+ if(*ptr=='\0') {
+ type=DATA;
+ atEnd=1;
+ } else if(!strncmp(ptr, "skip", 4)) {
+ type=SKIP;
+ ptr+=4;
+ } else if(!strncmp(ptr, "zero", 4)) {
+ type=ZERO;
+ ptr+=4;
+ } else if(!strncmp(ptr, "pos", 3)) {
+ type=POS;
+ ptr+=3;
+ } else {
+ type=DATA;
+ }
+
+ len=str_to_off_with_end(ptr,&eptr);
+ ptr=eptr;
+ switch(*ptr) {
+ case '\0':
+ /* End of string */
+ break;
+ case ',':
+ /* Move on to next item */
+ ptr++;
+ break;
+ default:
+ sprintf(errmsg, "Bad number %s\n", ptr);
+ return -1;
+ }
+
+ if(type == POS) {
+ orig = len;
+ continue;
+ }
+ if(type != SKIP) {
+ if(!countOnly) {
+ struct map *m = This->map+count;
+ m->orig = orig;
+ m->remapped = remapped;
+ m->type = type;
+ }
+ remapped+=len;
+ count++;
+ }
+ if(type != ZERO) {
+ orig+=len;
+ }
+
+ }
+ This->net_offset = orig-remapped;
+ return count;
+}
+
+
+Stream_t *Remap(Stream_t *Next, struct device *dev, char *errmsg) {
+ Remap_t *This;
+ int nrItems=0;
+ const char *map = dev->data_map;
+
+ This = New(Remap_t);
+ if (!This){
+ printOom();
+ return 0;
+ }
+ memset((void*)This, 0, sizeof(Remap_t));
+ init_head(&This->head, &RemapClass, Next);
+
+ /* First count number of items */
+ nrItems=process_map(This, map, 1, errmsg);
+ if(nrItems < 0) {
+ free(This);
+ return NULL;
+ }
+
+ This->map = calloc((size_t)nrItems, sizeof(struct map));
+ if(!This->map) {
+ printOom();
+ goto exit_0;
+ }
+
+ process_map(This, map, 0, errmsg);
+
+ if(adjust_tot_sectors(dev, This->net_offset, errmsg) < 0)
+ goto exit_1;
+
+ This->mapSize=nrItems;
+ return &This->head;
+ exit_1:
+ free(This->map);
+ exit_0:
+ free(This);
+ printOom();
+ return NULL;
+}
diff --git a/subdir.c b/remap.h
index 164fc0e..e1930ed 100644
--- a/subdir.c
+++ b/remap.h
@@ -1,5 +1,7 @@
-/* Copyright 1986-1992 Emmet P. Gray.
- * Copyright 1996,1997,2001,2002,2009 Alain Knaff.
+#ifndef MTOOLS_REMAP_H
+#define MTOOLS_REMAP_H
+
+/* Copyright 2021 Alain Knaff.
* This file is part of mtools.
*
* Mtools is free software: you can redistribute it and/or modify
@@ -16,29 +18,8 @@
* along with Mtools. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "sysincludes.h"
-#include "msdos.h"
-#include "mtools.h"
-#include "vfat.h"
-#include "file.h"
-#include "buffer.h"
-
-/*
- * Find the directory and load a new dir_chain[]. A null directory
- * is OK. Returns a 1 on error.
- */
-
+#include "stream.h"
-void bufferize(Stream_t **Dir)
-{
- Stream_t *BDir;
+Stream_t *Remap(Stream_t *Next, struct device *dev, char *errmsg);
+#endif
- if(!*Dir)
- return;
- BDir = buf_init(*Dir, 64*16384, 512, MDIR_SIZE);
- if(!BDir){
- FREE(Dir);
- *Dir = NULL;
- } else
- *Dir = BDir;
-}
diff --git a/scsi.c b/scsi.c
index 750e0cf..114eb8c 100644
--- a/scsi.c
+++ b/scsi.c
@@ -70,7 +70,7 @@
#include <sys/scsiio.h>
#endif
-int scsi_max_length(void)
+unsigned int scsi_max_length(void)
{
#ifdef OS_linux
return 8;
@@ -99,12 +99,12 @@ int scsi_open(const char *name, int flag UNUSEDP, int mode UNUSEDP,
#endif
}
-int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
- void *data, size_t len, void *extra_data UNUSEDP)
+int scsi_cmd(int fd, unsigned char *cdb, uint8_t cmdlen, scsi_io_mode_t mode,
+ void *data, uint32_t len, void *extra_data UNUSEDP)
{
#if defined OS_hpux
struct sctl_io sctl_io;
-
+
memset(&sctl_io, 0, sizeof sctl_io); /* clear reserved fields */
memcpy(sctl_io.cdb, cdb, cmdlen); /* copy command */
sctl_io.cdb_length = cmdlen; /* command length */
@@ -116,7 +116,7 @@ int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
sctl_io.data_length = len;
sctl_io.data = data;
break;
- case SCSI_IO_WRITE:
+ case SCSI_IO_WRITE:
sctl_io.flags = 0;
sctl_io.data_length = data ? len : 0;
sctl_io.data = len ? data : 0;
@@ -129,7 +129,7 @@ int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
}
return sctl_io.cdb_status;
-
+
#elif defined OS_sunos || defined OS_solaris
struct uscsi_cmd uscsi_cmd;
memset(&uscsi_cmd, 0, sizeof uscsi_cmd);
@@ -138,7 +138,7 @@ int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
#ifdef OS_solaris
uscsi_cmd.uscsi_timeout = 20; /* msec? */
#endif /* solaris */
-
+
uscsi_cmd.uscsi_buflen = (u_int)len;
uscsi_cmd.uscsi_bufaddr = data;
@@ -158,13 +158,13 @@ int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
if(uscsi_cmd.uscsi_status) {
errno = 0;
- fprintf(stderr,"scsi status=%x\n",
+ fprintf(stderr,"scsi status=%x\n",
(unsigned short)uscsi_cmd.uscsi_status);
return -1;
}
-
+
return 0;
-
+
#elif defined OS_linux
struct sg_io_hdr my_scsi_cmd;
@@ -179,7 +179,7 @@ int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
my_scsi_cmd.dxfer_len = len;
my_scsi_cmd.dxferp = data;
my_scsi_cmd.cmdp = cdb;
- my_scsi_cmd.timeout = ~0; /* where is MAX_UINT defined??? */
+ my_scsi_cmd.timeout = ~0u; /* where is MAX_UINT defined??? */
#ifdef DEBUG
printf("CMD(%d): %02x%02x%02x%02x%02x%02x %sdevice\n",cmdlen,cdb[0],cdb[1],cdb[2],cdb[3],cdb[4],cdb[5],
@@ -191,7 +191,7 @@ int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
perror("scsi_io");
return -1;
}
-
+
return my_scsi_cmd.status & STATUS_MASK;
#elif (defined _SCO_DS) && (defined SCSIUSERCMD)
@@ -227,7 +227,7 @@ int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
case SCSI_IO_WRITE:
my_scsi_cmd.ds_flags = DSRQ_WRITE|DSRQ_SENSE;
break;
- }
+ }
my_scsi_cmd.ds_time = 10000;
my_scsi_cmd.ds_link = 0;
my_scsi_cmd.ds_synch =0;
@@ -239,11 +239,11 @@ int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
if(my_scsi_cmd.ds_status) {
errno = 0;
- fprintf(stderr,"scsi status=%x\n",
+ fprintf(stderr,"scsi status=%x\n",
(unsigned short)my_scsi_cmd.ds_status);
return -1;
}
-
+
return 0;
#elif (defined OS_freebsd) && (__FreeBSD__ >= 2)
#define MSG_SIMPLE_Q_TAG 0x20 /* O/O */
@@ -278,7 +278,7 @@ int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
96,
cmdlen,
5000);
-
+
if (cam_send_ccb(cam_dev, ccb) < 0 ||
(ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
return -1;
@@ -310,7 +310,7 @@ int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
if (sc.retsts) {
errno = EIO;
- fprintf(stderr, "SCSI command failed, retsts %d\n",
+ fprintf(stderr, "SCSI command failed, retsts %d\n",
sc.retsts);
return -1;
}
diff --git a/scsi.h b/scsi.h
index 8803989..2e06663 100644
--- a/scsi.h
+++ b/scsi.h
@@ -29,9 +29,9 @@
typedef enum { SCSI_IO_READ, SCSI_IO_WRITE } scsi_io_mode_t;
-int scsi_max_length(void);
-int scsi_cmd(int fd, unsigned char cdb[6], int clen, scsi_io_mode_t mode,
- void *data, size_t len, void *extra_data);
+unsigned int scsi_max_length(void);
+int scsi_cmd(int fd, unsigned char cdb[6], uint8_t clen, scsi_io_mode_t mode,
+ void *data, uint32_t len, void *extra_data);
int scsi_open(const char *name, int flags, int mode, void **extra_data);
#endif /* __mtools_scsi_h */
diff --git a/scsi_io.c b/scsi_io.c
new file mode 100644
index 0000000..48abdcb
--- /dev/null
+++ b/scsi_io.c
@@ -0,0 +1,350 @@
+/* Copyright 2021 Alain Knaff.
+ * This file is part of mtools.
+ *
+ * Mtools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * I/O to a SCSI device
+ *
+ * written by:
+ *
+ * Alain L. Knaff
+ * alain@knaff.lu
+ *
+ */
+
+#include "sysincludes.h"
+#include "stream.h"
+#include "mtools.h"
+#include "msdos.h"
+#include "llong.h"
+
+#include "open_image.h"
+
+#include "scsi.h"
+#include "plain_io.h"
+#include "scsi_io.h"
+
+typedef struct ScsiDevice_t {
+ struct Stream_t head;
+
+ int fd;
+ int privileged;
+
+ uint32_t scsi_sector_size;
+ mt_off_t device_size;
+ uint32_t tot_sectors;
+ void *extra_data; /* extra system dependent information for scsi.
+ On some platforms, filled in by scsi_open, and to
+ be supplied to scsi_cmd */
+} ScsiDevice_t;
+
+/* ZIP or other scsi device on Solaris or SunOS system.
+ Since Sun won't accept a non-Sun label on a scsi disk, we must
+ bypass Sun's disk interface and use low-level SCSI commands to read
+ or write the ZIP drive. We thus replace the file_read and file_write
+ routines with our own scsi_read and scsi_write routines, that use the
+ uscsi ioctl interface. By James Dugal, jpd@usl.edu, 11-96. Tested
+ under Solaris 2.5 and SunOS 4.3.1_u1 using GCC.
+
+ Note: the mtools.conf entry for a ZIP drive would look like this:
+(solaris) drive C: file="/dev/rdsk/c0t5d0s2" partition=4 FAT=16 nodelay exclusive scsi=1
+(sunos) drive C: file="/dev/rsd5c" partition=4 FAT=16 nodelay exclusive scsi=1
+
+ Note 2: Sol 2.5 wants mtools to be suid-root, to use the ioctl. SunOS is
+ happy if we just have access to the device, so making mtools sgid to a
+ group called, say, "ziprw" which has rw permission on /dev/rsd5c, is fine.
+ */
+
+static int scsi_init(ScsiDevice_t *This)
+{
+ int fd = This->fd;
+ unsigned char cdb[10],buf[8];
+
+ memset(cdb, 0, sizeof cdb);
+ memset(buf,0, sizeof(buf));
+ cdb[0]=SCSI_READ_CAPACITY;
+ if (scsi_cmd(fd, (unsigned char *)cdb,
+ sizeof(cdb), SCSI_IO_READ, buf,
+ sizeof(buf), This->extra_data)==0)
+ {
+ This->tot_sectors=
+ ((unsigned)buf[0]<<24)|
+ ((unsigned)buf[1]<<16)|
+ ((unsigned)buf[2]<<8)|
+ (unsigned)buf[3];
+ if(This->tot_sectors < UINT32_MAX)
+ This->tot_sectors++;
+
+ This->scsi_sector_size=
+ ((unsigned)buf[5]<<16)|
+ ((unsigned)buf[6]<<8)|
+ (unsigned)buf[7];
+ if (This->scsi_sector_size != 512)
+ fprintf(stderr," (scsi_sector_size=%d)\n",This->scsi_sector_size);
+ return 0;
+ } else
+ return -1;
+}
+
+
+/**
+ * Overflow-safe conversion of bytes to sectors
+ */
+static uint32_t bytesToSectors(size_t bytes, uint32_t sector_size) {
+ size_t sectors = bytes / sector_size;
+ if(bytes % sector_size)
+ sectors++;
+ if(sectors > UINT32_MAX)
+ return UINT32_MAX;
+ else
+ return (uint32_t) sectors;
+}
+
+static ssize_t scsi_io(Stream_t *Stream, char *buf,
+ mt_off_t where, size_t len, scsi_io_mode_t rwcmd)
+{
+ unsigned int firstblock, nsect;
+ uint8_t clen;
+ int r;
+ unsigned int max;
+ uint32_t offset;
+ unsigned char cdb[10];
+ DeclareThis(ScsiDevice_t);
+
+ firstblock=truncMtOffTo32u(where/(mt_off_t)This->scsi_sector_size);
+ /* 512,1024,2048,... bytes/sector supported */
+ offset=(smt_off_t) where % This->scsi_sector_size;
+ nsect=bytesToSectors(offset+len, This->scsi_sector_size);
+#if defined(OS_sun) && defined(OS_i386)
+ if (This->scsi_sector_size>512)
+ firstblock*=This->scsi_sector_size/512; /* work around a uscsi bug */
+#endif /* sun && i386 */
+
+ if (len>512) {
+ /* avoid buffer overruns. The transfer MUST be smaller or
+ * equal to the requested size! */
+ while (nsect*This->scsi_sector_size>len)
+ --nsect;
+ if(!nsect) {
+ fprintf(stderr,"Scsi buffer too small\n");
+ exit(1);
+ }
+ if(rwcmd == SCSI_IO_WRITE && offset) {
+ /* there seems to be no memmove before a write */
+ fprintf(stderr,"Unaligned write\n");
+ exit(1);
+ }
+ /* a better implementation should use bounce buffers.
+ * However, in normal operation no buffer overruns or
+ * unaligned writes should happen anyways, as the logical
+ * sector size is (hopefully!) equal to the physical one
+ */
+ }
+
+
+ max = scsi_max_length();
+
+ if (nsect > max)
+ nsect=max;
+
+ /* set up SCSI READ/WRITE command */
+ memset(cdb, 0, sizeof cdb);
+
+ switch(rwcmd) {
+ case SCSI_IO_READ:
+ cdb[0] = SCSI_READ;
+ break;
+ case SCSI_IO_WRITE:
+ cdb[0] = SCSI_WRITE;
+ break;
+ }
+
+ cdb[1] = 0;
+
+ if (firstblock > 0x1fffff || nsect > 0xff) {
+ /* I suspect that the ZIP drive also understands Group 1
+ * commands. If that is indeed true, we may chose Group 1
+ * more aggressively in the future */
+
+ cdb[0] |= SCSI_GROUP1;
+ clen=10; /* SCSI Group 1 cmd */
+
+ /* this is one of the rare case where explicit coding is
+ * more portable than macros... The meaning of scsi command
+ * bytes is standardised, whereas the preprocessor macros
+ * handling it might be not... */
+
+ cdb[2] = (unsigned char) (firstblock >> 24) & 0xff;
+ cdb[3] = (unsigned char) (firstblock >> 16) & 0xff;
+ cdb[4] = (unsigned char) (firstblock >> 8) & 0xff;
+ cdb[5] = (unsigned char) firstblock & 0xff;
+ cdb[6] = 0;
+ cdb[7] = (unsigned char) (nsect >> 8) & 0xff;
+ cdb[8] = (unsigned char) nsect & 0xff;
+ cdb[9] = 0;
+ } else {
+ clen = 6; /* SCSI Group 0 cmd */
+ cdb[1] |= (unsigned char) ((firstblock >> 16) & 0x1f);
+ cdb[2] = (unsigned char) ((firstblock >> 8) & 0xff);
+ cdb[3] = (unsigned char) firstblock & 0xff;
+ cdb[4] = (unsigned char) nsect;
+ cdb[5] = 0;
+ }
+
+ if(This->privileged)
+ reclaim_privs();
+
+ r=scsi_cmd(This->fd, (unsigned char *)cdb, clen, rwcmd, buf,
+ nsect*This->scsi_sector_size, This->extra_data);
+
+ if(This->privileged)
+ drop_privs();
+
+ if(r) {
+ perror(rwcmd == SCSI_IO_READ ? "SCMD_READ" : "SCMD_WRITE");
+ return -1;
+ }
+#ifdef JPD
+ printf("finished %u for %u\n", firstblock, nsect);
+#endif
+
+#ifdef JPD
+ printf("zip: read or write OK\n");
+#endif
+ if (offset>0)
+ memmove(buf,buf+offset, nsect*This->scsi_sector_size-offset);
+ if (len==256) return 256;
+ else if (len==512) return 512;
+ else return (ssize_t)(nsect*This->scsi_sector_size-offset);
+}
+
+static ssize_t scsi_pread(Stream_t *Stream, char *buf,
+ mt_off_t where, size_t len)
+{
+#ifdef JPD
+ printf("zip: to read %d bytes at %d\n", len, where);
+#endif
+ return scsi_io(Stream, buf, where, len, SCSI_IO_READ);
+}
+
+static ssize_t scsi_pwrite(Stream_t *Stream, char *buf,
+ mt_off_t where, size_t len)
+{
+#ifdef JPD
+ Printf("zip: to write %d bytes at %d\n", len, where);
+#endif
+ return scsi_io(Stream, buf, where, len, SCSI_IO_WRITE);
+}
+
+static int scsi_get_data(Stream_t *Stream, time_t *date, mt_off_t *size,
+ int *type, uint32_t *address)
+{
+ DeclareThis(ScsiDevice_t);
+
+ if(date || type || address)
+ fprintf(stderr, "Get_data call not supported\n");
+ if(size)
+ *size = This->device_size;
+ return 0;
+}
+
+
+
+static Class_t ScsiDeviceClass = {
+ 0,
+ 0,
+ scsi_pread,
+ scsi_pwrite,
+ 0,
+ 0,
+ set_geom_noop,
+ scsi_get_data, /* get_data */
+ 0, /* pre-allocate */
+ 0, /* dos-convert */
+ 0 /* discard */
+};
+
+Stream_t *OpenScsi(struct device *dev,
+ const char *name, int mode, char *errmsg,
+ int mode2, int locked, int lockMode,
+ mt_off_t *maxSize)
+{
+ int ret;
+ ScsiDevice_t *This;
+ if (!IS_SCSI(dev))
+ return NULL;
+
+ This = New(ScsiDevice_t);
+ if (!This){
+ printOom();
+ return 0;
+ }
+ memset((void*)This, 0, sizeof(ScsiDevice_t));
+ init_head(&This->head, &ScsiDeviceClass, NULL);
+ This->scsi_sector_size = 512;
+
+ if(dev) {
+ if(!(mode2 & NO_PRIV))
+ This->privileged = IS_PRIVILEGED(dev);
+ mode |= dev->mode;
+ }
+
+ precmd(dev);
+ if(IS_PRIVILEGED(dev) && !(mode2 & NO_PRIV))
+ reclaim_privs();
+
+ /* End of stuff copied from top of plain_io.c before actual open */
+
+ This->fd = scsi_open(name, mode, IS_NOLOCK(dev)?0444:0666,
+ &This->extra_data);
+
+ if(IS_PRIVILEGED(dev) && !(mode2 & NO_PRIV))
+ drop_privs();
+
+ if (This->fd < 0) {
+ if(errmsg) {
+#ifdef HAVE_SNPRINTF
+ snprintf(errmsg, 199, "Can't open %s: %s",
+ name, strerror(errno));
+#else
+ sprintf(errmsg, "Can't open %s: %s",
+ name, strerror(errno));
+#endif
+ }
+ goto exit_1;
+ }
+
+ if(IS_PRIVILEGED(dev) && !(mode2 & NO_PRIV))
+ closeExec(This->fd);
+
+ if(LockDevice(This->fd, dev, locked, lockMode, errmsg) < 0)
+ goto exit_0;
+
+ if(maxSize)
+ *maxSize = MAX_OFF_T_B(31+log_2(This->scsi_sector_size));
+ if(This->privileged)
+ reclaim_privs();
+ ret=scsi_init(This);
+ if(This->privileged)
+ drop_privs();
+ if(ret < 0)
+ goto exit_0;
+ dev->tot_sectors = This->tot_sectors;
+ return &This->head;
+ exit_0:
+ close(This->fd);
+ exit_1:
+ Free(This);
+ return NULL;
+}
diff --git a/scsi_io.h b/scsi_io.h
new file mode 100644
index 0000000..8906815
--- /dev/null
+++ b/scsi_io.h
@@ -0,0 +1,5 @@
+Stream_t *OpenScsi(struct device *dev,
+ const char *name, int mode, char *errmsg,
+ int mode2, int locked, int lockMode,
+ mt_off_t *maxSize);
+
diff --git a/signal.c b/signal.c
index 46880a9..175876a 100644
--- a/signal.c
+++ b/signal.c
@@ -64,7 +64,7 @@ static void _allow_interrupt(saved_sig_state *ss, int sig, int slot)
{
struct sigaction new;
- bzero(&new, sizeof(new));
+ memset(&new, 0, sizeof(new));
new.sa_handler = signal_handler;
new.sa_flags &= ~SA_RESTART;
diff --git a/stream.c b/stream.c
index 2055f12..97a1351 100644
--- a/stream.c
+++ b/stream.c
@@ -21,6 +21,23 @@
int batchmode = 0;
+void limitSizeToOffT(size_t *len, mt_off_t maxLen)
+{
+#if SIZEOF_SIZE_T >= SIZEOF_MT_OFF_T
+ if(*len > (size_t) maxLen)
+#else
+ if(*len > maxLen)
+#endif
+ *len = (size_t) maxLen;
+}
+
+void init_head(Stream_t *Stream, struct Class_t *Class, Stream_t *Next)
+{
+ Stream->Class = Class;
+ Stream->refs = 1;
+ Stream->Next = Next;
+}
+
int flush_stream(Stream_t *Stream)
{
int ret=0;
@@ -54,8 +71,7 @@ int free_stream(Stream_t **Stream)
if((*Stream)->Next)
ret |= free_stream(&(*Stream)->Next);
Free(*Stream);
- } else if ( (*Stream)->Next )
- ret |= flush_stream((*Stream)->Next);
+ }
*Stream = NULL;
return ret;
}
@@ -64,24 +80,57 @@ int free_stream(Stream_t **Stream)
#define GET_DATA(stream, date, size, type, address) \
(stream)->Class->get_data( (stream), (date), (size), (type), (address) )
+int set_geom_pass_through(Stream_t *Stream, device_t *dev, device_t *orig_dev)
+{
+ return SET_GEOM(Stream->Next, dev, orig_dev);
+}
-int get_data_pass_through(Stream_t *Stream, time_t *date, mt_size_t *size,
- int *type, int *address)
+int set_geom_noop(Stream_t *Stream UNUSEDP,
+ device_t *dev UNUSEDP,
+ device_t *orig_dev UNUSEDP)
+{
+ return 0;
+}
+
+int get_data_pass_through(Stream_t *Stream, time_t *date, mt_off_t *size,
+ int *type, uint32_t *address)
{
return GET_DATA(Stream->Next, date, size, type, address);
}
-int read_pass_through(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+ssize_t pread_pass_through(Stream_t *Stream, char *buf,
+ mt_off_t start, size_t len)
{
- return READS(Stream->Next, buf, start, len);
+ return PREADS(Stream->Next, buf, start, len);
}
-int write_pass_through(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+ssize_t pwrite_pass_through(Stream_t *Stream, char *buf,
+ mt_off_t start, size_t len)
{
- return WRITES(Stream->Next, buf, start, len);
+ return PWRITES(Stream->Next, buf, start, len);
}
doscp_t *get_dosConvert_pass_through(Stream_t *Stream)
{
return GET_DOSCONVERT(Stream->Next);
}
+
+/*
+ * Adjust number of total sectors by given offset in bytes
+ */
+int adjust_tot_sectors(struct device *dev, mt_off_t offset, char *errmsg)
+{
+ if(!dev->tot_sectors)
+ /* tot_sectors not set, do nothing */
+ return 0;
+
+ mt_off_t offs_sectors = offset /
+ (dev->sector_size ? dev->sector_size : 512);
+ if(offs_sectors > 0 && dev->tot_sectors < (smt_off_t) offs_sectors) {
+ if(errmsg)
+ sprintf(errmsg,"init: Offset bigger than base image");
+ return -1;
+ }
+ dev->tot_sectors -= (uint32_t) offs_sectors;
+ return 0;
+}
diff --git a/stream.h b/stream.h
index f027ece..66dd0ed 100644
--- a/stream.h
+++ b/stream.h
@@ -22,39 +22,47 @@ typedef struct Stream_t {
struct Class_t *Class;
int refs;
struct Stream_t *Next;
- struct Stream_t *Buffer;
} Stream_t;
#include "mtools.h"
#include "msdos.h"
-
+#include "device.h"
#include "llong.h"
+void limitSizeToOffT(size_t *len, mt_off_t maxLen);
+
doscp_t *get_dosConvert_pass_through(Stream_t *Stream);
typedef struct Class_t {
- int (*read)(Stream_t *, char *, mt_off_t, size_t);
- int (*write)(Stream_t *, char *, mt_off_t, size_t);
+ ssize_t (*read)(Stream_t *, char *, size_t);
+ ssize_t (*write)(Stream_t *, char *, size_t);
+ ssize_t (*pread)(Stream_t *, char *, mt_off_t, size_t);
+ ssize_t (*pwrite)(Stream_t *, char *, mt_off_t, size_t);
int (*flush)(Stream_t *);
int (*freeFunc)(Stream_t *);
- int (*set_geom)(Stream_t *, device_t *, device_t *, int media,
- union bootsector *);
- int (*get_data)(Stream_t *, time_t *, mt_size_t *, int *, int *);
- int (*pre_allocate)(Stream_t *, mt_size_t);
+ int (*set_geom)(Stream_t *, device_t *, device_t *);
+ int (*get_data)(Stream_t *, time_t *, mt_off_t *, int *, uint32_t *);
+ int (*pre_allocate)(Stream_t *, mt_off_t);
doscp_t *(*get_dosConvert)(Stream_t *);
int (*discard)(Stream_t *);
} Class_t;
-#define READS(stream, buf, address, size) \
-((stream)->Class->read)( (stream), (char *) (buf), (address), (size) )
+#define READS(stream, buf, size) \
+((stream)->Class->read)( (stream), (char *) (buf), (size) )
+
+#define WRITES(stream, buf, size) \
+((stream)->Class->write)( (stream), (char *) (buf), (size) )
+
+#define PREADS(stream, buf, address, size) \
+((stream)->Class->pread)( (stream), (char *) (buf), (address), (size) )
-#define WRITES(stream, buf, address, size) \
-((stream)->Class->write)( (stream), (char *) (buf), (address), (size) )
+#define PWRITES(stream, buf, address, size) \
+((stream)->Class->pwrite)( (stream), (char *) (buf), (address), (size) )
-#define SET_GEOM(stream, dev, orig_dev, media, boot) \
-(stream)->Class->set_geom( (stream), (dev), (orig_dev), (media), (boot) )
+#define SET_GEOM(stream, dev, orig_dev) \
+(stream)->Class->set_geom( (stream), (dev), (orig_dev))
#define GET_DATA(stream, date, size, type, address) \
(stream)->Class->get_data( (stream), (date), (size), (type), (address) )
@@ -84,24 +92,34 @@ copy_stream( (stream) )
#define DeclareThis(x) x *This = (x *) Stream
-int force_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len);
-int force_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len);
+void init_head(Stream_t *Stream, struct Class_t *Class, Stream_t *Next);
-int get_data_pass_through(Stream_t *Stream, time_t *date, mt_size_t *size,
- int *type, int *address);
+ssize_t force_pwrite(Stream_t *Stream, char *buf, mt_off_t start, size_t len);
+ssize_t force_pread(Stream_t *Stream, char *buf, mt_off_t start, size_t len);
-int read_pass_through(Stream_t *Stream, char *buf, mt_off_t start, size_t len);
-int write_pass_through(Stream_t *Stream, char *buf, mt_off_t start, size_t len);
+ssize_t force_write(Stream_t *Stream, char *buf, size_t len);
-mt_off_t sectorsToBytes(Stream_t *This, off_t off);
+int set_geom_pass_through(Stream_t *Stream, device_t *dev, device_t *orig_dev);
-mt_size_t getfree(Stream_t *Stream);
-int getfreeMinBytes(Stream_t *Stream, mt_size_t ref);
+int set_geom_noop(Stream_t *Stream, device_t *dev, device_t *orig_dev);
+
+int get_data_pass_through(Stream_t *Stream, time_t *date, mt_off_t *size,
+ int *type, uint32_t *address);
+
+ssize_t pread_pass_through(Stream_t *Stream, char *buf,
+ mt_off_t start, size_t len);
+ssize_t pwrite_pass_through(Stream_t *Stream, char *buf,
+ mt_off_t start, size_t len);
+
+mt_off_t getfree(Stream_t *Stream);
+int getfreeMinBytes(Stream_t *Stream, mt_off_t ref);
Stream_t *find_device(char drive, int mode, struct device *out_dev,
union bootsector *boot,
- char *name, int *media, mt_size_t *maxSize,
+ char *name, int *media, mt_off_t *maxSize,
int *isRop);
+int adjust_tot_sectors(struct device *dev, mt_off_t offset, char *errmsg);
+
#endif
diff --git a/streamcache.c b/streamcache.c
index 4277ef0..be50248 100644
--- a/streamcache.c
+++ b/streamcache.c
@@ -54,17 +54,17 @@ static void init_streamcache(void)
atexit(finish_sc);
}
-Stream_t *open_root_dir(unsigned char drive, int flags, int *isRop)
+Stream_t *open_root_dir(char drive, int flags, int *isRop)
{
Stream_t *Fs;
init_streamcache();
- drive = toupper(drive);
-
+ drive = (char)toupper(drive);
+
/* open the drive */
- if(fss[drive])
- Fs = fss[drive];
+ if(fss[(unsigned char)drive])
+ Fs = fss[(unsigned char)drive];
else {
Fs = fs_init(drive, flags, isRop);
if (!Fs){
@@ -72,7 +72,7 @@ Stream_t *open_root_dir(unsigned char drive, int flags, int *isRop)
return NULL;
}
- fss[drive] = Fs;
+ fss[(unsigned char)drive] = Fs;
}
return OpenRoot(Fs);
diff --git a/strtonum.c b/strtonum.c
index d6324dc..defa18d 100644
--- a/strtonum.c
+++ b/strtonum.c
@@ -32,8 +32,8 @@ static long strtol_with_range(const char *nptr, char **endptr, int base,
return l;
}
-static long strtoul_with_range(const char *nptr, char **endptr, int base,
- unsigned long max) {
+static unsigned long strtoul_with_range(const char *nptr, char **endptr,
+ int base, unsigned long max) {
unsigned long l = strtoul(nptr, endptr, base);
if(l > max) {
errno = ERANGE;
@@ -85,3 +85,46 @@ uint32_t strtou32(const char *nptr, char **endptr, int base) {
uint32_t atou32(const char *str) {
return strtou32(str, 0, 0);
}
+
+static void checkOverflow(uint32_t tot_sectors, int bits) {
+ if(tot_sectors > UINT32_MAX >> bits) {
+ fprintf(stderr, "Too many sectors\n");
+ exit(1);
+ }
+}
+
+uint32_t parseSize(char *sizeStr) {
+ char *eptr;
+ uint32_t tot_sectors = strtou32(sizeStr, &eptr, 10);
+ if(eptr == sizeStr) {
+ fprintf(stderr, "Bad size %s\n", sizeStr);
+ exit(1);
+ }
+ switch(toupper(*eptr)) {
+ case 'T':
+ checkOverflow(tot_sectors, 10);
+ tot_sectors *= 1024;
+ /* FALL THROUGH */
+ case 'G':
+ checkOverflow(tot_sectors, 10);
+ tot_sectors *= 1024;
+ /* FALL THROUGH */
+ case 'M':
+ checkOverflow(tot_sectors, 10);
+ tot_sectors *= 1024;
+ /* FALL THROUGH */
+ case 'K':
+ checkOverflow(tot_sectors, 1);
+ tot_sectors *= 2;
+ eptr++;
+ break;
+ case '\0':
+ /* By default, assume sectors */
+ break;
+ }
+ if(*eptr) {
+ fprintf(stderr, "Bad suffix %s\n", eptr);
+ exit(1);
+ }
+ return tot_sectors;
+}
diff --git a/swap.c b/swap.c
new file mode 100644
index 0000000..28aad1b
--- /dev/null
+++ b/swap.c
@@ -0,0 +1,95 @@
+/* Copyright 2021 Alain Knaff.
+ * This file is part of mtools.
+ *
+ * Mtools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * filter to support byte-swapped filesystems
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "swap.h"
+
+typedef struct Swap_t {
+ struct Stream_t head;
+} Swap_t;
+
+static void swap_buffer(char *buf, size_t len)
+{
+ unsigned int i;
+ for (i=0; i<len; i+=2) {
+ char temp = buf[i];
+ buf[i] = buf[i+1];
+ buf[i+1] = temp;
+ }
+}
+
+
+static ssize_t swap_pread(Stream_t *Stream, char *buf,
+ mt_off_t where, size_t len)
+{
+ DeclareThis(Swap_t);
+
+ ssize_t result = PREADS(This->head.Next, buf, where, len);
+ if(result < 0)
+ return result;
+ swap_buffer( buf, (size_t) result);
+ return result;
+}
+
+static ssize_t swap_pwrite(Stream_t *Stream, char *buf,
+ mt_off_t where, size_t len)
+{
+ DeclareThis(Swap_t);
+
+ ssize_t result;
+ char *swapping = malloc( len );
+ memcpy( swapping, buf, len );
+ swap_buffer( swapping, len );
+
+ result = PWRITES(This->head.Next, swapping, where, len);
+
+ free(swapping);
+ return result;
+}
+
+
+static Class_t SwapClass = {
+ 0,
+ 0,
+ swap_pread,
+ swap_pwrite,
+ 0, /* flush */
+ 0, /* free */
+ set_geom_pass_through, /* set_geom */
+ 0, /* get_data */
+ 0, /* pre-allocate */
+ get_dosConvert_pass_through, /* dos convert */
+ 0, /* discard */
+};
+
+Stream_t *OpenSwap(Stream_t *Next) {
+ Swap_t *This;
+
+ This = New(Swap_t);
+ if (!This){
+ printOom();
+ return 0;
+ }
+ memset((void*)This, 0, sizeof(Swap_t));
+ init_head(&This->head, &SwapClass, Next);
+
+ return &This->head;
+}
diff --git a/swap.h b/swap.h
new file mode 100644
index 0000000..7bf02da
--- /dev/null
+++ b/swap.h
@@ -0,0 +1,2 @@
+Stream_t *OpenSwap(Stream_t *Next);
+
diff --git a/sysincludes.h b/sysincludes.h
index 0bfc818..6dccded 100644
--- a/sysincludes.h
+++ b/sysincludes.h
@@ -20,7 +20,6 @@
#ifndef SYSINCLUDES_H
#define SYSINCLUDES_H
-#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include "config.h"
@@ -53,10 +52,10 @@
#endif
-/* On AIX, we have to prefer strings.h, as string.h lacks a prototype
- * for strcasecmp. On most other architectures, it's string.h which seems
- * to be more complete */
-#if (defined OS_aix && defined HAVE_STRINGS_H)
+/* On AIX, we have to prefer strings.h, as string.h lacks a prototype
+ * for strcasecmp. On Solaris, string.h lacks a prototype for strncasecmp_l.
+ * On most other architectures, it's string.h which seems to be more complete */
+#if ((defined OS_aix || defined OS_solaris) && defined HAVE_STRINGS_H)
# undef HAVE_STRING_H
#endif
@@ -135,9 +134,9 @@ typedef void *caddr_t;
/* */
/***********************************************************************/
-#define _LARGEFILE64_SOURCE
-#define _GNU_SOURCE
-
+#ifdef HAVE_ASSERT_H
+# include <assert.h>
+#endif
#ifdef HAVE_FEATURES_H
# include <features.h>
@@ -150,6 +149,26 @@ typedef void *caddr_t;
# include <stdint.h>
#endif
+#ifdef HAVE_STDARG_H
+# include <stdarg.h>
+#endif
+
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# if ! HAVE__BOOL
+# ifdef __cplusplus
+typedef bool _Bool;
+# else
+typedef unsigned char _Bool;
+# endif
+# endif
+# define bool _Bool
+# define false 0
+# define true 1
+# define __bool_true_false_are_defined 1
+#endif
+
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
@@ -464,7 +483,7 @@ char *strerror(int errno);
#endif
#ifndef HAVE_ATEXIT
-int atexit(void (*function)(void));
+int atexit(void (*function)(void));
#ifndef HAVE_ON_EXIT
void myexit(int code) NORETURN;
@@ -519,7 +538,7 @@ void _stripexe(char *filename);
#ifndef __STDC__
# ifndef signed
# define signed /**/
-# endif
+# endif
#endif /* !__STDC__ */
diff --git a/texinfo.tex b/texinfo.tex
index 3c7051d..58b6abe 100644
--- a/texinfo.tex
+++ b/texinfo.tex
@@ -3,9 +3,9 @@
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
-\def\texinfoversion{2020-10-24.12}
+\def\texinfoversion{2022-01-02.12}
%
-% Copyright 1985, 1986, 1988, 1990-2020 Free Software Foundation, Inc.
+% Copyright 1985, 1986, 1988, 1990-2021 Free Software Foundation, Inc.
%
% This texinfo.tex file is free software: you can redistribute it and/or
% modify it under the terms of the GNU General Public License as
@@ -572,9 +572,8 @@
\fi
}
-% @end foo executes the definition of \Efoo.
-% But first, it executes a specialized version of \checkenv
-%
+
+% @end foo calls \checkenv and executes the definition of \Efoo.
\parseargdef\end{%
\if 1\csname iscond.#1\endcsname
\else
@@ -1003,6 +1002,14 @@ where each line of input produces a line of output.}
\global\everypar = {}%
}
+% leave vertical mode without cancelling any first paragraph indent
+\gdef\imageindent{%
+ \toks0=\everypar
+ \everypar={}%
+ \ptexnoindent
+ \global\everypar=\toks0
+}
+
% @refill is a no-op.
\let\refill=\relax
@@ -1863,19 +1870,23 @@ output) for that.)}
\closein 1
\endgroup
%
- \def\xetexpdfext{pdf}%
- \ifx\xeteximgext\xetexpdfext
- \XeTeXpdffile "#1".\xeteximgext ""
- \else
- \def\xetexpdfext{PDF}%
+ % Putting an \hbox around the image can prevent an over-long line
+ % after the image.
+ \hbox\bgroup
+ \def\xetexpdfext{pdf}%
\ifx\xeteximgext\xetexpdfext
\XeTeXpdffile "#1".\xeteximgext ""
\else
- \XeTeXpicfile "#1".\xeteximgext ""
+ \def\xetexpdfext{PDF}%
+ \ifx\xeteximgext\xetexpdfext
+ \XeTeXpdffile "#1".\xeteximgext ""
+ \else
+ \XeTeXpicfile "#1".\xeteximgext ""
+ \fi
\fi
- \fi
- \ifdim \wd0 >0pt width \xeteximagewidth \fi
- \ifdim \wd2 >0pt height \xeteximageheight \fi \relax
+ \ifdim \wd0 >0pt width \xeteximagewidth \fi
+ \ifdim \wd2 >0pt height \xeteximageheight \fi \relax
+ \egroup
}
\fi
@@ -2673,8 +2684,6 @@ end
\definetextfontsizexi
-\message{markup,}
-
% Check if we are currently using a typewriter font. Since all the
% Computer Modern typewriter fonts have zero interword stretch (and
% shrink), and it is reasonable to expect all typewriter fonts to have
@@ -2682,68 +2691,14 @@ end
%
\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
-% Markup style infrastructure. \defmarkupstylesetup\INITMACRO will
-% define and register \INITMACRO to be called on markup style changes.
-% \INITMACRO can check \currentmarkupstyle for the innermost
-% style.
-
-\let\currentmarkupstyle\empty
-
-\def\setupmarkupstyle#1{%
- \def\currentmarkupstyle{#1}%
- \markupstylesetup
-}
-
-\let\markupstylesetup\empty
-
-\def\defmarkupstylesetup#1{%
- \expandafter\def\expandafter\markupstylesetup
- \expandafter{\markupstylesetup #1}%
- \def#1%
-}
-
-% Markup style setup for left and right quotes.
-\defmarkupstylesetup\markupsetuplq{%
- \expandafter\let\expandafter \temp
- \csname markupsetuplq\currentmarkupstyle\endcsname
- \ifx\temp\relax \markupsetuplqdefault \else \temp \fi
-}
-
-\defmarkupstylesetup\markupsetuprq{%
- \expandafter\let\expandafter \temp
- \csname markupsetuprq\currentmarkupstyle\endcsname
- \ifx\temp\relax \markupsetuprqdefault \else \temp \fi
-}
-
{
\catcode`\'=\active
\catcode`\`=\active
-\gdef\markupsetuplqdefault{\let`\lq}
-\gdef\markupsetuprqdefault{\let'\rq}
-
-\gdef\markupsetcodequoteleft{\let`\codequoteleft}
-\gdef\markupsetcodequoteright{\let'\codequoteright}
+\gdef\setcodequotes{\let`\codequoteleft \let'\codequoteright}
+\gdef\setregularquotes{\let`\lq \let'\rq}
}
-\let\markupsetuplqcode \markupsetcodequoteleft
-\let\markupsetuprqcode \markupsetcodequoteright
-%
-\let\markupsetuplqexample \markupsetcodequoteleft
-\let\markupsetuprqexample \markupsetcodequoteright
-%
-\let\markupsetuplqkbd \markupsetcodequoteleft
-\let\markupsetuprqkbd \markupsetcodequoteright
-%
-\let\markupsetuplqsamp \markupsetcodequoteleft
-\let\markupsetuprqsamp \markupsetcodequoteright
-%
-\let\markupsetuplqverb \markupsetcodequoteleft
-\let\markupsetuprqverb \markupsetcodequoteright
-%
-\let\markupsetuplqverbatim \markupsetcodequoteleft
-\let\markupsetuprqverbatim \markupsetcodequoteright
-
% Allow an option to not use regular directed right quote/apostrophe
% (char 0x27), but instead the undirected quote from cmtt (char 0x0d).
% The undirected quote is ugly, so don't make it the default, but it
@@ -2906,7 +2861,7 @@ end
}
% @samp.
-\def\samp#1{{\setupmarkupstyle{samp}\lq\tclose{#1}\rq\null}}
+\def\samp#1{{\setcodequotes\lq\tclose{#1}\rq\null}}
% @indicateurl is \samp, that is, with quotes.
\let\indicateurl=\samp
@@ -2949,8 +2904,7 @@ end
\global\let'=\rq \global\let`=\lq % default definitions
%
\global\def\code{\begingroup
- \setupmarkupstyle{code}%
- % The following should really be moved into \setupmarkupstyle handlers.
+ \setcodequotes
\catcode\dashChar=\active \catcode\underChar=\active
\ifallowcodebreaks
\let-\codedash
@@ -3104,7 +3058,7 @@ end
\urefcatcodes
%
\global\def\urefcode{\begingroup
- \setupmarkupstyle{code}%
+ \setcodequotes
\urefcatcodes
\let&\urefcodeamp
\let.\urefcodedot
@@ -3225,8 +3179,8 @@ end
\def\kbdsub#1#2#3\par{%
\def\one{#1}\def\three{#3}\def\threex{??}%
\ifx\one\xkey\ifx\threex\three \key{#2}%
- \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi
- \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi
+ \else{\tclose{\kbdfont\setcodequotes\look}}\fi
+ \else{\tclose{\kbdfont\setcodequotes\look}}\fi
}
% definition of @key that produces a lozenge. Doesn't adjust to text size.
@@ -3239,14 +3193,9 @@ end
% \kern-0.4pt\hrule}%
% \kern-.06em\raise0.4pt\hbox{\angleright}}}}
-% definition of @key with no lozenge. If the current font is already
-% monospace, don't change it; that way, we respect @kbdinputstyle. But
-% if it isn't monospace, then use \tt.
+% definition of @key with no lozenge.
%
-\def\key#1{{\setupmarkupstyle{key}%
- \nohyphenation
- \ifmonospace\else\tt\fi
- #1}\null}
+\def\key#1{{\setregularquotes \nohyphenation \tt #1}\null}
% @clicksequence{File @click{} Open ...}
\def\clicksequence#1{\begingroup #1\endgroup}
@@ -3373,16 +3322,20 @@ end
{\obeylines
\globaldefs=1
\envdef\displaymath{%
-\tex
+\tex%
\def\thisenv{\displaymath}%
+\begingroup\let\end\displaymathend%
$$%
}
-\def\Edisplaymath{$$
+\def\displaymathend{$$\endgroup\end}%
+
+\def\Edisplaymath{%
\def\thisenv{\tex}%
\end tex
}}
+
% @inlinefmt{FMTNAME,PROCESSED-TEXT} and @inlineraw{FMTNAME,RAW-TEXT}.
% Ignore unless FMTNAME == tex; then it is like @iftex and @tex,
% except specified as a normal braced arg, so no newlines to worry about.
@@ -3656,6 +3609,9 @@ $$%
\def\quotedblbase{{\ecfont \char"12}}
\def\quotesinglbase{{\ecfont \char"0D}}
%
+\def\L{{\ecfont \char"8A}} % L with stroke
+\def\l{{\ecfont \char"AA}} % l with stroke
+%
% This positioning is not perfect (see the ogonek LaTeX package), but
% we have the precomposed glyphs for the most common cases. We put the
% tests to use those glyphs in the single \ogonek macro so we have fewer
@@ -4343,82 +4299,8 @@ $$%
\doitemize{#1.}\flushcr
}
-% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
-% to @enumerate.
-%
-\def\alphaenumerate{\enumerate{a}}
-\def\capsenumerate{\enumerate{A}}
-\def\Ealphaenumerate{\Eenumerate}
-\def\Ecapsenumerate{\Eenumerate}
-
% @multitable macros
-% Amy Hendrickson, 8/18/94, 3/6/96
-%
-% @multitable ... @end multitable will make as many columns as desired.
-% Contents of each column will wrap at width given in preamble. Width
-% can be specified either with sample text given in a template line,
-% or in percent of \hsize, the current width of text on page.
-
-% Table can continue over pages but will only break between lines.
-
-% To make preamble:
-%
-% Either define widths of columns in terms of percent of \hsize:
-% @multitable @columnfractions .25 .3 .45
-% @item ...
-%
-% Numbers following @columnfractions are the percent of the total
-% current hsize to be used for each column. You may use as many
-% columns as desired.
-
-
-% Or use a template:
-% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
-% @item ...
-% using the widest term desired in each column.
-
-% Each new table line starts with @item, each subsequent new column
-% starts with @tab. Empty columns may be produced by supplying @tab's
-% with nothing between them for as many times as empty columns are needed,
-% ie, @tab@tab@tab will produce two empty columns.
-
-% @item, @tab do not need to be on their own lines, but it will not hurt
-% if they are.
-
-% Sample multitable:
-
-% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
-% @item first col stuff @tab second col stuff @tab third col
-% @item
-% first col stuff
-% @tab
-% second col stuff
-% @tab
-% third col
-% @item first col stuff @tab second col stuff
-% @tab Many paragraphs of text may be used in any column.
-%
-% They will wrap at the width determined by the template.
-% @item@tab@tab This will be in third column.
-% @end multitable
-
-% Default dimensions may be reset by user.
-% @multitableparskip is vertical space between paragraphs in table.
-% @multitableparindent is paragraph indent in table.
-% @multitablecolmargin is horizontal space to be left between columns.
-% @multitablelinespace is space to leave between table items, baseline
-% to baseline.
-% 0pt means it depends on current normal line spacing.
-%
-\newskip\multitableparskip
-\newskip\multitableparindent
-\newdimen\multitablecolspace
-\newskip\multitablelinespace
-\multitableparskip=0pt
-\multitableparindent=6pt
-\multitablecolspace=12pt
-\multitablelinespace=0pt
% Macros used to set up halign preamble:
%
@@ -4466,8 +4348,6 @@ $$%
\go
}
-% multitable-only commands.
-%
% @headitem starts a heading row, which we typeset in bold. Assignments
% have to be global since we are inside the implicit group of an
% alignment entry. \everycr below resets \everytab so we don't have to
@@ -4484,14 +4364,8 @@ $$%
% default for tables with no headings.
\let\headitemcrhook=\relax
%
-% A \tab used to include \hskip1sp. But then the space in a template
-% line is not enough. That is bad. So let's go back to just `&' until
-% we again encounter the problem the 1sp was intended to solve.
-% --karl, nathan@acm.org, 20apr99.
\def\tab{\checkenv\multitable &\the\everytab}%
-% @multitable ... @end multitable definitions:
-%
\newtoks\everytab % insert after every tab.
%
\envdef\multitable{%
@@ -4506,9 +4380,8 @@ $$%
%
\tolerance=9500
\hbadness=9500
- \setmultitablespacing
- \parskip=\multitableparskip
- \parindent=\multitableparindent
+ \parskip=0pt
+ \parindent=6pt
\overfullrule=0pt
\global\colcount=0
%
@@ -4538,47 +4411,24 @@ $$%
% continue for many paragraphs if desired.
\halign\bgroup &%
\global\advance\colcount by 1
- \multistrut
+ \strut
\vtop{%
- % Use the current \colcount to find the correct column width:
+ \advance\hsize by -1\leftskip
+ % Find the correct column width
\hsize=\expandafter\csname col\the\colcount\endcsname
%
- % In order to keep entries from bumping into each other
- % we will add a \leftskip of \multitablecolspace to all columns after
- % the first one.
- %
- % If a template has been used, we will add \multitablecolspace
- % to the width of each template entry.
- %
- % If the user has set preamble in terms of percent of \hsize we will
- % use that dimension as the width of the column, and the \leftskip
- % will keep entries from bumping into each other. Table will start at
- % left margin and final column will justify at right margin.
- %
- % Make sure we don't inherit \rightskip from the outer environment.
\rightskip=0pt
\ifnum\colcount=1
- % The first column will be indented with the surrounding text.
- \advance\hsize by\leftskip
+ \advance\hsize by\leftskip % Add indent of surrounding text
\else
- \ifsetpercent \else
- % If user has not set preamble in terms of percent of \hsize
- % we will advance \hsize by \multitablecolspace.
- \advance\hsize by \multitablecolspace
- \fi
- % In either case we will make \leftskip=\multitablecolspace:
- \leftskip=\multitablecolspace
+ % In order to keep entries from bumping into each other.
+ \leftskip=12pt
+ \ifsetpercent \else
+ % If a template has been used
+ \advance\hsize by \leftskip
+ \fi
\fi
- % Ignoring space at the beginning and end avoids an occasional spurious
- % blank line, when TeX decides to break the line at the space before the
- % box from the multistrut, so the strut ends up on a line by itself.
- % For example:
- % @multitable @columnfractions .11 .89
- % @item @code{#}
- % @tab Legal holiday which is valid in major parts of the whole country.
- % Is automatically provided with highlighting sequences respectively
- % marking characters.
- \noindent\ignorespaces##\unskip\multistrut
+ \noindent\ignorespaces##\unskip\strut
}\cr
}
\def\Emultitable{%
@@ -4587,31 +4437,6 @@ $$%
\global\setpercentfalse
}
-\def\setmultitablespacing{%
- \def\multistrut{\strut}% just use the standard line spacing
- %
- % Compute \multitablelinespace (if not defined by user) for use in
- % \multitableparskip calculation. We used define \multistrut based on
- % this, but (ironically) that caused the spacing to be off.
- % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100.
-\ifdim\multitablelinespace=0pt
-\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip
-\global\advance\multitablelinespace by-\ht0
-\fi
-% Test to see if parskip is larger than space between lines of
-% table. If not, do nothing.
-% If so, set to same dimension as multitablelinespace.
-\ifdim\multitableparskip>\multitablelinespace
-\global\multitableparskip=\multitablelinespace
-\global\advance\multitableparskip-7pt % to keep parskip somewhat smaller
- % than skip between lines in the table.
-\fi%
-\ifdim\multitableparskip=0pt
-\global\multitableparskip=\multitablelinespace
-\global\advance\multitableparskip-7pt % to keep parskip somewhat smaller
- % than skip between lines in the table.
-\fi}
-
\message{conditionals,}
@@ -5225,30 +5050,29 @@ $$%
\let\lbracechar\{%
\let\rbracechar\}%
%
+ % Non-English letters.
+ \def\AA{AA}%
+ \def\AE{AE}%
+ \def\DH{DZZ}%
+ \def\L{L}%
+ \def\OE{OE}%
+ \def\O{O}%
+ \def\TH{TH}%
+ \def\aa{aa}%
+ \def\ae{ae}%
+ \def\dh{dzz}%
+ \def\exclamdown{!}%
+ \def\l{l}%
+ \def\oe{oe}%
+ \def\ordf{a}%
+ \def\ordm{o}%
+ \def\o{o}%
+ \def\questiondown{?}%
+ \def\ss{ss}%
+ \def\th{th}%
%
\let\do\indexnofontsdef
%
- % Non-English letters.
- \do\AA{AA}%
- \do\AE{AE}%
- \do\DH{DZZ}%
- \do\L{L}%
- \do\OE{OE}%
- \do\O{O}%
- \do\TH{TH}%
- \do\aa{aa}%
- \do\ae{ae}%
- \do\dh{dzz}%
- \do\exclamdown{!}%
- \do\l{l}%
- \do\oe{oe}%
- \do\ordf{a}%
- \do\ordm{o}%
- \do\o{o}%
- \do\questiondown{?}%
- \do\ss{ss}%
- \do\th{th}%
- %
\do\LaTeX{LaTeX}%
\do\TeX{TeX}%
%
@@ -7144,7 +6968,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% But \@ or @@ will get a plain @ character.
\envdef\tex{%
- \setupmarkupstyle{tex}%
+ \setregularquotes
\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
\catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie
@@ -7370,7 +7194,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% If you want all examples etc. small: @set dispenvsize small.
% If you want even small examples the full size: @set dispenvsize nosmall.
% This affects the following displayed environments:
-% @example, @display, @format, @lisp
+% @example, @display, @format, @lisp, @verbatim
%
\def\smallword{small}
\def\nosmallword{nosmall}
@@ -7416,9 +7240,9 @@ might help (with 'rm \jobname.?? \jobname.??s')%
%
\maketwodispenvdef{lisp}{example}{%
\nonfillstart
- \tt\setupmarkupstyle{example}%
+ \tt\setcodequotes
\let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
- \gobble % eat return
+ \parsearg\gobble
}
% @display/@smalldisplay: same as @lisp except keep current font.
%
@@ -7576,7 +7400,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\def\setupverb{%
\tt % easiest (and conventionally used) font for verbatim
\def\par{\leavevmode\endgraf}%
- \setupmarkupstyle{verb}%
+ \setcodequotes
\tabeightspaces
% Respect line breaks,
% print special symbols as themselves, and
@@ -7617,7 +7441,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\tt % easiest (and conventionally used) font for verbatim
\def\par{\egroup\leavevmode\box\verbbox\endgraf\starttabbox}%
\tabexpand
- \setupmarkupstyle{verbatim}%
+ \setcodequotes
% Respect line breaks,
% print special symbols as themselves, and
% make each space count.
@@ -7766,6 +7590,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
%
\def\printdefunline#1#2{%
\begingroup
+ \plainfrenchspacing
% call \deffnheader:
#1#2 \endheader
% common ending:
@@ -8036,7 +7861,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% leave the code in, but it's strange for @var to lead to typewriter.
% Nowadays we recommend @code, since the difference between a ttsl hyphen
% and a tt hyphen is pretty tiny. @code also disables ?` !`.
- \def\var##1{{\setupmarkupstyle{var}\ttslanted{##1}}}%
+ \def\var##1{{\setregularquotes\ttslanted{##1}}}%
#1%
\sl\hyphenchar\font=45
}
@@ -8145,11 +7970,18 @@ might help (with 'rm \jobname.?? \jobname.??s')%
}
\fi
+\let\E=\expandafter
+
% Used at the time of macro expansion.
% Argument is macro body with arguments substituted
\def\scanmacro#1{%
\newlinechar`\^^M
- \def\xeatspaces{\eatspaces}%
+ % expand the expansion of \eatleadingcr twice to maybe remove a leading
+ % newline (and \else and \fi tokens), then call \eatspaces on the result.
+ \def\xeatspaces##1{%
+ \E\E\E\E\E\E\E\eatspaces\E\E\E\E\E\E\E{\eatleadingcr##1%
+ }}%
+ \def\xempty##1{}%
%
% Process the macro body under the current catcode regime.
\scantokens{#1@comment}%
@@ -8202,6 +8034,11 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\unbrace{\gdef\trim@@@ #1 } #2@{#1}
}
+{\catcode`\^^M=\other%
+\gdef\eatleadingcr#1{\if\noexpand#1\noexpand^^M\else\E#1\fi}}%
+% Warning: this won't work for a delimited argument
+% or for an empty argument
+
% Trim a single trailing ^^M off a string.
{\catcode`\^^M=\other \catcode`\Q=3%
\gdef\eatcr #1{\eatcra #1Q^^MQ}%
@@ -8368,6 +8205,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\let\hash\relax
% \hash is redefined to `#' later to get it into definitions
\let\xeatspaces\relax
+ \let\xempty\relax
\parsemargdefxxx#1,;,%
\ifnum\paramno<10\relax\else
\paramno0\relax
@@ -8379,9 +8217,11 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\else \let\next=\parsemargdefxxx
\advance\paramno by 1
\expandafter\edef\csname macarg.\eatspaces{#1}\endcsname
- {\xeatspaces{\hash\the\paramno}}%
+ {\xeatspaces{\hash\the\paramno\noexpand\xempty{}}}%
\edef\paramlist{\paramlist\hash\the\paramno,}%
\fi\next}
+% the \xempty{} is to give \eatleadingcr an argument in the case of an
+% empty macro argument.
% \parsemacbody, \parsermacbody
%
@@ -8970,7 +8810,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\else
\ifhavexrefs
% We (should) know the real title if we have the xref values.
- \def\printedrefname{\refx{#1-title}{}}%
+ \def\printedrefname{\refx{#1-title}}%
\else
% Otherwise just copy the Info node name.
\def\printedrefname{\ignorespaces #1}%
@@ -9064,7 +8904,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% If the user specified the print name (third arg) to the ref,
% print it instead of our usual "Figure 1.2".
\ifdim\wd\printedrefnamebox = 0pt
- \refx{#1-snt}{}%
+ \refx{#1-snt}%
\else
\printedrefname
\fi
@@ -9099,28 +8939,30 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\else
% Reference within this manual.
%
- % Only output a following space if the -snt ref is nonempty; for
- % @unnumbered and @anchor, it won't be.
- \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}%
+ % Only output a following space if the -snt ref is nonempty, as the ref
+ % will be empty for @unnumbered and @anchor.
+ \setbox2 = \hbox{\ignorespaces \refx{#1-snt}}%
\ifdim \wd2 > 0pt \refx{#1-snt}\space\fi
%
% output the `[mynode]' via the macro below so it can be overridden.
\xrefprintnodename\printedrefname
%
- % But we always want a comma and a space:
- ,\space
- %
- % output the `page 3'.
- \turnoffactive \putwordpage\tie\refx{#1-pg}{}%
- % Add a , if xref followed by a space
- \if\space\noexpand\tokenafterxref ,%
- \else\ifx\ \tokenafterxref ,% @TAB
- \else\ifx\*\tokenafterxref ,% @*
- \else\ifx\ \tokenafterxref ,% @SPACE
- \else\ifx\
- \tokenafterxref ,% @NL
- \else\ifx\tie\tokenafterxref ,% @tie
- \fi\fi\fi\fi\fi\fi
+ \expandafter\ifx\csname SETtxiomitxrefpg\endcsname\relax
+ % But we always want a comma and a space:
+ ,\space
+ %
+ % output the `page 3'.
+ \turnoffactive \putwordpage\tie\refx{#1-pg}%
+ % Add a , if xref followed by a space
+ \if\space\noexpand\tokenafterxref ,%
+ \else\ifx\ \tokenafterxref ,% @TAB
+ \else\ifx\*\tokenafterxref ,% @*
+ \else\ifx\ \tokenafterxref ,% @SPACE
+ \else\ifx\
+ \tokenafterxref ,% @NL
+ \else\ifx\tie\tokenafterxref ,% @tie
+ \fi\fi\fi\fi\fi\fi
+ \fi
\fi\fi
\fi
\endlink
@@ -9187,9 +9029,8 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\fi\fi\fi
}
-% \refx{NAME}{SUFFIX} - reference a cross-reference string named NAME. SUFFIX
-% is output afterwards if non-empty.
-\def\refx#1#2{%
+% \refx{NAME} - reference a cross-reference string named NAME.
+\def\refx#1{%
\requireauxfile
{%
\indexnofonts
@@ -9216,7 +9057,6 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% It's defined, so just use it.
\thisrefX
\fi
- #2% Output the suffix in any case.
}
% This is the macro invoked by entries in the aux file. Define a control
@@ -9326,10 +9166,10 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\catcode`\[=\other
\catcode`\]=\other
\catcode`\"=\other
- \catcode`\_=\other
- \catcode`\|=\other
- \catcode`\<=\other
- \catcode`\>=\other
+ \catcode`\_=\active
+ \catcode`\|=\active
+ \catcode`\<=\active
+ \catcode`\>=\active
\catcode`\$=\other
\catcode`\#=\other
\catcode`\&=\other
@@ -9550,7 +9390,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup
\catcode`\^^M = 5 % in case we're inside an example
\normalturnoffactive % allow _ et al. in names
- \def\xprocessmacroarg{\eatspaces}% in case we are being used via a macro
+ \makevalueexpandable
% If the image is by itself, center it.
\ifvmode
\imagevmodetrue
@@ -9561,7 +9401,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\fi\fi
%
\ifimagevmode
- \nobreak\medskip
+ \medskip
% Usually we'll have text after the image which will insert
% \parskip glue, so insert it here too to equalize the space
% above and below.
@@ -9576,7 +9416,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% On the other hand, if we are in the case of @center @image, we don't
% want to start a paragraph, which will create a hsize-width box and
% eradicate the centering.
- \ifx\centersub\centerV\else \noindent \fi
+ \ifx\centersub\centerV \else \imageindent \fi
%
% Output the image.
\ifpdf
@@ -11403,23 +11243,6 @@ directory should work if nowhere else does.}
\defbodyindent = .5cm
}}
-% Use @smallerbook to reset parameters for 6x9 trim size.
-% (Just testing, parameters still in flux.)
-\def\smallerbook{{\globaldefs = 1
- \parskip = 1.5pt plus 1pt
- \textleading = 12pt
- %
- \internalpagesizes{7.4in}{4.8in}%
- {-.2in}{-.4in}%
- {0pt}{14pt}%
- {9in}{6in}%
- %
- \lispnarrowing = 0.25in
- \tolerance = 700
- \contentsrightmargin = 0pt
- \defbodyindent = .4cm
-}}
-
% Use @afourpaper to print on European A4 paper.
\def\afourpaper{{\globaldefs = 1
\parskip = 3pt plus 2pt minus 1pt
@@ -11603,7 +11426,7 @@ directory should work if nowhere else does.}
\let> = \activegtr
\let~ = \activetilde
\let^ = \activehat
- \markupsetuplqdefault \markupsetuprqdefault
+ \setregularquotes
\let\b = \strong
\let\i = \smartitalic
% in principle, all other definitions in \tex have to be undone too.
@@ -11662,8 +11485,7 @@ directory should work if nowhere else does.}
@let|=@normalverticalbar
@let~=@normaltilde
@let\=@ttbackslash
- @markupsetuplqdefault
- @markupsetuprqdefault
+ @setregularquotes
@unsepspaces
}
}
@@ -11756,17 +11578,15 @@ directory should work if nowhere else does.}
@c Do this last of all since we use ` in the previous @catcode assignments.
@catcode`@'=@active
@catcode`@`=@active
-@markupsetuplqdefault
-@markupsetuprqdefault
+@setregularquotes
@c Local variables:
-@c eval: (add-hook 'before-save-hook 'time-stamp)
+@c eval: (add-hook 'before-save-hook 'time-stamp nil t)
+@c time-stamp-pattern: "texinfoversion{%Y-%02m-%02d.%02H}"
@c page-delimiter: "^\\\\message\\|emacs-page"
-@c time-stamp-start: "def\\\\texinfoversion{"
-@c time-stamp-format: "%:y-%02m-%02d.%02H"
-@c time-stamp-end: "}"
@c End:
@c vim:sw=2:
@enablebackslashhack
+
diff --git a/tty.c b/tty.c
index 77529f8..88f9f55 100644
--- a/tty.c
+++ b/tty.c
@@ -15,12 +15,11 @@
* along with Mtools. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdarg.h>
#include "sysincludes.h"
#include "mtools.h"
static FILE *tty=NULL;
-static int notty=0;
+static int notty=0;
static int ttyfd=-1;
#ifdef USE_RAWTERM
int mtools_raw_tty = 1;
@@ -95,7 +94,7 @@ static void tty_time_out(int dummy UNUSEDP)
int exit_code;
signal(SIGALRM, SIG_IGN);
if(tty && need_tty_reset)
- restore_tty (&in_orig);
+ restore_tty (&in_orig);
#ifdef future
if (fail_on_timeout)
exit_code=SHFAIL;
@@ -118,7 +117,7 @@ static void tty_time_out(int dummy UNUSEDP)
}
static void cleanup_tty(void)
-{
+{
if(tty && need_tty_reset) {
restore_tty (&in_orig);
setup_signal();
@@ -143,7 +142,7 @@ static void set_raw_tty(int mode)
setup_signal();
signal (SIGALRM, tty_time_out);
-
+
/* Change STDIN settings to raw */
gtty (STDIN, &in_raw);
@@ -151,9 +150,9 @@ static void set_raw_tty(int mode)
#ifdef USE_SGTTY
in_raw.sg_flags |= CBREAK;
#else
- in_raw.c_lflag &= ~ICANON;
+ in_raw.c_lflag &= ~0u ^ ICANON;
in_raw.c_cc[VMIN]=1;
- in_raw.c_cc[VTIME]=0;
+ in_raw.c_cc[VTIME]=0;
#endif
stty (STDIN, &in_raw);
} else {
@@ -170,7 +169,7 @@ static void set_raw_tty(int mode)
}
#endif
-FILE *opentty(int mode)
+FILE *opentty(int mode UNUSEDP)
{
if(notty)
return NULL;
@@ -210,7 +209,12 @@ int ask_confirmation(const char *format, ...)
fflush(stderr);
fflush(opentty(-1));
if (mtools_raw_tty) {
- ans[0] = fgetc(opentty(1));
+ int c = fgetc(opentty(1));
+ if(c < 0)
+ /* Treat end-of-file or error as no */
+ ans[0] = 'n';
+ else
+ ans[0] = (char) c;
fputs("\n", stderr);
} else {
if(fgets(ans,9, opentty(0)) == NULL)
diff --git a/unix2dos.c b/unix2dos.c
new file mode 100644
index 0000000..1415691
--- /dev/null
+++ b/unix2dos.c
@@ -0,0 +1,117 @@
+/* Copyright 1996,1997,1999,2001-2003,2008,2009,2021 Alain Knaff.
+ * This file is part of mtools.
+ *
+ * Mtools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "codepage.h"
+
+#define U2D_BUFSIZE 4096
+
+typedef struct Filter_t {
+ struct Stream_t head;
+
+ char buffer[U2D_BUFSIZE];
+
+ size_t readBytes; /* how many bytes read into buffer */
+ size_t bufPos; /* position in buffer */
+
+ bool pendingNl;
+ bool eof;
+} Filter_t;
+
+/* Add CR before NL, and 0x1a at end of file */
+static ssize_t read_filter(Stream_t *Stream, char *output, size_t len)
+{
+ DeclareThis(Filter_t);
+ size_t i;
+
+ if(This->eof)
+ return 0;
+
+ for(i=0; i < len && !This->eof; i++) {
+ char c;
+ if(This->pendingNl) {
+ c='\n';
+ This->pendingNl=false;
+ } else {
+ if(This->bufPos == This->readBytes) {
+ ssize_t ret = READS(This->head.Next,
+ This->buffer,
+ U2D_BUFSIZE);
+ if(ret < 0) {
+ /* an error */
+ /* If we already have read some data,
+ * first return count of that data
+ * before returning error */
+ if(i == 0)
+ return -1;
+ else
+ break;
+ }
+ This->readBytes = (size_t) ret;
+ This->bufPos = 0;
+ }
+
+ if(This->bufPos == This->readBytes) {
+ /* Still at end of buffer, must be end
+ of file */
+ c='\032';
+ This->eof=true;
+ } else {
+ c = This->buffer[This->bufPos++];
+ if(c == '\n') {
+ This->pendingNl=true;
+ c = '\r';
+ }
+ }
+ }
+ output[i]=c;
+ }
+
+ return (ssize_t) i;
+}
+
+static Class_t FilterClass = {
+ read_filter,
+ 0,
+ 0,
+ 0,
+ 0, /* flush */
+ 0,
+ 0, /* set geometry */
+ get_data_pass_through,
+ 0,
+ 0, /* get_dosconvert */
+ 0 /* discard */
+};
+
+Stream_t *open_unix2dos(Stream_t *Next, int convertCharset UNUSEDP)
+{
+ Filter_t *This;
+
+ This = New(Filter_t);
+ if (!This)
+ return NULL;
+ init_head(&This->head, &FilterClass, Next);
+
+ This->readBytes = This->bufPos = 0;
+ This->pendingNl = false;
+ This->eof = false;
+
+ return &This->head;
+}
diff --git a/unixdir.c b/unixdir.c
index 1f71d92..7bd0dbc 100644
--- a/unixdir.c
+++ b/unixdir.c
@@ -19,17 +19,13 @@
#include "msdos.h"
#include "stream.h"
#include "mtools.h"
-#include "fsP.h"
#include "file.h"
#include "htable.h"
#include "mainloop.h"
#include <dirent.h>
typedef struct Dir_t {
- Class_t *Class;
- int refs;
- Stream_t *Next;
- Stream_t *Buffer;
+ struct Stream_t head;
struct MT_STAT statbuf;
char *pathname;
@@ -41,15 +37,15 @@ typedef struct Dir_t {
/*#define FCHDIR_MODE*/
-static int get_dir_data(Stream_t *Stream, time_t *date, mt_size_t *size,
- int *type, int *address)
+static int get_dir_data(Stream_t *Stream, time_t *date, mt_off_t *size,
+ int *type, unsigned int *address)
{
DeclareThis(Dir_t);
if(date)
*date = This->statbuf.st_mtime;
if(size)
- *size = (mt_size_t) This->statbuf.st_size;
+ *size = This->statbuf.st_size;
if(type)
*type = 1;
if(address)
@@ -66,9 +62,11 @@ static int dir_free(Stream_t *Stream)
return 0;
}
-static Class_t DirClass = {
+static Class_t DirClass = {
0, /* read */
0, /* write */
+ 0, /* pread */
+ 0, /* pwrite */
0, /* flush */
dir_free, /* free */
0, /* get_geom */
@@ -82,8 +80,8 @@ static Class_t DirClass = {
#define FCHDIR_MODE
#endif
-int unix_dir_loop(Stream_t *Stream, MainParam_t *mp);
-int unix_loop(Stream_t *Stream, MainParam_t *mp, char *arg,
+int unix_dir_loop(Stream_t *Stream, MainParam_t *mp);
+int unix_loop(Stream_t *Stream, MainParam_t *mp, char *arg,
int follow_dir_link);
int unix_dir_loop(Stream_t *Stream, MainParam_t *mp)
@@ -109,7 +107,7 @@ int unix_dir_loop(Stream_t *Stream, MainParam_t *mp)
if(isSpecial(entry->d_name))
continue;
#ifndef FCHDIR_MODE
- newName = malloc(strlen(This->pathname) + 1 +
+ newName = malloc(strlen(This->pathname) + 1 +
strlen(entry->d_name) + 1);
if(!newName) {
ret = ERROR_ONE;
@@ -139,11 +137,7 @@ Stream_t *OpenDir(const char *filename)
Dir_t *This;
This = New(Dir_t);
-
- This->Class = &DirClass;
- This->Next = 0;
- This->refs = 1;
- This->Buffer = 0;
+ init_head(&This->head, &DirClass, NULL);
This->pathname = malloc(strlen(filename)+1);
if(This->pathname == NULL) {
Free(This);
@@ -164,5 +158,5 @@ Stream_t *OpenDir(const char *filename)
return NULL;
}
- return (Stream_t *) This;
+ return &This->head;
}
diff --git a/version.texi b/version.texi
index 442de8e..cbd65ab 100644
--- a/version.texi
+++ b/version.texi
@@ -1,3 +1,3 @@
-@set EDITION 4.0.26
-@set VERSION 4.0.26
-@set UPDATED November 2020
+@set EDITION 4.0.37
+@set VERSION 4.0.37
+@set UPDATED January 2022
diff --git a/vfat.c b/vfat.c
index 3ca0fa3..01331bc 100644
--- a/vfat.c
+++ b/vfat.c
@@ -43,7 +43,7 @@ static void autorename(char *name,
unsigned int seqnum=0, maxseq=0;
char tmp;
char *p;
-
+
#ifdef DEBUG
printf("In autorename for name=%s.\n", name);
#endif
@@ -63,7 +63,7 @@ static void autorename(char *name,
seqnum = 0;
maxseq = 1;
} else if (name[dotpos] >= '0' && name[dotpos] <= '9') {
- seqnum = seqnum * 10 + name[dotpos] - '0';
+ seqnum = seqnum * 10 + (uint8_t)(name[dotpos] - '0');
maxseq = maxseq * 10;
} else
tildapos = -1; /* sequence number interrupted */
@@ -155,7 +155,7 @@ void clear_vfat(struct vfat_state *v)
* and adding in each character, from left to right, padding both
* the name and extension to maximum length with spaces and skipping
* the "." (hence always summing exactly 11 characters).
- *
+ *
* This exact algorithm is required in order to remain compatible
* with Microsoft Windows-95 and Microsoft Windows NT 3.5.
* Thanks to Jeffrey Richter of Microsoft Systems Journal for
@@ -171,7 +171,7 @@ static __inline__ unsigned char sum_shortname(const dos_name_t *dn)
for (sum=0; name<end; ++name)
sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1)
- + *name;
+ + (uint8_t) *name;
return(sum);
}
@@ -183,7 +183,7 @@ static __inline__ unsigned char sum_shortname(const dos_name_t *dn)
*/
static __inline__ void check_vfat(struct vfat_state *v, struct directory *dir)
{
- dos_name_t dn;;
+ dos_name_t dn;
if (! v->subentries) {
#ifdef DEBUG
@@ -197,7 +197,7 @@ static __inline__ void check_vfat(struct vfat_state *v, struct directory *dir)
if (v->sum != sum_shortname(&dn))
return;
-
+
if( (v->status & ((1<<v->subentries) - 1)) != (1<<v->subentries) - 1)
return; /* missing entries */
@@ -206,8 +206,16 @@ static __inline__ void check_vfat(struct vfat_state *v, struct directory *dir)
v->present = 1;
}
-
-int clear_vses(Stream_t *Dir, int entrySlot, size_t last)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+/* We have indeed different types for the entry slot
+ * - the higher levels have a "signed" type, in order to accomodate
+ * reserved values for "root directory" entry, "not found" entries, and
+ * "uninitialized"
+ * - the lower levels always consider it as an index into the
+ * directory viewed as a table, i.e. always positive
+ */
+int clear_vses(Stream_t *Dir, int entrySlot, unsigned int last)
{
direntry_t entry;
dirCache_t *cache;
@@ -240,11 +248,12 @@ int clear_vses(Stream_t *Dir, int entrySlot, size_t last)
return 0;
}
-int write_vfat(Stream_t *Dir, dos_name_t *shortname, char *longname, int start,
+int write_vfat(Stream_t *Dir, dos_name_t *shortname, char *longname,
+ unsigned int start,
direntry_t *mainEntry)
{
struct vfat_subentry *vse;
- int vse_id, num_vses;
+ uint8_t vse_id, num_vses;
wchar_t *c;
direntry_t entry;
dirCache_t *cache;
@@ -252,7 +261,7 @@ int write_vfat(Stream_t *Dir, dos_name_t *shortname, char *longname, int start,
doscp_t *cp = GET_DOSCONVERT(Dir);
wchar_t wlongname[MAX_VNAMELEN+1];
- int wlen;
+ size_t wlen;
if(longname) {
#ifdef DEBUG
@@ -272,12 +281,12 @@ int write_vfat(Stream_t *Dir, dos_name_t *shortname, char *longname, int start,
wlen = native_to_wchar(longname, wlongname, MAX_VNAMELEN+1,
0, 0);
- num_vses = (wlen + VSE_NAMELEN - 1)/VSE_NAMELEN;
+ num_vses = (uint8_t)((wlen + VSE_NAMELEN - 1)/VSE_NAMELEN);
for (vse_id = num_vses; vse_id; --vse_id) {
int end = 0;
-
+
c = wlongname + (vse_id - 1) * VSE_NAMELEN;
-
+
c += unicode_write(c, vse->text1, VSE1SIZE, &end);
c += unicode_write(c, vse->text2, VSE2SIZE, &end);
c += unicode_write(c, vse->text3, VSE3SIZE, &end);
@@ -288,7 +297,7 @@ int write_vfat(Stream_t *Dir, dos_name_t *shortname, char *longname, int start,
longname, vse_id, longname + (vse_id-1) * VSE_NAMELEN,
start + num_vses - vse_id, start + num_vses);
#endif
-
+
entry.entry = start + num_vses - vse_id;
low_level_dir_write(&entry);
}
@@ -339,15 +348,15 @@ void dir_write(direntry_t *entry)
* The following function translates a series of vfat_subentries into
* data suitable for a dircache entry
*/
-static __inline__ void parse_vses(direntry_t *entry,
+static __inline__ void parse_vses(direntry_t *entry,
struct vfat_state *v)
{
struct vfat_subentry *vse;
unsigned char id, last_flag;
wchar_t *c;
-
+
vse = (struct vfat_subentry *) &entry->dir;
-
+
id = vse->id & VSE_MASK;
last_flag = (vse->id & VSE_LAST);
if (id > MAX_VFAT_SUBENTRIES) {
@@ -355,7 +364,7 @@ static __inline__ void parse_vses(direntry_t *entry,
id, entry->entry);
return;
}
-
+
/* 950819: This code enforced finding the VSEs in order. Well, Win95
* likes to write them in *reverse* order for some bizarre reason! So
* we pretty much have to tolerate them coming in any possible order.
@@ -375,17 +384,17 @@ static __inline__ void parse_vses(direntry_t *entry,
clear_vfat(v);
v->sum = vse->sum;
}
-
+
#ifdef DEBUG
if(v->status & (1 << (id-1)))
fprintf(stderr,
"parse_vses: duplicate VSE %d\n", vse->id);
#endif
-
+
v->status |= 1 << (id-1);
if(last_flag)
v->subentries = id;
-
+
#ifdef DEBUG
if (id > v->subentries)
/* simple test to detect entries preceding
@@ -402,7 +411,7 @@ static __inline__ void parse_vses(direntry_t *entry,
#ifdef DEBUG
printf("Read VSE %d at %d, subentries=%d, = (%13ls).\n",
id,entry->entry,v->subentries,&(v->name[VSE_NAMELEN * (id-1)]));
-#endif
+#endif
if (last_flag)
*c = '\0'; /* Null terminate long name */
}
@@ -418,7 +427,7 @@ static dirCacheEntry_t *vfat_lookup_loop_common(doscp_t *cp,
int *io_error)
{
wchar_t newfile[13];
- int initpos = direntry->entry + 1;
+ unsigned int initpos = direntry->entry + 1;
struct vfat_state vfat;
wchar_t *longname;
int error;
@@ -438,7 +447,7 @@ static dirCacheEntry_t *vfat_lookup_loop_common(doscp_t *cp,
endmarkSeen);
return addEndEntry(cache, direntry->entry);
}
-
+
if (endmarkSeen || direntry->dir.name[0] == ENDMARK){
/* the end of the directory */
if(lookForFreeSpace) {
@@ -454,11 +463,11 @@ static dirCacheEntry_t *vfat_lookup_loop_common(doscp_t *cp,
/* the main entry */
break;
}
-
+
/* If we get here, it's a short name FAT entry, maybe erased.
* thus we should make sure that the vfat structure will be
* cleared before the next loop run */
-
+
/* deleted file */
if (direntry->dir.name[0] == DELMARK) {
return addFreeEntry(cache, initpos,
@@ -599,13 +608,22 @@ static result_t checkNameForMatch(struct direntry_t *direntry,
}
+int vfat_lookup_zt(direntry_t *direntry, const char *filename,
+ int flags, char *shortname, size_t shortname_size,
+ char *longname, size_t longname_size) {
+ return vfat_lookup(direntry, filename, strlen(filename),
+ flags, shortname, shortname_size,
+ longname, longname_size);
+}
+
/*
* vfat_lookup looks for filenames in directory dir.
* if a name if found, it is returned in outname
* if applicable, the file is opened and its stream is returned in File
*/
-int vfat_lookup(direntry_t *direntry, const char *filename, int length,
+int vfat_lookup(direntry_t *direntry, const char *filename,
+ size_t length,
int flags, char *shortname, size_t shortname_size,
char *longname, size_t longname_size)
{
@@ -616,9 +634,6 @@ int vfat_lookup(direntry_t *direntry, const char *filename, int length,
wchar_t wfilename[MAX_VNAMELEN+1];
doscp_t *cp = GET_DOSCONVERT(direntry->Dir);
- if(length == -1 && filename)
- length = strlen(filename);
-
if(filename != NULL)
length = native_to_wchar(filename, wfilename, MAX_VNAMELEN,
filename+length, 0);
@@ -644,7 +659,7 @@ int vfat_lookup(direntry_t *direntry, const char *filename, int length,
}
result = checkNameForMatch(direntry, dce,
wfilename,
- length, flags);
+ (int) length, flags);
} while(result == RES_NOMATCH);
if(result == RES_MATCH){
@@ -669,7 +684,7 @@ int vfat_lookup(direntry_t *direntry, const char *filename, int length,
static __inline__ dirCacheEntry_t *vfat_lookup_loop_for_insert(doscp_t *cp,
direntry_t *direntry,
- int initpos,
+ unsigned int initpos,
dirCache_t *cache)
{
dirCacheEntry_t *dce;
@@ -717,8 +732,8 @@ static void clear_scan(wchar_t *longname, int use_longname,
s->free_end = s->got_slots = s->free_start = 0;
if (use_longname & 1)
- s->size_needed = 1 +
- (wcslen(longname) + VSE_NAMELEN - 1)/VSE_NAMELEN;
+ s->size_needed = (unsigned)
+ (1 + (wcslen(longname) + VSE_NAMELEN - 1)/VSE_NAMELEN);
else
s->size_needed = 1;
}
@@ -741,7 +756,7 @@ int lookupForInsert(Stream_t *Dir,
int ignore_match;
dirCacheEntry_t *dce;
dirCache_t *cache;
- int pos; /* position _before_ the next answered entry */
+ unsigned int pos; /* position _before_ the next answered entry */
wchar_t shortName[13];
wchar_t wlongname[MAX_VNAMELEN+1];
doscp_t *cp = GET_DOSCONVERT(Dir);
@@ -828,13 +843,13 @@ int lookupForInsert(Stream_t *Dir,
return 6; /* Success */
/* Need more room. Can we grow the directory? */
- if(!isRootDir(Dir))
+ if(!isRootDir(Dir))
return 5; /* OK, try to grow the directory */
fprintf(stderr, "No directory slots\n");
return -1;
}
-
+#pragma GCC diagnostic pop
/* End vfat.c */
diff --git a/vfat.h b/vfat.h
index ca3f8e8..3cae89d 100644
--- a/vfat.h
+++ b/vfat.h
@@ -29,7 +29,7 @@
struct unicode_char {
unsigned char lchar;
unsigned char uchar;
-} PACKED;
+};
/* #define MAX_VFAT_SUBENTRIES 32 */ /* Theoretical max # of VSEs */
@@ -91,7 +91,7 @@ struct scan_state {
void clear_vfat(struct vfat_state *);
int unicode_write(wchar_t *, struct unicode_char *, int num, int *end);
-int clear_vses(Stream_t *, int, size_t);
+int clear_vses(Stream_t *, int, unsigned int);
void autorename_short(struct dos_name_t *, int);
void autorename_long(char *, int);
diff --git a/xdf_io.c b/xdf_io.c
index db02414..d84fd53 100644
--- a/xdf_io.c
+++ b/xdf_io.c
@@ -72,7 +72,7 @@ static struct {
typedef struct {
unsigned char begin; /* where it begins */
- unsigned char end;
+ unsigned char end;
unsigned char sector;
unsigned char sizecode;
@@ -85,23 +85,21 @@ typedef struct {
typedef struct Xdf_t {
- Class_t *Class;
- int refs;
- Stream_t *Next;
- Stream_t *Buffer;
+ struct Stream_t head;
int fd;
char *buffer;
-
- int current_track;
-
+
+ bool track_valid;
+ uint8_t current_track;
+
sector_map_t *map;
- int track_size;
+ uint32_t track_size;
int track0_size;
- int sector_size;
- unsigned int FatSize;
- unsigned int RootDirSize;
+ uint16_t sector_size;
+ uint8_t FatSize;
+ uint16_t RootDirSize;
TrackMap_t *track_map;
unsigned char last_sector;
@@ -141,7 +139,7 @@ static int analyze_reply(RawRequest_t *raw_cmd, int do_print)
}
}
}
-
+
static int send_cmd(int fd, RawRequest_t *raw_cmd, int nr,
@@ -149,7 +147,7 @@ static int send_cmd(int fd, RawRequest_t *raw_cmd, int nr,
{
int j;
int ret=-1;
-
+
if(!nr)
return 0;
for (j=0; j< retries; j++){
@@ -178,28 +176,28 @@ static int send_cmd(int fd, RawRequest_t *raw_cmd, int nr,
#define END(x) (This->track_map[(x)].end)
#define BEGIN(x) (This->track_map[(x)].begin)
-static int add_to_request(Xdf_t *This, int ptr,
+static int add_to_request(Xdf_t *This, unsigned char ptr,
RawRequest_t *request, int *nr,
int direction, Compactify_t *compactify)
{
#if 0
if(direction == MT_WRITE) {
- printf("writing %d: %d %d %d %d [%02x]\n",
+ printf("writing %d: %u %d %d %d [%02x]\n",
ptr, This->current_track,
REC.head, REC.sector, REC.sizecode,
*(This->buffer + ptr * This->sector_size));
} else
- printf(" load %d.%d\n", This->current_track, ptr);
+ printf(" load %d.%u\n", This->current_track, ptr);
#endif
if(REC.phantom) {
- if(direction== MT_READ)
+ if(direction== MT_READ)
memset(This->buffer + ptr * This->sector_size, 0,
- 128 << REC.sizecode);
+ 128u << REC.sizecode);
return 0;
}
-
+
if(*nr &&
- RR_SIZECODE(request+(*nr)-1) == REC.sizecode &&
+ RR_SIZECODE(request+(*nr)-1) == REC.sizecode &&
compactify->head == REC.head &&
compactify->ptr + 1 == ptr &&
compactify->sector +1 == REC.sector) {
@@ -211,7 +209,7 @@ static int add_to_request(Xdf_t *This, int ptr,
RR_SETDRIVE(request+(*nr), This->drive);
RR_SETRATE(request+(*nr), This->rate);
RR_SETTRACK(request+(*nr), This->current_track);
- RR_SETPTRACK(request+(*nr),
+ RR_SETPTRACK(request+(*nr),
This->current_track << This->stretch);
RR_SETHEAD(request+(*nr), REC.head);
RR_SETSECTOR(request+(*nr), REC.sector);
@@ -228,7 +226,7 @@ static int add_to_request(Xdf_t *This, int ptr,
}
-static void add_to_request_if_invalid(Xdf_t *This, int ptr,
+static void add_to_request_if_invalid(Xdf_t *This, unsigned char ptr,
RawRequest_t *request, int *nr,
Compactify_t *compactify)
{
@@ -238,23 +236,25 @@ static void add_to_request_if_invalid(Xdf_t *This, int ptr,
}
-static void adjust_bounds(Xdf_t *This, off_t *begin, off_t *end)
+static void adjust_bounds(Xdf_t *This, uint32_t ibegin, uint32_t iend,
+ uint8_t *begin, uint8_t *end)
{
/* translates begin and end from byte to sectors */
- *begin = *begin / This->sector_size;
- *end = (*end + This->sector_size - 1) / This->sector_size;
+ *begin = (uint8_t) (ibegin / This->sector_size);
+ *end = (uint8_t) ((iend + This->sector_size - 1) / This->sector_size);
}
static __inline__ int try_flush_dirty(Xdf_t *This)
{
- int ptr, nr, bytes;
+ unsigned char ptr;
+ int nr, bytes;
RawRequest_t requests[100];
Compactify_t compactify;
- if(This->current_track < 0)
+ if(!This->track_valid)
return 0;
-
+
nr = 0;
for(ptr=0; ptr < This->last_sector; ptr=REC.end)
if(REC.dirty)
@@ -282,25 +282,27 @@ static __inline__ int try_flush_dirty(Xdf_t *This)
static int flush_dirty(Xdf_t *This)
-{
+{
int ret;
while((ret = try_flush_dirty(This))) {
- if(ret < 0)
+ if(ret < 0)
return ret;
}
return 0;
}
-static int load_data(Xdf_t *This, off_t begin, off_t end, int retries)
+static ssize_t load_data(Xdf_t *This, uint32_t ibegin, uint32_t iend,
+ int retries)
{
- int ptr, nr, bytes;
+ unsigned char ptr;
+ int nr, bytes;
RawRequest_t requests[100];
Compactify_t compactify;
+ unsigned char begin, end;
+ adjust_bounds(This, ibegin, iend, &begin, &end);
- adjust_bounds(This, &begin, &end);
-
ptr = begin;
nr = 0;
for(ptr=REC.begin; ptr < end ; ptr = REC.end)
@@ -324,12 +326,13 @@ static int load_data(Xdf_t *This, off_t begin, off_t end, int retries)
return end * This->sector_size;
}
-static void mark_dirty(Xdf_t *This, off_t begin, off_t end)
+static void mark_dirty(Xdf_t *This, uint32_t ibegin, uint32_t iend)
{
int ptr;
+ unsigned char begin, end;
+
+ adjust_bounds(This, ibegin, iend, &begin, &end);
- adjust_bounds(This, &begin, &end);
-
ptr = begin;
for(ptr=REC.begin; ptr < end ; ptr = REC.end) {
REC.valid = 1;
@@ -339,15 +342,11 @@ static void mark_dirty(Xdf_t *This, off_t begin, off_t end)
}
-static int load_bounds(Xdf_t *This, off_t begin, off_t end)
+static ssize_t load_bounds(Xdf_t *This, uint32_t begin, uint32_t end)
{
- off_t lbegin, lend;
- int endp1, endp2;
-
- lbegin = begin;
- lend = end;
+ unsigned char lbegin, lend;
- adjust_bounds(This, &lbegin, &lend);
+ adjust_bounds(This, begin, end, &lbegin, &lend);
if(begin != BEGIN(lbegin) * This->sector_size &&
end != BEGIN(lend) * This->sector_size &&
@@ -356,24 +355,44 @@ static int load_bounds(Xdf_t *This, off_t begin, off_t end)
return load_data(This, begin, end, 4);
if(begin != BEGIN(lbegin) * This->sector_size) {
- endp1 = load_data(This, begin, begin, 4);
- if(endp1 < 0)
- return endp1;
+ ssize_t ret = load_data(This, begin, begin, 4);
+ if(ret < 0)
+ return ret;
}
if(end != BEGIN(lend) * This->sector_size) {
- endp2 = load_data(This, end, end, 4);
- if(endp2 < 0)
+ ssize_t ret = load_data(This, end, end, 4);
+ if(ret < 0)
return BEGIN(lend) * This->sector_size;
}
return lend * This->sector_size;
}
+/* Fill out a map that is just sufficient to read boot sector */
+static void fill_boot(Xdf_t *This)
+{
+ uint8_t ptr=0;
+
+ REC.head = 0;
+ REC.sector = 129;
+ REC.phantom = 0;
+
+ REC.begin = ptr;
+ REC.end = ptr+1;
+
+ REC.sizecode = 2;
+
+ REC.valid = 0;
+ REC.dirty = 0;
+ This->last_sector=1;
+ This->current_track=0;
+}
+
-static int fill_t0(Xdf_t *This, int ptr, unsigned int size,
- int *sector, int *head)
+static uint8_t fill_t0(Xdf_t *This, uint8_t ptr, unsigned int size,
+ uint8_t *sector, uint8_t *head)
{
- int n;
+ unsigned int n;
for(n = 0; n < size; ptr++,n++) {
REC.head = *head;
@@ -389,48 +408,56 @@ static int fill_t0(Xdf_t *This, int ptr, unsigned int size,
}
-static int fill_phantoms(Xdf_t *This, int ptr, unsigned int size)
+static uint8_t fill_phantoms(Xdf_t *This, uint8_t ptr, uint8_t size)
{
- int n;
+ unsigned int n;
for(n = 0; n < size; ptr++,n++)
REC.phantom = 1;
return ptr;
}
-static void decompose(Xdf_t *This, int where, int len, off_t *begin,
- off_t *end, int boot)
+static int decompose(Xdf_t *This, mt_off_t iwhere, size_t len,
+ uint32_t *begin, uint32_t *end, uint8_t boot)
{
- int ptr, track;
+ uint8_t ptr;
sector_map_t *map;
- int lbegin, lend;
-
- track = where / This->track_size / 1024;
-
- *begin = where - track * This->track_size * 1024;
- *end = where + len - track * This->track_size * 1024;
- maximize(*end, This->track_size * 1024);
+ uint8_t lbegin, lend;
+ uint32_t track_size = This->track_size * 1024;
+
+ smt_off_t track = (smt_off_t) iwhere / track_size;
+ uint32_t where = (smt_off_t) iwhere % track_size;
+
+ *begin = where;
+ if(where + len > track_size)
+ *end = track_size;
+ else
+ *end = (uint32_t) (where + len);
if(This->current_track == track && !boot)
/* already OK, return immediately */
- return;
+ return 0;
if(!boot)
flush_dirty(This);
- This->current_track = track;
+ if(track >= 80)
+ return -1;
+ This->current_track = (uint8_t) track;
+ This->track_valid = true;
if(track) {
for(ptr=0, map=This->map; map->size; map++) {
/* iterate through all sectors */
lbegin = ptr;
- lend = ptr + (128 << map->size) / This->sector_size;
+ lend = ptr +
+ (uint8_t) ((128u<<map->size)/This->sector_size);
for( ; ptr < lend ; ptr++) {
REC.begin = lbegin;
REC.end = lend;
-
+
REC.head = map->head;
REC.sector = map->size + 128;
REC.sizecode = map->size;
-
+
REC.valid = 0;
REC.dirty = 0;
REC.phantom = 0;
@@ -438,7 +465,7 @@ static void decompose(Xdf_t *This, int where, int len, off_t *begin,
}
REC.begin = REC.end = ptr;
} else {
- int sector, head;
+ uint8_t sector, head;
head = 0;
sector = 0;
@@ -446,9 +473,9 @@ static void decompose(Xdf_t *This, int where, int len, off_t *begin,
for(ptr=boot; ptr < 2 * This->track_size; ptr++) {
REC.begin = ptr;
REC.end = ptr+1;
-
+
REC.sizecode = 2;
-
+
REC.valid = 0;
REC.dirty = 0;
}
@@ -461,7 +488,7 @@ static void decompose(Xdf_t *This, int where, int len, off_t *begin,
/* root dir */
ptr=fill_t0(This, ptr, This->RootDirSize, &sector, &head);
-
+
/* "bad sectors" at the beginning of the fs */
ptr=fill_phantoms(This, ptr, 5);
@@ -475,44 +502,57 @@ static void decompose(Xdf_t *This, int where, int len, off_t *begin,
&sector, &head);
}
This->last_sector = ptr;
+ return 0;
}
-static int xdf_read(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
-{
- off_t begin, end;
- size_t len2;
+static ssize_t xdf_pread(Stream_t *Stream, char *buf,
+ mt_off_t where, size_t len)
+{
+ uint32_t begin, end;
+ ssize_t ret;
DeclareThis(Xdf_t);
- decompose(This, truncBytes32(where), len, &begin, &end, 0);
- len2 = load_data(This, begin, end, 4);
- len2 -= begin;
- maximize(len, len2);
+ if(decompose(This, truncBytes32(where), len, &begin, &end, 0) < 0)
+ /* Read beyond end of device */
+ return 0;
+ ret = load_data(This, begin, end, 4);
+ if(ret < 0 || (size_t) ret < begin)
+ return -1;
+ maximize(len, (size_t) ret - begin);
memcpy(buf, This->buffer + begin, len);
- return end - begin;
+ return (ssize_t) (end - begin);
}
-static int xdf_write(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
-{
- off_t begin, end;
- size_t len2;
+static ssize_t xdf_pwrite(Stream_t *Stream, char *buf,
+ mt_off_t where, size_t len)
+{
+ uint32_t begin, end;
+ ssize_t len2;
DeclareThis(Xdf_t);
- decompose(This, truncBytes32(where), len, &begin, &end, 0);
+ if(decompose(This, truncBytes32(where), len, &begin, &end, 0) < 0) {
+ /* Write beyond end of device */
+ errno = EFBIG;
+ return -1;
+ }
+
len2 = load_bounds(This, begin, end);
- smaximize(end, (off_t)len2);
+ if(len2 < 0)
+ return -1;
+ maximize(end, (uint32_t)len2);
len2 -= begin;
- sizemaximize(len, (off_t)len2);
+ maximize(len, (size_t) len2);
memcpy(This->buffer + begin, buf, len);
mark_dirty(This, begin, end);
- return end - begin;
+ return (ssize_t) (end - begin);
}
static int xdf_flush(Stream_t *Stream)
{
DeclareThis(Xdf_t);
- return flush_dirty(This);
+ return flush_dirty(This);
}
static int xdf_free(Stream_t *Stream)
@@ -524,12 +564,9 @@ static int xdf_free(Stream_t *Stream)
}
-static int check_geom(struct device *dev, int media, union bootsector *boot)
+static int check_geom(Xdf_t *This, struct device *dev)
{
- int sect;
-
- if(media >= 0xfc && media <= 0xff)
- return 1; /* old DOS */
+ unsigned int sect;
if (!IS_MFORMAT_ONLY(dev)) {
if(compare(dev->sectors, 19) &&
@@ -538,79 +575,81 @@ static int check_geom(struct device *dev, int media, union bootsector *boot)
compare(dev->sectors, 46) &&
compare(dev->sectors, 48))
return 1;
-
+
/* check against contradictory info from configuration file */
if(compare(dev->heads, 2))
return 1;
}
/* check against info from boot */
- if(boot) {
- sect = WORD(nsect);
+ if(This) {
+ sect = This->track_size;
if((sect != 19 && sect != 23 && sect != 24 &&
sect != 46 && sect != 48) ||
- (!IS_MFORMAT_ONLY(dev) && compare(dev->sectors, sect)) ||
- WORD(nheads) !=2)
- return 1;
+ (!IS_MFORMAT_ONLY(dev) && compare(dev->sectors, sect)))
+ return 1;
}
return 0;
}
-static void set_geom(union bootsector *boot, struct device *dev)
+static void set_geom(Xdf_t *This, struct device *dev)
{
/* fill in config info to be returned to user */
dev->heads = 2;
dev->use_2m = 0xff;
- if(boot) {
- dev->sectors = WORD(nsect);
- if(WORD(psect))
- dev->tracks = WORD(psect) / dev->sectors / 2;
- }
+ dev->sectors = (uint16_t) This->track_size;
+ dev->tracks = 80;
}
-static int config_geom(Stream_t *Stream UNUSEDP, struct device *dev,
- struct device *orig_dev UNUSEDP, int media,
- union bootsector *boot)
+static int config_geom(Stream_t *Stream UNUSEDP, struct device *dev,
+ struct device *orig_dev UNUSEDP)
{
- if(check_geom(dev, media, boot))
+ DeclareThis(Xdf_t);
+ if(check_geom(This, dev))
return 1;
- set_geom(boot,dev);
+ set_geom(This, dev);
return 0;
}
static Class_t XdfClass = {
- xdf_read,
- xdf_write,
- xdf_flush,
- xdf_free,
- config_geom,
+ 0,
+ 0,
+ xdf_pread,
+ xdf_pwrite,
+ xdf_flush,
+ xdf_free,
+ config_geom,
0, /* get_data */
0, /* pre-allocate */
0, /* get_dosConvert */
0 /* discard */
};
-Stream_t *XdfOpen(struct device *dev, char *name,
+Stream_t *XdfOpen(struct device *dev, const char *name,
int mode, char *errmsg, struct xdf_info *info)
{
Xdf_t *This;
- off_t begin, end;
+ uint32_t begin, end;
union bootsector *boot;
unsigned int type;
+ uint16_t fatSize;
- if(dev && (!SHOULD_USE_XDF(dev) || check_geom(dev, 0, 0)))
+ if(dev && ((!SHOULD_USE_XDF(dev) && !getenv("MTOOLS_USE_XDF")) ||
+ check_geom(NULL, dev)))
return NULL;
This = New(Xdf_t);
if (!This)
return NULL;
+ init_head(&This->head, &XdfClass, NULL);
- This->Class = &XdfClass;
This->sector_size = 512;
This->stretch = 0;
precmd(dev);
- This->fd = open(name, mode | dev->mode | O_EXCL | O_NDELAY);
+ This->fd = open(name,
+ ((mode | dev->mode) & ~O_ACCMODE) |
+ O_EXCL | O_NDELAY | O_RDWR);
if(This->fd < 0) {
#ifdef HAVE_SNPRINTF
snprintf(errmsg,199,"xdf floppy: open: \"%s\"", strerror(errno));
@@ -630,7 +669,7 @@ Stream_t *XdfOpen(struct device *dev, char *name,
if (!This->buffer)
goto exit_1;
- This->current_track = -1;
+ This->track_valid = false;
This->track_map = (TrackMap_t *)
calloc(96, sizeof(TrackMap_t));
if(!This->track_map)
@@ -639,31 +678,33 @@ Stream_t *XdfOpen(struct device *dev, char *name,
/* lock the device on writes */
if (lock_dev(This->fd, mode == O_RDWR, dev)) {
#ifdef HAVE_SNPRINTF
- snprintf(errmsg,199,"xdf floppy: device \"%s\" busy:",
+ snprintf(errmsg,199,"xdf floppy: device \"%s\" busy:",
dev->name);
#else
- sprintf(errmsg,"xdf floppy: device \"%s\" busy:",
+ sprintf(errmsg,"xdf floppy: device \"%s\" busy:",
dev->name);
#endif
goto exit_3;
}
/* Before reading the boot sector, assume dummy values suitable
- * for reading at least the boot sector */
- This->track_size = 11;
- This->track0_size = 6;
+ * for reading just the boot sector */
+ fill_boot(This);
This->rate = 0;
- This->FatSize = 9;
- This->RootDirSize = 1;
- decompose(This, 0, 512, &begin, &end, 0);
- if (load_data(This, 0, 1, 1) < 0 ) {
+ if (load_data(This, 0, 1, 4) < 0 ) {
This->rate = 0x43;
- if(load_data(This, 0, 1, 1) < 0)
+ if(load_data(This, 0, 1, 4) < 0)
goto exit_3;
}
boot = (union bootsector *) This->buffer;
- This->FatSize = WORD(fatlen);
+
+ fatSize = WORD(fatlen);
+ if(fatSize > UINT8_MAX) {
+ fprintf(stderr, "Fat size %d too large\n", fatSize);
+ exit(1);
+ }
+ This->FatSize = (uint8_t) fatSize;
This->RootDirSize = WORD(dirents)/16;
This->track_size = WORD(nsect);
for(type=0; type < NUMBER(xdf_table); type++) {
@@ -685,12 +726,9 @@ Stream_t *XdfOpen(struct device *dev, char *name,
}
decompose(This, 0, 512, &begin, &end, 1);
- This->refs = 1;
- This->Next = 0;
- This->Buffer = 0;
if(dev)
- set_geom(boot, dev);
- return (Stream_t *) This;
+ set_geom(This, dev);
+ return &This->head;
exit_3:
Free(This->track_map);
@@ -706,4 +744,3 @@ exit_0:
#endif
/* Algorithms can't be patented */
-
diff --git a/xdf_io.h b/xdf_io.h
index ac45a37..5ef2931 100644
--- a/xdf_io.h
+++ b/xdf_io.h
@@ -23,11 +23,11 @@
struct xdf_info {
unsigned int FatSize;
- unsigned int RootDirSize;
+ uint16_t RootDirSize;
unsigned int BadSectors;
};
-Stream_t *XdfOpen(struct device *dev, char *name,
+Stream_t *XdfOpen(struct device *dev, const char *name,
int mode, char *errmsg, struct xdf_info *info);
#endif