# 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
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
+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
--- /dev/null
+--- 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
#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? */
{
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",
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;
}
}
-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;
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;
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);
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;
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 */
}
static Class_t BufferClass = {
- buf_read,
- buf_write,
+ 0,
+ 0,
+ buf_pread,
+ buf_pwrite,
buf_flush,
buf_free,
0, /* set_geom */
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) {
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;
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;
}
# 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
# 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
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]* \
*-*)
# 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
;;
*-*)
# 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*)
# 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*)
| 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*)
# 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
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;
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
+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
* 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)
{
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;
}
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;
if (!getfreeMinClusters(Dir, 1))
return -1;
- buflen = This->cluster_size * This->sector_size;
+ buflen = getClusterBytes(This);
if(! (buffer=malloc(buflen)) ){
perror("dir_grow: malloc");
}
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;
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);
}
/*
--- /dev/null
+/* 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;
+}
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);
}
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);
#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;
unsigned int loopDetectRel;
unsigned int loopDetectAbs;
+
+ uint32_t where;
} File_t;
static Class_t FileClass;
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)
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) {
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);
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;
}
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;
*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;
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;
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);
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){
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;
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;
} 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;
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
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);
static Class_t FileClass = {
read_file,
write_file,
+ pread_file,
+ pwrite_file,
flush_file, /* flush */
free_file, /* free */
0, /* get_geom */
{
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)
File_t *This2 = (File_t *) Stream2;
- return This->Fs != This2->Fs ||
+ return _getFs(This) != _getFs(This2) ||
getAbsCluNr(This) != getAbsCluNr(This2);
}
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
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;
}
}
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;
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
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;
--- /dev/null
+--- 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;
+ }
+
+
+++ /dev/null
-/* 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;
-}
'\" 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
'\" 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
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;
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);
}
/* ######################################################################## */
static Class_t FloppydFileClass = {
- floppyd_read,
- floppyd_write,
+ 0,
+ 0,
+ floppyd_pread,
+ floppyd_pwrite,
floppyd_flush,
floppyd_free,
set_geom_noop,
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) {
((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,
#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;
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);
}
#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);
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
} 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;
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;
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);
}
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 */
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;
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;
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;
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;
}
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;
}
{
DeclareThis(Fs_t);
- if(This->Class != &FsClass)
+ if(This->head.Class != &FsClass)
return getDrive(GetFs(Stream));
else
return This->drive;
'\" 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
'\" 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
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) {
}
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;
}
} else {
Stream_t *dev;
- dev = Fs->Next;
+ dev = Fs->head.Next;
if(dev->Next)
dev = dev->Next;
'\" 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
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;
}
} 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;
}
'\" t
-.TH mcd 1 "06Aug21" mtools-4.0.35
+.TH mcd 1 "21Nov21" mtools-4.0.36
.SH Name
mcd - change MSDOS directory
'\" t
'\" t
-.TH mclasserase 1 "06Aug21" mtools-4.0.35
+.TH mclasserase 1 "21Nov21" mtools-4.0.36
.SH Name
mclasserase - erase memory cards
'\" t
'\" 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
/* 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
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;
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;
}
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;
}
'\" 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
'\" 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
'\" 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
{
Stream_t *Stream = GetFs(Dir);
direntry_t entry;
- DeclareThis(FsPublic_t);
+ DeclareThis(Fs_t);
char shortname[13];
char longname[VBUFSIZE];
int r;
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;
}
/* 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
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;
'\" 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
'\" 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
} 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])
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;
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)
{
/* 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;
#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)
}
#endif
- if (!Fs->Direct)
+ if (!Fs->head.Next)
continue;
if(tot_sectors)
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;
}
/* 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,
"Error reading from '%s', wrong parameters?",
name);
#endif
- FREE(&Fs->Direct);
+ FREE(&Fs->head.Next);
continue;
}
break;
/* print error msg if needed */
if ( dev->drive == 0 ){
- FREE(&Fs->Direct);
+ FREE(&Fs->head.Next);
fprintf(stderr,"%s: %s\n", argv[0],errmsg);
exit(1);
}
/* 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 */
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)
#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);
}
'\" 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
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)
exit(1);
}
- ssize = READS(Stream, buf, 0, size);
+ ssize = PREADS(Stream, buf, 0, size);
if(ssize < 0) {
perror("read boot sector");
exit(1);
'\" 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
'\" 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
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));
}
}
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));
}
}
'\" 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
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);
'\" 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
'\" 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
'\" 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
break;
case 'l':
size_set = 1;
- length = strtoui(optarg, &endptr, 0);
+ length = parseSize(optarg);
break;
default:
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?",
/* 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);
}
'\" 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
'\" 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
'\" 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
'\" 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
'\" 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
.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
'\" t
-.TH mtools 5 "23Jul21" MTOOLS MTOOLS
+.TH mtools 5 "20Nov21" MTOOLS MTOOLS
.SH Name
mtools.conf - mtools configuration files
'\" t
.tr \(if`
.tr \(pd"
-.ds St Mtools\ 4.0.34
+.ds St Mtools\ 4.0.35
.PP
.SH Description
.PP
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);
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);
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
#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);
-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
'/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
*********************
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
\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:
%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
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
'\" 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
.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
'\" t
-.TH mtools 5 "06Aug21" MTOOLS MTOOLS
+.TH mtools 5 "21Nov21" MTOOLS MTOOLS
.SH Name
mtools.conf - mtools configuration files
'\" t
.tr \(if`
.tr \(pd"
-.ds St Mtools\ 4.0.35
+.ds St Mtools\ 4.0.36
.PP
.SH Description
.PP
'\" 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
'\" 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
'\" 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
if(request & ZIP_MODE_CHANGE) usage(1); \
request |= ZIP_MODE_CHANGE; \
newMode = x; \
- break;
+ break
/* get command line options */
if(helpFlag(argc, argv))
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 */
#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 */
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;
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;
#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 */
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,
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;
}
}
static Class_t PartitionClass = {
- partition_read,
- partition_write,
+ 0,
+ 0,
+ partition_pread,
+ partition_pwrite,
0, /* flush */
0, /* free */
partition_geom, /* set_geom */
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 */
}
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;
#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";
#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;
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
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)
static Class_t SimpleFileClass = {
file_read,
file_write,
+ file_pread,
+ file_pwrite,
file_flush,
file_free,
file_geom,
#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)
return NULL;
}
- return (Stream_t *) This;
+ return &This->head;
}
}
}
- 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:
{
Class_t *clazz;
DeclareThis(SimpleFile_t);
- clazz = This->Class;
+ clazz = This->head.Class;
if(clazz != &SimpleFileClass)
return -1;
else
};
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;
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
}
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 */
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);
goto exit_1;
This->mapSize=nrItems;
- return (Stream_t *) This;
+ return &This->head;
exit_1:
free(This->map);
exit_0:
#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;
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);
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);
static Class_t ScsiDeviceClass = {
- scsi_read,
- scsi_write,
+ 0,
+ 0,
+ scsi_pread,
+ scsi_pwrite,
0,
0,
set_geom_noop,
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))
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);
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:
*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)
{
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)
struct Class_t *Class;
int refs;
struct Stream_t *Next;
- struct Stream_t *Buffer;
} Stream_t;
#include "mtools.h"
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 *);
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))
#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);
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);
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;
+}
+++ /dev/null
-/* 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;
-}
#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)
}
-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);
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;
static Class_t SwapClass = {
- swap_read,
- swap_write,
+ 0,
+ 0,
+ swap_pread,
+ swap_pwrite,
0, /* flush */
0, /* free */
set_geom_pass_through, /* set_geom */
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;
}
% 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.
%
\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
%
\def\printdefunline#1#2{%
\begingroup
+ \plainfrenchspacing
% call \deffnheader:
#1#2 \endheader
% common ending:
\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.
@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:
--- /dev/null
+/* 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;
+}
#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;
static Class_t DirClass = {
0, /* read */
0, /* write */
+ 0, /* pread */
+ 0, /* pwrite */
0, /* flush */
dir_free, /* free */
0, /* get_geom */
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);
return NULL;
}
- return (Stream_t *) This;
+ return &This->head;
}
-@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
*/
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
typedef struct Xdf_t {
- Class_t *Class;
- int refs;
- Stream_t *Next;
- Stream_t *Buffer;
+ struct Stream_t head;
int fd;
char *buffer;
}
-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;
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;
}
static Class_t XdfClass = {
- xdf_read,
- xdf_write,
+ 0,
+ 0,
+ xdf_pread,
+ xdf_pwrite,
xdf_flush,
xdf_free,
config_geom,
This = New(Xdf_t);
if (!This)
return NULL;
+ init_head(&This->head, &XdfClass, NULL);
- This->Class = &XdfClass;
This->sector_size = 512;
This->stretch = 0;
}
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);