Imported Upstream version 4.0.36 upstream/4.0.36
authorDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 14 Jan 2022 01:51:44 +0000 (10:51 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 14 Jan 2022 01:51:44 +0000 (10:51 +0900)
79 files changed:
Makefile.in
NEWS
NEWS.rej [new file with mode: 0644]
buffer.c
config.sub
copyfile.c
debian/changelog
directory.c
dos2unix.c [new file with mode: 0644]
fat.c
file.c
file.c.rej [new file with mode: 0644]
filter.c [deleted file]
floppyd.1
floppyd_installtest.1
floppyd_io.c
force_io.c
fs.h
fsP.h
init.c
mattrib.1
mbadblocks.1
mbadblocks.c
mcat.1
mcat.c
mcd.1
mclasserase.1
mcopy.1
mcopy.c
mdel.1
mdeltree.1
mdir.1
mdir.c
mdu.1
mformat.1
mformat.c
minfo.1
minfo.c
mkmanifest.1
mlabel.1
mlabel.c
mmd.1
mmd.c
mmount.1
mmove.1
mpartition.1
mpartition.c
mrd.1
mren.1
mshortname.1
mshowfat.1
mtools.1
mtools.5
mtools.h
mtools.info
mtools.spec
mtools.tmpl.1
mtools.tmpl.5
mtoolstest.1
mtype.1
mzip.1
mzip.c
offset.c
partition.c
patchlevel.c
plain_io.c
remap.c
scsi_io.c
stream.c
stream.h
strtonum.c
subdir.c [deleted file]
swap.c
texinfo.tex
unix2dos.c [new file with mode: 0644]
unixdir.c
version.texi
vfat.c
xdf_io.c

index 420dc72..d897f5f 100644 (file)
@@ -86,16 +86,16 @@ MAN5DIR     = $(DESTDIR)$(mandir)/man${MAN5EXT}
 
 # 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 expand.o fat.o    \
-fat_free.o file.o file_name.o filter.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 mclasserase.o mcopy.o mdel.o mdir.o mdoctorfat.o mdu.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 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  \
 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 subdir.o swap.o unixdir.o tty.o vfat.o strtonum.o                \
-@FLOPPYD_IO_OBJ@ @XDF_IO_OBJ@
+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
@@ -108,16 +108,16 @@ 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 expand.c fat.c fat_free.c file.c     \
-file_name.c file_read.c filter.c force_io.c hash.c init.c lba.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 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 subdir.c      \
-swap.c unixdir.c tty.c vfat.c mkmanifest.c @FLOPPYD_IO_SRC@            \
-@XDF_IO_SRC@
+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 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  \
+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
diff --git a/NEWS b/NEWS
index 2813189..e48cbb2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,13 @@
+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
+         comments about what happens here
 
 v4_0_34
        - Fix mcopy -s issue
diff --git a/NEWS.rej b/NEWS.rej
new file mode 100644 (file)
index 0000000..81ae14c
--- /dev/null
+++ b/NEWS.rej
@@ -0,0 +1,16 @@
+--- NEWS       2021-07-23 13:23:07.000000000 +0200
++++ NEWS       2021-08-06 20:13:15.351297435 +0200
+@@ -1,8 +1,12 @@
++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.34)
++      - 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
index a630efb..9b40727 100644 (file)
--- a/buffer.c
+++ b/buffer.c
 #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? */
@@ -69,7 +66,11 @@ static int _buf_flush(Buffer_t *Buffer)
 {
        ssize_t ret;
 
-       if (!Buffer->Next || !Buffer->dirty)
+#ifdef HAVE_ASSERT_H
+       assert(Buffer->head.Next != NULL);
+#endif
+       
+       if (!Buffer->dirty)
                return 0;
 #ifdef DEBUG
        fprintf(stderr, "write %08x -- %02x %08x %08x\n",
@@ -79,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 + (mt_off_t) 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;
@@ -146,7 +149,8 @@ static position_t isInBuffer(Buffer_t *This, mt_off_t start, size_t *len)
        }
 }
 
-static ssize_t 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;
        size_t offset;
@@ -166,10 +170,10 @@ static ssize_t buf_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
                        maximize(length, This->size - This->cur_size);
 
                        /* read it! */
-                       ret=READS(This->Next,
-                                 This->buf + This->cur_size,
-                                 This->current + (mt_off_t) 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 += (size_t) ret;
@@ -192,8 +196,8 @@ static ssize_t buf_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
        return (ssize_t) len;
 }
 
-static ssize_t 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);
@@ -227,7 +231,8 @@ static ssize_t buf_write(Stream_t *Stream, char *buf,
                                readSize = This->cylinderSize -
                                        (size_t)(This->current % (mt_off_t) This->cylinderSize);
 
-                               ret=READS(This->Next, This->buf, (mt_off_t)This->current, readSize);
+                               ret=PREADS(This->head.Next, This->buf,
+                                          (mt_off_t)This->current, readSize);
                                /* read it! */
                                if ( ret < 0 )
                                        return ret;
@@ -258,8 +263,8 @@ static ssize_t buf_write(Stream_t *Stream, char *buf,
                        offset = OFFSET;
                        maximize(len, This->size - offset);
                        This->cur_size += len;
-                       if(This->Next->Class->pre_allocate)
-                               PRE_ALLOCATE(This->Next, cur_end(This));
+                       if(This->head.Next->Class->pre_allocate)
+                               PRE_ALLOCATE(This->head.Next, cur_end(This));
                        break;
                case INSIDE:
                        /* nothing to do */
@@ -337,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 */
@@ -353,12 +360,12 @@ Stream_t *buf_init(Stream_t *Next, size_t size,
                   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) {
@@ -370,19 +377,13 @@ Stream_t *buf_init(Stream_t *Next, size_t 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;
@@ -396,11 +397,6 @@ Stream_t *buf_init(Stream_t *Next, size_t 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;
 }
 
index d80c5d7..d74fb6d 100755 (executable)
@@ -4,7 +4,7 @@
 
 # shellcheck disable=SC2006,SC2268 # see below for rationale
 
-timestamp='2021-07-03'
+timestamp='2021-08-14'
 
 # 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
@@ -121,9 +121,11 @@ esac
 
 # Split fields of configuration type
 # shellcheck disable=SC2162
+saved_IFS=$IFS
 IFS="-" read field1 field2 field3 field4 <<EOF
 $1
 EOF
+IFS=$saved_IFS
 
 # Separate into logical components for further validation
 case $1 in
@@ -172,6 +174,10 @@ case $1 in
                                                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]* \
@@ -931,9 +937,11 @@ case $basic_machine in
 
        *-*)
                # shellcheck disable=SC2162
+               saved_IFS=$IFS
                IFS="-" read cpu vendor <<EOF
 $basic_machine
 EOF
+               IFS=$saved_IFS
                ;;
        # We use `pc' rather than `unknown'
        # because (1) that's what they normally are, and
@@ -1313,9 +1321,11 @@ case $basic_os in
                ;;
        *-*)
                # 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*)
@@ -1697,7 +1707,7 @@ 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* | uclibc*)
+       musl* | newlib* | relibc* | uclibc*)
                ;;
        # Likewise for "kernel-abi"
        eabi* | gnueabi*)
@@ -1738,7 +1748,7 @@ case $os in
             | skyos* | haiku* | rdos* | toppers* | drops* | es* \
             | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
             | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
-            | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx*)
+            | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr*)
                ;;
        # This one is extra strict with allowed versions
        sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
@@ -1755,11 +1765,12 @@ 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-uclibc* )
+       linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
+                  | linux-musl* | linux-relibc* | linux-uclibc* )
                ;;
        uclinux-uclibc* )
                ;;
