diff options
-rw-r--r-- | Makefile.in | 23 | ||||
-rw-r--r-- | NEWS | 19 | ||||
-rw-r--r-- | buffer.c | 3 | ||||
-rw-r--r-- | charsetConv.c | 6 | ||||
-rw-r--r-- | config.c | 2 | ||||
-rw-r--r-- | config.h.in | 6 | ||||
-rwxr-xr-x | configure | 4 | ||||
-rw-r--r-- | configure-stamp | 0 | ||||
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | debian/changelog | 16 | ||||
-rw-r--r-- | devices.c | 12 | ||||
-rw-r--r-- | direntry.c | 2 | ||||
-rw-r--r-- | fat.c | 7 | ||||
-rw-r--r-- | file.c | 5 | ||||
-rw-r--r-- | file_name.h | 2 | ||||
-rw-r--r-- | filter.c | 4 | ||||
-rw-r--r-- | floppyd.1 | 2 | ||||
-rw-r--r-- | floppyd.c | 12 | ||||
-rw-r--r-- | floppyd_installtest.1 | 2 | ||||
-rw-r--r-- | floppyd_io.c | 19 | ||||
-rw-r--r-- | init.c | 90 | ||||
-rw-r--r-- | lockdev.c | 179 | ||||
-rw-r--r-- | lockdev.h | 54 | ||||
-rw-r--r-- | mainloop.c | 6 | ||||
-rw-r--r-- | mattrib.1 | 2 | ||||
-rw-r--r-- | mbadblocks.1 | 2 | ||||
-rw-r--r-- | mbadblocks.c | 2 | ||||
-rw-r--r-- | mcat.1 | 2 | ||||
-rw-r--r-- | mcd.1 | 2 | ||||
-rw-r--r-- | mclasserase.1 | 2 | ||||
-rw-r--r-- | mclasserase.c | 2 | ||||
-rw-r--r-- | mcopy.1 | 2 | ||||
-rw-r--r-- | mcopy.c | 2 | ||||
-rw-r--r-- | mdel.1 | 2 | ||||
-rw-r--r-- | mdeltree.1 | 2 | ||||
-rw-r--r-- | mdir.1 | 2 | ||||
-rw-r--r-- | mdir.c | 5 | ||||
-rw-r--r-- | mdu.1 | 2 | ||||
-rw-r--r-- | mformat.1 | 9 | ||||
-rw-r--r-- | mformat.c | 113 | ||||
-rw-r--r-- | minfo.1 | 2 | ||||
-rw-r--r-- | minfo.c | 171 | ||||
-rw-r--r-- | misc.c | 29 | ||||
-rw-r--r-- | missFuncs.c | 21 | ||||
-rw-r--r-- | mk_direntry.c | 4 | ||||
-rw-r--r-- | mkmanifest.1 | 2 | ||||
-rw-r--r-- | mlabel.1 | 2 | ||||
-rw-r--r-- | mlabel.c | 15 | ||||
-rw-r--r-- | mmd.1 | 2 | ||||
-rw-r--r-- | mmd.c | 6 | ||||
-rw-r--r-- | mmount.1 | 2 | ||||
-rw-r--r-- | mmount.c | 2 | ||||
-rw-r--r-- | mmove.1 | 2 | ||||
-rw-r--r-- | mmove.c | 2 | ||||
-rw-r--r-- | mpartition.1 | 2 | ||||
-rw-r--r-- | mpartition.c | 2 | ||||
-rw-r--r-- | mrd.1 | 2 | ||||
-rw-r--r-- | mren.1 | 2 | ||||
-rw-r--r-- | msdos.h | 15 | ||||
-rw-r--r-- | mshortname.1 | 2 | ||||
-rw-r--r-- | mshortname.c | 4 | ||||
-rw-r--r-- | mshowfat.1 | 2 | ||||
-rw-r--r-- | mshowfat.c | 4 | ||||
-rw-r--r-- | mtools.1 | 10 | ||||
-rw-r--r-- | mtools.5 | 10 | ||||
-rw-r--r-- | mtools.h | 25 | ||||
-rw-r--r-- | mtools.info | 159 | ||||
-rw-r--r-- | mtools.spec | 26 | ||||
-rw-r--r-- | mtools.texi | 13 | ||||
-rw-r--r-- | mtools.tmpl.1 | 10 | ||||
-rw-r--r-- | mtools.tmpl.5 | 10 | ||||
-rw-r--r-- | mtoolstest.1 | 2 | ||||
-rw-r--r-- | mtype.1 | 2 | ||||
-rw-r--r-- | mzip.1 | 2 | ||||
-rw-r--r-- | mzip.c | 2 | ||||
-rw-r--r-- | nameclash.h | 1 | ||||
-rw-r--r-- | old_dos.c | 68 | ||||
-rw-r--r-- | patchlevel.c | 6 | ||||
-rw-r--r-- | plain_io.c | 20 | ||||
-rw-r--r-- | privileges.c | 7 | ||||
-rwxr-xr-x | scripts/uz | 17 | ||||
-rw-r--r-- | scsi.c | 5 | ||||
-rw-r--r-- | signal.c | 2 | ||||
-rw-r--r-- | strip-pp.sed | 2 | ||||
-rw-r--r-- | tty.c | 2 | ||||
-rw-r--r-- | unixdir.c | 4 | ||||
-rw-r--r-- | version.texi | 6 | ||||
-rw-r--r-- | xdf_io.c | 18 |
88 files changed, 889 insertions, 469 deletions
diff --git a/Makefile.in b/Makefile.in index 1e2c12a..7ea3384 100644 --- a/Makefile.in +++ b/Makefile.in @@ -107,27 +107,28 @@ vfat.c vfat.h xdf_io.c xdf_io.h OBJS1 = buffer.o charsetConv.o codepages.o config.o copyfile.o \ devices.o dirCache.o directory.o direntry.o expand.o fat.o fat_free.o file.o \ -file_name.o filter.o floppyd_io.o force_io.o hash.o init.o llong.o match.o \ -mainloop.o mattrib.o mbadblocks.o mcat.o mcd.o mclasserase.o mcopy.o mdel.o \ -mdir.o mdoctorfat.o mdu.o \ +file_name.o filter.o floppyd_io.o force_io.o hash.o init.o llong.o lockdev.o \ +match.o mainloop.o mattrib.o mbadblocks.o mcat.o mcd.o mclasserase.o mcopy.o \ +mdel.o mdir.o mdoctorfat.o mdu.o \ mformat.o minfo.o misc.o missFuncs.o mk_direntry.o mlabel.o mmd.o mmount.o \ -mmove.o mpartition.o mshortname.o mshowfat.o mzip.o mtools.o patchlevel.o \ -plain_io.o precmd.o privileges.o scsi.o signal.o stream.o streamcache.o \ -subdir.o unixdir.o tty.o vfat.o xdf_io.o +mmove.o mpartition.o mshortname.o mshowfat.o mzip.o mtools.o old_dos.o \ +patchlevel.o plain_io.o precmd.o privileges.o scsi.o signal.o stream.o \ +streamcache.o subdir.o unixdir.o tty.o vfat.o xdf_io.o OBJS2 = missFuncs.o mkmanifest.o misc.o patchlevel.o -OBJS3 = floppyd.o llong.o +OBJS3 = floppyd.o llong.o lockdev.o OBJS4 = floppyd_installtest.o misc.o expand.o privileges.o SRCS = buffer.c codepages.c config.c copyfile.c devices.c \ dirCache.c directory.c direntry.c expand.c fat.c fat_free.c file.c file_name.c \ -file_read.c filter.c floppyd_io.c force_io.c hash.c init.c 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 \ +file_read.c filter.c floppyd_io.c force_io.c hash.c init.c lockdev.c match.c \ +mainloop.c mattrib.c mbadblocks.c mcat.c mcd.c mclasserase.c mcopy.c mdel.c \ +mdir.c mdu.c mdoctorfat.c mformat.c minfo.c misc.c \ missFuncs.c mk_direntry.c mlabel.c mmd.c mmount.c mmove.c mpartition.c \ -mshortname.c mshowfat.c mzip.c mtools.c plain_io.c precmd.c privileges.c \ +mshortname.c mshowfat.c mzip.c mtools.c old_dos.c plain_io.c precmd.c \ +privileges.c \ scsi.c signal.c stream.c streamcache.c subdir.c unixdir.c tty.o vfat.c \ xdf_io.c mkmanifest.c @@ -1,3 +1,22 @@ +v4_0_20 + - initialize directory entries to 0 + - bad message "Too few sectors" replaced with "Too many sectors" + - apostrophe in mlabel no longer causes generation of long entry + - option to fake system date for file creation using the + SOURCE_DATE_EPOCH environment variables + + - can now be compiled with "clang" compiler + - fallback function for strndup, for those platforms that don't have it + - fixed a number of -Wextra warnings + + - new compressed archive formats for uz/lz + + - allow to specify number of reserved sectors for FAT32. + - file/device locking with timeout (rather than immediate failure) + - fixed support for BPB-less legacy formats. + - removed check that disk must be an integer number of tracks. + + - removed .eh/.oh macros from manual pages v4_0_19 - Fix for short file names starting with character 0xE5 (by remapping it to 0x5) @@ -331,7 +331,8 @@ static Class_t BufferClass = { 0, /* set_geom */ get_data_pass_through, /* get_data */ 0, /* pre-allocate */ - get_dosConvert_pass_through /* dos convert */ + get_dosConvert_pass_through, /* dos convert */ + 0, /* discard */ }; Stream_t *buf_init(Stream_t *Next, int size, diff --git a/charsetConv.c b/charsetConv.c index 0dc1b6d..7466844 100644 --- a/charsetConv.c +++ b/charsetConv.c @@ -152,13 +152,15 @@ void cp_close(doscp_t *cp) free(cp); } -int dos_to_wchar(doscp_t *cp, char *dos, wchar_t *wchar, size_t len) +int dos_to_wchar(doscp_t *cp, const char *dos, wchar_t *wchar, size_t len) { int r; size_t in_len=len; size_t out_len=len*sizeof(wchar_t); wchar_t *dptr=wchar; - r=iconv(cp->from, &dos, &in_len, (char **)&dptr, &out_len); + char *dos2 = (char *) dos; /* Magic to be able to call iconv with its + buggy prototype */ + r=iconv(cp->from, &dos2, &in_len, (char **)&dptr, &out_len); if(r < 0) return r; *dptr = L'\0'; @@ -63,6 +63,7 @@ unsigned int mtools_no_vfat=0; unsigned int mtools_numeric_tail=1; unsigned int mtools_dotted_dir=0; unsigned int mtools_twenty_four_hour_clock=1; +unsigned int mtools_lock_timeout=30; unsigned int mtools_default_codepage=850; const char *mtools_date_string="yyyy-mm-dd"; char *country_string=0; @@ -90,6 +91,7 @@ static switches_t global_switches[] = { (caddr_t) &mtools_twenty_four_hour_clock, T_UINT }, { "MTOOLS_DATE_STRING", (caddr_t) &mtools_date_string, T_STRING }, + { "MTOOLS_LOCK_TIMEOUT", (caddr_t) &mtools_lock_timeout, T_UINT }, { "DEFAULT_CODEPAGE", (caddr_t) &mtools_default_codepage, T_UINT } }; diff --git a/config.h.in b/config.h.in index 330dabc..3b55084 100644 --- a/config.h.in +++ b/config.h.in @@ -207,6 +207,9 @@ /* Define to 1 if you have the `strncasecmp' function. */ #undef HAVE_STRNCASECMP +/* Define to 1 if you have the `strndup' function. */ +#undef HAVE_STRNDUP + /* Define to 1 if you have the `strnlen' function. */ #undef HAVE_STRNLEN @@ -282,6 +285,9 @@ /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the `usleep' function. */ +#undef HAVE_USLEEP + /* Define to 1 if you have the `utime' function. */ #undef HAVE_UTIME @@ -4812,13 +4812,13 @@ _ACEOF for ac_func in strerror random srandom strchr strrchr lockf flock \ strcasecmp strncasecmp strnlen atexit on_exit getpass memmove \ -strdup strcspn strspn strtoul strtol memcpy strpbrk memset setenv \ +strdup strndup strcspn strspn strtoul strtol memcpy strpbrk memset setenv \ seteuid setresuid setpgrp \ tcsetattr tcflush basename fchdir media_oldaliases llseek lseek64 \ snprintf stat64 setlocale \ wcsdup wcscasecmp wcsnlen putwc \ getuserid getgroupid \ -sigaction +sigaction usleep do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/configure-stamp b/configure-stamp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/configure-stamp diff --git a/configure.in b/configure.in index b9f74b5..859c94d 100644 --- a/configure.in +++ b/configure.in @@ -152,13 +152,13 @@ dnl Checks for library functions. AC_TYPE_SIGNAL AC_CHECK_FUNCS(strerror random srandom strchr strrchr lockf flock \ strcasecmp strncasecmp strnlen atexit on_exit getpass memmove \ -strdup strcspn strspn strtoul strtol memcpy strpbrk memset setenv \ +strdup strndup strcspn strspn strtoul strtol memcpy strpbrk memset setenv \ seteuid setresuid setpgrp \ tcsetattr tcflush basename fchdir media_oldaliases llseek lseek64 \ snprintf stat64 setlocale \ wcsdup wcscasecmp wcsnlen putwc \ getuserid getgroupid \ -sigaction) +sigaction usleep) dnl dnl Check for 64-bit off_t diff --git a/debian/changelog b/debian/changelog index 074a925..c21f868 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,19 @@ +mtools (4.0.20) stable; urgency=low + * initialize directory entries to 0 + * bad message "Too few sectors" replaced with "Too many sectors" + * apostrophe in mlabel no longer causes generation of long entry + * option to fake system date for file creation using the SOURCE_DATE_EPOCH environment variables + * can now be compiled with "clang" compiler + * fallback function for strndup, for those platforms that don't have it + * fixed a number of -Wextra warnings + * new compressed archive formats for uz/lz + * allow to specify number of reserved sectors for FAT32. + * file/device locking with timeout (rather than immediate failure) + * fixed support for BPB-less legacy formats. + * removed check that disk must be an integer number of tracks. + * removed .eh/.oh macros from manual pages + -- Alain Knaff <alain@knaff.lu> Sun, 11 Nov 2018 14:56:06 +0100 + mtools (4.0.19) stable; urgency=low * Fix for short file names starting with character 0xE5 (by remapping it to 0x5) @@ -66,7 +66,7 @@ #define ZIP(x) ZIPJAZ(x,96, 64, 32, 0) #define RZIP(x) ZIPJAZ(x,96, 64, 32, SCSI_FLAG|PRIV_FLAG) -#define REMOTE {"$DISPLAY", 'X', 0,0, 0,0, 0,0,0L, DEF_ARG0(FLOPPYD_FLAG)} +#define REMOTE {"$DISPLAY", 'X', 0,0, 0,0, 0,0,0L, DEF_ARG0(FLOPPYD_FLAG),0,0} @@ -730,12 +730,12 @@ int analyze_one_reply(RawRequest_t *raw_cmd, int *bytes, int do_print) #define predefined_devices struct device devices[] = { - {"/dev/fd0", 'A', 0, 0, 80,2, 18,0, MDEF_ARG}, - {"/dev/fd1", 'B', 0, 0, 0,0, 0,0, FDEF_ARG}, + {"/dev/fd0", 'A', 0, 0, 80,2, 18,0, MDEF_ARG, 0, 0}, + {"/dev/fd1", 'B', 0, 0, 0,0, 0,0, FDEF_ARG, 0, 0}, /* we assume that the Zip or Jaz drive is the second on the SCSI bus */ - {"/dev/sdb4",'J', GENHD }, - {"/dev/sdb4",'Z', GENHD }, - /* {"/dev/sda4",'D', GENHD },*/ + {"/dev/sdb4",'J', GENHD, 0, 0 }, + {"/dev/sdb4",'Z', GENHD, 0, 0 }, + /* {"/dev/sda4",'D', GENHD, 0, 0 },*/ REMOTE }; @@ -24,8 +24,8 @@ void initializeDirentry(direntry_t *entry, Stream_t *Dir) { + memset(entry, 0, sizeof(direntry_t)); entry->entry = -1; -/* entry->parent = getDirentry(Dir);*/ entry->Dir = Dir; entry->beginSlot = 0; entry->endSlot = 0; @@ -53,13 +53,6 @@ static __inline__ int forceReadSector(Fs_t *This, char *buf, unsigned int off, } -static __inline__ int writeSector(Fs_t *This, char *buf, unsigned int off, - size_t size) -{ - return WRITES(This->Next, buf, sectorsToBytes((Stream_t*)This, off), - size << This->sectorShift); -} - static __inline__ int forceWriteSector(Fs_t *This, char *buf, unsigned int off, size_t size) { @@ -364,7 +364,7 @@ static int root_map(File_t *This, off_t where, size_t *len, int mode UNUSEDP, return -2; } - maximize(*len, Fs->dir_len * Fs->sector_size - where); + smaximize(*len, Fs->dir_len * Fs->sector_size - where); if (*len == 0) return 0; @@ -549,7 +549,8 @@ static Class_t FileClass = { 0, /* get_geom */ get_file_data, pre_allocate_file, - get_dosConvert_pass_through + get_dosConvert_pass_through, + 0 /* discard */ }; static unsigned int getAbsCluNr(File_t *This) diff --git a/file_name.h b/file_name.h index 0d9ac90..132a391 100644 --- a/file_name.h +++ b/file_name.h @@ -31,7 +31,7 @@ struct dos_name_t { char sentinel; }; -int dos_to_wchar(doscp_t *fromDos, char *dos, wchar_t *wchar, size_t len); +int dos_to_wchar(doscp_t *fromDos, const char *dos, wchar_t *wchar, size_t len); void wchar_to_dos(doscp_t *toDos, wchar_t *wchar, char *dos, size_t len, int *mangled); doscp_t *cp_open(int codepage); @@ -150,7 +150,9 @@ static Class_t FilterClass = { free_filter, 0, /* set geometry */ get_data_pass_through, - 0 + 0, + 0, /* get_dosconvert */ + 0 /* discard */ }; Stream_t *open_filter(Stream_t *Next, int convertCharset UNUSEDP) @@ -1,5 +1,5 @@ '\" t -.TH floppyd 1 "29Sep18" mtools-4.0.19 +.TH floppyd 1 "11Nov18" mtools-pre-4.0.20 .SH Name floppyd - floppy daemon for remote access to floppy drive '\" t @@ -110,6 +110,7 @@ typedef mt_off_t Qword; #define MAX_DATA_REQUEST 3000000 #define BUFFERED_IO_SIZE 16348 +unsigned int mtools_lock_timeout=30; void serve_client(int sock, char **device_name, int n_dev, int close_stderr); @@ -154,7 +155,7 @@ static void free_io_buffer(io_buffer buffer) { static size_t buf_read (io_buffer buf, Byte* buffer, size_t nbytes) { - size_t rval; + ssize_t rval; if (nbytes <= buf->in_valid) { memcpy(buffer, buf->in_buffer+buf->in_start, nbytes); @@ -323,7 +324,7 @@ static char send_packet(Packet packet, io_buffer fp) static char recv_packet(Packet packet, io_buffer fp, Dword maxlength) { - int start; + Dword start; int l; Dword length = read_dword(fp); #if DEBUG @@ -725,7 +726,7 @@ static int sockethandle_now = -1; /* * Catch alarm signals and exit. */ -static void alarm_signal(int a) +static void alarm_signal(int a UNUSEDP) { if (sockethandle_now != -1) { close(sockethandle_now); @@ -1037,7 +1038,7 @@ static void send_reply64(int rval, io_buffer sock, mt_off_t len) { destroyPacket(reply); } -static void cleanup(int x) { +static void cleanup(int x UNUSEDP) { unlink(XauFileName()); exit(-1); } @@ -1186,8 +1187,7 @@ void serve_client(int sockhandle, char **device_name, int n_dev, #endif read_packet(parm, devFd, get_dword(parm, 0)); send_reply(devFd, sock, get_length(parm)); - if(get_length(parm) >= 0) - send_packet(parm, sock); + send_packet(parm, sock); break; case OP_WRITE: #if DEBUG diff --git a/floppyd_installtest.1 b/floppyd_installtest.1 index e446561..7a14ab6 100644 --- a/floppyd_installtest.1 +++ b/floppyd_installtest.1 @@ -1,5 +1,5 @@ '\" t -.TH floppyd_installtest 1 "29Sep18" mtools-4.0.19 +.TH floppyd_installtest 1 "11Nov18" mtools-pre-4.0.20 .SH Name floppyd_installtest - tests whether floppyd is installed and running '\" t diff --git a/floppyd_io.c b/floppyd_io.c index d8e0fdb..b5fc549 100644 --- a/floppyd_io.c +++ b/floppyd_io.c @@ -417,17 +417,9 @@ static int floppyd_geom(Stream_t *Stream, struct device *dev, tot_sectors += sect_per_track - 1; /* round size up */ dev->tracks = tot_sectors / sect_per_track; - } else if (media >= 0xf8){ - media &= 3; - dev->heads = old_dos[media].heads; - dev->tracks = old_dos[media].tracks; - dev->sectors = old_dos[media].sectors; - dev->ssize = 0x80; - dev->use_2m = ~1; - } else { - fprintf(stderr,"Unknown media type\n"); - exit(1); - } + } else + if(setDeviceFromOldDos(media, dev) < 0) + exit(1); This->size = (mt_off_t) 512 * dev->sectors * dev->tracks * dev->heads; @@ -461,7 +453,10 @@ static Class_t FloppydFileClass = { floppyd_flush, floppyd_free, floppyd_geom, - floppyd_data + floppyd_data, + 0, /* pre_allocate */ + 0, /* get_dosConvert */ + 0 /* discard */ }; /* ######################################################################## */ @@ -86,8 +86,14 @@ Class_t FsClass = { get_data_pass_through, 0, /* pre allocate */ get_dosConvert, /* dosconvert */ + 0 /* discard */ }; +/** + * Get media type byte from boot sector (BIOS Parameter Block 2) or + * from FAT (if media byte from BPB 2 looks fishy) + * Return the media byte + 0x100 if found in BPB 2, or as is if found in FAT. + */ static int get_media_type(Stream_t *St, union bootsector *boot) { int media; @@ -96,7 +102,7 @@ static int get_media_type(Stream_t *St, union bootsector *boot) if(media < 0xf0){ char temp[512]; /* old DOS disk. Media descriptor in the first FAT byte */ - /* old DOS disk always have 512-byte sectors */ + /* we assume 512-byte sectors here */ if (force_read(St,temp,(mt_off_t) 512,512) == 512) media = (unsigned char) temp[0]; else @@ -114,6 +120,22 @@ Stream_t *GetFs(Stream_t *Fs) return Fs; } +/** + * Tries out all device definitions for the given drive number, until one + * is found that is able to read from the device + * Parameters + * - drive: drive letter to check + * - mode: file open mode + * - out_dev: device parameters (geometry, etc.) are returned here + * - boot: boot sector is read from the disk into this structure + * - name: "name" of device definition (returned) + * - media: media byte is returned here (ored with 0x100 if there is a + * BIOS Parameter block present) + * - maxSize: maximal size supported by (physical) drive returned here + * - isRop: whether device is read-only is returned here + * Return value: + * - a Stream allowing to read from this device, must be closed by caller + */ Stream_t *find_device(char drive, int mode, struct device *out_dev, union bootsector *boot, char *name, int *media, mt_size_t *maxSize, @@ -233,7 +255,7 @@ Stream_t *find_device(char drive, int mode, struct device *out_dev, Stream_t *fs_init(char drive, int mode, int *isRop) { int blocksize; - int media,i; + int media; int disk_size = 0; /* In case we don't happen to set this below */ size_t tot_sectors; char name[EXPAND_BUF]; @@ -266,32 +288,20 @@ Stream_t *fs_init(char drive, int mode, int *isRop) if(!This->Direct) return NULL; - This->sector_size = WORD_S(secsiz); - if(This->sector_size > MAX_SECTOR){ - fprintf(stderr,"init %c: sector size too big\n", drive); - return NULL; - } - - i = log_2(This->sector_size); - - if(i == 24) { - fprintf(stderr, - "init %c: sector size (%d) not a small power of two\n", - drive, This->sector_size); - return NULL; - } - This->sectorShift = i; - This->sectorMask = This->sector_size - 1; - cylinder_size = dev.heads * dev.sectors; This->serialized = 0; if ((media & ~7) == 0xf8){ - i = media & 3; - This->cluster_size = old_dos[i].cluster_size; - tot_sectors = cylinder_size * old_dos[i].tracks; + /* This bit of code is only entered if there is no BPB, or + * else result of the AND would be 0x1xx + */ + struct OldDos_t *params=getOldDosByMedia(media); + if(params == NULL) + return NULL; + This->cluster_size = params->cluster_size; + tot_sectors = cylinder_size * params->tracks; This->fat_start = 1; - This->fat_len = old_dos[i].fat_len; - This->dir_len = old_dos[i].dir_len; + This->fat_len = params->fat_len; + This->dir_len = params->dir_len; This->num_fat = 2; This->sector_size = 512; This->sectorShift = 9; @@ -299,6 +309,25 @@ Stream_t *fs_init(char drive, int mode, int *isRop) This->fat_bits = 12; } else { struct label_blk_t *labelBlock; + int i; + + This->sector_size = WORD_S(secsiz); + if(This->sector_size > MAX_SECTOR){ + fprintf(stderr,"init %c: sector size too big\n", drive); + return NULL; + } + + i = log_2(This->sector_size); + + if(i == 24) { + fprintf(stderr, + "init %c: sector size (%d) not a small power of two\n", + drive, This->sector_size); + return NULL; + } + This->sectorShift = i; + This->sectorMask = This->sector_size - 1; + /* * all numbers are in sectors, except num_clus * (which is in clusters) @@ -319,7 +348,7 @@ Stream_t *fs_init(char drive, int mode, int *isRop) labelBlock = &boot.boot.ext.fat32.labelBlock; } - if(labelBlock->dos4 == 0x29) { + if(has_BPB4) { This->serialized = 1; This->serial_number = _DWORD(labelBlock->serial); } @@ -330,17 +359,6 @@ Stream_t *fs_init(char drive, int mode, int *isRop) exit(1); } - if(!mtools_skip_check && (tot_sectors % dev.sectors)){ - fprintf(stderr, - "Total number of sectors (%d) not a multiple of" - " sectors per track (%d)!\n", (int) tot_sectors, - dev.sectors); - fprintf(stderr, - "Add mtools_skip_check=1 to your .mtoolsrc file " - "to skip this test\n"); - exit(1); - } - /* full cylinder buffering */ #ifdef FULL_CYL disk_size = (dev.tracks) ? cylinder_size : 512; diff --git a/lockdev.c b/lockdev.c new file mode 100644 index 0000000..b07db60 --- /dev/null +++ b/lockdev.c @@ -0,0 +1,179 @@ +/* Copyright 2005,2009,2018 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/>. + * + * Create an advisory lock on the device to prevent concurrent writes. + * Uses either lockf, flock, or fcntl locking methods. See the Makefile + * and the Configure files for how to specify the proper method. + */ + +#include "sysincludes.h" +#include "mtools.h" +#include "lockdev.h" + +#ifdef HAVE_SIGACTION +# define ALRM +#endif + + +#if (defined(HAVE_FLOCK) && defined (LOCK_EX) && (defined(LOCK_NB) || defined(ALRM))) + +# ifdef ALRM +# define USE_FLOCK_W +# else +# define USE_FLOCK +# endif + +#else /* FLOCK */ + +#if (defined(HAVE_LOCKF) && (defined(F_TLOCK) || defined(ALRM))) + +# ifdef ALRM +# define USE_LOCKF_W +# else +# define USE_LOCKF +# endif + +#else /* LOCKF */ + +#if (defined(F_SETLK) && defined(F_WRLCK)) + +# if (defined ALRM && defined F_SETLKW) +# define USE_SETLK_W +# else +# define USE_SETLK_W +# endif + +#else + +#endif /* FCNTL */ +#endif /* LOCKF */ +#endif /* FLOCK */ + + +#undef USE_FLOCK_W + +#define USE_SETLK_W + +#if defined(USE_FLOCK_W) || defined(USE_LOCKF_W) || defined (USE_SETLK_W) +static void alrm(int a UNUSEDP) { +} +#endif + +int lock_dev(int fd, int mode, struct device *dev) +{ + int retries = 0; + if(IS_NOLOCK(dev)) + return 0; + + while(1) { + int ret=0; +#if defined(USE_FLOCK_W) || defined(USE_LOCKF_W) || defined (USE_SETLK_W) + struct sigaction alrm_action, old_alrm_action; + int old_alrm = alarm(0); + memset(&alrm_action, 0, sizeof(alrm_action)); + alrm_action.sa_handler = alrm; + alrm_action.sa_flags = 0; + sigaction(SIGALRM, &alrm_action, &old_alrm_action); + alarm(mtools_lock_timeout); +#endif + +#ifdef USE_FLOCK + ret = flock(fd, (mode ? LOCK_EX : LOCK_SH)|LOCK_NB); +#endif + +#ifdef USE_FLOCK_W + ret = flock(fd, (mode ? LOCK_EX : LOCK_SH)); +#endif + +#if (defined(USE_LOCKF) || defined(USE_LOCKF_W)) + if(mode) +# ifdef USE_LOCKF + ret = lockf(fd, F_TLOCK, 0); +# else + ret = lockf(fd, F_LOCK, 0); +# endif + else + ret = 0; +#endif + +#if (defined(USE_SETLK) || defined(USE_SETLK_W)) + { + struct flock flk; + flk.l_type = mode ? F_WRLCK : F_RDLCK; + flk.l_whence = 0; + flk.l_start = 0L; + flk.l_len = 0L; + +# ifdef USE_SETLK_W + ret = fcntl(fd, F_SETLKW, &flk); +# else + ret = fcntl(fd, F_SETLK, &flk); +# endif + } +#endif + +#if defined(USE_FLOCK_W) || defined(USE_LOCKF_W) || defined (USE_SETLK_W) + /* Cancel the alarm */ + sigaction(SIGALRM, &old_alrm_action, NULL); + alarm(old_alrm); +#endif + + if(ret < 0) { +#if defined(USE_FLOCK_W) || defined(USE_LOCKF_W) || defined (USE_SETLK_W) + /* ALARM fired ==> this means we are still locked */ + if(errno == EINTR) { + return 1; + } +#endif + + if( +#ifdef EWOULDBLOCK + (errno != EWOULDBLOCK) +#else + 1 +#endif + && +#ifdef EAGAIN + (errno != EAGAIN) +#else + 1 +#endif + && +#ifdef EINTR + (errno != EINTR) +#else + 1 +#endif + ) { + /* Error other than simply being locked */ + return -1; + } + /* Locked ==> continue until timeout */ + } else /* no error => we got the lock! */ + return 0; + +#ifdef HAVE_USLEEP + if(retries++ < mtools_lock_timeout * 10) + usleep(100000); +#else + if(retries++ < mtools_lock_timeout) + sleep(1); +#endif + else + /* waited for too long => give up */ + return 1; + } +} @@ -1,7 +1,7 @@ #ifndef LOCK_DEV #define LOCK_DEV -/* Copyright 2005,2009 Alain Knaff. +/* Copyright 2005,2009,2018 Alain Knaff. * This file is part of mtools. * * Mtools is free software: you can redistribute it and/or modify @@ -22,56 +22,6 @@ * and the Configure files for how to specify the proper method. */ -int lock_dev(int fd, int mode, struct device *dev) -{ -#if (defined(HAVE_FLOCK) && defined (LOCK_EX) && defined(LOCK_NB)) - /**/ -#else /* FLOCK */ - -#if (defined(HAVE_LOCKF) && defined(F_TLOCK)) - /**/ -#else /* LOCKF */ - -#if (defined(F_SETLK) && defined(F_WRLCK)) - struct flock flk; - -#endif /* FCNTL */ -#endif /* LOCKF */ -#endif /* FLOCK */ - - if(IS_NOLOCK(dev)) - return 0; - -#if (defined(HAVE_FLOCK) && defined (LOCK_EX) && defined(LOCK_NB)) - if (flock(fd, (mode ? LOCK_EX : LOCK_SH)|LOCK_NB) < 0) -#else /* FLOCK */ - -#if (defined(HAVE_LOCKF) && defined(F_TLOCK)) - if (mode && lockf(fd, F_TLOCK, 0) < 0) -#else /* LOCKF */ - -#if (defined(F_SETLK) && defined(F_WRLCK)) - flk.l_type = mode ? F_WRLCK : F_RDLCK; - flk.l_whence = 0; - flk.l_start = 0L; - flk.l_len = 0L; - - if (fcntl(fd, F_SETLK, &flk) < 0) -#endif /* FCNTL */ -#endif /* LOCKF */ -#endif /* FLOCK */ - { - if(errno == EINVAL -#ifdef EOPNOTSUPP - || errno == EOPNOTSUPP -#endif - ) - return 0; - else - return 1; - } - return 0; -} - +extern int lock_dev(int fd, int mode, struct device *dev); #endif @@ -86,7 +86,7 @@ static const char *fix_mcwd(char *ans) } int unix_dir_loop(Stream_t *Stream, MainParam_t *mp); -int unix_loop(UNUSED(Stream_t *Stream), MainParam_t *mp, char *arg, +int unix_loop(Stream_t *Stream UNUSEDP, MainParam_t *mp, char *arg, int follow_dir_link); static int _unix_loop(Stream_t *Dir, MainParam_t *mp, @@ -95,11 +95,11 @@ static int _unix_loop(Stream_t *Dir, MainParam_t *mp, return unix_dir_loop(Dir, mp); } -int unix_loop(UNUSED(Stream_t *Stream), MainParam_t *mp, +int unix_loop(Stream_t *Stream UNUSEDP, MainParam_t *mp, char *arg, int follow_dir_link) { int ret; - int isdir; + int isdir=0; int unixNameLength; mp->File = NULL; @@ -1,5 +1,5 @@ '\" t -.TH mattrib 1 "29Sep18" mtools-4.0.19 +.TH mattrib 1 "11Nov18" mtools-pre-4.0.20 .SH Name mattrib - change MSDOS file attribute flags '\" t diff --git a/mbadblocks.1 b/mbadblocks.1 index 81dfae6..1413239 100644 --- a/mbadblocks.1 +++ b/mbadblocks.1 @@ -1,5 +1,5 @@ '\" t -.TH mbadblocks 1 "29Sep18" mtools-4.0.19 +.TH mbadblocks 1 "11Nov18" mtools-pre-4.0.20 .SH Name mbadblocks - tests a floppy disk, and marks the bad blocks in the FAT '\" t diff --git a/mbadblocks.c b/mbadblocks.c index df5605f..a8fd6d0 100644 --- a/mbadblocks.c +++ b/mbadblocks.c @@ -119,7 +119,7 @@ void mbadblocks(int argc, char **argv, int type UNUSEDP) Stream_t *Dir; int ret; char *filename = NULL; - char c; + int c; unsigned int badClus; int sectorMode=0; int writeMode=0; @@ -1,5 +1,5 @@ '\" t -.TH mcat 1 "29Sep18" mtools-4.0.19 +.TH mcat 1 "11Nov18" mtools-pre-4.0.20 .SH Name mcat - dump raw disk image '\" t @@ -1,5 +1,5 @@ '\" t -.TH mcd 1 "29Sep18" mtools-4.0.19 +.TH mcd 1 "11Nov18" mtools-pre-4.0.20 .SH Name mcd - change MSDOS directory '\" t diff --git a/mclasserase.1 b/mclasserase.1 index d0692ad..c684cfd 100644 --- a/mclasserase.1 +++ b/mclasserase.1 @@ -1,5 +1,5 @@ '\" t -.TH mclasserase 1 "29Sep18" mtools-4.0.19 +.TH mclasserase 1 "11Nov18" mtools-pre-4.0.20 .SH Name mclasserase - erase memory cards '\" t diff --git a/mclasserase.c b/mclasserase.c index fb610eb..5d03516 100644 --- a/mclasserase.c +++ b/mclasserase.c @@ -284,7 +284,7 @@ void mclasserase(int argc, char **argv, int type UNUSEDP) /* char* tempFilePath=NULL; */ char drive='a'; - int extern optind; + extern int optind; destroy_privs(); @@ -1,5 +1,5 @@ '\" t -.TH mcopy 1 "29Sep18" mtools-4.0.19 +.TH mcopy 1 "11Nov18" mtools-pre-4.0.20 .SH Name mcopy - copy MSDOS files to/from Unix '\" t @@ -119,7 +119,7 @@ static int _unix_write(MainParam_t *mp, int needfilter, const char *unixFile) /* if we are creating a file, check whether it already exists */ if(!arg->type) { - if (!arg->nowarn && &arg->type && !access(unixFile, 0)){ + if (!arg->nowarn && !access(unixFile, 0)){ if(arg->noClobber) { fprintf(stderr, "File \"%s\" exists. To overwrite, try again, and explicitly specify target directory\n",unixFile); return ERROR_ONE; @@ -1,5 +1,5 @@ '\" t -.TH mdel 1 "29Sep18" mtools-4.0.19 +.TH mdel 1 "11Nov18" mtools-pre-4.0.20 .SH Name mdel - delete an MSDOS file '\" t @@ -1,5 +1,5 @@ '\" t -.TH mdeltree 1 "29Sep18" mtools-4.0.19 +.TH mdeltree 1 "11Nov18" mtools-pre-4.0.20 .SH Name mdeltree - recursively delete an MSDOS directory and its contents '\" t @@ -1,5 +1,5 @@ '\" t -.TH mdir 1 "29Sep18" mtools-4.0.19 +.TH mdir 1 "11Nov18" mtools-pre-4.0.20 .SH Name mdir - display an MSDOS directory '\" t @@ -130,11 +130,6 @@ static const char *dotted_num(mt_size_t num, int width, char **buf) unsigned long numlo; unsigned long numhi; - if (num < 0) { - /* warn about negative numbers here. They should not occur */ - fprintf(stderr, "Invalid negative number\n"); - } - size = width + width; *buf = malloc(size+1); @@ -1,5 +1,5 @@ '\" t -.TH mdu 1 "29Sep18" mtools-4.0.19 +.TH mdu 1 "11Nov18" mtools-pre-4.0.20 .SH Name mdu - display the amount of space occupied by an MSDOS directory '\" t @@ -1,5 +1,5 @@ '\" t -.TH mformat 1 "29Sep18" mtools-4.0.19 +.TH mformat 1 "11Nov18" mtools-pre-4.0.20 .SH Name mformat - add an MSDOS filesystem to a low-level formatted floppy disk '\" t @@ -36,6 +36,7 @@ low-level formatted diskette. Its syntax is: [\fR\&\f(CW-B\fR \fIboot_sector\fR] [\fR\&\f(CW-k\fR] [\fR\&\f(CW-m\fR \fImedia_descriptor\fR] [\fR\&\f(CW-K\fR \fIbackup_boot\fR] + [\fR\&\f(CW-R\fR \fInb_reserved_sectors\fR] [\fR\&\f(CW-c\fR \fIclusters_per_sector\fR] [\fR\&\f(CW-d\fR \fIfat_copies\fR] [\fR\&\f(CW-X\fR] [\fR\&\f(CW-2\fR \fIsectors_on_track_0\fR] [\fR\&\f(CW-3\fR] @@ -214,6 +215,12 @@ disks parameters. Sets the sector number where the backup of the boot sector should be stored (only relevant on FAT32). .TP +\&\fR\&\f(CWR\fR\ +Sets the number of reserved sectors for this filesystem. This must be +at least 1 for non-FAT32 disks, and at least 3 for FAT disks (in order +to accomodate the boot sector, the info sector and the backup boot +sector). +.TP \&\fR\&\f(CWm\fR\ Use a non-standard media descriptor byte for this disk. The media descriptor is stored at position 21 of the boot sector, and as first @@ -587,65 +587,40 @@ static void calc_cluster_size(struct Fs_t *Fs, unsigned long tot_sectors, } -struct OldDos_t old_dos[]={ -{ 40, 9, 1, 4, 1, 2, 0xfc }, -{ 40, 9, 2, 7, 2, 2, 0xfd }, -{ 40, 8, 1, 4, 1, 1, 0xfe }, -{ 40, 8, 2, 7, 2, 1, 0xff }, -{ 80, 9, 2, 7, 2, 3, 0xf9 }, -{ 80, 15, 2,14, 1, 7, 0xf9 }, -{ 80, 18, 2,14, 1, 9, 0xf0 }, -{ 80, 36, 2,15, 2, 9, 0xf0 }, -{ 1, 8, 1, 1, 1, 1, 0xf0 }, -}; - static int old_dos_size_to_geom(size_t size, int *cyls, int *heads, int *sects) { - unsigned int i; - size = size * 2; - for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){ - if (old_dos[i].sectors * - old_dos[i].tracks * - old_dos[i].heads == size) { - *cyls = old_dos[i].tracks; - *heads = old_dos[i].heads; - *sects = old_dos[i].sectors; - return 0; - } - } - return 1; + struct OldDos_t *params = getOldDosBySize(size); + if(params != NULL) { + *cyls = params->tracks; + *heads = params->heads; + *sects = params->sectors; + return 0; + } else + return 1; } static void calc_fs_parameters(struct device *dev, unsigned long tot_sectors, struct Fs_t *Fs, union bootsector *boot) { - unsigned int i; - - for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){ - if (dev->sectors == old_dos[i].sectors && - dev->tracks == old_dos[i].tracks && - dev->heads == old_dos[i].heads && - (dev->fat_bits == 0 || abs(dev->fat_bits) == 12) && - (Fs->dir_len == 0 || Fs->dir_len == old_dos[i].dir_len) && - (Fs->cluster_size == 0 || - Fs->cluster_size == old_dos[i].cluster_size)) { - boot->boot.descr = old_dos[i].media; - Fs->cluster_size = old_dos[i].cluster_size; - Fs->dir_len = old_dos[i].dir_len; - Fs->fat_len = old_dos[i].fat_len; - Fs->fat_bits = 12; - break; - } - } - if (i == sizeof(old_dos) / sizeof(old_dos[0]) ){ + struct OldDos_t *params=NULL; + if(dev->fat_bits == 0 || abs(dev->fat_bits) == 12) + params = getOldDosByParams(dev->tracks,dev->heads,dev->sectors, + Fs->dir_len, Fs->cluster_size); + if(params != NULL) { + boot->boot.descr = params->media; + Fs->cluster_size = params->cluster_size; + Fs->dir_len = params->dir_len; + Fs->fat_len = params->fat_len; + Fs->fat_bits = 12; + } else { int may_change_cluster_size = (Fs->cluster_size == 0); int may_change_root_size = (Fs->dir_len == 0); /* a non-standard format */ if(DWORD(nhs) || tot_sectors % (dev->sectors * dev->heads)) boot->boot.descr = 0xf8; - else + else boot->boot.descr = 0xf0; @@ -885,7 +860,7 @@ static int get_lba_geom(Stream_t *Direct, unsigned long tot_sectors, struct devi return 0; } -void mformat(int argc, char **argv, int dummy) +void mformat(int argc, char **argv, int dummy UNUSEDP) { int r; /* generic return value */ Fs_t Fs; @@ -933,7 +908,10 @@ void mformat(int argc, char **argv, int dummy) int Atari = 0; /* should we add an Atari-style serial number ? */ int backupBoot = 6; + int backupBootSet = 0; + int resvSects = 0; + char *endptr; hs = hs_set = 0; @@ -971,7 +949,7 @@ void mformat(int argc, char **argv, int dummy) usage(0); while ((c = getopt(argc,argv, "i:148f:t:n:v:qub" - "kK:B:r:L:I:FCc:Xh:s:T:l:N:H:M:S:2:30:Aad:m:"))!= EOF) { + "kK:R:B:r:L:I:FCc:Xh:s:T:l:N:H:M:S:2:30:Aad:m:"))!= EOF) { endptr = NULL; switch (c) { case 'i': @@ -1119,11 +1097,15 @@ void mformat(int argc, char **argv, int dummy) break; case 'K': backupBoot = atoi(optarg); - if(backupBoot < 2 || backupBoot >= 32) { - fprintf(stderr, "Backupboot must be comprised between 2 and 32\n"); + backupBootSet=1; + if(backupBoot < 2) { + fprintf(stderr, "Backupboot must be greater than 2\n"); exit(1); } break; + case 'R': + resvSects = atoi(optarg); + break; case 'h': argheads = atoi(optarg); break; @@ -1321,7 +1303,7 @@ void mformat(int argc, char **argv, int dummy) tot_sectors = used_dev.tracks*sect_per_track - used_dev.hidden%sect_per_track; /* Number of sectors must fit into 32bit value */ if (tot_sectors > 0xFFFFFFFF) { - fprintf(stderr, "Too few sectors\n"); + fprintf(stderr, "Too many sectors\n"); exit(1); } } @@ -1385,7 +1367,26 @@ void mformat(int argc, char **argv, int dummy) if(used_dev.fat_bits == 32) { Fs.primaryFat = 0; Fs.writeAllFats = 1; - Fs.fat_start = 32; + if(resvSects) { + if(resvSects < 3) { + fprintf(stderr, + "For FAT 32, reserved sectors need to be at least 3\n"); + resvSects = 32; + } + + if(resvSects <= backupBoot && !backupBootSet) + backupBoot = resvSects - 1; + Fs.fat_start = resvSects; + } else + Fs.fat_start = 32; + + if(Fs.fat_start <= backupBoot) { + fprintf(stderr, + "Reserved sectors (%d) must be more than backupBoot (%d)\n", Fs.fat_start, backupBoot); + backupBoot = 6; + Fs.fat_start = 32; + } + calc_fs_parameters_32(tot_sectors, &Fs, &boot); Fs.clus_start = Fs.num_fat * Fs.fat_len + Fs.fat_start; @@ -1409,7 +1410,15 @@ void mformat(int argc, char **argv, int dummy) labelBlock = & boot.boot.ext.fat32.labelBlock; } else { Fs.infoSectorLoc = 0; - Fs.fat_start = 1; + if(resvSects) { + if(resvSects < 1) { + fprintf(stderr, + "Reserved sectors need to be at least 1\n"); + resvSects = 1; + } + Fs.fat_start = resvSects; + } else + Fs.fat_start = 1; calc_fs_parameters(&used_dev, tot_sectors, &Fs, &boot); Fs.dir_start = Fs.num_fat * Fs.fat_len + Fs.fat_start; Fs.clus_start = Fs.dir_start + Fs.dir_len; @@ -1,5 +1,5 @@ '\" t -.TH minfo 1 "29Sep18" mtools-4.0.19 +.TH minfo 1 "11Nov18" mtools-pre-4.0.20 .SH Name minfo - print the parameters of a MSDOS filesystem '\" t @@ -56,27 +56,83 @@ static void displayInfosector(Stream_t *Stream, union bootsector *boot) } -void minfo(int argc, char **argv, int type) +static void displayBPB(Stream_t *Stream, union bootsector *boot) { + struct label_blk_t *labelBlock; + + printf("bootsector information\n"); + printf("======================\n"); + printf("banner:\"%.8s\"\n", boot->boot.banner); + printf("sector size: %d bytes\n", WORD(secsiz)); + printf("cluster size: %d sectors\n", boot->boot.clsiz); + printf("reserved (boot) sectors: %d\n", WORD(nrsvsect)); + printf("fats: %d\n", boot->boot.nfat); + printf("max available root directory slots: %d\n", + WORD(dirents)); + printf("small size: %d sectors\n", WORD(psect)); + printf("media descriptor byte: 0x%x\n", boot->boot.descr); + printf("sectors per fat: %d\n", WORD(fatlen)); + printf("sectors per track: %d\n", WORD(nsect)); + printf("heads: %d\n", WORD(nheads)); + printf("hidden sectors: %d\n", DWORD(nhs)); + printf("big size: %d sectors\n", DWORD(bigsect)); + + if(WORD(fatlen)) { + labelBlock = &boot->boot.ext.old.labelBlock; + } else { + labelBlock = &boot->boot.ext.fat32.labelBlock; + } + + if(has_BPB4) { + printf("physical drive id: 0x%x\n", + labelBlock->physdrive); + printf("reserved=0x%x\n", + labelBlock->reserved); + printf("dos4=0x%x\n", + labelBlock->dos4); + printf("serial number: %08X\n", + _DWORD(labelBlock->serial)); + printf("disk label=\"%11.11s\"\n", + labelBlock->label); + printf("disk type=\"%8.8s\"\n", + labelBlock->fat_type); + } + + if(!WORD(fatlen)){ + printf("Big fatlen=%u\n", + DWORD(ext.fat32.bigFat)); + printf("Extended flags=0x%04x\n", + WORD(ext.fat32.extFlags)); + printf("FS version=0x%04x\n", + WORD(ext.fat32.fsVersion)); + printf("rootCluster=%u\n", + DWORD(ext.fat32.rootCluster)); + if(WORD(ext.fat32.infoSector) != MAX16) + printf("infoSector location=%d\n", + WORD(ext.fat32.infoSector)); + if(WORD(ext.fat32.backupBoot) != MAX16) + printf("backup boot sector=%d\n", + WORD(ext.fat32.backupBoot)); + displayInfosector(Stream, boot); + } +} + +void minfo(int argc, char **argv, int type UNUSEDP) { union bootsector boot; char name[EXPAND_BUF]; int media; - unsigned long tot_sectors; + int haveBPB; int size_code; - int sector_size; int i; struct device dev; char drive; int verbose=0; int c; Stream_t *Stream; - struct label_blk_t *labelBlock; int have_drive = 0; unsigned long sect_per_track; - int tracks_match=0; - int hidden; char *imgFile=NULL; @@ -114,27 +170,46 @@ void minfo(int argc, char **argv, int type) name, &media, 0, NULL))) exit(1); - tot_sectors = DWORD_S(bigsect); - SET_INT(tot_sectors, WORD_S(psect)); - sector_size = WORD_S(secsiz); - size_code=2; - for(i=0; i<7; i++) { - if(sector_size == 128 << i) { - size_code = i; - break; - } - } + haveBPB = media >= 0x100; + media = media & 0xff; + printf("device information:\n"); printf("===================\n"); printf("filename=\"%s\"\n", name); printf("sectors per track: %d\n", dev.sectors); printf("heads: %d\n", dev.heads); printf("cylinders: %d\n\n", dev.tracks); + printf("media byte: %02x\n\n", media & 0xff); sect_per_track = dev.sectors * dev.heads; if(sect_per_track != 0) { + int hidden; + unsigned long tot_sectors; + int tracks_match=0; printf("mformat command line: mformat "); - hidden = DWORD_S(nhs); + + if(haveBPB) { + int sector_size; + tot_sectors = DWORD_S(bigsect); + SET_INT(tot_sectors, WORD_S(psect)); + sector_size = WORD_S(secsiz); + size_code=2; + for(i=0; i<7; i++) { + if(sector_size == 128 << i) { + size_code = i; + break; + } + } + if(media == 0xf0) + hidden = DWORD_S(nhs); + else + hidden = 0; + } else { + tot_sectors = dev.tracks * sect_per_track; + size_code=2; + hidden = 0; + } + if(tot_sectors == dev.tracks * sect_per_track - hidden % sect_per_track) { tracks_match=1; @@ -142,69 +217,19 @@ void minfo(int argc, char **argv, int type) } else { printf("-T %ld ", tot_sectors); } - if(imgFile != NULL) - printf("-i %s ", imgFile); - printf (" -h %d -s %d ", dev.heads, dev.sectors); - if(hidden || !tracks_match) + printf ("-h %d -s %d ", dev.heads, dev.sectors); + if(haveBPB && (hidden || !tracks_match)) printf("-H %d ", hidden); if(size_code != 2) printf("-S %d ",size_code); + if(imgFile != NULL) + printf("-i \"%s\" ", imgFile); printf("%c:\n", tolower(drive)); printf("\n"); } - printf("bootsector information\n"); - printf("======================\n"); - printf("banner:\"%.8s\"\n", boot.boot.banner); - printf("sector size: %d bytes\n", WORD_S(secsiz)); - printf("cluster size: %d sectors\n", boot.boot.clsiz); - printf("reserved (boot) sectors: %d\n", WORD_S(nrsvsect)); - printf("fats: %d\n", boot.boot.nfat); - printf("max available root directory slots: %d\n", - WORD_S(dirents)); - printf("small size: %d sectors\n", WORD_S(psect)); - printf("media descriptor byte: 0x%x\n", boot.boot.descr); - printf("sectors per fat: %d\n", WORD_S(fatlen)); - printf("sectors per track: %d\n", WORD_S(nsect)); - printf("heads: %d\n", WORD_S(nheads)); - printf("hidden sectors: %d\n", DWORD_S(nhs)); - printf("big size: %d sectors\n", DWORD_S(bigsect)); - - if(WORD_S(fatlen)) { - labelBlock = &boot.boot.ext.old.labelBlock; - } else { - labelBlock = &boot.boot.ext.fat32.labelBlock; - } - printf("physical drive id: 0x%x\n", - labelBlock->physdrive); - printf("reserved=0x%x\n", - labelBlock->reserved); - printf("dos4=0x%x\n", - labelBlock->dos4); - printf("serial number: %08X\n", - _DWORD(labelBlock->serial)); - printf("disk label=\"%11.11s\"\n", - labelBlock->label); - printf("disk type=\"%8.8s\"\n", - labelBlock->fat_type); - - if(!WORD_S(fatlen)){ - printf("Big fatlen=%u\n", - DWORD_S(ext.fat32.bigFat)); - printf("Extended flags=0x%04x\n", - WORD_S(ext.fat32.extFlags)); - printf("FS version=0x%04x\n", - WORD_S(ext.fat32.fsVersion)); - printf("rootCluster=%u\n", - DWORD_S(ext.fat32.rootCluster)); - if(WORD_S(ext.fat32.infoSector) != MAX16) - printf("infoSector location=%d\n", - WORD_S(ext.fat32.infoSector)); - if(WORD_S(ext.fat32.backupBoot) != MAX16) - printf("backup boot sector=%d\n", - WORD_S(ext.fat32.backupBoot)); - displayInfosector(Stream,&boot); - } + if(haveBPB || verbose) + displayBPB(Stream, &boot); if(verbose) { int size; @@ -163,6 +163,35 @@ time_t getTimeNow(time_t *now) static time_t sharedNow; if(!haveTime) { + const char *source_date_epoch = getenv("SOURCE_DATE_EPOCH"); + if (source_date_epoch) { + char *endptr; + unsigned long long epoch = + strtoll(source_date_epoch, &endptr, 10); + + if (endptr == source_date_epoch) + fprintf(stderr, "SOURCE_DATE_EPOCH invalid\n"); + else if ((errno == ERANGE && + (epoch == ULLONG_MAX || epoch == 0)) + || (errno != 0 && epoch == 0)) + fprintf(stderr, + "SOURCE_DATE_EPOCH: strtoll: %s: %llu\n", + strerror(errno), epoch); + else if (*endptr != '\0') + fprintf(stderr, + "SOURCE_DATE_EPOCH has trailing garbage\n"); + else if (epoch > ULONG_MAX) + fprintf(stderr, + "SOURCE_DATE_EPOCH must be <= %lu but saw: %llu\n", + ULONG_MAX, epoch); + else { + sharedNow = epoch; + haveTime = 1; + } + } + } + + if(!haveTime) { time(&sharedNow); haveTime = 1; } diff --git a/missFuncs.c b/missFuncs.c index e16d9e3..e760336 100644 --- a/missFuncs.c +++ b/missFuncs.c @@ -43,6 +43,27 @@ char *strdup(const char *str) } #endif /* HAVE_STRDUP */ +#ifndef HAVE_STRNDUP +char *strndup( const char *s, size_t n ) +{ + size_t nAvail; + char *p; + + if ( !s ) + return 0; + + nAvail = min( strlen(s) + 1, n + 1 ); + p = malloc( nAvail ); + if ( !p ) + return 0; + memcpy( p, s, nAvail ); + p[nAvail - 1] = '\0'; + + return p; +} +#endif /* HAVE_STRNDUP */ + + #ifdef HAVE_WCHAR_H #ifndef HAVE_WCSDUP wchar_t *wcsdup(const wchar_t *wcs) diff --git a/mk_direntry.c b/mk_direntry.c index a9b5a2c..ccb39c5 100644 --- a/mk_direntry.c +++ b/mk_direntry.c @@ -371,7 +371,8 @@ static __inline__ clash_action get_slots(Stream_t *Dir, reason = RESERVED; ch->use_longname = 1; isprimary = 0; - } else if(contains_illegals(dosname->base,short_illegals,11)) { + } else if(!ch->is_label && + contains_illegals(dosname->base,short_illegals,11)) { reason = ILLEGALS; ch->use_longname = 1; isprimary = 0; @@ -671,6 +672,7 @@ void init_clash_handling(ClashHandling_t *ch) ch->namematch_default[1] = NAMEMATCH_NONE; ch->name_converter = dos_name; /* changed by mlabel */ ch->source = -2; + ch->is_label = 0; } int handle_clash_options(ClashHandling_t *ch, char c) diff --git a/mkmanifest.1 b/mkmanifest.1 index a6b5a5a..ef5504a 100644 --- a/mkmanifest.1 +++ b/mkmanifest.1 @@ -1,5 +1,5 @@ '\" t -.TH mkmanifest 1 "29Sep18" mtools-4.0.19 +.TH mkmanifest 1 "11Nov18" mtools-pre-4.0.20 .SH Name mkmanifest - makes list of file names and their DOS 8+3 equivalent '\" t @@ -1,5 +1,5 @@ '\" t -.TH mlabel 1 "29Sep18" mtools-4.0.19 +.TH mlabel 1 "11Nov18" mtools-pre-4.0.20 .SH Name mlabel - make an MSDOS volume label '\" t @@ -27,7 +27,7 @@ #include "nameclash.h" #include "file_name.h" -static void _label_name(doscp_t *cp, const char *filename, int verbose, +static void _label_name(doscp_t *cp, const char *filename, int verbose UNUSEDP, int *mangled, dos_name_t *ans, int preserve_case) { int len; @@ -81,8 +81,8 @@ void label_name_pc(doscp_t *cp, const char *filename, int verbose, } int labelit(struct dos_name_t *dosname, - char *longname, - void *arg0, + char *longname UNUSEDP, + void *arg0 UNUSEDP, direntry_t *entry) { time_t now; @@ -103,7 +103,7 @@ static void usage(int ret) } -void mlabel(int argc, char **argv, int type) +void mlabel(int argc, char **argv, int type UNUSEDP) { const char *newLabel=""; @@ -133,6 +133,7 @@ void mlabel(int argc, char **argv, int type) init_clash_handling(&ch); ch.name_converter = label_name_uc; ch.ignore_entry = -2; + ch.is_label = 1; verbose = 0; clear = 0; @@ -299,8 +300,7 @@ void mlabel(int argc, char **argv, int type) cp = GET_DOSCONVERT(Fs); label_name_pc(cp, shrtLabel, verbose, &mangled, &dosname); - if(have_boot && boot.boot.descr >= 0xf0 && - labelBlock->dos4 == 0x29) { + if(have_boot && boot.boot.descr >= 0xf0 && has_BPB4) { strncpy(labelBlock->label, dosname.base, 11); need_write_boot = 1; @@ -308,8 +308,7 @@ void mlabel(int argc, char **argv, int type) } if((set_serial != SER_NONE) & have_boot) { - if(have_boot && boot.boot.descr >= 0xf0 && - labelBlock->dos4 == 0x29) { + if(have_boot && boot.boot.descr >= 0xf0 && has_BPB4) { set_dword(labelBlock->serial, serial); need_write_boot = 1; } @@ -1,5 +1,5 @@ '\" t -.TH mmd 1 "29Sep18" mtools-4.0.19 +.TH mmd 1 "11Nov18" mtools-pre-4.0.20 .SH Name mmd - make an MSDOS subdirectory '\" t @@ -59,7 +59,7 @@ typedef struct CreateArg_t { * directory structure or NULL on error. */ static int makeit(dos_name_t *dosname, - char *longname, + char *longname UNUSEDP, void *arg0, direntry_t *targetEntry) { @@ -137,7 +137,7 @@ Stream_t *createDir(Stream_t *Dir, const char *filename, ClashHandling_t *ch, return arg.NewDir; } -static int createDirCallback(direntry_t *entry, MainParam_t *mp) +static int createDirCallback(direntry_t *entry UNUSEDP, MainParam_t *mp) { Stream_t *ret; time_t now; @@ -153,7 +153,7 @@ static int createDirCallback(direntry_t *entry, MainParam_t *mp) } -void mmd(int argc, char **argv, int type) +void mmd(int argc, char **argv, int type UNUSEDP) { Arg_t arg; int c; @@ -1,5 +1,5 @@ '\" t -.TH mmount 1 "29Sep18" mtools-4.0.19 +.TH mmount 1 "11Nov18" mtools-pre-4.0.20 .SH Name mmount - mount an MSDOS disk '\" t @@ -32,7 +32,7 @@ #include "mainloop.h" #include "fs.h" -void mmount(int argc, char **argv, int type) +void mmount(int argc, char **argv, int type UNUSEDP) { char drive; int pid; @@ -1,5 +1,5 @@ '\" t -.TH mmove 1 "29Sep18" mtools-4.0.19 +.TH mmove 1 "11Nov18" mtools-pre-4.0.20 .SH Name mmove - move or rename an MSDOS file or subdirectory '\" t @@ -51,7 +51,7 @@ typedef struct Arg_t { * directory structure or NULL on error. */ static int renameit(dos_name_t *dosname, - char *longname, + char *longname UNUSEDP, void *arg0, direntry_t *targetEntry) { diff --git a/mpartition.1 b/mpartition.1 index b3f1c16..325c46c 100644 --- a/mpartition.1 +++ b/mpartition.1 @@ -1,5 +1,5 @@ '\" t -.TH mpartition 1 "29Sep18" mtools-4.0.19 +.TH mpartition 1 "11Nov18" mtools-pre-4.0.20 .SH Name mpartition - partition an MSDOS hard disk '\" t diff --git a/mpartition.c b/mpartition.c index eeded93..8b42825 100644 --- a/mpartition.c +++ b/mpartition.c @@ -319,7 +319,7 @@ static void usage(int ret) exit(ret); } -void mpartition(int argc, char **argv, int dummy) +void mpartition(int argc, char **argv, int dummy UNUSEDP) { Stream_t *Stream; unsigned int dummy2; @@ -1,5 +1,5 @@ '\" t -.TH mrd 1 "29Sep18" mtools-4.0.19 +.TH mrd 1 "11Nov18" mtools-pre-4.0.20 .SH Name mrd - remove an MSDOS subdirectory '\" t @@ -1,5 +1,5 @@ '\" t -.TH mren 1 "29Sep18" mtools-4.0.19 +.TH mren 1 "11Nov18" mtools-pre-4.0.20 .SH Name mren - rename an existing MSDOS file '\" t @@ -130,6 +130,8 @@ typedef struct label_blk_t { char fat_type[8]; /* 54 FAT type */ } label_blk_t; +#define has_BPB4 (labelBlock->dos4 == 0x28 || labelBlock->dos4 == 0x29) + /* FAT32 specific info in the bootsector */ struct fat32_t { unsigned char bigFat[4]; /* 36 nb of sectors per FAT */ @@ -199,19 +201,6 @@ union bootsector { #define OFFSET(x) (((char *) (boot->x)) - ((char *)(boot->jump))) - -extern struct OldDos_t { - unsigned int tracks; - unsigned int sectors; - unsigned int heads; - - unsigned int dir_len; - unsigned int cluster_size; - unsigned int fat_len; - - int media; -} old_dos[]; - /* max FAT12/FAT16 sizes, according to https://staff.washington.edu/dittrich/misc/fatgen103.pdf diff --git a/mshortname.1 b/mshortname.1 index 65dfb78..76164cb 100644 --- a/mshortname.1 +++ b/mshortname.1 @@ -1,5 +1,5 @@ '\" t -.TH mshortname 1 "29Sep18" mtools-4.0.19 +.TH mshortname 1 "11Nov18" mtools-pre-4.0.20 .SH Name mshortname - shows short name of a file '\" t diff --git a/mshortname.c b/mshortname.c index 5cdfa3f..e7a7db5 100644 --- a/mshortname.c +++ b/mshortname.c @@ -23,7 +23,7 @@ #include "mtools.h" #include "mainloop.h" -static int print_short_name(direntry_t *entry, MainParam_t *mp) +static int print_short_name(direntry_t *entry, MainParam_t *mp UNUSEDP) { fprintShortPwd(stdout, entry); putchar('\n'); @@ -42,7 +42,7 @@ static void usage(int ret) exit(ret); } -void mshortname(int argc, char **argv, int type) +void mshortname(int argc, char **argv, int type UNUSEDP) { struct MainParam_t mp; int c; @@ -1,5 +1,5 @@ '\" t -.TH mshowfat 1 "29Sep18" mtools-4.0.19 +.TH mshowfat 1 "11Nov18" mtools-pre-4.0.20 .SH Name mshowfat - shows FAT clusters allocated to file '\" t @@ -52,7 +52,7 @@ static int dos_showfat(direntry_t *entry, MainParam_t *mp) return GOT_ONE; } -static int unix_showfat(MainParam_t *mp) +static int unix_showfat(MainParam_t *mp UNUSEDP) { fprintf(stderr,"File does not reside on a Dos fs\n"); return ERROR_ONE; @@ -69,7 +69,7 @@ static void usage(int ret) exit(ret); } -void mshowfat(int argc, char **argv, int mtype) +void mshowfat(int argc, char **argv, int mtype UNUSEDP) { Arg_t arg; int c, ret; @@ -1,5 +1,5 @@ '\" t -.TH mtools 1 "29Sep18" mtools-4.0.19 +.TH mtools 1 "11Nov18" mtools-pre-4.0.20 .SH Name mtools - utilities to access DOS disks in Unix. '\" t @@ -36,10 +36,10 @@ 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.19.tar.gz -http://mtools.linux.lu/mtools-4.0.19.tar.gz -ftp://www.tux.org/pub/knaff/mtools/mtools-4.0.19.tar.gz -ftp://ibiblio.unc.edu/pub/Linux/utils/disk-management/mtools-4.0.19.tar.gz +http://ftp.gnu.org/gnu/mtools/mtools-4.0.20.tar.gz +http://mtools.linux.lu/mtools-4.0.20.tar.gz +ftp://www.tux.org/pub/knaff/mtools/mtools-4.0.20.tar.gz +ftp://ibiblio.unc.edu/pub/Linux/utils/disk-management/mtools-4.0.20.tar.gz .fi .in -0.3i .ft R @@ -1,5 +1,5 @@ '\" t -.TH mtools 5 "29Sep18" MTOOLS MTOOLS +.TH mtools 5 "11Nov18" MTOOLS MTOOLS .SH Name mtools.conf - mtools configuration files '\" t @@ -13,9 +13,7 @@ mtools.conf - mtools configuration files .tr \(if` .tr \(pd" -.ds St Mtools\ 4.0.19 -.oh '\\*(St''%' -.eh '%''\\*(St' +.ds St Mtools\ 4.0.20 .PP .SH Description .PP @@ -106,6 +104,10 @@ clash would have happened. \&\fR\&\f(CWMTOOLS_TWENTY_FOUR_HOUR_CLOCK\fR\ If 1, uses the European notation for times (twenty four hour clock), else uses the UK/US notation (am/pm) +.TP +\&\fR\&\f(CWMTOOLS_LOCK_TIMEOUT\fR\ +How long, in seconds, to wait for a locked device to become free. +Defaults to 30. .PP Example: Inserting the following line into your configuration file instructs @@ -79,6 +79,24 @@ typedef struct device { const char *cfg_filename; /* used for debugging purposes */ } device_t; +struct OldDos_t { + unsigned int tracks; + unsigned int sectors; + unsigned int heads; + + unsigned int dir_len; + unsigned int cluster_size; + unsigned int fat_len; + + int media; +}; + +extern struct OldDos_t *getOldDosBySize(size_t size); +extern struct OldDos_t *getOldDosByMedia(int media); +extern struct OldDos_t *getOldDosByParams(int tracks, int heads, int sectors, + int dir_len, int cluster_size); +int setDeviceFromOldDos(int media, struct device *dev); + #ifndef OS_linux #define BOOTSIZE 512 @@ -94,6 +112,12 @@ typedef struct doscp_t doscp_t; extern const char *short_illegals, *long_illegals; #define maximize(target, max) do { \ + if(target > max) { \ + target = max; \ + } \ +} while(0) + +#define smaximize(target, max) do { \ if(max < 0) { \ if(target > 0) \ target = 0; \ @@ -188,6 +212,7 @@ extern unsigned int mtools_ignore_short_case; extern unsigned int mtools_no_vfat; extern unsigned int mtools_numeric_tail; extern unsigned int mtools_dotted_dir; +extern unsigned int mtools_lock_timeout; extern unsigned int mtools_twenty_four_hour_clock; extern const char *mtools_date_string; extern unsigned int mtools_rate_0, mtools_rate_any; diff --git a/mtools.info b/mtools.info index 3ab13ee..5d0b24c 100644 --- a/mtools.info +++ b/mtools.info @@ -1,6 +1,6 @@ This is mtools.info, produced by makeinfo version 6.3 from mtools.texi. -This manual is for Mtools (version 4.0.19, September 2018), which is a +This manual is for Mtools (version 4.0.20, November 2018), which is a collection of tools to allow Unix systems to manipulate MS-DOS files. Copyright (C) 2007, 2009 Free Software Foundation, Inc. Copyright @@ -41,8 +41,8 @@ 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.19, September 2018), which is -a collection of tools to allow Unix systems to manipulate MS-DOS files. + This manual is for Mtools (version 4.0.20, November 2018), which is a +collection of tools to allow Unix systems to manipulate MS-DOS files. Copyright (C) 2007, 2009 Free Software Foundation, Inc. Copyright (C) 1996-2005,2007-2011,2013 Alain Knaff. @@ -75,10 +75,10 @@ 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.19.tar.gz - http://mtools.linux.lu/mtools-4.0.19.tar.gz - ftp://www.tux.org/pub/knaff/mtools/mtools-4.0.19.tar.gz - ftp://ibiblio.unc.edu/pub/Linux/utils/disk-management/mtools-4.0.19.tar.gz + http://ftp.gnu.org/gnu/mtools/mtools-4.0.20.tar.gz + http://mtools.linux.lu/mtools-4.0.20.tar.gz + ftp://www.tux.org/pub/knaff/mtools/mtools-4.0.20.tar.gz + ftp://ibiblio.unc.edu/pub/Linux/utils/disk-management/mtools-4.0.20.tar.gz Before reporting a bug, make sure that it has not yet been fixed in the Alpha patches which can be found at: @@ -614,6 +614,9 @@ Global flags may be set to 1 or to 0. 'MTOOLS_TWENTY_FOUR_HOUR_CLOCK' If 1, uses the European notation for times (twenty four hour clock), else uses the UK/US notation (am/pm) +'MTOOLS_LOCK_TIMEOUT' + How long, in seconds, to wait for a locked device to become free. + Defaults to 30. Example: Inserting the following line into your configuration file instructs mtools to skip the sanity checks: @@ -1522,6 +1525,7 @@ low-level formatted diskette. Its syntax is: ['-B' BOOT_SECTOR] ['-k'] ['-m' MEDIA_DESCRIPTOR] ['-K' BACKUP_BOOT] + ['-R' NB_RESERVED_SECTORS] ['-c' CLUSTERS_PER_SECTOR] ['-d' FAT_COPIES] ['-X'] ['-2' SECTORS_ON_TRACK_0] ['-3'] @@ -1674,6 +1678,11 @@ has a different meaning. 'K' Sets the sector number where the backup of the boot sector should be stored (only relevant on FAT32). +'R' + Sets the number of reserved sectors for this filesystem. This must + be at least 1 for non-FAT32 disks, and at least 3 for FAT disks (in + order to accomodate the boot sector, the info sector and the backup + boot sector). 'm' Use a non-standard media descriptor byte for this disk. The media @@ -2397,10 +2406,14 @@ Variable index * heads: geometry description. (line 63) * mformat_only: miscellaneous flags. (line 74) * MTOOLSRC: Configuration. (line 9) +* MTOOLS_DOTTED_DIR: global variables. (line 6) * MTOOLS_FAT_COMPATIBILITY: global variables. (line 6) +* MTOOLS_LOCK_TIMEOUT: global variables. (line 6) * MTOOLS_LOWER_CASE: global variables. (line 6) +* MTOOLS_NAME_NUMERIC_TAIL: global variables. (line 6) * MTOOLS_NO_VFAT: global variables. (line 6) * MTOOLS_SKIP_CHECK: global variables. (line 6) +* MTOOLS_TWENTY_FOUR_HOUR_CLOCK: global variables. (line 6) * nodelay: open flags. (line 6) * sectors: geometry description. (line 65) * sync: open flags. (line 6) @@ -2668,71 +2681,71 @@ Concept index Tag Table: -Node: Top873 -Node: Location2962 -Node: Common features4351 -Node: arguments5115 -Node: drive letters6776 -Node: directory8130 -Node: long names8576 -Node: name clashes11122 -Node: case sensitivity13406 -Node: high capacity formats14640 -Node: more sectors15758 -Node: bigger sectors16813 -Node: 2m17539 -Node: XDF18721 -Node: exit codes20064 -Node: bugs20702 -Node: Configuration21235 -Node: configuration file location22372 -Node: general syntax22796 -Node: default values23627 -Node: global variables24155 -Node: per drive variables26234 -Node: general information27069 -Node: location information27511 -Node: geometry description29040 -Node: open flags32901 -Node: miscellaneous variables33501 -Node: miscellaneous flags35577 -Node: multiple descriptions39207 -Node: parsing order40881 -Node: old style configuration41912 -Node: Commands42611 -Node: floppyd44533 -Node: floppyd_installtest49326 -Node: mattrib49957 -Node: mbadblocks51750 -Node: mcat53044 -Node: mcd53858 -Node: mclasserase54719 -Node: mcopy55395 -Node: mdel58409 -Node: mdeltree58748 -Node: mdir59167 -Node: mdu60443 -Node: mformat60949 -Node: mkmanifest69183 -Node: minfo71157 -Node: mlabel71727 -Node: mmd72880 -Node: mmount73229 -Node: mmove73828 -Node: mpartition74635 -Node: mrd80148 -Node: mren80506 -Node: mshortname81255 -Node: mshowfat81585 -Node: mtoolstest81994 -Node: mtype82566 -Node: mzip83417 -Ref: mzip-Footnote-185442 -Ref: mzip-Footnote-285523 -Node: Compiling mtools85810 -Node: Porting mtools86909 -Node: Command Index92813 -Node: Variable Index92941 -Node: Concept Index94472 +Node: Top872 +Node: Location2960 +Node: Common features4349 +Node: arguments5113 +Node: drive letters6774 +Node: directory8128 +Node: long names8574 +Node: name clashes11120 +Node: case sensitivity13404 +Node: high capacity formats14638 +Node: more sectors15756 +Node: bigger sectors16811 +Node: 2m17537 +Node: XDF18719 +Node: exit codes20062 +Node: bugs20700 +Node: Configuration21233 +Node: configuration file location22370 +Node: general syntax22794 +Node: default values23625 +Node: global variables24153 +Node: per drive variables26346 +Node: general information27181 +Node: location information27623 +Node: geometry description29152 +Node: open flags33013 +Node: miscellaneous variables33613 +Node: miscellaneous flags35689 +Node: multiple descriptions39319 +Node: parsing order40993 +Node: old style configuration42024 +Node: Commands42723 +Node: floppyd44645 +Node: floppyd_installtest49438 +Node: mattrib50069 +Node: mbadblocks51862 +Node: mcat53156 +Node: mcd53970 +Node: mclasserase54831 +Node: mcopy55507 +Node: mdel58521 +Node: mdeltree58860 +Node: mdir59279 +Node: mdu60555 +Node: mformat61061 +Node: mkmanifest69571 +Node: minfo71545 +Node: mlabel72115 +Node: mmd73268 +Node: mmount73617 +Node: mmove74216 +Node: mpartition75023 +Node: mrd80536 +Node: mren80894 +Node: mshortname81643 +Node: mshowfat81973 +Node: mtoolstest82382 +Node: mtype82954 +Node: mzip83805 +Ref: mzip-Footnote-185830 +Ref: mzip-Footnote-285911 +Node: Compiling mtools86198 +Node: Porting mtools87297 +Node: Command Index93201 +Node: Variable Index93329 +Node: Concept Index95152 End Tag Table diff --git a/mtools.spec b/mtools.spec index 7fc29ef..b655176 100644 --- a/mtools.spec +++ b/mtools.spec @@ -1,7 +1,7 @@ %define _binary_payload w9.gzdio Name: mtools Summary: mtools, read/write/list/format DOS disks under Unix -Version: 4.0.19 +Version: 4.0.20 Release: 1 License: GPLv3+ Group: Utilities/System @@ -135,6 +135,30 @@ if [ -f %{_bindir}/install-info ] ; then fi %changelog +* Sun Nov 11 2018 Alain Knaff <alain@knaff.lu> +- initialize directory entries to 0 +- bad message "Too few sectors" replaced with "Too many sectors" +- apostrophe in mlabel no longer causes generation of long entry +- option to fake system date for file creation using the SOURCE_DATE_EPOCH environment variables +- can now be compiled with "clang" compiler +- fallback function for strndup, for those platforms that do not have it +- fixed a number of -Wextra warnings +- new compressed archive formats for uz/lz +- allow to specify number of reserved sectors for FAT32. +- file/device locking with timeout (rather than immediate failure) +- fixed support for BPB-less legacy formats. +- removed check that disk must be an integer number of tracks. +- removed .eh/.oh macros from manual pages +* Sat Sep 29 2018 Alain Knaff <alain@knaff.lu> +- Fix for short file names starting with character 0xE5 (by remapping it to 0x5) +- mpartition: Partition types closer to what Microsoft uses +- mformat: figure out LBA geometry as last resort if geometry +is neither specified in config and/or commandline, nor can be +queried from the device +- mformat: use same default cluster size by size as Microsoft for FAT32 +- additional sanity checks +- document how cluster size is picked in mformat.c man page +- document how partition types are picked in mpartition.c man page * Wed Jan 09 2013 Alain Knaff <alain@knaff.lu> - Fix for names of iconv encodings on AIX - Fix mt_size_t on NetBSD diff --git a/mtools.texi b/mtools.texi index 8b675b7..27dff44 100644 --- a/mtools.texi +++ b/mtools.texi @@ -658,6 +658,10 @@ DOSEMU image files. @vindex MTOOLS_FAT_COMPATIBILITY @vindex MTOOLS_LOWER_CASE @vindex MTOOLS_NO_VFAT +@vindex MTOOLS_DOTTED_DIR +@vindex MTOOLS_NAME_NUMERIC_TAIL +@vindex MTOOLS_TWENTY_FOUR_HOUR_CLOCK +@vindex MTOOLS_LOCK_TIMEOUT @cindex FreeDOS Global flags may be set to 1 or to 0. @@ -692,6 +696,9 @@ clash would have happened. @item MTOOLS_TWENTY_FOUR_HOUR_CLOCK If 1, uses the European notation for times (twenty four hour clock), else uses the UK/US notation (am/pm) +@item MTOOLS_LOCK_TIMEOUT +How long, in seconds, to wait for a locked device to become free. +Defaults to 30. @end table Example: @@ -1756,6 +1763,7 @@ low-level formatted diskette. Its syntax is: [@code{-B} @var{boot_sector}] [@code{-k}] [@code{-m} @var{media_descriptor}] [@code{-K} @var{backup_boot}] + [@code{-R} @var{nb_reserved_sectors}] [@code{-c} @var{clusters_per_sector}] [@code{-d} @var{fat_copies}] [@code{-X}] [@code{-2} @var{sectors_on_track_0}] [@code{-3}] @@ -1906,6 +1914,11 @@ disks parameters. @item K Sets the sector number where the backup of the boot sector should be stored (only relevant on FAT32). +@item R +Sets the number of reserved sectors for this filesystem. This must be +at least 1 for non-FAT32 disks, and at least 3 for FAT disks (in order +to accomodate the boot sector, the info sector and the backup boot +sector). @item m Use a non-standard media descriptor byte for this disk. The media diff --git a/mtools.tmpl.1 b/mtools.tmpl.1 index d9ed267..f6d0e3d 100644 --- a/mtools.tmpl.1 +++ b/mtools.tmpl.1 @@ -1,5 +1,5 @@ '\" t -.TH mtools 1 "29Sep18" mtools-4.0.19 +.TH mtools 1 "11Nov18" mtools-pre-4.0.20 .SH Name mtools - utilities to access DOS disks in Unix. '\" t @@ -36,10 +36,10 @@ 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.19.tar.gz -http://mtools.linux.lu/mtools-4.0.19.tar.gz -ftp://www.tux.org/pub/knaff/mtools/mtools-4.0.19.tar.gz -ftp://ibiblio.unc.edu/pub/Linux/utils/disk-management/mtools-4.0.19.tar.gz +http://ftp.gnu.org/gnu/mtools/mtools-4.0.20.tar.gz +http://mtools.linux.lu/mtools-4.0.20.tar.gz +ftp://www.tux.org/pub/knaff/mtools/mtools-4.0.20.tar.gz +ftp://ibiblio.unc.edu/pub/Linux/utils/disk-management/mtools-4.0.20.tar.gz .fi .in -0.3i .ft R diff --git a/mtools.tmpl.5 b/mtools.tmpl.5 index ad1d5b8..77d9996 100644 --- a/mtools.tmpl.5 +++ b/mtools.tmpl.5 @@ -1,5 +1,5 @@ '\" t -.TH mtools 5 "29Sep18" MTOOLS MTOOLS +.TH mtools 5 "11Nov18" MTOOLS MTOOLS .SH Name mtools.conf - mtools configuration files '\" t @@ -13,9 +13,7 @@ mtools.conf - mtools configuration files .tr \(if` .tr \(pd" -.ds St Mtools\ 4.0.19 -.oh '\\*(St''%' -.eh '%''\\*(St' +.ds St Mtools\ 4.0.20 .PP .SH Description .PP @@ -106,6 +104,10 @@ clash would have happened. \&\fR\&\f(CWMTOOLS_TWENTY_FOUR_HOUR_CLOCK\fR\ If 1, uses the European notation for times (twenty four hour clock), else uses the UK/US notation (am/pm) +.TP +\&\fR\&\f(CWMTOOLS_LOCK_TIMEOUT\fR\ +How long, in seconds, to wait for a locked device to become free. +Defaults to 30. .PP Example: Inserting the following line into your configuration file instructs diff --git a/mtoolstest.1 b/mtoolstest.1 index fac3d0d..ca18eba 100644 --- a/mtoolstest.1 +++ b/mtoolstest.1 @@ -1,5 +1,5 @@ '\" t -.TH mtoolstest 1 "29Sep18" mtools-4.0.19 +.TH mtoolstest 1 "11Nov18" mtools-pre-4.0.20 .SH Name mtoolstest - tests and displays the configuration '\" t @@ -1,5 +1,5 @@ '\" t -.TH mtype 1 "29Sep18" mtools-4.0.19 +.TH mtype 1 "11Nov18" mtools-pre-4.0.20 .SH Name mtype - display contents of an MSDOS file '\" t @@ -1,5 +1,5 @@ '\" t -.TH mzip 1 "29Sep18" mtools-4.0.19 +.TH mzip 1 "11Nov18" mtools-pre-4.0.20 .SH Name mzip - change protection mode and eject disk on Zip/Jaz drive '\" t @@ -221,7 +221,7 @@ static int door_command(int priv, int fd, int cmd1, int cmd2, return short_command(priv, fd, cmd1, 0, cmd2, 0, extra_data); } -void mzip(int argc, char **argv, int type) +void mzip(int argc, char **argv, int type UNUSEDP) { void *extra_data; int c; diff --git a/nameclash.h b/nameclash.h index 8ebdb4c..7c69706 100644 --- a/nameclash.h +++ b/nameclash.h @@ -54,6 +54,7 @@ typedef struct ClashHandling_t { void (*name_converter)(doscp_t *cp, const char *filename, int verbose, int *mangled, dos_name_t *ans); + int is_label; } ClashHandling_t; /* write callback */ diff --git a/old_dos.c b/old_dos.c new file mode 100644 index 0000000..6ecf024 --- /dev/null +++ b/old_dos.c @@ -0,0 +1,68 @@ +#include "sysincludes.h" +#include "mtools.h" + +static struct OldDos_t old_dos[]={ +{ 40, 9, 1, 4, 1, 2, 0xfc }, /* 180 KB */ +{ 40, 9, 2, 7, 2, 2, 0xfd }, /* 360 KB */ +{ 40, 8, 1, 4, 1, 1, 0xfe }, /* 160 KB */ +{ 40, 8, 2, 7, 2, 1, 0xff }, /* 320 KB */ +{ 80, 9, 2, 7, 2, 3, 0xf9 }, /* 720 KB */ +{ 80, 15, 2,14, 1, 7, 0xf9 }, /* 1200 KB */ +{ 80, 18, 2,14, 1, 9, 0xf0 }, /* 1440 KB */ +{ 80, 36, 2,15, 2, 9, 0xf0 }, /* 2880 KB */ + +/* Source: https://en.wikipedia.org/w/index.php?title=File_Allocation_Table&oldid=560606333#Exceptions : */ +/* https://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html */ +{ 80, 8, 2, 7, 2, 2, 0xfb }, /* 640 KB */ +{ 80, 8, 1, 7, 2, 2, 0xfa }, /* 320 KB */ +{ 80, 9, 1, 7, 2, 2, 0xf8 }, /* 360 KB */ +}; + +struct OldDos_t *getOldDosBySize(size_t size) { + int i; + for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){ + if (old_dos[i].sectors * + old_dos[i].tracks * + old_dos[i].heads == size) + return &old_dos[i]; + } + return NULL; +} + +struct OldDos_t *getOldDosByMedia(int media) { + int i; + for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){ + if (old_dos[i].media == media) + return &old_dos[i]; + } + fprintf(stderr, "Unknown media type %02x\n", media); + return NULL; +} + +struct OldDos_t *getOldDosByParams(int tracks, int heads, int sectors, + int dir_len, int cluster_size) { + int i; + for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){ + if (sectors == old_dos[i].sectors && + tracks == old_dos[i].tracks && + heads == old_dos[i].heads && + (dir_len == 0 || dir_len == old_dos[i].dir_len) && + (cluster_size == 0 || + cluster_size == old_dos[i].cluster_size)) { + return &old_dos[i]; + } + } + return NULL; +} + +int setDeviceFromOldDos(int media, struct device *dev) { + struct OldDos_t *params=getOldDosByMedia(media); + if(params == NULL) + return -1; + dev->heads = params->heads; + dev->tracks = params->tracks; + dev->sectors = params->sectors; + dev->ssize = 0x80; + dev->use_2m = ~1; + return 0; +} diff --git a/patchlevel.c b/patchlevel.c index 0871038..51bd2ce 100644 --- a/patchlevel.c +++ b/patchlevel.c @@ -15,10 +15,10 @@ * along with Mtools. If not, see <http://www.gnu.org/licenses/>. */ -const char *mversion="4.0.19"; +const char *mversion="pre-4.0.20"; /* Multiple releases on same day should be marked with (b), (cd), (d) after * date string below */ -const char *mdate = "September 29th, 2018"; +const char *mdate = "November 11th, 2018"; -const char *mformat_banner = "MTOO4019"; +const char *mformat_banner = "MTOO4020"; @@ -150,7 +150,7 @@ static int file_write(Stream_t *Stream, char *buf, mt_off_t where, size_t len) } } -static int file_flush(Stream_t *Stream) +static int file_flush(Stream_t *Stream UNUSEDP) { #if 0 DeclareThis(SimpleFile_t); @@ -223,7 +223,7 @@ static int file_geom(Stream_t *Stream, struct device *dev, } if (boot->boot.descr >= 0xf0 && - labelBlock->dos4 == 0x29 && + has_BPB4 && strncmp( boot->boot.banner,"2M", 2 ) == 0 && BootP < 512 && Infp0 < 512 && InfpX < 512 && InfTm < 512 && BootP >= InfTm + 2 && InfTm >= InfpX && InfpX >= Infp0 && @@ -236,17 +236,9 @@ static int file_geom(Stream_t *Stream, struct device *dev, dev->ssize |= 0x80; /* is set */ } } - } else if (media >= 0xf8){ - media &= 3; - dev->heads = old_dos[media].heads; - dev->tracks = old_dos[media].tracks; - dev->sectors = old_dos[media].sectors; - dev->ssize = 0x80; - dev->use_2m = ~1; - } else { - fprintf(stderr,"Unknown media type\n"); - exit(1); - } + } else + if(setDeviceFromOldDos(media, dev) < 0) + exit(1); sectors = dev->sectors; dev->sectors = dev->sectors * WORD(secsiz) / 512; @@ -705,7 +697,7 @@ APIRET rc; This->swap = DO_SWAP( dev ); if(!(mode2 & NO_OFFSET) && - dev && (dev->partition > 4 || dev->partition < 0)) + dev && (dev->partition > 4)) fprintf(stderr, "Invalid partition %d (must be between 0 and 4), ignoring it\n", dev->partition); diff --git a/privileges.c b/privileges.c index c2f5c74..88f385f 100644 --- a/privileges.c +++ b/privileges.c @@ -61,7 +61,7 @@ int setresuid(int a, int b, int c) } #endif -static __inline__ void print_privs(const char *message) +static __inline__ void print_privs(const char *message UNUSEDP) { #ifdef PRIV_DEBUG /* for debugging purposes only */ @@ -173,7 +173,10 @@ void init_privs(void) exit(1); } #endif - + + if(euid != ruid) { + unsetenv("SOURCE_DATE_EPOCH"); + } if(euid == 0 && ruid != 0) { #ifdef HAVE_SETEUID setuid(0); /* set real uid to 0 */ @@ -43,10 +43,12 @@ uzcmd='gzip -cd' case $0 in *uz) tarparam="-pxvf" + zipparam="" action="Extracting from " ;; *lz) tarparam="-tvf" + zipparam="-l" action="Reading directory of " ;; *) @@ -65,26 +67,37 @@ while [ $# -ge 1 ]; do echo >&2 found= - for suffix in "" .gz .tgz .tar.gz .z .tar.z .taz .tpz .Z .tar.Z .tar.bz2 tar.lz ; do + for suffix in "" .gz .tgz .tar.gz .z .tar.z .taz .tpz .Z .tar.Z .tar.bz2 tar.lz .zip .jar .war .ear .aar .tar.xz; do if [ -r "${1}$suffix" ]; then found=$1$suffix break fi done + unzip=0 case $found in *.tar.bz2 | *.tb2) uzcmd='bzip2 -cd' ;; + *.zip | *.jar | *.war | *.ear | *.aar) + unzip=1 + ;; *.tar.lz) uzcmd='lzip -cd' ;; + *.tar.xz) + uzcmd='xz -cd' + ;; esac if [ -z "$found" ]; then echo "$0: could not read \"$1\"." >&2 else echo "$action \"$found\"." >&2 - $uzcmd -- "$found" | tar "$tarparam" - + if [ $unzip = 1 ]; then + unzip $zipparam -- "$found" + else + $uzcmd -- "$found" | tar "$tarparam" - + fi fi shift done @@ -79,7 +79,8 @@ int scsi_max_length(void) #endif } -int scsi_open(const char *name, int flag, int mode, void **extra_data) +int scsi_open(const char *name, int flag UNUSEDP, int mode UNUSEDP, + void **extra_data UNUSEDP) { #if (defined(OS_freebsd)) && (__FreeBSD__ >= 2) struct cam_device *cam_dev; @@ -99,7 +100,7 @@ int scsi_open(const char *name, int flag, int mode, void **extra_data) } int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode, - void *data, size_t len, void *extra_data) + void *data, size_t len, void *extra_data UNUSEDP) { #if defined OS_hpux struct sctl_io sctl_io; @@ -22,7 +22,7 @@ int got_signal = 0; -static void signal_handler(int dummy) +static void signal_handler(int dummy UNUSEDP) { got_signal = 1; #if 0 diff --git a/strip-pp.sed b/strip-pp.sed index 1624aa0..0707b76 100644 --- a/strip-pp.sed +++ b/strip-pp.sed @@ -18,3 +18,5 @@ s/^\.[IlP][pP]\n\(\.[IlTP][pP]\)$/\1/ s/^\.l[pP]/.PP/ /^\.PP$/b1 +/^\.eh/d +/^\.oh/d @@ -87,7 +87,7 @@ static Terminal in_orig; /*--------------- Signal Handler routines -------------*/ -static void tty_time_out(int dummy) +static void tty_time_out(int dummy UNUSEDP) { int exit_code; signal(SIGALRM, SIG_IGN); @@ -73,7 +73,9 @@ static Class_t DirClass = { dir_free, /* free */ 0, /* get_geom */ get_dir_data , - 0 /* pre-allocate */ + 0, /* pre-allocate */ + 0, /* get_dosConvert */ + 0 /* discard */ }; #ifdef HAVE_FCHDIR diff --git a/version.texi b/version.texi index e73a1a2..cd0690a 100644 --- a/version.texi +++ b/version.texi @@ -1,3 +1,3 @@ -@set EDITION 4.0.19 -@set VERSION 4.0.19 -@set UPDATED September 2018 +@set EDITION 4.0.20 +@set VERSION 4.0.20 +@set UPDATED November 2018 @@ -408,7 +408,7 @@ static void decompose(Xdf_t *This, int where, int len, off_t *begin, *begin = where - track * This->track_size * 1024; *end = where + len - track * This->track_size * 1024; - maximize(*end, This->track_size * 1024); + smaximize(*end, This->track_size * 1024); if(This->current_track == track && !boot) /* already OK, return immediately */ @@ -485,8 +485,6 @@ static int xdf_read(Stream_t *Stream, char *buf, mt_off_t where, size_t len) decompose(This, truncBytes32(where), len, &begin, &end, 0); len2 = load_data(This, begin, end, 4); - if(len2 < 0) - return len2; len2 -= begin; maximize(len, len2); memcpy(buf, This->buffer + begin, len); @@ -501,11 +499,9 @@ static int xdf_write(Stream_t *Stream, char *buf, mt_off_t where, size_t len) decompose(This, truncBytes32(where), len, &begin, &end, 0); len2 = load_bounds(This, begin, end); - if(len2 < 0) - return len2; - maximize(end, (off_t)len2); + smaximize(end, (off_t)len2); len2 -= begin; - maximize(len, (off_t)len2); + smaximize(len, (off_t)len2); memcpy(This->buffer + begin, buf, len); mark_dirty(This, begin, end); return end - begin; @@ -571,8 +567,8 @@ static void set_geom(union bootsector *boot, struct device *dev) } } -static int config_geom(Stream_t *Stream, struct device *dev, - struct device *orig_dev, int media, +static int config_geom(Stream_t *Stream UNUSEDP, struct device *dev, + struct device *orig_dev UNUSEDP, int media, union bootsector *boot) { if(check_geom(dev, media, boot)) @@ -588,7 +584,9 @@ static Class_t XdfClass = { xdf_free, config_geom, 0, /* get_data */ - 0 /* pre-allocate */ + 0, /* pre-allocate */ + 0, /* get_dosConvert */ + 0 /* discard */ }; Stream_t *XdfOpen(struct device *dev, char *name, |