-       -dietlibc* | -newlib* | -musl* | -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
index 4c689f7..cf0eeeb 100644 (file)
@@ -43,7 +43,7 @@ mt_off_t copyfile(Stream_t *Source, Stream_t *Target)
 
        pos = 0;
        while(1){
-               ret = READS(Source, buffer, pos, 8*16384);
+               ret = READS(Source, buffer, 8*16384);
                if (ret < 0 ){
                        perror("file read");
                        return -1;
@@ -54,8 +54,7 @@ mt_off_t copyfile(Stream_t *Source, Stream_t *Target)
                        return -1;
                if (ret == 0)
                        break;
-               if ((retw = force_write(Target, buffer,
-                                       pos, (size_t) ret)) != ret){
+               if ((retw = force_write(Target, buffer, (size_t) ret)) != ret){
                        if(retw < 0 )
                                perror("write in copy");
                        else
index a300e5b..471dfc7 100644 (file)
@@ -1,3 +1,12 @@
+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
@@ -8,7 +17,7 @@ mtools (4.0.34) stable; urgency=low
 
   *  Fix mcopy -s issue
 
- -- Alain Knaff <alain@knaff.lu>  Fri, 23 Jul 2021 12:41:11 +0200
 -- 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)
index 7625699..79a4624 100644 (file)
@@ -32,9 +32,9 @@ struct directory *dir_read(direntry_t *entry, int *error)
 {
        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,7 +52,7 @@ 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);
+       DeclareThis(Fs_t);
        ssize_t ret;
        unsigned int buflen;
        char *buffer;
@@ -60,7 +60,7 @@ int dir_grow(Stream_t *Dir, int size)
        if (!getfreeMinClusters(Dir, 1))
                return -1;
 
-       buflen = This->cluster_size * This->sector_size;
+       buflen = getClusterBytes(This);
 
        if(! (buffer=malloc(buflen)) ){
                perror("dir_grow: malloc");
@@ -68,7 +68,7 @@ int dir_grow(Stream_t *Dir, int size)
        }
 
        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);
 }
 
 /*
diff --git a/dos2unix.c b/dos2unix.c
new file mode 100644 (file)
index 0000000..78982d1
--- /dev/null
@@ -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 a2c4303..3a2f9e3 100644 (file)
--- a/fat.c
+++ b/fat.c
@@ -41,24 +41,24 @@ typedef struct FatMap_t {
 static __inline__ ssize_t readSector(Fs_t *This, char *buf, unsigned int off,
                                     size_t size)
 {
-       return READS(This->Next, buf, sectorsToBytes(This, off),
-                    size << This->sectorShift);
+       return PREADS(This->head.Next, buf, sectorsToBytes(This, off),
+                     size << This->sectorShift);
 }
 
 
 static __inline__ ssize_t forceReadSector(Fs_t *This, char *buf,
                                          unsigned int off, size_t size)
 {
-       return force_read(This->Next, buf, sectorsToBytes(This, off),
-                                         size << This->sectorShift);
+       return force_pread(This->head.Next, buf, sectorsToBytes(This, off),
+                          size << This->sectorShift);
 }
 
 
 static __inline__ ssize_t forceWriteSector(Fs_t *This, char *buf, unsigned int off,
                                           size_t size)
 {
-       return force_write(This->Next, buf, sectorsToBytes(This, off),
-                                          size << This->sectorShift);
+       return force_pwrite(This->head.Next, buf, sectorsToBytes(This, off),
+                           size << This->sectorShift);
 }
 
 
@@ -863,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);
diff --git a/file.c b/file.c
index d72c7d0..8165d4f 100644 (file)
--- a/file.c
+++ b/file.c
 #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;
 
+       struct Stream_t *Buffer;
+       
        int (*map)(struct File_t *this, uint32_t where, uint32_t *len, int mode,
                           mt_off_t *res);
        uint32_t FileSize;
@@ -57,6 +57,8 @@ typedef struct File_t {
 
        unsigned int loopDetectRel;
        unsigned int loopDetectAbs;
+
+       uint32_t where;
 } File_t;
 
 static Class_t FileClass;
@@ -69,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)
@@ -99,7 +106,7 @@ static int recalcPreallocSize(File_t *This)
        uint32_t currentClusters, neededClusters;
        unsigned int clus_size;
        uint32_t neededPrealloc;
-       Fs_t *Fs = This->Fs;
+       Fs_t *Fs = _getFs(This);
 
 #if 0
        if(This->FileSize & 0xc0000000) {
@@ -221,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);
@@ -245,15 +252,15 @@ 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;
        }
@@ -272,7 +279,7 @@ static int normal_map(File_t *This, uint32_t where, uint32_t *len, int mode,
        uint32_t NewCluNr;
        uint32_t AbsCluNr;
        uint32_t clus_size;
-       Fs_t *Fs = This->Fs;
+       Fs_t *Fs = _getFs(This);
 
        *res = 0;
        clus_size = Fs->cluster_size * Fs->sector_size;
@@ -288,7 +295,7 @@ static int normal_map(File_t *This, uint32_t where, uint32_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;
@@ -296,7 +303,7 @@ static int normal_map(File_t *This, uint32_t where, uint32_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;
@@ -318,7 +325,7 @@ static int normal_map(File_t *This, uint32_t where, uint32_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);
@@ -328,12 +335,12 @@ static int normal_map(File_t *This, uint32_t where, uint32_t *len, int mode,
                        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){
@@ -379,7 +386,7 @@ static int normal_map(File_t *This, uint32_t where, uint32_t *len, int mode,
 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 < where) {
                *len = 0;
@@ -396,35 +403,35 @@ static int root_map(File_t *This, uint32_t where, uint32_t *len,
        return 1;
 }
 
-
-static ssize_t read_file(Stream_t *Stream, char *buf, mt_off_t iwhere,
-                        size_t ilen)
+static ssize_t read_file(Stream_t *Stream, char *buf, size_t ilen)
 {
        DeclareThis(File_t);
        mt_off_t pos;
        int err;
-       uint32_t where = truncMtOffTo32u(iwhere);
        uint32_t len = truncSizeTo32u(ilen);
+       ssize_t ret;
+       
+       Stream_t *Disk = _getFs(This)->head.Next;
 
-       Stream_t *Disk = This->Fs->Next;
-
-       err = This->map(This, where, &len, MT_READ, &pos);
+       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 ssize_t write_file(Stream_t *Stream, char *buf,
-                         mt_off_t iwhere, size_t ilen)
+static ssize_t write_file(Stream_t *Stream, char *buf, size_t ilen)
 {
        DeclareThis(File_t);
        mt_off_t pos;
        ssize_t ret;
        uint32_t requestedLen;
        uint32_t bytesWritten;
-       Stream_t *Disk = This->Fs->Next;
-       uint32_t where = truncMtOffTo32u(iwhere);
-       uint32_t maxLen = UINT32_MAX-where;
+       Stream_t *Disk = _getFs(This)->head.Next;
+       uint32_t maxLen = UINT32_MAX-This->where;
        uint32_t len;
        int err;
 
@@ -433,13 +440,13 @@ static ssize_t write_file(Stream_t *Stream, char *buf,
        } 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);
+               ret = PWRITES(Disk, buf, pos, len);
        if(ret < 0)
                /* Error occured */
                return ret;
@@ -451,12 +458,26 @@ static ssize_t write_file(Stream_t *Stream, char *buf,
                bytesWritten = requestedLen;
        else
                bytesWritten = (uint32_t)ret;
-       if (where + bytesWritten > This->FileSize )
-               This->FileSize = where + bytesWritten;
+       This->where += bytesWritten;
+       if (This->where > This->FileSize )
+               This->FileSize = This->where;
        recalcPreallocSize(This);
-       return (ssize_t)bytesWritten;
+       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
@@ -542,7 +563,7 @@ static int get_file_data(Stream_t *Stream, time_t *date, mt_off_t *size,
 static int free_file(Stream_t *Stream)
 {
        DeclareThis(File_t);
-       Fs_t *Fs = This->Fs;
+       Fs_t *Fs = _getFs(This);
        fsReleasePreallocateClusters(Fs, This->preallocatedClusters);
        FREE(&This->direntry.Dir);
        freeDirCache(Stream);
@@ -585,6 +606,8 @@ static int pre_allocate_file(Stream_t *Stream, mt_off_t isize)
 static Class_t FileClass = {
        read_file,
        write_file,
+       pread_file,
+       pwrite_file,
        flush_file, /* flush */
        free_file, /* free */
        0, /* get_geom */
@@ -607,7 +630,7 @@ static uint32_t func1(void *Stream)
 {
        DeclareThis(File_t);
 
-       return getAbsCluNr(This) ^ (uint32_t) (unsigned long) This->Fs;
+       return getAbsCluNr(This) ^ (uint32_t) (unsigned long) This->head.Next;
 }
 
 static uint32_t func2(void *Stream)
@@ -623,7 +646,7 @@ 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);
 }
 
@@ -647,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
@@ -663,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;
                }
        }
@@ -672,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;
@@ -681,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
@@ -698,12 +720,36 @@ 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;
diff --git a/file.c.rej b/file.c.rej
new file mode 100644 (file)
index 0000000..29c30ab
--- /dev/null
@@ -0,0 +1,22 @@
+--- file.c     2021-07-23 12:11:15.000000000 +0200
++++ file.c     2021-08-06 20:08:10.971108060 +0200
+@@ -444,13 +447,17 @@
+               /* 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 = requestedLen;
++              bytesWritten = (uint32_t)ret;
+       if (where + bytesWritten > This->FileSize )
+               This->FileSize = where + bytesWritten;
+       recalcPreallocSize(This);
+-      return ret;
++      return (ssize_t)bytesWritten;
+ }
diff --git a/filter.c b/filter.c
deleted file mode 100644 (file)
index 0cf57ae..0000000
--- a/filter.c
+++ /dev/null
@@ -1,178 +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 ssize_t read_filter(Stream_t *Stream, char *buf,
-                          mt_off_t iwhere, size_t len)
-{
-       DeclareThis(Filter_t);
-       int i,j;
-       ssize_t ret;
-       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, 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 ssize_t write_filter(Stream_t *Stream, char *buf, mt_off_t iwhere,
-                           size_t len)
-{
-       DeclareThis(Filter_t);
-       unsigned int i;
-       size_t j;
-       ssize_t ret;
-       char buffer[1025];
-       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, 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 (ssize_t)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, This->dospos, 1) < 0;
-       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;
-}
index 7a91d63..cabbba7 100644 (file)
--- a/floppyd.1
+++ b/floppyd.1
@@ -1,5 +1,5 @@
 '\" t
-.TH floppyd 1 "06Aug21" mtools-4.0.35
+.TH floppyd 1 "21Nov21" mtools-4.0.36
 .SH Name
 floppyd - floppy daemon for remote access to floppy drive
 '\" t
index 8e13b6b..7a7e91e 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.TH floppyd_installtest 1 "06Aug21" mtools-4.0.35
+.TH floppyd_installtest 1 "21Nov21" mtools-4.0.36
 .SH Name
 floppyd_installtest - tests whether floppyd is installed and running
 '\" t
index 8cd271d..f7142b9 100644 (file)
@@ -47,10 +47,8 @@ static const char* AuthErrors[] = {
 
 
 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;
@@ -347,14 +345,14 @@ static ssize_t floppyd_io(Stream_t *Stream, char *buf, mt_off_t where,
        return ret;
 }
 
-static ssize_t 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 ssize_t 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);
 }
@@ -436,8 +434,10 @@ static int floppyd_data(Stream_t *Stream, time_t *date, mt_off_t *size,
 /* ######################################################################## */
 
 static Class_t FloppydFileClass = {
-       floppyd_read,
-       floppyd_write,
+       0,
+       0,
+       floppyd_pread,
+       floppyd_pwrite,
        floppyd_flush,
        floppyd_free,
        set_geom_noop,
@@ -576,12 +576,10 @@ Stream_t *FloppydOpen(struct device *dev,
                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) {
@@ -602,7 +600,7 @@ Stream_t *FloppydOpen(struct device *dev,
                        ((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,
index 520a110..7884c22 100644 (file)
@@ -27,9 +27,9 @@
 #include "msdos.h"
 #include "stream.h"
 
-static ssize_t force_io(Stream_t *Stream,
-                       char *buf, mt_off_t start, size_t len,
-                       ssize_t (*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))
 {
        ssize_t ret;
        int done=0;
@@ -51,14 +51,25 @@ static ssize_t force_io(Stream_t *Stream,
        return done;
 }
 
-ssize_t 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 force_io(Stream, buf, start, len,
-                       Stream->Class->write);
+       return Stream->Class->write(Stream, buf, len);
 }
 
-ssize_t force_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+ssize_t force_write(Stream_t *Stream, char *buf, size_t len)
 {
-       return force_io(Stream, buf, start, len,
-                                       Stream->Class->read);
+       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_pio(Stream, buf, start, len,
+                        Stream->Class->pwrite);
+}
+
+ssize_t force_pread(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+{
+       return force_pio(Stream, buf, start, len,
+                        Stream->Class->pread);
 }
diff --git a/fs.h b/fs.h
index aa0371d..f856be8 100644 (file)
--- a/fs.h
+++ b/fs.h
 #include "stream.h"
 
 
-typedef struct FsPublic_t {
-       Class_t *Class;
-       int refs;
-       Stream_t *Next;
-       Stream_t *Buffer;
-
-       int serialized;
-       unsigned long serial_number;
-       uint8_t cluster_size;
-       uint16_t 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);
@@ -40,4 +28,9 @@ int fat_error(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 42f3eff..d8deaea 100644 (file)
--- a/fsP.h
+++ b/fsP.h
@@ -27,17 +27,12 @@ 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;
        uint8_t cluster_size;
        uint16_t sector_size;
-       /* Beware: anything up to this point is duplicated in
-          FsPublic_t in fs.h */
        
        int fat_error;
 
@@ -45,7 +40,6 @@ typedef struct Fs_t {
        void (*fat_encode)(struct Fs_t *This, unsigned int num,
                           unsigned int code);
 
-       Stream_t *Direct;
        int fat_dirty;
        uint16_t fat_start;
        uint32_t fat_len;
diff --git a/init.c b/init.c
index bb9d698..4b9b7e5 100644 (file)
--- a/init.c
+++ b/init.c
@@ -51,7 +51,7 @@ static int read_boot(Stream_t *Stream, union bootsector * boot, size_t size)
        if(size > MAX_BOOT)
                size = MAX_BOOT;
 
-       if (force_read(Stream, boot->characters, 0, size) != (ssize_t) size)
+       if (force_pread(Stream, boot->characters, 0, size) != (ssize_t) size)
                return -1;
 
        boot_sector_size = WORD(secsiz);
@@ -79,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 */
@@ -104,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,512,512) == 512)
+               if (force_pread(St,temp,512,512) == 512)
                        media = (unsigned char) temp[0];
                else
                        media = 0;
@@ -501,11 +503,7 @@ Stream_t *fs_init(char drive, int mode, int *isRop)
        if (!This)
                return NULL;
 
-       This->Direct = NULL;
-       This->Next = NULL;
-       This->refs = 1;
-       This->Buffer = 0;
-       This->Class = &FsClass;
+       init_head(&This->head, &FsClass, NULL);
        This->preallocatedClusters = 0;
        This->lastFatSectorNr = 0;
        This->lastFatAccessMode = 0;
@@ -513,9 +511,9 @@ Stream_t *fs_init(char drive, int mode, int *isRop)
        This->drive = drive;
        This->last = 0;
 
-       This->Direct = find_device(drive, mode, &dev, &boot, name, &media,
-                                  &maxSize, isRop);
-       if(!This->Direct)
+       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;
@@ -565,25 +563,24 @@ 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, 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;
        }
 
@@ -592,8 +589,8 @@ Stream_t *fs_init(char drive, int mode, int *isRop)
        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;
        }
 
@@ -604,7 +601,7 @@ 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;
index 37bf243..b269d85 100644 (file)
--- a/mattrib.1
+++ b/mattrib.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mattrib 1 "06Aug21" mtools-4.0.35
+.TH mattrib 1 "21Nov21" mtools-4.0.36
 .SH Name
 mattrib - change MSDOS file attribute flags
 '\" t
index d08c316..73c673f 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.TH mbadblocks 1 "06Aug21" mtools-4.0.35
+.TH mbadblocks 1 "21Nov21" mtools-4.0.36
 .SH Name
 mbadblocks - tests a floppy disk, and marks the bad blocks in the FAT
 '\" t
index 684d2cc..e1dcdfa 100644 (file)
@@ -84,11 +84,11 @@ static int scan(Fs_t *Fs, Stream_t *dev,
        start = (cluster - 2) * Fs->cluster_size + Fs->clus_start;
        pos = sectorsToBytes(Fs, start);
        if(doWrite) {
-               ret = force_write(dev, buffer, pos, 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) {
@@ -190,8 +190,8 @@ void mbadblocks(int argc, char **argv, int type UNUSEDP)
        }
        for(i=0; i < Fs->clus_start; i++ ){
                ssize_t r;
-               r = READS(Fs->Next, in_buf,
-                         sectorsToBytes(Fs, i), Fs->sector_size);
+               r = PREADS(Fs->head.Next, in_buf,
+                          sectorsToBytes(Fs, i), Fs->sector_size);
                if( r < 0 ){
                        perror("early error");
                        ret = -1;
@@ -238,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;
 
diff --git a/mcat.1 b/mcat.1
index a5174a1..fa44608 100644 (file)
--- a/mcat.1
+++ b/mcat.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mcat 1 "06Aug21" mtools-4.0.35
+.TH mcat 1 "21Nov21" mtools-4.0.36
 .SH Name
 mcat - dump raw disk image
 '\" t
diff --git a/mcat.c b/mcat.c
index 8616def..c0633e6 100644 (file)
--- a/mcat.c
+++ b/mcat.c
@@ -131,7 +131,7 @@ void mcat(int argc, char **argv, int type UNUSEDP)
                while ((len = fread(buf, 1,
                                    bufLen(BUF_SIZE, size, address),
                                    stdin)) > 0) {
-                       ssize_t r = WRITES(Stream, buf, address, len);
+                       ssize_t r = PWRITES(Stream, buf, address, len);
                        fprintf(stderr, "Wrote to %d\n", (int) address);
                        if(r < 0)
                                break;
@@ -139,7 +139,7 @@ void mcat(int argc, char **argv, int type UNUSEDP)
                }
        } else {
                ssize_t len;
-               while ((len = READS(Stream, buf, address, BUF_SIZE)) > 0) {
+               while ((len = PREADS(Stream, buf, address, BUF_SIZE)) > 0) {
                        fwrite(buf, 1, (size_t) len, stdout);
                        address += (size_t) len;
                }
diff --git a/mcd.1 b/mcd.1
index eea447a..8aad260 100644 (file)
--- a/mcd.1
+++ b/mcd.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mcd 1 "06Aug21" mtools-4.0.35
+.TH mcd 1 "21Nov21" mtools-4.0.36
 .SH Name
 mcd - change MSDOS directory
 '\" t
index d5fd399..6785c69 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.TH mclasserase 1 "06Aug21" mtools-4.0.35
+.TH mclasserase 1 "21Nov21" mtools-4.0.36
 .SH Name
 mclasserase - erase memory cards
 '\" t
diff --git a/mcopy.1 b/mcopy.1
index da924b5..c96dccd 100644 (file)
--- a/mcopy.1
+++ b/mcopy.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mcopy 1 "06Aug21" mtools-4.0.35
+.TH mcopy 1 "21Nov21" mtools-4.0.36
 .SH Name
 mcopy - copy MSDOS files to/from Unix
 '\" t
diff --git a/mcopy.c b/mcopy.c
index 0cb1cd3..c96089c 100644 (file)
--- 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
@@ -163,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))) {
-               mt_off_t 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;
@@ -290,13 +289,12 @@ static int writeit(struct dos_name_t *dosname,
        mt_off_t ret;
        uint32_t fat;
        time_t date;
-       mt_off_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;
        }
@@ -335,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, (uint32_t)newsize,
+               mk_entry(dosname, arg->attr, fat, (uint32_t)ret,
                                 now, &entry->dir);
                return 0;
        }
diff --git a/mdel.1 b/mdel.1
index 97474ee..3bd735f 100644 (file)
--- a/mdel.1
+++ b/mdel.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mdel 1 "06Aug21" mtools-4.0.35
+.TH mdel 1 "21Nov21" mtools-4.0.36
 .SH Name
 mdel - delete an MSDOS file
 '\" t
index 9862a08..d04b5ac 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.TH mdeltree 1 "06Aug21" mtools-4.0.35
+.TH mdeltree 1 "21Nov21" mtools-4.0.36
 .SH Name
 mdeltree - recursively delete an MSDOS directory and its contents
 '\" t
diff --git a/mdir.1 b/mdir.1
index fbd34e9..10b564d 100644 (file)
--- a/mdir.1
+++ b/mdir.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mdir 1 "06Aug21" mtools-4.0.35
+.TH mdir 1 "21Nov21" mtools-4.0.36
 .SH Name
 mdir - display an MSDOS directory
 '\" t
diff --git a/mdir.c b/mdir.c
index a6ba92e..b1d4685 100644 (file)
--- a/mdir.c
+++ b/mdir.c
@@ -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;
@@ -210,10 +210,12 @@ 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;
 }
 
@@ -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
@@ -602,9 +604,10 @@ void mdir(int argc, char **argv, int type UNUSEDP)
                mp.dirCallback = test_directory;
        } 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/mdu.1 b/mdu.1
index 9ac990d..a4103ae 100644 (file)
--- a/mdu.1
+++ b/mdu.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mdu 1 "06Aug21" mtools-4.0.35
+.TH mdu 1 "21Nov21" mtools-4.0.36
 .SH Name
 mdu - display the amount of space occupied by an MSDOS directory
 '\" t
index 795c856..bc3eeda 100644 (file)
--- a/mformat.1
+++ b/mformat.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mformat 1 "06Aug21" mtools-4.0.35
+.TH mformat 1 "21Nov21" mtools-4.0.36
 .SH Name
 mformat - add an MSDOS filesystem to a low-level formatted floppy disk
 '\" t
index 1f3858c..75cc926 100644 (file)
--- a/mformat.c
+++ b/mformat.c
@@ -203,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(Fs, i),
-                          Fs->sector_size);
+               PWRITES(RootDir, buf, sectorsToBytes(Fs, i),
+                       Fs->sector_size);
 
        ch.ignore_entry = 1;
        if(label[0])
@@ -778,9 +778,7 @@ int calc_fs_parameters(struct device *dev, bool fat32,
 void initFsForFormat(Fs_t *Fs)
 {
        memset(Fs, 0, sizeof(*Fs));
-
-       Fs->Class = &FsClass;
-       Fs->refs = 1;
+       init_head(&Fs->head, &FsClass, NULL);
 
        Fs->cluster_size = 0;
        Fs->dir_len = 0;
@@ -821,49 +819,6 @@ static int old_dos_size_to_geom(size_t size,
                return 1;
 }
 
-static void checkOverflow(uint32_t tot_sectors, int bits) {
-       if(tot_sectors > UINT32_MAX >> bits) {
-               fprintf(stderr, "Too many sectors\n");
-               exit(1);
-       }
-}
-
-static uint32_t parseSize(char *sizeStr) {
-       char *eptr;
-       uint32_t tot_sectors = strtou32(sizeStr, &eptr, 10);
-       if(eptr == optarg) {
-               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;
-}
-
 static void usage(int ret) NORETURN;
 static void usage(int ret)
 {
@@ -1181,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;
@@ -1210,20 +1164,20 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
 #endif
                if(tot_sectors)
                        used_dev.tot_sectors = tot_sectors;
-               Fs->Direct = OpenImage(&used_dev, dev, name,
-                                     O_RDWR|create, errmsg,
-                                     ALWAYS_GET_GEOMETRY,
-                                     O_RDWR,
-                                     &maxSize, NULL,
+               Fs->head.Next = OpenImage(&used_dev, dev, name,
+                                         O_RDWR|create, errmsg,
+                                         ALWAYS_GET_GEOMETRY,
+                                         O_RDWR,
+                                         &maxSize, NULL,
 #ifdef USE_XDF
-                                     &info
+                                         &info
 #else
-                                     NULL
+                                         NULL
 #endif
-                                     );
+                                         );
 
 #ifdef USE_XDF
-               if(Fs->Direct && info.FatSize) {
+               if(Fs->head.Next && info.FatSize) {
                        if(!Fs->fat_len)
                                Fs->fat_len = info.FatSize;
                        if(!Fs->dir_len)
@@ -1231,7 +1185,7 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
                }
 #endif
 
-               if (!Fs->Direct)
+               if (!Fs->head.Next)
                        continue;
 
                if(tot_sectors)
@@ -1250,7 +1204,7 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
                if(chs_to_totsectors(&used_dev, errmsg) < 0 ||
                   check_if_sectors_fit(dev->tot_sectors, maxSize, blocksize,
                                        errmsg) < 0) {
-                       FREE(&Fs->Direct);
+                       FREE(&Fs->head.Next);
                        continue;
                }
 
@@ -1259,7 +1213,8 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
 
                /* do a "test" read */
                if (!create &&
-                   READS(Fs->Direct, &boot.characters, 0, 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,
@@ -1270,7 +1225,7 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
                                "Error reading from '%s', wrong parameters?",
                                name);
 #endif
-                       FREE(&Fs->Direct);
+                       FREE(&Fs->head.Next);
                        continue;
                }
                break;
@@ -1278,7 +1233,7 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
 
        /* 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);
        }
@@ -1290,9 +1245,9 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
 
        /* create the image file if needed */
        if (create) {
-               WRITES(Fs->Direct, &boot.characters,
-                      sectorsToBytes(Fs, tot_sectors-1),
-                      Fs->sector_size);
+               PWRITES(Fs->head.Next, &boot.characters,
+                       sectorsToBytes(Fs, tot_sectors-1),
+                       Fs->sector_size);
        }
 
        /* the boot sector */
@@ -1316,11 +1271,10 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
        if(!keepBoot && !(used_dev.use_2m & 0x7f))
                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;
        if(!keepBoot)
@@ -1465,15 +1419,15 @@ void mformat(int argc, char **argv, int dummy UNUSEDP)
 #endif
 
        format_root(Fs, label, &boot);
-       if(WRITES((Stream_t *)Fs, boot.characters, 0, Fs->sector_size) < 0) {
+       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) {
-               if(WRITES((Stream_t *)Fs, boot.characters,
-                         sectorsToBytes(Fs, WORD_S(ext.fat32.backupBoot)),
-                         Fs->sector_size) < 0) {
+               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);
                }
diff --git a/minfo.1 b/minfo.1
index adb447c..ba80f59 100644 (file)
--- a/minfo.1
+++ b/minfo.1
@@ -1,5 +1,5 @@
 '\" t
-.TH minfo 1 "06Aug21" mtools-4.0.35
+.TH minfo 1 "21Nov21" mtools-4.0.36
 .SH Name
 minfo - print the parameters of a MSDOS filesystem
 '\" t
diff --git a/minfo.c b/minfo.c
index 7f46d72..07a1773 100644 (file)
--- a/minfo.c
+++ b/minfo.c
@@ -45,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)
@@ -333,7 +333,7 @@ void minfo(int argc, char **argv, int type UNUSEDP)
                                exit(1);
                        }
 
-                       ssize = READS(Stream, buf, 0, size);
+                       ssize = PREADS(Stream, buf, 0, size);
                        if(ssize < 0) {
                                perror("read boot sector");
                                exit(1);
index 410f851..496b496 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.TH mkmanifest 1 "06Aug21" mtools-4.0.35
+.TH mkmanifest 1 "21Nov21" mtools-4.0.36
 .SH Name
 mkmanifest - makes list of file names and their DOS 8+3 equivalent
 '\" t
index 9663c87..6f289e3 100644 (file)
--- a/mlabel.1
+++ b/mlabel.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mlabel 1 "06Aug21" mtools-4.0.35
+.TH mlabel 1 "21Nov21" mtools-4.0.36
 .SH Name
 mlabel - make an MSDOS volume label
 '\" t
index 380e781..4b08791 100644 (file)
--- a/mlabel.c
+++ b/mlabel.c
@@ -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));
        }
 
@@ -320,13 +320,13 @@ void mlabel(int argc, char **argv, int type UNUSEDP)
        }
 
        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 a2fc353..a864fb4 100644 (file)
--- a/mmd.1
+++ b/mmd.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mmd 1 "06Aug21" mtools-4.0.35
+.TH mmd 1 "21Nov21" mtools-4.0.36
 .SH Name
 mmd - make an MSDOS subdirectory
 '\" t
diff --git a/mmd.c b/mmd.c
index b8f74fe..b252a27 100644 (file)
--- a/mmd.c
+++ b/mmd.c
@@ -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);
index 984b299..8d27833 100644 (file)
--- a/mmount.1
+++ b/mmount.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mmount 1 "06Aug21" mtools-4.0.35
+.TH mmount 1 "21Nov21" mtools-4.0.36
 .SH Name
 mmount - mount an MSDOS disk
 '\" t
diff --git a/mmove.1 b/mmove.1
index 9fecda7..985f884 100644 (file)
--- a/mmove.1
+++ b/mmove.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mmove 1 "06Aug21" mtools-4.0.35
+.TH mmove 1 "21Nov21" mtools-4.0.36
 .SH Name
 mmove - move or rename an MSDOS file or subdirectory
 '\" t
index 55ad600..2023ecf 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.TH mpartition 1 "06Aug21" mtools-4.0.35
+.TH mpartition 1 "21Nov21" mtools-4.0.36
 .SH Name
 mpartition - partition an MSDOS hard disk
 '\" t
index fa660f8..efc5d40 100644 (file)
@@ -379,7 +379,7 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
                                break;
                        case 'l':
                                size_set = 1;
-                               length = strtoui(optarg, &endptr, 0);
+                               length = parseSize(optarg);
                                break;
 
                        default:
@@ -442,7 +442,7 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
                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?",
@@ -671,7 +671,7 @@ void mpartition(int argc, char **argv, int dummy UNUSEDP)
                /* 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 8666f8a..455d6a2 100644 (file)
--- a/mrd.1
+++ b/mrd.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mrd 1 "06Aug21" mtools-4.0.35
+.TH mrd 1 "21Nov21" mtools-4.0.36
 .SH Name
 mrd - remove an MSDOS subdirectory
 '\" t
diff --git a/mren.1 b/mren.1
index 0071bf5..3e025c2 100644 (file)
--- a/mren.1
+++ b/mren.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mren 1 "06Aug21" mtools-4.0.35
+.TH mren 1 "21Nov21" mtools-4.0.36
 .SH Name
 mren - rename an existing MSDOS file
 '\" t
index 8674262..d0dd03b 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.TH mshortname 1 "06Aug21" mtools-4.0.35
+.TH mshortname 1 "21Nov21" mtools-4.0.36
 .SH Name
 mshortname - shows short name of a file
 '\" t
index 0ba2d6b..97d6e99 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.TH mshowfat 1 "06Aug21" mtools-4.0.35
+.TH mshowfat 1 "21Nov21" mtools-4.0.36
 .SH Name
 mshowfat - shows FAT clusters allocated to file
 '\" t
index 724fd3c..18cd98e 100644 (file)
--- a/mtools.1
+++ b/mtools.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mtools 1 "23Jul21" mtools-4.0.34
+.TH mtools 1 "20Nov21" mtools-4.0.35
 .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.34.tar.gz
+http://ftp.gnu.org/gnu/mtools/mtools-4.0.35.tar.gz
 .fi
 .in -0.3i
 .ft R
index 3744e18..fd7d5dc 100644 (file)
--- a/mtools.5
+++ b/mtools.5
@@ -1,5 +1,5 @@
 '\" t
-.TH mtools 5 "23Jul21" MTOOLS MTOOLS
+.TH mtools 5 "20Nov21" 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.34
+.ds St Mtools\ 4.0.35
 .PP
 .SH Description
 .PP
index d417f80..9efe22f 100644 (file)
--- a/mtools.h
+++ b/mtools.h
@@ -94,7 +94,6 @@ 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);
@@ -103,7 +102,8 @@ wchar_t *unix_name(doscp_t *fromDos,
                   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);
@@ -185,6 +185,7 @@ 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
@@ -200,7 +201,7 @@ uint32_t atou32(const char *str);
 
 #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);
index 3e6b80d..cd125aa 100644 (file)
@@ -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.35, August 2021), which is a
+This manual is for Mtools (version 4.0.36, November 2021), 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.35, August 2021), which is a
+   This manual is for Mtools (version 4.0.36, November 2021), 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.35.tar.gz
+     http://ftp.gnu.org/gnu/mtools/mtools-4.0.36.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
@@ -2723,71 +2723,76 @@ Concept index
 
 \1f
 Tag Table:
-Node: Top\7f870
-Node: Location\7f3125
-Node: Common features\7f4063
-Node: arguments\7f4827
-Node: drive letters\7f6488
-Node: directory\7f7842
-Node: long names\7f8288
-Node: name clashes\7f10834
-Node: case sensitivity\7f13118
-Node: high capacity formats\7f14355
-Node: more sectors\7f15400
-Node: bigger sectors\7f16455
-Node: 2m\7f17184
-Node: XDF\7f18370
-Node: exit codes\7f19713
-Node: bugs\7f20351
-Node: Configuration\7f20884
-Node: configuration file location\7f22173
-Node: general syntax\7f22626
-Node: default values\7f23457
-Node: global variables\7f23985
-Node: per drive variables\7f26178
-Node: general information\7f27013
-Node: location information\7f27455
-Node: geometry description\7f28984
-Node: open flags\7f32845
-Node: miscellaneous variables\7f33445
-Node: miscellaneous flags\7f37035
-Node: multiple descriptions\7f40665
-Node: parsing order\7f42339
-Node: old style configuration\7f43370
-Node: Commands\7f44069
-Node: floppyd\7f45991
-Node: floppyd_installtest\7f50784
-Node: mattrib\7f51415
-Node: mbadblocks\7f53210
-Node: mcat\7f54504
-Node: mcd\7f55318
-Node: mclasserase\7f56179
-Node: mcopy\7f56855
-Node: mdel\7f59873
-Node: mdeltree\7f60212
-Node: mdir\7f60631
-Node: mdu\7f61907
-Node: mformat\7f62413
-Node: mkmanifest\7f70924
-Node: minfo\7f72898
-Node: mlabel\7f73468
-Node: mmd\7f74621
-Node: mmount\7f74970
-Node: mmove\7f75573
-Node: mpartition\7f76378
-Node: mrd\7f81904
-Node: mren\7f82262
-Node: mshortname\7f83011
-Node: mshowfat\7f83341
-Node: mtoolstest\7f83750
-Node: mtype\7f84322
-Node: mzip\7f85173
-Ref: mzip-Footnote-1\7f87198
-Ref: mzip-Footnote-2\7f87279
-Node: Compiling mtools\7f87566
-Node: Porting mtools\7f88665
-Node: Command Index\7f94573
-Node: Variable Index\7f94701
-Node: Concept Index\7f96524
+Node: Top\7f872
+Node: Location\7f3129
+Node: Common features\7f4067
+Node: arguments\7f4831
+Node: drive letters\7f6492
+Node: directory\7f7846
+Node: long names\7f8292
+Node: name clashes\7f10838
+Node: case sensitivity\7f13122
+Node: high capacity formats\7f14359
+Node: more sectors\7f15404
+Node: bigger sectors\7f16459
+Node: 2m\7f17188
+Node: XDF\7f18374
+Node: exit codes\7f19717
+Node: bugs\7f20355
+Node: Configuration\7f20888
+Node: configuration file location\7f22177
+Node: general syntax\7f22630
+Node: default values\7f23461
+Node: global variables\7f23989
+Node: per drive variables\7f26182
+Node: general information\7f27017
+Node: location information\7f27459
+Node: geometry description\7f28988
+Node: open flags\7f32849
+Node: miscellaneous variables\7f33449
+Node: miscellaneous flags\7f37039
+Node: multiple descriptions\7f40669
+Node: parsing order\7f42343
+Node: old style configuration\7f43374
+Node: Commands\7f44073
+Node: floppyd\7f45995
+Node: floppyd_installtest\7f50788
+Node: mattrib\7f51419
+Node: mbadblocks\7f53214
+Node: mcat\7f54508
+Node: mcd\7f55322
+Node: mclasserase\7f56183
+Node: mcopy\7f56859
+Node: mdel\7f59877
+Node: mdeltree\7f60216
+Node: mdir\7f60635
+Node: mdu\7f61911
+Node: mformat\7f62417
+Node: mkmanifest\7f70928
+Node: minfo\7f72902
+Node: mlabel\7f73472
+Node: mmd\7f74625
+Node: mmount\7f74974
+Node: mmove\7f75577
+Node: mpartition\7f76382
+Node: mrd\7f81908
+Node: mren\7f82266
+Node: mshortname\7f83015
+Node: mshowfat\7f83345
+Node: mtoolstest\7f83754
+Node: mtype\7f84326
+Node: mzip\7f85177
+Ref: mzip-Footnote-1\7f87202
+Ref: mzip-Footnote-2\7f87283
+Node: Compiling mtools\7f87570
+Node: Porting mtools\7f88669
+Node: Command Index\7f94577
+Node: Variable Index\7f94705
+Node: Concept Index\7f96528
 \1f
 End Tag Table
+
+\1f
+Local Variables:
+coding: utf-8
+End:
index 20ed218..9b1a2f6 100644 (file)
@@ -1,7 +1,7 @@
 %define _binary_payload w9.gzdio
 Name:           mtools
 Summary:        mtools, read/write/list/format DOS disks under Unix
-Version:        4.0.35
+Version:        4.0.36
 Release:        1
 License:        GPLv3+
 Group:          Utilities/System
@@ -135,6 +135,12 @@ if [ -f %{_bindir}/install-info ] ; then
 fi
 
 %changelog
+* 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
index b9af635..cae1d40 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.TH mtools 1 "06Aug21" mtools-4.0.35
+.TH mtools 1 "21Nov21" mtools-4.0.36
 .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.35.tar.gz
+http://ftp.gnu.org/gnu/mtools/mtools-4.0.36.tar.gz
 .fi
 .in -0.3i
 .ft R
index 787afe2..030ec73 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.TH mtools 5 "06Aug21" MTOOLS MTOOLS
+.TH mtools 5 "21Nov21" 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.35
+.ds St Mtools\ 4.0.36
 .PP
 .SH Description
 .PP
index 95b7029..78ef3b8 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.TH mtoolstest 1 "06Aug21" mtools-4.0.35
+.TH mtoolstest 1 "21Nov21" mtools-4.0.36
 .SH Name
 mtoolstest - tests and displays the configuration
 '\" t
diff --git a/mtype.1 b/mtype.1
index bf3a606..8a19266 100644 (file)
--- a/mtype.1
+++ b/mtype.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mtype 1 "06Aug21" mtools-4.0.35
+.TH mtype 1 "21Nov21" mtools-4.0.36
 .SH Name
 mtype - display contents of an MSDOS file
 '\" t
diff --git a/mzip.1 b/mzip.1
index 52d6015..2d3a62d 100644 (file)
--- a/mzip.1
+++ b/mzip.1
@@ -1,5 +1,5 @@
 '\" t
-.TH mzip 1 "06Aug21" mtools-4.0.35
+.TH mzip 1 "21Nov21" mtools-4.0.36
 .SH Name
 mzip - change protection mode and eject disk on Zip/Jaz drive
 '\" t
diff --git a/mzip.c b/mzip.c
index ebd9a30..1148fa3 100644 (file)
--- a/mzip.c
+++ b/mzip.c
@@ -245,7 +245,7 @@ void mzip(int argc, char **argv, int type UNUSEDP)
        if(request & ZIP_MODE_CHANGE) usage(1); \
        request |= ZIP_MODE_CHANGE; \
        newMode = x; \
-       break;
+       break
 
        /* get command line options */
        if(helpFlag(argc, argv))
@@ -279,7 +279,7 @@ 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 */
index f84718c..e8be549 100644 (file)
--- a/offset.c
+++ b/offset.c
 #include "offset.h"
 
 typedef struct Offset_t {
-       struct Class_t *Class;
-       int refs;
-       struct Stream_t *Next;
-       struct Stream_t *Buffer;
+       struct Stream_t head;
 
        mt_off_t offset;
 } Offset_t;
 
-static ssize_t offset_read(Stream_t *Stream, char *buf,
-                         mt_off_t start, size_t len)
+static ssize_t offset_pread(Stream_t *Stream, char *buf,
+                           mt_off_t start, size_t len)
 {
        DeclareThis(Offset_t);
-       return READS(This->Next, buf, start+This->offset, len);
+       return PREADS(This->head.Next, buf, start+This->offset, len);
 }
 
-static ssize_t offset_write(Stream_t *Stream, char *buf,
-                          mt_off_t start, size_t len)
+static ssize_t offset_pwrite(Stream_t *Stream, char *buf,
+                            mt_off_t start, size_t len)
 {
        DeclareThis(Offset_t);
-       return WRITES(This->Next, buf, start+This->offset, len);
+       return PWRITES(This->head.Next, buf, start+This->offset, len);
 }
 
 static Class_t OffsetClass = {
-       offset_read,
-       offset_write,
+       0,
+       0,
+       offset_pread,
+       offset_pwrite,
        0, /* flush */
        0, /* free */
        set_geom_pass_through, /* set_geom */
@@ -67,9 +66,7 @@ Stream_t *OpenOffset(Stream_t *Next, struct device *dev, off_t offset,
                return 0;
        }
        memset((void*)This, 0, sizeof(Offset_t));
-       This->Class = &OffsetClass;
-       This->refs = 1;
-       This->Next = Next;
+       init_head(&This->head, &OffsetClass, Next);
 
        This->offset = offset;
 
@@ -86,7 +83,7 @@ Stream_t *OpenOffset(Stream_t *Next, struct device *dev, off_t offset,
        if(adjust_tot_sectors(dev, This->offset, errmsg) < 0)
                goto exit_0;
 
-       return (Stream_t *) This;
+       return &This->head;
  exit_0:
        Free(This);
        return NULL;
index 16b351b..240f0f5 100644 (file)
 #include "partition.h"
 
 typedef struct Partition_t {
-       struct Class_t *Class;
-       int refs;
-       struct Stream_t *Next;
-       struct Stream_t *Buffer;
+       struct Stream_t head;
 
        mt_off_t offset; /* Offset, in bytes */
        mt_off_t size; /* size, in bytes */
@@ -140,22 +137,22 @@ static int limit_size(Partition_t *This, mt_off_t start, size_t *len)
        return 0;
 }
 
-static ssize_t partition_read(Stream_t *Stream, char *buf,
-                             mt_off_t start, size_t len)
+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 READS(This->Next, buf, start+This->offset, len);
+       return PREADS(This->head.Next, buf, start+This->offset, len);
 }
 
-static ssize_t partition_write(Stream_t *Stream, char *buf,
-                              mt_off_t start, size_t 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 WRITES(This->Next, buf, start+This->offset, len);
+       return PWRITES(This->head.Next, buf, start+This->offset, len);
 }
 
 static int partition_data(Stream_t *Stream, time_t *date, mt_off_t *size,
@@ -164,7 +161,7 @@ static int partition_data(Stream_t *Stream, time_t *date, mt_off_t *size,
        DeclareThis(Partition_t);
 
        if(date || type || address) {
-               int ret = GET_DATA(This->Next, date, NULL, type, address);
+               int ret = GET_DATA(This->head.Next, date, NULL, type, address);
                if(ret < 0)
                        return ret;
        }
@@ -186,8 +183,10 @@ static int partition_geom(Stream_t *Stream, struct device *dev,
 }
 
 static Class_t PartitionClass = {
-       partition_read,
-       partition_write,
+       0,
+       0,
+       partition_pread,
+       partition_pwrite,
        0, /* flush */
        0, /* free */
        partition_geom, /* set_geom */
@@ -219,13 +218,11 @@ Stream_t *OpenPartition(Stream_t *Next, struct device *dev,
                return 0;
        }
        memset((void*)This, 0, sizeof(Partition_t));
-       This->Class = &PartitionClass;
-       This->refs = 1;
-       This->Next = Next;
+       init_head(&This->head, &PartitionClass, Next);
 
 
        /* read the first sector, or part of it */
-       if (force_read(This->Next, (char*) buf, 0, 512) != 512)
+       if (force_pread(This->head.Next, (char*) buf, 0, 512) != 512)
                goto exit_0;
        if( _WORD(buf+510) != 0xaa55) {
                /* Not a partition table */
@@ -276,7 +273,7 @@ Stream_t *OpenPartition(Stream_t *Next, struct device *dev,
        }
        dev->tot_sectors = This->nbSect = PART_SIZE(partition);
        This->size = (mt_off_t) This->nbSect << 9;
-       return (Stream_t *) This;
+       return &This->head;
  exit_0:
        Free(This);
        return NULL;
index f0ab6e9..41672ed 100644 (file)
 #include "sysincludes.h"
 #include "msdos.h"
 
-const char *mversion="4.0.35";
+const char *mversion="4.0.36";
 
 /* Multiple releases on same day should be marked with (b), (cd), (d) after
  * date string below */
-const char *mdate = "August 6th, 2021";
+const char *mdate = "November 21st, 2021";
 
-const char *mformat_banner = "MTOO4035";
+const char *mformat_banner = "MTOO4036";
index a1cf445..9a40e12 100644 (file)
 #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 lastwhere;
@@ -56,18 +54,19 @@ typedef struct SimpleFile_t {
 
 typedef ssize_t (*iofn) (int, void *, size_t);
 
-static ssize_t file_io(Stream_t *Stream, char *buf, mt_off_t where, size_t len,
+static ssize_t file_io(SimpleFile_t *This, char *buf,
+                      mt_off_t where, size_t len,
                       iofn io)
 {
-       DeclareThis(SimpleFile_t);
        ssize_t ret;
 
        if (This->seekable && where != This->lastwhere ){
                if(mt_lseek( This->fd, where, SEEK_SET) < 0 ){
                        perror("seek");
-                       This->lastwhere = -1;
-                       return -1;
+                       return -1; /* If seek failed, lastwhere did
+                                     not change */
                }
+               This->lastwhere = where;
        }
 
 #ifdef OS_hpux
@@ -93,25 +92,36 @@ static ssize_t file_io(Stream_t *Stream, char *buf, mt_off_t where, size_t len,
 
        if ( ret == -1 ){
                perror("plain_io");
-               This->lastwhere = -1;
                return -1;
        }
        This->lastwhere = where + ret;
        return ret;
 }
 
+static ssize_t file_read(Stream_t *Stream, char *buf, size_t len)
+{
+       DeclareThis(SimpleFile_t);
+       return file_io(This, buf, This->lastwhere, len, read);
+}
 
-
-static ssize_t file_read(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)
 {
-       return file_io(Stream, buf, where, len, read);
+       DeclareThis(SimpleFile_t);
+       return file_io(This, buf, This->lastwhere, len, (iofn) write);
 }
 
-static ssize_t file_write(Stream_t *Stream, char *buf,
+static ssize_t file_pread(Stream_t *Stream, char *buf,
                          mt_off_t where, size_t len)
 {
-       return file_io(Stream, buf, where, len, (iofn) write);
+       DeclareThis(SimpleFile_t);
+       return file_io(This, buf, where, len, read);
+}
+
+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)
@@ -220,6 +230,8 @@ static int file_discard(Stream_t *Stream UNUSEDP)
 static Class_t SimpleFileClass = {
        file_read,
        file_write,
+       file_pread,
+       file_pwrite,
        file_flush,
        file_free,
        file_geom,
@@ -296,16 +308,13 @@ APIRET rc;
 #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)
@@ -319,7 +328,7 @@ APIRET rc;
                    return NULL;
                }
 
-               return (Stream_t *) This;
+               return &This->head;
        }
 
 
@@ -428,16 +437,12 @@ APIRET rc;
                }
        }
 
-       This->refs = 1;
-       This->Next = 0;
-       This->Buffer = 0;
-
        if(maxSize)
                *maxSize = max_off_t_seek;
 
        This->lastwhere = 0;
 
-       return (Stream_t *) This;
+       return &This->head;
  exit_0:
        close(This->fd);
  exit_1:
@@ -449,7 +454,7 @@ int get_fd(Stream_t *Stream)
 {
        Class_t *clazz;
        DeclareThis(SimpleFile_t);
-       clazz = This->Class;
+       clazz = This->head.Class;
        if(clazz != &SimpleFileClass)
          return -1;
        else
diff --git a/remap.c b/remap.c
index 35bafbc..ab96d04 100644 (file)
--- a/remap.c
+++ b/remap.c
@@ -36,10 +36,7 @@ struct map {
 };
 
 typedef struct Remap_t {
-       struct Class_t *Class;
-       int refs;
-       struct Stream_t *Next;
-       struct Stream_t *Buffer;
+       struct Stream_t head;
 
        struct map *map;
        int mapSize;
@@ -58,24 +55,24 @@ static enum map_type_t remap(Remap_t *This, mt_off_t *start, size_t *len) {
        return This->map[i].type;
 }
 
-static ssize_t remap_read(Stream_t *Stream, char *buf,
+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 READS(This->Next, buf, start, len);
+               return PREADS(This->head.Next, buf, start, len);
        else {
                memset(buf, 0, len);
                return (ssize_t) len;
        }
 }
 
-static ssize_t remap_write(Stream_t *Stream, char *buf,
+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 WRITES(This->Next, buf, start, len);
+               return PWRITES(This->head.Next, buf, start, len);
        else {
                unsigned int i;
                /* When writing to a "zero" sector, make sure that we
@@ -102,8 +99,10 @@ static int remap_free(Stream_t *Stream)
 }
 
 static Class_t RemapClass = {
-       remap_read,
-       remap_write,
+       0,
+       0,
+       remap_pread,
+       remap_pwrite,
        0, /* flush */
        remap_free, /* free */
        set_geom_pass_through, /* set_geom */
@@ -189,9 +188,7 @@ Stream_t *Remap(Stream_t *Next, struct device *dev, char *errmsg) {
                return 0;
        }
        memset((void*)This, 0, sizeof(Remap_t));
-       This->Class = &RemapClass;
-       This->refs = 1;
-       This->Next = Next;
+       init_head(&This->head, &RemapClass, Next);
 
        /* First count number of items */
        nrItems=process_map(This, map, 1, errmsg);
@@ -212,7 +209,7 @@ Stream_t *Remap(Stream_t *Next, struct device *dev, char *errmsg) {
                goto exit_1;
 
        This->mapSize=nrItems;
-       return (Stream_t *) This;
+       return &This->head;
  exit_1:
        free(This->map);
  exit_0:
index f6e12b0..48abdcb 100644 (file)
--- a/scsi_io.c
+++ b/scsi_io.c
 #include "scsi_io.h"
 
 typedef struct ScsiDevice_t {
-       Class_t *Class;
-       int refs;
-       Stream_t *Next;
-       Stream_t *Buffer;
+       struct Stream_t head;
 
        int fd;
        int privileged;
@@ -232,7 +229,8 @@ static ssize_t scsi_io(Stream_t *Stream, char *buf,
        else return (ssize_t)(nsect*This->scsi_sector_size-offset);
 }
 
-static ssize_t scsi_read(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
+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);
@@ -240,8 +238,8 @@ static ssize_t scsi_read(Stream_t *Stream, char *buf, mt_off_t where, size_t len
        return scsi_io(Stream, buf, where, len, SCSI_IO_READ);
 }
 
-static ssize_t scsi_write(Stream_t *Stream, char *buf,
-                         mt_off_t where, size_t len)
+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);
@@ -264,8 +262,10 @@ static int scsi_get_data(Stream_t *Stream, time_t *date, mt_off_t *size,
 
 
 static Class_t ScsiDeviceClass = {
-       scsi_read,
-       scsi_write,
+       0,
+       0,
+       scsi_pread,
+       scsi_pwrite,
        0,
        0,
        set_geom_noop,
@@ -291,8 +291,8 @@ Stream_t *OpenScsi(struct device *dev,
                return 0;
        }
        memset((void*)This, 0, sizeof(ScsiDevice_t));
+       init_head(&This->head, &ScsiDeviceClass, NULL);
        This->scsi_sector_size = 512;
-       This->Class = &ScsiDeviceClass;
 
        if(dev) {
                if(!(mode2 & NO_PRIV))
@@ -330,13 +330,9 @@ Stream_t *OpenScsi(struct device *dev,
 
        if(LockDevice(This->fd, dev, locked, lockMode, errmsg) < 0)
                goto exit_0;
-       This->refs = 1;
-       This->Next = 0;
-       This->Buffer = 0;
 
        if(maxSize)
                *maxSize = MAX_OFF_T_B(31+log_2(This->scsi_sector_size));
-       This->Class = &ScsiDeviceClass;
        if(This->privileged)
                reclaim_privs();
        ret=scsi_init(This);
@@ -345,7 +341,7 @@ Stream_t *OpenScsi(struct device *dev,
        if(ret < 0)
                goto exit_0;
        dev->tot_sectors = This->tot_sectors;
-       return (Stream_t *) This;
+       return &This->head;
  exit_0:
        close(This->fd);
  exit_1:
index 8b54e81..97a1351 100644 (file)
--- a/stream.c
+++ b/stream.c
@@ -31,6 +31,12 @@ void limitSizeToOffT(size_t *len, mt_off_t maxLen)
                *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)
 {
@@ -92,16 +98,16 @@ int get_data_pass_through(Stream_t *Stream, time_t *date, mt_off_t *size,
        return GET_DATA(Stream->Next, date, size, type, address);
 }
 
-ssize_t 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);
 }
 
-ssize_t 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)
index 6fe3601..66dd0ed 100644 (file)
--- a/stream.h
+++ b/stream.h
@@ -22,7 +22,6 @@ typedef struct Stream_t {
        struct Class_t *Class;
        int refs;
        struct Stream_t *Next;
-       struct Stream_t *Buffer;
 } Stream_t;
 
 #include "mtools.h"
@@ -35,8 +34,10 @@ void limitSizeToOffT(size_t *len, mt_off_t maxLen);
 doscp_t *get_dosConvert_pass_through(Stream_t *Stream);
 
 typedef struct Class_t {
-       ssize_t (*read)(Stream_t *, char *, mt_off_t, size_t);
-       ssize_t (*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 *);
@@ -48,11 +49,17 @@ typedef struct Class_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, address, size) \
-((stream)->Class->write)( (stream), (char *) (buf), (address), (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 PWRITES(stream, buf, address, size) \
+((stream)->Class->pwrite)( (stream), (char *) (buf), (address), (size) )
 
 #define SET_GEOM(stream, dev, orig_dev) \
 (stream)->Class->set_geom( (stream), (dev), (orig_dev))
@@ -85,8 +92,12 @@ copy_stream( (stream) )
 
 #define DeclareThis(x) x *This = (x *) Stream
 
-ssize_t force_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len);
-ssize_t 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);
+
+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);
+
+ssize_t force_write(Stream_t *Stream, char *buf, size_t len);
 
 int set_geom_pass_through(Stream_t *Stream, device_t *dev, device_t *orig_dev);
 
@@ -95,10 +106,10 @@ 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 read_pass_through(Stream_t *Stream, char *buf,
-                         mt_off_t start, size_t len);
-ssize_t write_pass_through(Stream_t *Stream, char *buf,
+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);
index 4c9f55c..defa18d 100644 (file)
@@ -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/subdir.c b/subdir.c
deleted file mode 100644 (file)
index 164fc0e..0000000
--- a/subdir.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*  Copyright 1986-1992 Emmet P. Gray.
- *  Copyright 1996,1997,2001,2002,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 "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.
- */
-
-
-void bufferize(Stream_t **Dir)
-{
-       Stream_t *BDir;
-
-       if(!*Dir)
-               return;
-       BDir = buf_init(*Dir, 64*16384, 512, MDIR_SIZE);
-       if(!BDir){
-               FREE(Dir);
-               *Dir = NULL;
-       } else
-               *Dir = BDir;
-}
diff --git a/swap.c b/swap.c
index f809115..28aad1b 100644 (file)
--- a/swap.c
+++ b/swap.c
 #include "swap.h"
 
 typedef struct Swap_t {
-       struct Class_t *Class;
-       int refs;
-       struct Stream_t *Next;
-       struct Stream_t *Buffer;
-
+       struct Stream_t head;
 } Swap_t;
 
 static void swap_buffer(char *buf, size_t len)
@@ -41,19 +37,19 @@ static void swap_buffer(char *buf, size_t len)
 }
 
 
-static ssize_t swap_read(Stream_t *Stream, char *buf,
-                        mt_off_t where, size_t len)
+static ssize_t swap_pread(Stream_t *Stream, char *buf,
+                         mt_off_t where, size_t len)
 {
        DeclareThis(Swap_t);
 
-       ssize_t result = READS(This->Next, buf, where, len);
+       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_write(Stream_t *Stream, char *buf,
+static ssize_t swap_pwrite(Stream_t *Stream, char *buf,
                          mt_off_t where, size_t len)
 {
        DeclareThis(Swap_t);
@@ -63,7 +59,7 @@ static ssize_t swap_write(Stream_t *Stream, char *buf,
        memcpy( swapping, buf, len );
        swap_buffer( swapping, len );
 
-       result = WRITES(This->Next, swapping, where, len);
+       result = PWRITES(This->head.Next, swapping, where, len);
 
        free(swapping);
        return result;
@@ -71,8 +67,10 @@ static ssize_t swap_write(Stream_t *Stream, char *buf,
 
 
 static Class_t SwapClass = {
-       swap_read,
-       swap_write,
+       0,
+       0,
+       swap_pread,
+       swap_pwrite,
        0, /* flush */
        0, /* free */
        set_geom_pass_through, /* set_geom */
@@ -91,9 +89,7 @@ Stream_t *OpenSwap(Stream_t *Next) {
                return 0;
        }
        memset((void*)This, 0, sizeof(Swap_t));
-       This->Class = &SwapClass;
-       This->refs = 1;
-       This->Next = Next;
+       init_head(&This->head, &SwapClass, Next);
 
-       return (Stream_t *) This;
+       return &This->head;
 }
index e48383d..6e19429 100644 (file)
@@ -3,7 +3,7 @@
 % Load plain if necessary, i.e., if running under initex.
 \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
 %
-\def\texinfoversion{2021-04-25.21}
+\def\texinfoversion{2021-11-01.16}
 %
 % Copyright 1985, 1986, 1988, 1990-2021 Free Software Foundation, Inc.
 %
@@ -3614,6 +3614,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
@@ -7592,6 +7595,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
 %
 \def\printdefunline#1#2{%
   \begingroup
+    \plainfrenchspacing
     % call \deffnheader:
     #1#2 \endheader
     % common ending:
@@ -9402,7 +9406,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.
@@ -11599,11 +11603,9 @@ directory should work if nowhere else does.}
 @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:
diff --git a/unix2dos.c b/unix2dos.c
new file mode 100644 (file)
index 0000000..1415691
--- /dev/null
@@ -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;
+}
index 17b2172..7bd0dbc 100644 (file)
--- a/unixdir.c
+++ b/unixdir.c
 #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;
@@ -68,6 +65,8 @@ static int dir_free(Stream_t *Stream)
 static Class_t DirClass = {
        0, /* read */
        0, /* write */
+       0, /* pread */
+       0, /* pwrite */
        0, /* flush */
        dir_free, /* free */
        0, /* get_geom */
@@ -138,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);
@@ -163,5 +158,5 @@ Stream_t *OpenDir(const char *filename)
                return NULL;
        }
 
-       return (Stream_t *) This;
+       return &This->head;
 }
index d82aad0..0f62787 100644 (file)
@@ -1,3 +1,3 @@
-@set EDITION 4.0.35
-@set VERSION 4.0.35
-@set UPDATED August 2021
+@set EDITION 4.0.36
+@set VERSION 4.0.36
+@set UPDATED November 2021
diff --git a/vfat.c b/vfat.c
index 1761e14..01331bc 100644 (file)
--- a/vfat.c
+++ b/vfat.c
@@ -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
index 1339adf..d84fd53 100644 (file)
--- a/xdf_io.c
+++ b/xdf_io.c
@@ -85,10 +85,7 @@ 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;
@@ -509,8 +506,8 @@ static int decompose(Xdf_t *This, mt_off_t iwhere, size_t len,
 }
 
 
-static ssize_t xdf_read(Stream_t *Stream, char *buf,
-                       mt_off_t where, size_t len)
+static ssize_t xdf_pread(Stream_t *Stream, char *buf,
+                        mt_off_t where, size_t len)
 {
        uint32_t begin, end;
        ssize_t ret;
@@ -527,7 +524,8 @@ static ssize_t xdf_read(Stream_t *Stream, char *buf,
        return (ssize_t) (end - begin);
 }
 
-static ssize_t xdf_write(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
+static ssize_t xdf_pwrite(Stream_t *Stream, char *buf,
+                         mt_off_t where, size_t len)
 {
        uint32_t begin, end;
        ssize_t len2;
@@ -614,8 +612,10 @@ static int config_geom(Stream_t *Stream UNUSEDP, struct device *dev,
 }
 
 static Class_t XdfClass = {
-       xdf_read,
-       xdf_write,
+       0,
+       0,
+       xdf_pread,
+       xdf_pwrite,
        xdf_flush,
        xdf_free,
        config_geom,
@@ -641,8 +641,8 @@ Stream_t *XdfOpen(struct device *dev, const char *name,
        This = New(Xdf_t);
        if (!This)
                return NULL;
+       init_head(&This->head, &XdfClass, NULL);
 
-       This->Class = &XdfClass;
        This->sector_size = 512;
        This->stretch = 0;
 
@@ -726,12 +726,9 @@ Stream_t *XdfOpen(struct device *dev, const char *name,
        }
        decompose(This, 0, 512, &begin, &end, 1);
 
-       This->refs = 1;
-       This->Next = 0;
-       This->Buffer = 0;
        if(dev)
                set_geom(This, dev);
-       return (Stream_t *) This;
+       return &This->head;
 
 exit_3:
        Free(This->track_map);