- Time to say goodbye to dosfsck port, it's been fully integrated into vfatlib, and the need in a standalone version disappeared.

svn path=/trunk/; revision=37356
This commit is contained in:
Aleksey Bragin 2008-11-14 09:35:59 +00:00
parent a2d0db9460
commit 8efe45f028
33 changed files with 0 additions and 5675 deletions

View file

@ -1 +0,0 @@
dosfsck

View file

@ -1,10 +0,0 @@
Changes from version 0 to 1
===========================
- fixed an off-by-two error in check.c:check_file
- fixed marking clusters bad in fat.c:set_fat
- fat.c:reclaim_free was also reclaiming bad clusters.
- fixed many incorrect byte sex conversions in check.c and fat.c
- -t and -w now require -a or -r
- added option -d to drop files.
- added option -u to try to "undelete" non-directory files.

View file

@ -1,345 +0,0 @@
The license below applies to dosfsck, which is copyrighted by
Werner Almesberger <almesber@lrc.di.epfl.ch> and Roman Hodek
<Roman.Hodek@informatik.uni-erlangen.de>.
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program 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 2 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View file

@ -1,44 +0,0 @@
CC=mingw32-gcc
OBJECTS = boot.o check.o common.o dosfsck.o fat.o file.o io.o lfn.o
all: dosfsck.exe
dosfsck.exe: $(OBJECTS)
$(CC) -o $@ $(LDFLAGS) $^
.c.o:
$(CC) -c $(CFLAGS) $*.c
install: dosfsck
mkdir -p $(SBINDIR) $(MANDIR)
install -m 755 dosfsck $(SBINDIR)
install -m 644 dosfsck.8 $(MANDIR)
rm -f $(SBINDIR)/fsck.msdos
rm -f $(SBINDIR)/fsck.vfat
ln -s dosfsck $(SBINDIR)/fsck.msdos
ln -s dosfsck $(SBINDIR)/fsck.vfat
rm -f $(MANDIR)/fsck.msdos.8
ln -s dosfsck.8 $(MANDIR)/fsck.msdos.8
ln -s dosfsck.8 $(MANDIR)/fsck.vfat.8
clean:
rm -f *.o *.s *.i *~ \#*# tmp_make .#* .new*
distclean: clean
rm -f *.a dosfsck
dep:
sed '/\#\#\# Dependencies/q' <Makefile >tmp_make
$(CPP) $(CFLAGS) -MM *.c >>tmp_make
mv tmp_make Makefile
### Dependencies
boot.o: boot.c common.h dosfsck.h io.h boot.h
check.o: check.c common.h dosfsck.h io.h fat.h file.h lfn.h check.h
common.o: common.c common.h
dosfsck.o: dosfsck.c common.h dosfsck.h io.h boot.h fat.h file.h \
check.h
fat.o: fat.c common.h dosfsck.h io.h check.h fat.h
file.o: file.c common.h file.h
io.o: io.c dosfsck.h common.h io.h
lfn.o: lfn.c common.h io.h dosfsck.h lfn.h file.h

View file

@ -1,60 +0,0 @@
dosfsck, version 1
==================
WARNING: This is ALPHA test software. Use at your own risk.
dosfsck is the Linux equivalent of PC/MS-DOS' CHKDSK. It checks the
consistency of PC/MS-DOS file systems and optionally tries to repair
them. The tests dosfsck performs are described in the man page.
dosfsck needs header files from dosfs.9 (or later) to compile.
Before using dosfsck to repair a file system that contains data of any
value, you should verify that dosfsck is able to correct all reported
errors. (Except fatal errors and those reported as unfixable, of
course.) In order to do this, run it with the -V option, e.g.
dosfsck -V /dev/sda1 (automatic check)
or dosfsck -V -r /dev/sda1 (interactive check and repair)
dosfsck will perform two passes: in the first pass, inconsistencies are
detected and a list of changes to correct the problems is generated. In
the second pass, those changes are applied whenever dosfsck reads data
from disk. Hence no fixable errors should be reported in the second
pass if the first pass was successful.
Please notify the author if fixable errors are reported in the second
pass.
After verifying that dosfsck appears to be able to perform the desired
operations, either confirm that you want the changes to be performed
(if dosfsck was started with -r) or re-run dosfsck with the -a option
(if it was started without -r).
Please send bug reports, comments, flames, etc. to
almesber@nessie.cs.id.ethz.ch or almesber@bernina.ethz.ch
- Werner
FAT32 and LFN support
=====================
I've finally implemented some of the new features of MS-DOS
filesystems: FAT32 and long filenames.
FAT32 is automatically detected and of course the different FAT
structure is handled. (Internally many changes were needed, so 32 bit
variables for all cluster numbers and 64 bit vars for offsets inside
the filesystem.) New checks for FAT32 are most notably on the backup
boot sector and the new info sector. Also the possibility that the
root directory resides in a cluster chain (instead of in a static
area) on FAT32 is handled.
dosfscheck also knows about VFAT long filenames now. It parses those
names and uses them in listings etc. when available. There are also
some checks on the (cruel) structure of how LFNs are stored and some
attempts to fix problems.
- Roman <roman@hodek.net>
BTW, version 2 isn't ALPHA anymore :-)

View file

@ -1,370 +0,0 @@
/* boot.c - Read and analyze ia PC/MS-DOS boot sector */
/* Written 1993 by Werner Almesberger */
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "common.h"
#include "dosfsck.h"
#include "io.h"
#include "boot.h"
#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
/* don't divide by zero */
static struct {
__u8 media;
char *descr;
} mediabytes[] = {
{ 0xf0, "5.25\" or 3.5\" HD floppy" },
{ 0xf8, "hard disk" },
{ 0xf9, "3,5\" 720k floppy 2s/80tr/9sec or "
"5.25\" 1.2M floppy 2s/80tr/15sec" },
{ 0xfa, "5.25\" 320k floppy 1s/80tr/8sec" },
{ 0xfb, "3.5\" 640k floppy 2s/80tr/8sec" },
{ 0xfc, "5.25\" 180k floppy 1s/40tr/9sec" },
{ 0xfd, "5.25\" 360k floppy 2s/40tr/9sec" },
{ 0xfe, "5.25\" 160k floppy 1s/40tr/8sec" },
{ 0xff, "5.25\" 320k floppy 2s/40tr/8sec" },
};
#if defined __alpha || defined __ia64__ || defined __s390x__ || defined __x86_64__ || defined __ppc64__
/* Unaligned fields must first be copied byte-wise */
#define GET_UNALIGNED_W(f) \
({ \
unsigned short __v; \
memcpy( &__v, &f, sizeof(__v) ); \
CF_LE_W( *(unsigned short *)&f ); \
})
#else
#define GET_UNALIGNED_W(f) CF_LE_W( *(unsigned short *)&f )
#endif
static char *get_media_descr( unsigned char media )
{
int i;
for( i = 0; i < sizeof(mediabytes)/sizeof(*mediabytes); ++i ) {
if (mediabytes[i].media == media)
return( mediabytes[i].descr );
}
return( "undefined" );
}
static void dump_boot(DOS_FS *fs,struct boot_sector *b,unsigned lss)
{
unsigned short sectors;
printf("Boot sector contents:\n");
if (!atari_format) {
char id[9];
strncpy(id,b->system_id,8);
id[8] = 0;
printf("System ID \"%s\"\n",id);
}
else {
/* On Atari, a 24 bit serial number is stored at offset 8 of the boot
* sector */
printf("Serial number 0x%x\n",
b->system_id[5] | (b->system_id[6]<<8) | (b->system_id[7]<<16));
}
printf("Media byte 0x%02x (%s)\n",b->media,get_media_descr(b->media));
printf("%10d bytes per logical sector\n",GET_UNALIGNED_W(b->sector_size));
printf("%10d bytes per cluster\n",fs->cluster_size);
printf("%10d reserved sector%s\n",CF_LE_W(b->reserved),
CF_LE_W(b->reserved) == 1 ? "" : "s");
printf("First FAT starts at byte %llu (sector %llu)\n",
(__u64)fs->fat_start,
(__u64)fs->fat_start/lss);
printf("%10d FATs, %d bit entries\n",b->fats,fs->fat_bits);
printf("%10d bytes per FAT (= %u sectors)\n",fs->fat_size,
fs->fat_size/lss);
if (!fs->root_cluster) {
printf("Root directory starts at byte %llu (sector %llu)\n",
(__u64)fs->root_start,
(__u64)fs->root_start/lss);
printf("%10d root directory entries\n",fs->root_entries);
}
else {
printf( "Root directory start at cluster %lu (arbitrary size)\n",
fs->root_cluster);
}
printf("Data area starts at byte %llu (sector %llu)\n",
(__u64)fs->data_start,
(__u64)fs->data_start/lss);
printf("%10lu data clusters (%llu bytes)\n",fs->clusters,
(__u64)fs->clusters*fs->cluster_size);
printf("%u sectors/track, %u heads\n",CF_LE_W(b->secs_track),
CF_LE_W(b->heads));
printf("%10u hidden sectors\n",
atari_format ?
/* On Atari, the hidden field is only 16 bit wide and unused */
(((unsigned char *)&b->hidden)[0] |
((unsigned char *)&b->hidden)[1] << 8) :
CF_LE_L(b->hidden));
sectors = GET_UNALIGNED_W( b->sectors );
printf("%10u sectors total\n", sectors ? sectors : CF_LE_L(b->total_sect));
}
static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, int lss)
{
struct boot_sector b2;
if (!fs->backupboot_start) {
printf( "There is no backup boot sector.\n" );
if (CF_LE_W(b->reserved) < 3) {
printf( "And there is no space for creating one!\n" );
return;
}
if (interactive)
printf( "1) Create one\n2) Do without a backup\n" );
else printf( " Auto-creating backup boot block.\n" );
if (!interactive || get_key("12","?") == '1') {
int bbs;
/* The usual place for the backup boot sector is sector 6. Choose
* that or the last reserved sector. */
if (CF_LE_W(b->reserved) >= 7 && CF_LE_W(b->info_sector) != 6)
bbs = 6;
else {
bbs = CF_LE_W(b->reserved) - 1;
if (bbs == CF_LE_W(b->info_sector))
--bbs; /* this is never 0, as we checked reserved >= 3! */
}
fs->backupboot_start = bbs*lss;
b->backup_boot = CT_LE_W(bbs);
fs_write(fs->backupboot_start,sizeof(*b),b);
fs_write((off_t)offsetof(struct boot_sector,backup_boot),
sizeof(b->backup_boot),&b->backup_boot);
printf( "Created backup of boot sector in sector %d\n", bbs );
return;
}
else return;
}
fs_read(fs->backupboot_start,sizeof(b2),&b2);
if (memcmp(b,&b2,sizeof(b2)) != 0) {
/* there are any differences */
__u8 *p, *q;
int i, pos, first = 1;
char buf[20];
printf( "There are differences between boot sector and its backup.\n" );
printf( "Differences: (offset:original/backup)\n " );
pos = 2;
for( p = (__u8 *)b, q = (__u8 *)&b2, i = 0; i < sizeof(b2);
++p, ++q, ++i ) {
if (*p != *q) {
sprintf( buf, "%s%u:%02x/%02x", first ? "" : ", ",
(unsigned)(p-(__u8 *)b), *p, *q );
if (pos + strlen(buf) > 78) printf( "\n " ), pos = 2;
printf( "%s", buf );
pos += strlen(buf);
first = 0;
}
}
printf( "\n" );
if (interactive)
printf( "1) Copy original to backup\n"
"2) Copy backup to original\n"
"3) No action\n" );
else printf( " Not automatically fixing this.\n" );
switch (interactive ? get_key("123","?") : '3') {
case '1':
fs_write(fs->backupboot_start,sizeof(*b),b);
break;
case '2':
fs_write(0,sizeof(b2),&b2);
break;
default:
break;
}
}
}
static void init_fsinfo(struct info_sector *i)
{
i->magic = CT_LE_L(0x41615252);
i->signature = CT_LE_L(0x61417272);
i->free_clusters = CT_LE_L(-1);
i->next_cluster = CT_LE_L(2);
i->boot_sign = CT_LE_W(0xaa55);
}
static void read_fsinfo(DOS_FS *fs, struct boot_sector *b,int lss)
{
struct info_sector i;
if (!b->info_sector) {
printf( "No FSINFO sector\n" );
if (interactive)
printf( "1) Create one\n2) Do without FSINFO\n" );
else printf( " Not automatically creating it.\n" );
if (interactive && get_key("12","?") == '1') {
/* search for a free reserved sector (not boot sector and not
* backup boot sector) */
__u32 s;
for( s = 1; s < CF_LE_W(b->reserved); ++s )
if (s != CF_LE_W(b->backup_boot)) break;
if (s > 0 && s < CF_LE_W(b->reserved)) {
init_fsinfo(&i);
fs_write((off_t)s*lss,sizeof(i),&i);
b->info_sector = CT_LE_W(s);
fs_write((off_t)offsetof(struct boot_sector,info_sector),
sizeof(b->info_sector),&b->info_sector);
if (fs->backupboot_start)
fs_write(fs->backupboot_start+
offsetof(struct boot_sector,info_sector),
sizeof(b->info_sector),&b->info_sector);
}
else {
printf( "No free reserved sector found -- "
"no space for FSINFO sector!\n" );
return;
}
}
else return;
}
fs->fsinfo_start = CF_LE_W(b->info_sector)*lss;
fs_read(fs->fsinfo_start,sizeof(i),&i);
if (i.magic != CT_LE_L(0x41615252) ||
i.signature != CT_LE_L(0x61417272) ||
i.boot_sign != CT_LE_W(0xaa55)) {
printf( "FSINFO sector has bad magic number(s):\n" );
if (i.magic != CT_LE_L(0x41615252))
printf( " Offset %llu: 0x%08x != expected 0x%08x\n",
(__u64)offsetof(struct info_sector,magic),
CF_LE_L(i.magic),0x41615252);
if (i.signature != CT_LE_L(0x61417272))
printf( " Offset %llu: 0x%08x != expected 0x%08x\n",
(__u64)offsetof(struct info_sector,signature),
CF_LE_L(i.signature),0x61417272);
if (i.boot_sign != CT_LE_W(0xaa55))
printf( " Offset %llu: 0x%04x != expected 0x%04x\n",
(__u64)offsetof(struct info_sector,boot_sign),
CF_LE_W(i.boot_sign),0xaa55);
if (interactive)
printf( "1) Correct\n2) Don't correct (FSINFO invalid then)\n" );
else printf( " Auto-correcting it.\n" );
if (!interactive || get_key("12","?") == '1') {
init_fsinfo(&i);
fs_write(fs->fsinfo_start,sizeof(i),&i);
}
else fs->fsinfo_start = 0;
}
if (fs->fsinfo_start)
fs->free_clusters = CF_LE_L(i.free_clusters);
}
void read_boot(DOS_FS *fs)
{
struct boot_sector b;
unsigned total_sectors;
unsigned short logical_sector_size, sectors;
unsigned fat_length;
loff_t data_size;
fs_read(0,sizeof(b),&b);
logical_sector_size = GET_UNALIGNED_W(b.sector_size);
if (!logical_sector_size) die("Logical sector size is zero.");
fs->cluster_size = b.cluster_size*logical_sector_size;
if (!fs->cluster_size) die("Cluster size is zero.");
if (b.fats != 2 && b.fats != 1)
die("Currently, only 1 or 2 FATs are supported, not %d.\n",b.fats);
fs->nfats = b.fats;
sectors = GET_UNALIGNED_W(b.sectors);
total_sectors = sectors ? sectors : CF_LE_L(b.total_sect);
if (verbose) printf("Checking we can access the last sector of the filesystem\n");
/* Can't access last odd sector anyway, so round down */
fs_test((loff_t)((total_sectors & ~1)-1)*(loff_t)logical_sector_size,
logical_sector_size);
fat_length = CF_LE_W(b.fat_length) ?
CF_LE_W(b.fat_length) : CF_LE_L(b.fat32_length);
fs->fat_start = (off_t)CF_LE_W(b.reserved)*logical_sector_size;
fs->root_start = ((off_t)CF_LE_W(b.reserved)+b.fats*fat_length)*
logical_sector_size;
fs->root_entries = GET_UNALIGNED_W(b.dir_entries);
fs->data_start = fs->root_start+ROUND_TO_MULTIPLE(fs->root_entries <<
MSDOS_DIR_BITS,logical_sector_size);
data_size = (loff_t)total_sectors*logical_sector_size-fs->data_start;
fs->clusters = data_size/fs->cluster_size;
fs->root_cluster = 0; /* indicates standard, pre-FAT32 root dir */
fs->fsinfo_start = 0; /* no FSINFO structure */
fs->free_clusters = -1; /* unknown */
if (!b.fat_length && b.fat32_length) {
fs->fat_bits = 32;
fs->root_cluster = CF_LE_L(b.root_cluster);
if (!fs->root_cluster && fs->root_entries)
/* M$ hasn't specified this, but it looks reasonable: If
* root_cluster is 0 but there is a separate root dir
* (root_entries != 0), we handle the root dir the old way. Give a
* warning, but convertig to a root dir in a cluster chain seems
* to complex for now... */
printf( "Warning: FAT32 root dir not in cluster chain! "
"Compability mode...\n" );
else if (!fs->root_cluster && !fs->root_entries)
die("No root directory!");
else if (fs->root_cluster && fs->root_entries)
printf( "Warning: FAT32 root dir is in a cluster chain, but "
"a separate root dir\n"
" area is defined. Cannot fix this easily.\n" );
fs->backupboot_start = CF_LE_W(b.backup_boot)*logical_sector_size;
check_backup_boot(fs,&b,logical_sector_size);
read_fsinfo(fs,&b,logical_sector_size);
}
else if (!atari_format) {
/* On real MS-DOS, a 16 bit FAT is used whenever there would be too
* much clusers otherwise. */
fs->fat_bits = (fs->clusters > MSDOS_FAT12) ? 16 : 12;
}
else {
/* On Atari, things are more difficult: GEMDOS always uses 12bit FATs
* on floppies, and always 16 bit on harddisks. */
fs->fat_bits = 16; /* assume 16 bit FAT for now */
/* If more clusters than fat entries in 16-bit fat, we assume
* it's a real MSDOS FS with 12-bit fat. */
if (fs->clusters+2 > fat_length*logical_sector_size*8/16 ||
/* if it's a floppy disk --> 12bit fat */
device_no == 2 ||
/* if it's a ramdisk or loopback device and has one of the usual
* floppy sizes -> 12bit FAT */
((device_no == 1 || device_no == 7) &&
(total_sectors == 720 || total_sectors == 1440 ||
total_sectors == 2880)))
fs->fat_bits = 12;
}
/* On FAT32, the high 4 bits of a FAT entry are reserved */
fs->eff_fat_bits = (fs->fat_bits == 32) ? 28 : fs->fat_bits;
fs->fat_size = fat_length*logical_sector_size;
if (fs->clusters > ((__u64)fs->fat_size*8/fs->fat_bits)-2)
die("File system has %d clusters but only space for %d FAT entries.",
fs->clusters,((__u64)fs->fat_size*8/fs->fat_bits)-2);
if (!fs->root_entries && !fs->root_cluster)
die("Root directory has zero size.");
if (fs->root_entries & (MSDOS_DPS-1))
die("Root directory (%d entries) doesn't span an integral number of "
"sectors.",fs->root_entries);
if (logical_sector_size & (SECTOR_SIZE-1))
die("Logical sector size (%d bytes) is not a multiple of the physical "
"sector size.",logical_sector_size);
/* ++roman: On Atari, these two fields are often left uninitialized */
if (!atari_format && (!b.secs_track || !b.heads))
die("Invalid disk format in boot sector.");
if (verbose) dump_boot(fs,&b,logical_sector_size);
}
/* Local Variables: */
/* tab-width: 8 */
/* End: */

View file

@ -1,13 +0,0 @@
/* boot.h - Read and analyze ia PC/MS-DOS boot sector */
/* Written 1993 by Werner Almesberger */
#ifndef _BOOT_H
#define _BOOT_H
void read_boot(DOS_FS *fs);
/* Reads the boot sector from the currently open device and initializes *FS */
#endif

View file

@ -1,59 +0,0 @@
#ifndef _I386_BYTEORDER_H
#define _I386_BYTEORDER_H
//#include "types.h"
#include "compiler.h"
#ifdef __GNUC__
/* For avoiding bswap on i386 */
//#ifdef __KERNEL__
//#include <linux/config.h>
//#endif
static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
{
#ifdef CONFIG_X86_BSWAP
__asm__("bswap %0" : "=r" (x) : "0" (x));
#else
__asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
"rorl $16,%0\n\t" /* swap words */
"xchgb %b0,%h0" /* swap higher bytes */
:"=q" (x)
: "0" (x));
#endif
return x;
}
static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 val)
{
union {
struct { __u32 a,b; } s;
__u64 u;
} v;
v.u = val;
#ifdef CONFIG_X86_BSWAP
asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
: "=r" (v.s.a), "=r" (v.s.b)
: "0" (v.s.a), "1" (v.s.b));
#else
v.s.a = ___arch__swab32(v.s.a);
v.s.b = ___arch__swab32(v.s.b);
asm("xchgl %0,%1" : "=r" (v.s.a), "=r" (v.s.b) : "0" (v.s.a), "1" (v.s.b));
#endif
return v.u;
}
/* Do not define swab16. Gcc is smart enough to recognize "C" version and
convert it into rotation or exhange. */
#define __arch__swab64(x) ___arch__swab64(x)
#define __arch__swab32(x) ___arch__swab32(x)
#define __BYTEORDER_HAS_U64__
#endif /* __GNUC__ */
//#include "little_endian.h"
#endif /* _I386_BYTEORDER_H */

View file

@ -1,40 +0,0 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _BYTESWAP_H
#define _BYTESWAP_H 1
/* Get the machine specific, optimized definitions. */
#include "byteswap1.h"
/* The following definitions must all be macros since otherwise some
of the possible optimizations are not possible. */
/* Return a value with all bytes in the 16 bit argument swapped. */
#define bswap_16(x) __bswap_16 (x)
/* Return a value with all bytes in the 32 bit argument swapped. */
#define bswap_32(x) __bswap_32 (x)
#if defined __GNUC__ && __GNUC__ >= 2
/* Return a value with all bytes in the 64 bit argument swapped. */
# define bswap_64(x) __bswap_64 (x)
#endif
#endif /* byteswap.h */

View file

@ -1,133 +0,0 @@
/* Macros to swap the order of bytes in integer values.
Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#if !defined _BYTESWAP_H && !defined _NETINET_IN_H
# error "Never use <bits/byteswap.h> directly; include <byteswap.h> instead."
#endif
#ifndef _BITS_BYTESWAP_H
#define _BITS_BYTESWAP_H 1
/* Swap bytes in 16 bit value. */
#define __bswap_constant_16(x) \
((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
#ifdef __GNUC__
# if __GNUC__ >= 2
# define __bswap_16(x) \
(__extension__ \
({ register unsigned short int __v, __x = (x); \
if (__builtin_constant_p (__x)) \
__v = __bswap_constant_16 (__x); \
else \
__asm__ ("rorw $8, %w0" \
: "=r" (__v) \
: "0" (__x) \
: "cc"); \
__v; }))
# else
/* This is better than nothing. */
# define __bswap_16(x) \
(__extension__ \
({ register unsigned short int __x = (x); __bswap_constant_16 (__x); }))
# endif
#else
static __inline unsigned short int
__bswap_16 (unsigned short int __bsx)
{
return __bswap_constant_16 (__bsx);
}
#endif
/* Swap bytes in 32 bit value. */
#define __bswap_constant_32(x) \
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
#ifdef __GNUC__
# if __GNUC__ >= 2
/* To swap the bytes in a word the i486 processors and up provide the
`bswap' opcode. On i386 we have to use three instructions. */
# if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ \
&& !defined __pentium4__
# define __bswap_32(x) \
(__extension__ \
({ register unsigned int __v, __x = (x); \
if (__builtin_constant_p (__x)) \
__v = __bswap_constant_32 (__x); \
else \
__asm__ ("rorw $8, %w0;" \
"rorl $16, %0;" \
"rorw $8, %w0" \
: "=r" (__v) \
: "0" (__x) \
: "cc"); \
__v; }))
# else
# define __bswap_32(x) \
(__extension__ \
({ register unsigned int __v, __x = (x); \
if (__builtin_constant_p (__x)) \
__v = __bswap_constant_32 (__x); \
else \
__asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); \
__v; }))
# endif
# else
# define __bswap_32(x) \
(__extension__ \
({ register unsigned int __x = (x); __bswap_constant_32 (__x); }))
# endif
#else
static __inline unsigned int
__bswap_32 (unsigned int __bsx)
{
return __bswap_constant_32 (__bsx);
}
#endif
#if defined __GNUC__ && __GNUC__ >= 2
/* Swap bytes in 64 bit value. */
#define __bswap_constant_64(x) \
((((x) & 0xff00000000000000ull) >> 56) \
| (((x) & 0x00ff000000000000ull) >> 40) \
| (((x) & 0x0000ff0000000000ull) >> 24) \
| (((x) & 0x000000ff00000000ull) >> 8) \
| (((x) & 0x00000000ff000000ull) << 8) \
| (((x) & 0x0000000000ff0000ull) << 24) \
| (((x) & 0x000000000000ff00ull) << 40) \
| (((x) & 0x00000000000000ffull) << 56))
# define __bswap_64(x) \
(__extension__ \
({ union { __extension__ unsigned long long int __ll; \
unsigned long int __l[2]; } __w, __r; \
if (__builtin_constant_p (x)) \
__r.__ll = __bswap_constant_64 (x); \
else \
{ \
__w.__ll = (x); \
__r.__l[0] = __bswap_32 (__w.__l[1]); \
__r.__l[1] = __bswap_32 (__w.__l[0]); \
} \
__r.__ll; }))
#endif
#endif /* _BITS_BYTESWAP_H */

View file

@ -1,867 +0,0 @@
/* check.c - Check and repair a PC/MS-DOS file system */
/* Written 1993 by Werner Almesberger */
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include <windows.h>
#include "common.h"
#include "dosfsck.h"
#include "io.h"
#include "fat.h"
#include "file.h"
#include "lfn.h"
#include "check.h"
static DOS_FILE *root;
/* get start field of a dir entry */
#define FSTART(p,fs) \
((unsigned long)CF_LE_W(p->dir_ent.start) | \
(fs->fat_bits == 32 ? CF_LE_W(p->dir_ent.starthi) << 16 : 0))
#define MODIFY(p,i,v) \
do { \
if (p->offset) { \
p->dir_ent.i = v; \
fs_write(p->offset+offsetof(DIR_ENT,i), \
sizeof(p->dir_ent.i),&p->dir_ent.i); \
} \
} while(0)
#define MODIFY_START(p,v,fs) \
do { \
unsigned long __v = (v); \
if (!p->offset) { \
/* writing to fake entry for FAT32 root dir */ \
if (!__v) die("Oops, deleting FAT32 root dir!"); \
fs->root_cluster = __v; \
p->dir_ent.start = CT_LE_W(__v&0xffff); \
p->dir_ent.starthi = CT_LE_W(__v>>16); \
__v = CT_LE_L(__v); \
fs_write((loff_t)offsetof(struct boot_sector,root_cluster), \
sizeof(((struct boot_sector *)0)->root_cluster), \
&__v); \
} \
else { \
MODIFY(p,start,CT_LE_W((__v)&0xffff)); \
if (fs->fat_bits == 32) \
MODIFY(p,starthi,CT_LE_W((__v)>>16)); \
} \
} while(0)
loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern)
{
static int curr_num = 0;
loff_t offset;
if (fs->root_cluster) {
DIR_ENT d2;
int i = 0, got = 0;
unsigned long clu_num, prev = 0;
loff_t offset2;
clu_num = fs->root_cluster;
offset = cluster_start(fs,clu_num);
while (clu_num > 0 && clu_num != -1) {
fs_read(offset,sizeof(DIR_ENT),&d2);
if (IS_FREE(d2.name) && d2.attr != VFAT_LN_ATTR) {
got = 1;
break;
}
i += sizeof(DIR_ENT);
offset += sizeof(DIR_ENT);
if ((i % fs->cluster_size) == 0) {
prev = clu_num;
if ((clu_num = next_cluster(fs,clu_num)) == 0 || clu_num == -1)
break;
offset = cluster_start(fs,clu_num);
}
}
if (!got) {
/* no free slot, need to extend root dir: alloc next free cluster
* after previous one */
if (!prev)
die("Root directory has no cluster allocated!");
for (clu_num = prev+1; clu_num != prev; clu_num++) {
if (clu_num >= fs->clusters+2) clu_num = 2;
if (!fs->fat[clu_num].value)
break;
}
if (clu_num == prev)
die("Root directory full and no free cluster");
set_fat(fs,prev,clu_num);
set_fat(fs,clu_num,-1);
set_owner(fs, clu_num, get_owner(fs, fs->root_cluster));
/* clear new cluster */
memset( &d2, 0, sizeof(d2) );
offset = cluster_start(fs,clu_num);
for( i = 0; i < (int)fs->cluster_size; i += sizeof(DIR_ENT) )
fs_write( offset+i, sizeof(d2), &d2 );
}
memset(de,0,sizeof(DIR_ENT));
while (1) {
sprintf(de->name,pattern,curr_num);
clu_num = fs->root_cluster;
i = 0;
offset2 = cluster_start(fs,clu_num);
while (clu_num > 0 && clu_num != -1) {
fs_read(offset2,sizeof(DIR_ENT),&d2);
if (offset2 != offset &&
!strncmp(d2.name,de->name,MSDOS_NAME))
break;
i += sizeof(DIR_ENT);
offset2 += sizeof(DIR_ENT);
if ((i % fs->cluster_size) == 0) {
if ((clu_num = next_cluster(fs,clu_num)) == 0 ||
clu_num == -1)
break;
offset2 = cluster_start(fs,clu_num);
}
}
if (clu_num == 0 || clu_num == -1)
break;
if (++curr_num >= 10000) die("Unable to create unique name");
}
}
else {
DIR_ENT *root;
int next_free = 0, scan;
root = alloc(fs->root_entries*sizeof(DIR_ENT));
fs_read(fs->root_start,fs->root_entries*sizeof(DIR_ENT),root);
while (next_free < (int)fs->root_entries)
if (IS_FREE(root[next_free].name) &&
root[next_free].attr != VFAT_LN_ATTR)
break;
else next_free++;
if (next_free == (int)fs->root_entries)
die("Root directory is full.");
offset = fs->root_start+next_free*sizeof(DIR_ENT);
memset(de,0,sizeof(DIR_ENT));
while (1) {
sprintf(de->name,pattern,curr_num);
for (scan = 0; scan < (int)fs->root_entries; scan++)
if (scan != next_free &&
!strncmp(root[scan].name,de->name,MSDOS_NAME))
break;
if (scan == (int)fs->root_entries) break;
if (++curr_num >= 10000) die("Unable to create unique name");
}
free(root);
}
++n_files;
return offset;
}
static char *path_name(DOS_FILE *file)
{
// static char path[PATH_MAX*2];
static char path[MAX_PATH*2];
if (!file) *path = 0;
else {
if (strlen(path_name(file->parent)) > MAX_PATH)
die("Path name too long.");
if (strcmp(path,"/") != 0) strcat(path,"/");
strcpy(strrchr(path,0),file->lfn?file->lfn:file_name(file->dir_ent.name));
}
return path;
}
static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
/* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
time_t date_dos2unix(unsigned short time,unsigned short date)
{
int month,year;
time_t secs;
month = ((date >> 5) & 15)-1;
year = date >> 9;
secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
month < 2 ? 1 : 0)+3653);
/* days since 1.1.70 plus 80's leap day */
return secs;
}
static char *file_stat(DOS_FILE *file)
{
static char temp[100];
struct tm *tm;
char tmp[100];
time_t date;
date = date_dos2unix(CF_LE_W(file->dir_ent.time),CF_LE_W(file->
dir_ent.date));
tm = localtime(&date);
strftime(tmp,99,"%H:%M:%S %b %d %Y",tm);
sprintf(temp," Size %u bytes, date %s",CF_LE_L(file->dir_ent.size),tmp);
return temp;
}
static int bad_name(unsigned char *name)
{
int i, spc, suspicious = 0;
char *bad_chars = atari_format ? "*?\\/:" : "*?<>|\"\\/:";
/* Do not complain about (and auto-correct) the extended attribute files
* of OS/2. */
if (strncmp(name,"EA DATA SF",11) == 0 ||
strncmp(name,"WP ROOT SF",11) == 0) return 0;
for (i = 0; i < 8; i++) {
if (name[i] < ' ' || name[i] == 0x7f) return 1;
if (name[i] > 0x7f) ++suspicious;
if (strchr(bad_chars,name[i])) return 1;
}
for (i = 8; i < 11; i++) {
if (name[i] < ' ' || name[i] == 0x7f) return 1;
if (name[i] > 0x7f) ++suspicious;
if (strchr(bad_chars,name[i])) return 1;
}
spc = 0;
for (i = 0; i < 8; i++) {
if (name[i] == ' ')
spc = 1;
else if (spc)
/* non-space after a space not allowed, space terminates the name
* part */
return 1;
}
spc = 0;
for (i = 8; i < 11; i++) {
if (name[i] == ' ')
spc = 1;
else if (spc)
/* non-space after a space not allowed, space terminates the name
* part */
return 1;
}
/* Under GEMDOS, chars >= 128 are never allowed. */
if (atari_format && suspicious)
return 1;
/* Only complain about too much suspicious chars in interactive mode,
* never correct them automatically. The chars are all basically ok, so we
* shouldn't auto-correct such names. */
if (interactive && suspicious > 6)
return 1;
return 0;
}
static void drop_file(DOS_FS *fs,DOS_FILE *file)
{
unsigned long cluster;
MODIFY(file,name[0],DELETED_FLAG);
for (cluster = FSTART(file,fs); cluster > 0 && cluster <
fs->clusters+2; cluster = next_cluster(fs,cluster))
set_owner(fs,cluster,NULL);
--n_files;
}
static void truncate_file(DOS_FS *fs,DOS_FILE *file,unsigned long clusters)
{
int deleting;
unsigned long walk,next,prev;
walk = FSTART(file,fs);
prev = 0;
if ((deleting = !clusters)) MODIFY_START(file,0,fs);
while (walk > 0 && walk != -1) {
next = next_cluster(fs,walk);
if (deleting) set_fat(fs,walk,0);
else if ((deleting = !--clusters)) set_fat(fs,walk,-1);
prev = walk;
walk = next;
}
}
static void auto_rename(DOS_FILE *file)
{
DOS_FILE *first,*walk;
int number;
if (!file->offset) return; /* cannot rename FAT32 root dir */
first = file->parent ? file->parent->first : root;
number = 0;
while (1) {
sprintf(file->dir_ent.name,"FSCK%04d",number);
strncpy(file->dir_ent.ext,"REN",3);
for (walk = first; walk; walk = walk->next)
if (walk != file && !strncmp(walk->dir_ent.name,file->dir_ent.
name,MSDOS_NAME)) break;
if (!walk) {
fs_write(file->offset,MSDOS_NAME,file->dir_ent.name);
return;
}
number++;
}
die("Can't generate a unique name.");
}
static void rename_file(DOS_FILE *file)
{
unsigned char name[46];
unsigned char *walk,*here;
if (!file->offset) {
printf( "Cannot rename FAT32 root dir\n" );
return; /* cannot rename FAT32 root dir */
}
while (1) {
printf("New name: ");
fflush(stdout);
if (fgets(name,45,stdin)) {
if ((here = strchr(name,'\n'))) *here = 0;
for (walk = strrchr(name,0); walk >= name && (*walk == ' ' ||
*walk == '\t'); walk--);
walk[1] = 0;
for (walk = name; *walk == ' ' || *walk == '\t'; walk++);
if (file_cvt(walk,file->dir_ent.name)) {
fs_write(file->offset,MSDOS_NAME,file->dir_ent.name);
return;
}
}
}
}
static int handle_dot(DOS_FS *fs,DOS_FILE *file,int dots)
{
char *name;
name = strncmp(file->dir_ent.name,MSDOS_DOT,MSDOS_NAME) ? ".." : ".";
if (!(file->dir_ent.attr & ATTR_DIR)) {
printf("%s\n Is a non-directory.\n",path_name(file));
if (interactive)
printf("1) Drop it\n2) Auto-rename\n3) Rename\n"
"4) Convert to directory\n");
else printf(" Auto-renaming it.\n");
switch (interactive ? get_key("1234","?") : '2') {
case '1':
drop_file(fs,file);
return 1;
case '2':
auto_rename(file);
printf(" Renamed to %s\n",file_name(file->dir_ent.name));
return 0;
case '3':
rename_file(file);
return 0;
case '4':
MODIFY(file,size,CT_LE_L(0));
MODIFY(file,attr,file->dir_ent.attr | ATTR_DIR);
break;
}
}
if (!dots) {
printf("Root contains directory \"%s\". Dropping it.\n",name);
drop_file(fs,file);
return 1;
}
return 0;
}
static int check_file(DOS_FS *fs,DOS_FILE *file)
{
DOS_FILE *owner;
int restart;
unsigned long expect,curr,this,clusters,prev,walk,clusters2;
if (file->dir_ent.attr & ATTR_DIR) {
if (CF_LE_L(file->dir_ent.size)) {
printf("%s\n Directory has non-zero size. Fixing it.\n",
path_name(file));
MODIFY(file,size,CT_LE_L(0));
}
if (file->parent && !strncmp(file->dir_ent.name,MSDOS_DOT,MSDOS_NAME)) {
expect = FSTART(file->parent,fs);
if (FSTART(file,fs) != expect) {
printf("%s\n Start (%ld) does not point to parent (%ld)\n",
path_name(file),FSTART(file,fs),expect);
MODIFY_START(file,expect,fs);
}
return 0;
}
if (file->parent && !strncmp(file->dir_ent.name,MSDOS_DOTDOT,
MSDOS_NAME)) {
expect = file->parent->parent ? FSTART(file->parent->parent,fs):0;
if (fs->root_cluster && expect == fs->root_cluster)
expect = 0;
if (FSTART(file,fs) != expect) {
printf("%s\n Start (%lu) does not point to .. (%lu)\n",
path_name(file),FSTART(file,fs),expect);
MODIFY_START(file,expect,fs);
}
return 0;
}
if (FSTART(file,fs)==0){
printf ("%s\n Start does point to root directory. Deleting dir. \n",
path_name(file));
MODIFY(file,name[0],DELETED_FLAG);
return 0;
}
}
if (FSTART(file,fs) >= fs->clusters+2) {
printf("%s\n Start cluster beyond limit (%lu > %lu). Truncating file.\n",
path_name(file),FSTART(file,fs),fs->clusters+1);
if (!file->offset)
die( "Bad FAT32 root directory! (bad start cluster)\n" );
MODIFY_START(file,0,fs);
}
clusters = prev = 0;
for (curr = FSTART(file,fs) ? FSTART(file,fs) :
-1; curr != -1; curr = next_cluster(fs,curr)) {
if (!fs->fat[curr].value || bad_cluster(fs,curr)) {
printf("%s\n Contains a %s cluster (%lu). Assuming EOF.\n",
path_name(file),fs->fat[curr].value ? "bad" : "free",curr);
if (prev) set_fat(fs,prev,-1);
else if (!file->offset)
die( "FAT32 root dir starts with a bad cluster!" );
else MODIFY_START(file,0,fs);
break;
}
if (!(file->dir_ent.attr & ATTR_DIR) && CF_LE_L(file->dir_ent.size) <=
clusters*fs->cluster_size) {
printf("%s\n File size is %u bytes, cluster chain length is > %lu "
"bytes.\n Truncating file to %u bytes.\n",path_name(file),
CF_LE_L(file->dir_ent.size),clusters*fs->cluster_size,
CF_LE_L(file->dir_ent.size));
truncate_file(fs,file,clusters);
break;
}
if ((owner = get_owner(fs,curr))) {
int do_trunc = 0;
printf("%s and\n",path_name(owner));
printf("%s\n share clusters.\n",path_name(file));
clusters2 = 0;
for (walk = FSTART(owner,fs); walk > 0 && walk != -1; walk =
next_cluster(fs,walk))
if (walk == curr) break;
else clusters2++;
restart = file->dir_ent.attr & ATTR_DIR;
if (!owner->offset) {
printf( " Truncating second to %lu bytes because first "
"is FAT32 root dir.\n", clusters2*fs->cluster_size );
do_trunc = 2;
}
else if (!file->offset) {
printf( " Truncating first to %lu bytes because second "
"is FAT32 root dir.\n", clusters*fs->cluster_size );
do_trunc = 1;
}
else if (interactive)
printf("1) Truncate first to %lu bytes%s\n"
"2) Truncate second to %lu bytes\n",clusters*fs->cluster_size,
restart ? " and restart" : "",clusters2*fs->cluster_size);
else printf(" Truncating second to %lu bytes.\n",clusters2*
fs->cluster_size);
if (do_trunc != 2 &&
(do_trunc == 1 ||
(interactive && get_key("12","?") == '1'))) {
prev = 0;
clusters = 0;
for (this = FSTART(owner,fs); this > 0 && this != -1; this =
next_cluster(fs,this)) {
if (this == curr) {
if (prev) set_fat(fs,prev,-1);
else MODIFY_START(owner,0,fs);
MODIFY(owner,size,CT_LE_L(clusters*fs->cluster_size));
if (restart) return 1;
while (this > 0 && this != -1) {
set_owner(fs,this,NULL);
this = next_cluster(fs,this);
}
break;
}
clusters++;
prev = this;
}
if (this != curr)
die("Internal error: didn't find cluster %d in chain"
" starting at %d",curr,FSTART(owner,fs));
}
else {
if (prev) set_fat(fs,prev,-1);
else MODIFY_START(file,0,fs);
break;
}
}
set_owner(fs,curr,file);
clusters++;
prev = curr;
}
if (!(file->dir_ent.attr & ATTR_DIR) && CF_LE_L(file->dir_ent.size) >
clusters*fs->cluster_size) {
printf("%s\n File size is %u bytes, cluster chain length is %lu bytes."
"\n Truncating file to %lu bytes.\n",path_name(file),CF_LE_L(file->
dir_ent.size),clusters*fs->cluster_size,clusters*fs->cluster_size);
MODIFY(file,size,CT_LE_L(clusters*fs->cluster_size));
}
return 0;
}
static int check_files(DOS_FS *fs,DOS_FILE *start)
{
while (start) {
if (check_file(fs,start)) return 1;
start = start->next;
}
return 0;
}
static int check_dir(DOS_FS *fs,DOS_FILE **root,int dots)
{
DOS_FILE *parent,**walk,**scan;
int dot,dotdot,skip,redo;
int good,bad;
if (!*root) return 0;
parent = (*root)->parent;
good = bad = 0;
for (walk = root; *walk; walk = &(*walk)->next)
if (bad_name((*walk)->dir_ent.name)) bad++;
else good++;
if (*root && parent && good+bad > 4 && bad > good/2) {
printf("%s\n Has a large number of bad entries. (%d/%d)\n",
path_name(parent),bad,good+bad);
if (!dots) printf( " Not dropping root directory.\n" );
else if (!interactive) printf(" Not dropping it in auto-mode.\n");
else if (get_key("yn","Drop directory ? (y/n)") == 'y') {
truncate_file(fs,parent,0);
MODIFY(parent,name[0],DELETED_FLAG);
/* buglet: deleted directory stays in the list. */
return 1;
}
}
dot = dotdot = redo = 0;
walk = root;
while (*walk) {
if (!strncmp((*walk)->dir_ent.name,MSDOS_DOT,MSDOS_NAME) ||
!strncmp((*walk)->dir_ent.name,MSDOS_DOTDOT,MSDOS_NAME)) {
if (handle_dot(fs,*walk,dots)) {
*walk = (*walk)->next;
continue;
}
if (!strncmp((*walk)->dir_ent.name,MSDOS_DOT,MSDOS_NAME)) dot++;
else dotdot++;
}
if (!((*walk)->dir_ent.attr & ATTR_VOLUME) &&
bad_name((*walk)->dir_ent.name)) {
printf("%s\n Bad file name.\n",path_name(*walk));
if (interactive)
printf("1) Drop file\n2) Rename file\n3) Auto-rename\n"
"4) Keep it\n");
else printf(" Auto-renaming it.\n");
switch (interactive ? get_key("1234","?") : '3') {
case '1':
drop_file(fs,*walk);
walk = &(*walk)->next;
continue;
case '2':
rename_file(*walk);
redo = 1;
break;
case '3':
auto_rename(*walk);
printf(" Renamed to %s\n",file_name((*walk)->dir_ent.
name));
break;
case '4':
break;
}
}
/* don't check for duplicates of the volume label */
if (!((*walk)->dir_ent.attr & ATTR_VOLUME)) {
scan = &(*walk)->next;
skip = 0;
while (*scan && !skip) {
if (!((*scan)->dir_ent.attr & ATTR_VOLUME) &&
!strncmp((*walk)->dir_ent.name,(*scan)->dir_ent.name,MSDOS_NAME)) {
printf("%s\n Duplicate directory entry.\n First %s\n",
path_name(*walk),file_stat(*walk));
printf(" Second %s\n",file_stat(*scan));
if (interactive)
printf("1) Drop first\n2) Drop second\n3) Rename first\n"
"4) Rename second\n5) Auto-rename first\n"
"6) Auto-rename second\n");
else printf(" Auto-renaming second.\n");
switch (interactive ? get_key("123456","?") : '6') {
case '1':
drop_file(fs,*walk);
*walk = (*walk)->next;
skip = 1;
break;
case '2':
drop_file(fs,*scan);
*scan = (*scan)->next;
continue;
case '3':
rename_file(*walk);
printf(" Renamed to %s\n",path_name(*walk));
redo = 1;
break;
case '4':
rename_file(*scan);
printf(" Renamed to %s\n",path_name(*walk));
redo = 1;
break;
case '5':
auto_rename(*walk);
printf(" Renamed to %s\n",file_name((*walk)->dir_ent.
name));
break;
case '6':
auto_rename(*scan);
printf(" Renamed to %s\n",file_name((*scan)->dir_ent.
name));
break;
}
}
scan = &(*scan)->next;
}
if (skip) continue;
}
if (!redo) walk = &(*walk)->next;
else {
walk = root;
dot = dotdot = redo = 0;
}
}
if (dots && !dot)
printf("%s\n \".\" is missing. Can't fix this yet.\n",
path_name(parent));
if (dots && !dotdot)
printf("%s\n \"..\" is missing. Can't fix this yet.\n",
path_name(parent));
return 0;
}
static void test_file(DOS_FS *fs,DOS_FILE *file,int read_test)
{
DOS_FILE *owner;
unsigned long walk,prev,clusters,next_clu;
prev = clusters = 0;
for (walk = FSTART(file,fs); walk > 0 && walk < fs->clusters+2;
walk = next_clu) {
next_clu = next_cluster(fs,walk);
if ((owner = get_owner(fs,walk))) {
if (owner == file) {
printf("%s\n Circular cluster chain. Truncating to %lu "
"cluster%s.\n",path_name(file),clusters,clusters == 1 ? "" :
"s");
if (prev) set_fat(fs,prev,-1);
else if (!file->offset)
die( "Bad FAT32 root directory! (bad start cluster)\n" );
else MODIFY_START(file,0,fs);
}
break;
}
if (bad_cluster(fs,walk)) break;
if (read_test) {
if (fs_test(cluster_start(fs,walk),fs->cluster_size)) {
prev = walk;
clusters++;
}
else {
printf("%s\n Cluster %lu (%lu) is unreadable. Skipping it.\n",
path_name(file),clusters,walk);
if (prev) set_fat(fs,prev,next_cluster(fs,walk));
else MODIFY_START(file,next_cluster(fs,walk),fs);
set_fat(fs,walk,-2);
}
}
set_owner(fs,walk,file);
}
for (walk = FSTART(file,fs); walk > 0 && walk < fs->clusters+2;
walk = next_cluster(fs,walk))
if (bad_cluster(fs,walk)) break;
else if (get_owner(fs,walk) == file) set_owner(fs,walk,NULL);
else break;
}
static void undelete(DOS_FS *fs,DOS_FILE *file)
{
unsigned long clusters,left,prev,walk;
clusters = left = (CF_LE_L(file->dir_ent.size)+fs->cluster_size-1)/
fs->cluster_size;
prev = 0;
for (walk = FSTART(file,fs); left && walk >= 2 && walk <
fs->clusters+2 && !fs->fat[walk].value; walk++) {
left--;
if (prev) set_fat(fs,prev,walk);
prev = walk;
}
if (prev) set_fat(fs,prev,-1);
else MODIFY_START(file,0,fs);
if (left)
printf("Warning: Did only undelete %lu of %lu cluster%s.\n",clusters-left,
clusters,clusters == 1 ? "" : "s");
}
static void new_dir( void )
{
lfn_reset();
}
static void add_file(DOS_FS *fs,DOS_FILE ***chain,DOS_FILE *parent,
loff_t offset,FDSC **cp)
{
DOS_FILE *new;
DIR_ENT de;
FD_TYPE type;
char tmpBuffer[512]; // TMN:
if (offset) {
// fs_read(offset,sizeof(DIR_ENT),&de);
fs_read(offset,sizeof(tmpBuffer),&tmpBuffer); // TMN:
memcpy(&de, tmpBuffer, sizeof(DIR_ENT)); // TMN:
} else {
memcpy(de.name," ",MSDOS_NAME);
de.attr = ATTR_DIR;
de.size = de.time = de.date = 0;
de.start = CT_LE_W(fs->root_cluster & 0xffff);
de.starthi = CT_LE_W((fs->root_cluster >> 16) & 0xffff);
}
if ((type = file_type(cp,de.name)) != fdt_none) {
if (type == fdt_undelete && (de.attr & ATTR_DIR))
die("Can't undelete directories.");
file_modify(cp,de.name);
fs_write(offset,1,&de);
}
if (IS_FREE(de.name)) {
lfn_check_orphaned();
return;
}
if (de.attr == VFAT_LN_ATTR) {
lfn_add_slot(&de,offset);
return;
}
new = qalloc(&mem_queue,sizeof(DOS_FILE));
new->lfn = lfn_get(&de);
new->offset = offset;
memcpy(&new->dir_ent,&de,sizeof(de));
new->next = new->first = NULL;
new->parent = parent;
if (type == fdt_undelete) undelete(fs,new);
**chain = new;
*chain = &new->next;
if (list) {
printf("Checking file %s",path_name(new));
if (new->lfn)
printf(" (%s)", file_name(new->dir_ent.name) );
printf("\n");
}
if (offset &&
strncmp(de.name,MSDOS_DOT,MSDOS_NAME) != 0 &&
strncmp(de.name,MSDOS_DOTDOT,MSDOS_NAME) != 0)
++n_files;
test_file(fs,new,test);
}
static int subdirs(DOS_FS *fs,DOS_FILE *parent,FDSC **cp);
static int scan_dir(DOS_FS *fs,DOS_FILE *this,FDSC **cp)
{
DOS_FILE **chain;
int i;
unsigned long clu_num;
chain = &this->first;
i = 0;
clu_num = FSTART(this,fs);
new_dir();
while (clu_num > 0 && clu_num != -1) {
add_file(fs,&chain,this,cluster_start(fs,clu_num)+(i % fs->
cluster_size),cp);
i += sizeof(DIR_ENT);
if (!(i % fs->cluster_size))
if ((clu_num = next_cluster(fs,clu_num)) == 0 || clu_num == -1)
break;
}
lfn_check_orphaned();
if (check_dir(fs,&this->first,this->offset)) return 0;
if (check_files(fs,this->first)) return 1;
return subdirs(fs,this,cp);
}
static int subdirs(DOS_FS *fs,DOS_FILE *parent,FDSC **cp)
{
DOS_FILE *walk;
for (walk = parent ? parent->first : root; walk; walk = walk->next)
if (walk->dir_ent.attr & ATTR_DIR)
if (strncmp(walk->dir_ent.name,MSDOS_DOT,MSDOS_NAME) &&
strncmp(walk->dir_ent.name,MSDOS_DOTDOT,MSDOS_NAME))
if (scan_dir(fs,walk,file_cd(cp,walk->dir_ent.name))) return 1;
return 0;
}
int scan_root(DOS_FS *fs)
{
DOS_FILE **chain;
int i;
root = NULL;
chain = &root;
new_dir();
if (fs->root_cluster) {
add_file(fs,&chain,NULL,0,&fp_root);
}
else {
for (i = 0; i < fs->root_entries; i++)
add_file(fs,&chain,NULL,fs->root_start+i*sizeof(DIR_ENT),&fp_root);
}
lfn_check_orphaned();
(void) check_dir(fs,&root,0);
if (check_files(fs,root)) return 1;
return subdirs(fs,NULL,&fp_root);
}
/* Local Variables: */
/* tab-width: 8 */
/* End: */

View file

@ -1,23 +0,0 @@
/* check.h - Check and repair a PC/MS-DOS file system */
/* Written 1993 by Werner Almesberger */
#ifndef _CHECK_H
#define _CHECK_H
loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern);
/* Allocate a free slot in the root directory for a new file. The file name is
constructed after 'pattern', which must include a %d type format for printf
and expand to exactly 11 characters. The name actually used is written into
the 'de' structure, the rest of *de is cleared. The offset returned is to
where in the filesystem the entry belongs. */
int scan_root(DOS_FS *fs);
/* Scans the root directory and recurses into all subdirectories. See check.c
for all the details. Returns a non-zero integer if the file system has to
be checked again. */
#endif

View file

@ -1,110 +0,0 @@
/* common.c - Common functions */
/* Written 1993 by Werner Almesberger */
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include "common.h"
typedef struct _link {
void *data;
struct _link *next;
} LINK;
void die(char *msg,...)
{
va_list args;
va_start(args,msg);
vfprintf(stderr,msg,args);
va_end(args);
fprintf(stderr,"\n");
exit(1);
}
void pdie(char *msg,...)
{
va_list args;
va_start(args,msg);
vfprintf(stderr,msg,args);
va_end(args);
fprintf(stderr,":%s\n",strerror(errno));
exit(1);
}
void *alloc(int size)
{
void *this;
if ((this = malloc(size))) return this;
pdie("malloc");
return NULL; /* for GCC */
}
void *qalloc(void **root,int size)
{
LINK *link;
link = alloc(sizeof(LINK));
link->next = *root;
*root = link;
return link->data = alloc(size);
}
void qfree(void **root)
{
LINK *this;
while (*root) {
this = (LINK *) *root;
*root = this->next;
free(this->data);
free(this);
}
}
#ifdef min
#undef min
#endif
int min(int a,int b)
{
return a < b ? a : b;
}
char get_key(char *valid,char *prompt)
{
int ch,okay;
while (1) {
if (prompt) printf("%s ",prompt);
fflush(stdout);
while (ch = getchar(), ch == ' ' || ch == '\t');
if (ch == EOF) exit(1);
if (!strchr(valid,okay = ch)) okay = 0;
while (ch = getchar(), ch != '\n' && ch != EOF);
if (ch == EOF) exit(1);
if (okay) return okay;
printf("Invalid input.\n");
}
}
/* Local Variables: */
/* tab-width: 8 */
/* End: */

View file

@ -1,42 +0,0 @@
/* common.h - Common functions */
# define MSDOS_FAT12 4084 /* maximum number of clusters in a 12 bit FAT */
#include "version.h"
#ifndef _COMMON_H
#define _COMMON_H
//void die(char *msg,...) __attribute((noreturn));
__declspec(noreturn) void die(char *msg,...);
/* Displays a prinf-style message and terminates the program. */
//void pdie(char *msg,...) __attribute((noreturn));
__declspec(noreturn) void pdie(char *msg,...);
/* Like die, but appends an error message according to the state of errno. */
void *alloc(int size);
/* mallocs SIZE bytes and returns a pointer to the data. Terminates the program
if malloc fails. */
void *qalloc(void **root,int size);
/* Like alloc, but registers the data area in a list described by ROOT. */
void qfree(void **root);
/* Deallocates all qalloc'ed data areas described by ROOT. */
//int min(int a,int b);
/* Returns the smaller integer value of a and b. */
char get_key(char *valid,char *prompt);
/* Displays PROMPT and waits for user input. Only characters in VALID are
accepted. Terminates the program on EOF. Returns the character. */
#endif

View file

@ -1,158 +0,0 @@
#ifndef __LINUX_COMPILER_H
#define __LINUX_COMPILER_H
#ifndef __ASSEMBLY__
#ifdef __CHECKER__
# define __user __attribute__((noderef, address_space(1)))
# define __kernel /* default address space */
# define __safe __attribute__((safe))
# define __force __attribute__((force))
# define __nocast __attribute__((nocast))
# define __iomem __attribute__((noderef, address_space(2)))
# define __acquires(x) __attribute__((context(0,1)))
# define __releases(x) __attribute__((context(1,0)))
# define __acquire(x) __context__(1)
# define __release(x) __context__(-1)
# define __cond_lock(x) ((x) ? ({ __context__(1); 1; }) : 0)
extern void __chk_user_ptr(void __user *);
extern void __chk_io_ptr(void __iomem *);
#else
# define __user
# define __kernel
# define __safe
# define __force
# define __nocast
# define __iomem
# define __chk_user_ptr(x) (void)0
# define __chk_io_ptr(x) (void)0
//# define __builtin_warning(x, y...) (1)
# define __acquires(x)
# define __releases(x)
# define __acquire(x) (void)0
# define __release(x) (void)0
# define __cond_lock(x) (x)
#endif
#ifdef __KERNEL__
#if __GNUC__ > 4
#error no compiler-gcc.h file for this gcc version
#elif __GNUC__ == 4
# include <linux/compiler-gcc4.h>
#elif __GNUC__ == 3
# include <linux/compiler-gcc3.h>
#elif __GNUC__ == 2
# include <linux/compiler-gcc2.h>
#else
# error Sorry, your compiler is too old/not recognized.
#endif
/* Intel compiler defines __GNUC__. So we will overwrite implementations
* coming from above header files here
*/
#ifdef __INTEL_COMPILER
# include <linux/compiler-intel.h>
#endif
/*
* Generic compiler-dependent macros required for kernel
* build go below this comment. Actual compiler/compiler version
* specific implementations come from the above header files
*/
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
/* Optimization barrier */
#ifndef barrier
# define barrier() __memory_barrier()
#endif
#ifndef RELOC_HIDE
# define RELOC_HIDE(ptr, off) \
({ unsigned long __ptr; \
__ptr = (unsigned long) (ptr); \
(typeof(ptr)) (__ptr + (off)); })
#endif
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
/*
* Allow us to mark functions as 'deprecated' and have gcc emit a nice
* warning for each use, in hopes of speeding the functions removal.
* Usage is:
* int __deprecated foo(void)
*/
#ifndef __deprecated
# define __deprecated /* unimplemented */
#endif
#ifdef MODULE
#define __deprecated_for_modules __deprecated
#else
#define __deprecated_for_modules
#endif
#ifndef __must_check
#define __must_check
#endif
/*
* Allow us to avoid 'defined but not used' warnings on functions and data,
* as well as force them to be emitted to the assembly file.
*
* As of gcc 3.3, static functions that are not marked with attribute((used))
* may be elided from the assembly file. As of gcc 3.3, static data not so
* marked will not be elided, but this may change in a future gcc version.
*
* In prior versions of gcc, such functions and data would be emitted, but
* would be warned about except with attribute((unused)).
*/
#ifndef __attribute_used__
# define __attribute_used__ /* unimplemented */
#endif
/*
* From the GCC manual:
*
* Many functions have no effects except the return value and their
* return value depends only on the parameters and/or global
* variables. Such a function can be subject to common subexpression
* elimination and loop optimization just as an arithmetic operator
* would be.
* [...]
*/
#ifndef __attribute_pure__
# define __attribute_pure__ /* unimplemented */
#endif
/*
* From the GCC manual:
*
* Many functions do not examine any values except their arguments,
* and have no effects except the return value. Basically this is
* just slightly more strict class than the `pure' attribute above,
* since function is not allowed to read global memory.
*
* Note that a function that has pointer arguments and examines the
* data pointed to must _not_ be declared `const'. Likewise, a
* function that calls a non-`const' function usually must not be
* `const'. It does not make sense for a `const' function to return
* `void'.
*/
#ifndef __attribute_const__
# define __attribute_const__ /* unimplemented */
#endif
#ifndef noinline
#define noinline
#endif
#ifndef __always_inline
#define __always_inline inline
#endif
#endif /* __LINUX_COMPILER_H */

View file

@ -1,143 +0,0 @@
.TH DOSFSCK 8 "December 31 1997" "Linux" "MAINTENANCE COMMANDS"
.SH NAME
dosfsck \- check and repair MS-DOS file systems
.SH SYNOPSIS
.ad l
.B dosfsck
.RB [ \-aAflnrtvVwy ]
.RB [ \-d\ \fIpath\fB\ \-d\ \fI...\fB ]
.RB [ \-u\ \fIpath\fB\ \-u\ \fI...\fB ]
.I device
.ad b
.SH DESCRIPTION
.B dosfsck
verifies the consistency of MS-DOS file systems and optionally tries to
repair them. The following file system problems can be corrected (in this
order):
.IP \-
FAT contains invalid cluster numbers. Cluster is changed to EOF.
.PD 0
.IP \-
File's cluster chain contains a loop. The loop is broken.
.IP \-
Bad clusters (read errors). The clusters are marked bad and they are
removed from files owning them. This check is optional.
.IP \-
Directories with a large number of bad entries (probably corrupt). The
directory can be dropped.
.IP \-
Files . and .. are non-directories. They can be dropped or renamed.
.IP \-
Directories . and .. in root directory. They are dropped.
.IP \-
Bad file names. They can be renamed.
.IP \-
Duplicate directory entries. They can be dropped or renamed.
.IP \-
Directories with non-zero size field. Size is set to zero.
.IP \-
Directory . does not point to parent directory. The start pointer is
adjusted.
.IP \-
Directory .. does not point to parent of parent directory. The start pointer
is adjusted.
.IP \-
Start cluster number of a file is invalid. The file is truncated.
.IP \-
File contains bad or free clusters. The file is truncated.
.IP \-
File's cluster chain is longer than indicated by the size fields. The file
is truncated.
.IP \-
Two or more files share the same cluster(s). All but one of the files are
truncated. If the file being truncated is a directory file that has already
been read, the file system check is restarted after truncation.
.IP \-
File's cluster chain is shorter than indicated by the size fields. The file
is truncated.
.IP \-
Clusters are marked as used but are not owned by a file. They are marked
as free.
.PD
.LP
Additionally, the following problems are detected, but not repaired:
.IP \-
Invalid parameters in boot sector.
.PD 0
.IP \-
Absence of . and .. entries in non-root directories
.PD
.LP
When \fBdosfsck\fP checks a file system, it accumulates all changes in memory
and performs them only after all checks are complete. This can be disabled
with the \fB\-w\fP option.
.SH OPTIONS
.IP \fB\-a\fP
Automatically repair the file system. No user intervention is necessary.
Whenever there is more than one method to solve a problem, the least
destructive approach is used.
.IP \fB\-A\fP
Use Atari variation of the MS-DOS filesystem. This is default if
\fBdosfsck\fP is run on an Atari, then this option turns off Atari
format. There are some minor differences in Atari format: Some boot
sector fields are interpreted slightly different, and the special FAT
entries for end-of-file and bad cluster can be different. Under
MS-DOS 0xfff8 is used for EOF and Atari employs 0xffff by default, but
both systems recognize all values from 0xfff8...0xffff as end-of-file.
MS-DOS uses only 0xfff7 for bad clusters, where on Atari values
0xfff0...0xfff7 are for this purpose (but the standard value is still
0xfff7).
.IP \fB\-d\fP
Drop the specified file. If more that one file with that name exists, the
first one is dropped.
.IP \fB\-f\fP
Salvage unused cluster chains to files. By default, unused clusters are
added to the free disk space except in auto mode (\fB-a\fP).
.IP \fB\-l\fP
List path names of files being processed.
.IP \fB\-n\fP
No-operation mode: non-interactively check for errors, but don't write
anything to the filesystem.
.IP \fB\-r\fP
Interactively repair the file system. The user is asked for advice whenever
there is more than one approach to fix an inconsistency.
.IP \fB\-t\fP
Mark unreadable clusters as bad.
.IP \fB-u\fP
Try to undelete the specified file. \fBdosfsck\fP tries to allocate a chain
of contiguous unallocated clusters beginning with the start cluster of the
undeleted file.
.IP \fB\-v\fP
Verbose mode. Generates slightly more output.
.IP \fB\-V\fP
Perform a verification pass. The file system check is repeated after the
first run. The second pass should never report any fixable errors. It may
take considerably longer than the first pass, because the first pass may
have generated long list of modifications that have to be scanned for each
disk read.
.IP \fB\-w\fP
Write changes to disk immediately.
.IP \fB\-y\fP
Same as \fB\-a\fP (automatically repair filesystem) for compatibility
with other fsck tools.
.LP
If \fB\-a\fP and \fB\-r\fP are absent, the file system is only checked,
but not repaired.
.SH "EXIT STATUS"
.IP 0
No recoverable errors have been detected.
.IP 1
Recoverable errors have been detected or \fBdosfsck\fP has discovered an
internal inconsistency.
.IP 2
Usage error. \fBdosfsck\fP did not access the file system.
.SH BUGS
Does not create . and .. files where necessary. Does not remove entirely
empty directories. Should give more diagnostic messages. Undeleting files
should use a more sophisticated algorithm.
.\".SH "SEE ALSO"
.\"fs(5)
.SH AUTHORS
Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
Extensions (FAT32, VFAT) by and current maintainer:
Roman Hodek <roman@hodek.net>

View file

@ -1,184 +0,0 @@
/* dosfsck.c - User interface */
/* Written 1993 by Werner Almesberger */
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#include "version.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include "common.h"
#include "dosfsck.h"
#include "io.h"
#include "boot.h"
#include "fat.h"
#include "file.h"
#include "check.h"
int interactive = 0,list = 0,test = 0,verbose = 0,write_immed = 0;
int atari_format = 0;
unsigned n_files = 0;
void *mem_queue = NULL;
static void usage(char *name)
{
fprintf(stderr,"usage: %s [-aAflrtvVwy] [-d path -d ...] "
"[-u path -u ...]\n%15sdevice\n",name,"");
fprintf(stderr," -a automatically repair the file system\n");
fprintf(stderr," -A toggle Atari file system format\n");
fprintf(stderr," -d path drop that file\n");
fprintf(stderr," -f salvage unused chains to files\n");
fprintf(stderr," -l list path names\n");
fprintf(stderr," -n no-op, check non-interactively without changing\n");
fprintf(stderr," -r interactively repair the file system\n");
fprintf(stderr," -t test for bad clusters\n");
fprintf(stderr," -u path try to undelete that (non-directory) file\n");
fprintf(stderr," -v verbose mode\n");
fprintf(stderr," -V perform a verification pass\n");
fprintf(stderr," -w write changes to disk immediately\n");
fprintf(stderr," -y same as -a, for compat with other *fsck\n");
exit(2);
}
/*
* ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
* of MS-DOS filesystem by default.
*/
static void check_atari( void )
{
#ifdef __mc68000__
FILE *f;
char line[128], *p;
if (!(f = fopen( "/proc/hardware", "r" ))) {
perror( "/proc/hardware" );
return;
}
while( fgets( line, sizeof(line), f ) ) {
if (strncmp( line, "Model:", 6 ) == 0) {
p = line + 6;
p += strspn( p, " \t" );
if (strncmp( p, "Atari ", 6 ) == 0)
atari_format = 1;
break;
}
}
fclose( f );
#endif
}
int main(int argc,char **argv)
{
DOS_FS fs;
int rw,salvage_files,verify,c;
unsigned long free_clusters;
rw = salvage_files = verify = 0;
interactive = 1;
check_atari();
while ((c = getopt(argc,argv,"Aad:flnrtu:vVwy")) != EOF)
switch (c) {
case 'A': /* toggle Atari format */
atari_format = !atari_format;
break;
case 'a':
case 'y':
rw = 1;
interactive = 0;
salvage_files = 1;
break;
case 'd':
file_add(optarg,fdt_drop);
break;
case 'f':
salvage_files = 1;
break;
case 'l':
list = 1;
break;
case 'n':
rw = 0;
interactive = 0;
break;
case 'r':
rw = 1;
interactive = 1;
break;
case 't':
test = 1;
break;
case 'u':
file_add(optarg,fdt_undelete);
break;
case 'v':
verbose = 1;
printf("dosfsck " VERSION " (" VERSION_DATE ")\n");
break;
case 'V':
verify = 1;
break;
case 'w':
write_immed = 1;
break;
default:
usage(argv[0]);
}
if ((test || write_immed) && !rw) {
fprintf(stderr,"-t and -w require -a or -r\n");
exit(2);
}
if (optind != argc-1) usage(argv[0]);
printf( "dosfsck " VERSION ", " VERSION_DATE ", FAT32, LFN\n" );
fs_open(argv[optind],rw);
read_boot(&fs);
if (verify) printf("Starting check/repair pass.\n");
while (read_fat(&fs), scan_root(&fs)) qfree(&mem_queue);
if (test) fix_bad(&fs);
if (salvage_files) reclaim_file(&fs);
else reclaim_free(&fs);
free_clusters = update_free(&fs);
file_unused();
qfree(&mem_queue);
if (verify) {
printf("Starting verification pass.\n");
read_fat(&fs);
scan_root(&fs);
reclaim_free(&fs);
qfree(&mem_queue);
}
if (fs_changed()) {
if (rw) {
if (interactive)
rw = get_key("yn","Perform changes ? (y/n)") == 'y';
else printf("Performing changes.\n");
}
else
printf("Leaving file system unchanged.\n");
}
printf( "%s: %u files, %lu/%lu clusters\n", argv[optind],
n_files, fs.clusters - free_clusters, fs.clusters );
return fs_close(rw) ? 1 : 0;
}
/* Local Variables: */
/* tab-width: 8 */
/* End: */

View file

@ -1,187 +0,0 @@
/* dosfsck.h - Common data structures and global variables */
/* Written 1993 by Werner Almesberger */
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#ifndef _DOSFSCK_H
#define _DOSFSCK_H
//#include "types.h"
#ifdef _WIN32
typedef unsigned char __u8;
typedef unsigned short __u16;
typedef unsigned int __u32;
typedef unsigned __int64 __u64;
typedef unsigned short __le16;
typedef unsigned int __le32;
typedef __int64 loff_t;
typedef __int64 ll_t;
#define CF_LE_W(v) (v)
#define CF_LE_L(v) (v)
#define CT_LE_W(v) (v)
#define CT_LE_L(v) (v)
#endif
#define _LINUX_STAT_H /* hack to avoid inclusion of <linux/stat.h> */
#define _LINUX_STRING_H_ /* hack to avoid inclusion of <linux/string.h>*/
#define _LINUX_FS_H /* hack to avoid inclusion of <linux/fs.h> */
//#include <linux/version.h>
//# include "types.h"
# include "byteorder.h"
#include "msdos_fs.h"
#if 0
#undef CF_LE_W
#undef CF_LE_L
#undef CT_LE_W
#undef CT_LE_L
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
#include "byteswap.h"
#if 0
#define CF_LE_W(v) bswap_16(v)
#define CF_LE_L(v) bswap_32(v)
#define CT_LE_W(v) CF_LE_W(v)
#define CT_LE_L(v) CF_LE_L(v)
#endif
#else
#define CF_LE_W(v) (v)
#define CF_LE_L(v) (v)
#define CT_LE_W(v) (v)
#define CT_LE_L(v) (v)
#endif /* __BIG_ENDIAN */
#define VFAT_LN_ATTR (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
#include <pshpack1.h>
/* ++roman: Use own definition of boot sector structure -- the kernel headers'
* name for it is msdos_boot_sector in 2.0 and fat_boot_sector in 2.1 ... */
struct boot_sector {
__u8 ignored[3]; /* Boot strap short or near jump */
__u8 system_id[8]; /* Name - can be used to special case
partition manager volumes */
__u8 sector_size[2]; /* bytes per logical sector */
__u8 cluster_size; /* sectors/cluster */
__u16 reserved; /* reserved sectors */
__u8 fats; /* number of FATs */
__u8 dir_entries[2]; /* root directory entries */
__u8 sectors[2]; /* number of sectors */
__u8 media; /* media code (unused) */
__u16 fat_length; /* sectors/FAT */
__u16 secs_track; /* sectors per track */
__u16 heads; /* number of heads */
__u32 hidden; /* hidden sectors (unused) */
__u32 total_sect; /* number of sectors (if sectors == 0) */
/* The following fields are only used by FAT32 */
__u32 fat32_length; /* sectors/FAT */
__u16 flags; /* bit 8: fat mirroring, low 4: active fat */
__u8 version[2]; /* major, minor filesystem version */
__u32 root_cluster; /* first cluster in root directory */
__u16 info_sector; /* filesystem info sector */
__u16 backup_boot; /* backup boot sector */
__u16 reserved2[6]; /* Unused */
/* fill up to 512 bytes */
__u8 junk[448];
};
#include <poppack.h>
struct info_sector {
__u32 magic; /* Magic for info sector ('RRaA') */
__u8 junk[0x1dc];
__u32 reserved1; /* Nothing as far as I can tell */
__u32 signature; /* 0x61417272 ('rrAa') */
__u32 free_clusters; /* Free cluster count. -1 if unknown */
__u32 next_cluster; /* Most recently allocated cluster. */
__u32 reserved2[3];
__u16 reserved3;
__u16 boot_sign;
};
typedef struct {
__u8 name[8],ext[3]; /* name and extension */
__u8 attr; /* attribute bits */
__u8 lcase; /* Case for base and extension */
__u8 ctime_ms; /* Creation time, milliseconds */
__u16 ctime; /* Creation time */
__u16 cdate; /* Creation date */
__u16 adate; /* Last access date */
__u16 starthi; /* High 16 bits of cluster in FAT32 */
__u16 time,date,start;/* time, date and first cluster */
__u32 size; /* file size (in bytes) */
} DIR_ENT;
typedef struct _dos_file {
DIR_ENT dir_ent;
char *lfn;
loff_t offset;
struct _dos_file *parent; /* parent directory */
struct _dos_file *next; /* next entry */
struct _dos_file *first; /* first entry (directory only) */
} DOS_FILE;
typedef struct {
unsigned long value;
unsigned long reserved;
DOS_FILE *owner;
int prev; /* number of previous clusters */
} FAT_ENTRY;
typedef struct {
int nfats;
loff_t fat_start;
unsigned int fat_size; /* unit is bytes */
unsigned int fat_bits; /* size of a FAT entry */
unsigned int eff_fat_bits; /* # of used bits in a FAT entry */
unsigned long root_cluster; /* 0 for old-style root dir */
loff_t root_start;
unsigned int root_entries;
loff_t data_start;
unsigned int cluster_size;
unsigned long clusters;
loff_t fsinfo_start; /* 0 if not present */
long free_clusters;
loff_t backupboot_start; /* 0 if not present */
FAT_ENTRY *fat;
} DOS_FS;
#ifndef offsetof
#define offsetof(t,e) ((int)&(((t *)0)->e))
#endif
extern int interactive,list,verbose,test,write_immed;
extern int atari_format;
extern unsigned n_files;
extern void *mem_queue;
/* value to use as end-of-file marker */
#define FAT_EOF(fs) ((atari_format ? 0xfff : 0xff8) | FAT_EXTD(fs))
#define FAT_IS_EOF(fs,v) ((unsigned long)(v) >= (0xff8|FAT_EXTD(fs)))
/* value to mark bad clusters */
#define FAT_BAD(fs) (0xff7 | FAT_EXTD(fs))
/* range of values used for bad clusters */
#define FAT_MIN_BAD(fs) ((atari_format ? 0xff0 : 0xff7) | FAT_EXTD(fs))
#define FAT_MAX_BAD(fs) ((atari_format ? 0xff7 : 0xff7) | FAT_EXTD(fs))
#define FAT_IS_BAD(fs,v) ((v) >= FAT_MIN_BAD(fs) && (v) <= FAT_MAX_BAD(fs))
/* return -16 as a number with fs->fat_bits bits */
#define FAT_EXTD(fs) (((1 << fs->eff_fat_bits)-1) & ~0xf)
#endif
/* Local Variables: */
/* tab-width: 8 */
/* End: */

View file

@ -1,15 +0,0 @@
<module name="dosfsck" type="win32cui" installbase="system32" installname="dosfsck.exe" unicode="no" allowwarnings="true">
<library>kernel32</library>
<library>user32</library>
<file>boot.c</file>
<file>check.c</file>
<file>common.c</file>
<file>dosfsck.c</file>
<file>fat.c</file>
<file>file.c</file>
<file>io.c</file>
<file>lfn.c</file>
<file>dosfsck.rc</file>
</module>

View file

@ -1,7 +0,0 @@
#include <windows.h>
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS FAT checker\0"
#define REACTOS_STR_INTERNAL_NAME "dosfsck\0"
#define REACTOS_STR_ORIGINAL_FILENAME "dosfsck.exe\0"
#define REACTOS_STR_ORIGINAL_COPYRIGHT "Copyright ReactOS Development team\0"
#include <reactos/version.rc>

View file

@ -1,366 +0,0 @@
/* fat.c - Read/write access to the FAT */
/* Written 1993 by Werner Almesberger */
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <unistd.h>
#include "common.h"
#include "dosfsck.h"
#include "io.h"
#include "check.h"
#include "fat.h"
#pragma warning(disable: 4018)
static void get_fat(FAT_ENTRY *entry,void *fat,unsigned long cluster,DOS_FS *fs)
{
unsigned char *ptr;
switch(fs->fat_bits) {
case 12:
ptr = &((unsigned char *) fat)[cluster*3/2];
entry->value = 0xfff & (cluster & 1 ? (ptr[0] >> 4) | (ptr[1] << 4) :
(ptr[0] | ptr[1] << 8));
break;
case 16:
entry->value = CF_LE_W(((unsigned short *) fat)[cluster]);
break;
case 32:
/* According to M$, the high 4 bits of a FAT32 entry are reserved and
* are not part of the cluster number. So we cut them off. */
{
unsigned long e = CF_LE_L(((unsigned int *) fat)[cluster]);
entry->value = e & 0xfffffff;
entry->reserved = e >> 28;
}
break;
default:
die("Bad FAT entry size: %d bits.",fs->fat_bits);
}
entry->owner = NULL;
}
void read_fat(DOS_FS *fs)
{
int eff_size;
unsigned long i;
void *first,*second,*use;
int first_ok,second_ok;
eff_size = ((fs->clusters+2)*fs->fat_bits+7)/8;
// TMN: Must round up to disk-sector boundary. For now, assume 512-byte disk.
if (eff_size % 512) {
eff_size += 512 - (eff_size % 512);
}
first = alloc(eff_size);
fs_read(fs->fat_start,eff_size,first);
use = first;
if (fs->nfats > 1) {
second = alloc(eff_size);
fs_read(fs->fat_start+fs->fat_size,eff_size,second);
}
else
second = NULL;
if (second && memcmp(first,second,eff_size) != 0) {
FAT_ENTRY first_media, second_media;
get_fat(&first_media,first,0,fs);
get_fat(&second_media,second,0,fs);
first_ok = (first_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs);
second_ok = (second_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs);
if (first_ok && !second_ok) {
printf("FATs differ - using first FAT.\n");
fs_write(fs->fat_start+fs->fat_size,eff_size,use = first);
}
if (!first_ok && second_ok) {
printf("FATs differ - using second FAT.\n");
fs_write(fs->fat_start,eff_size,use = second);
}
if (first_ok && second_ok) {
if (interactive) {
printf("FATs differ but appear to be intact. Use which FAT ?\n"
"1) Use first FAT\n2) Use second FAT\n");
if (get_key("12","?") == '1')
fs_write(fs->fat_start+fs->fat_size,eff_size,use = first);
else fs_write(fs->fat_start,eff_size,use = second);
}
else {
printf("FATs differ but appear to be intact. Using first "
"FAT.\n");
fs_write(fs->fat_start+fs->fat_size,eff_size,use = first);
}
}
if (!first_ok && !second_ok) {
printf("Both FATs appear to be corrupt. Giving up.\n");
exit(1);
}
}
fs->fat = qalloc(&mem_queue,sizeof(FAT_ENTRY)*(fs->clusters+2));
for (i = 2; i < fs->clusters+2; i++) get_fat(&fs->fat[i],use,i,fs);
for (i = 2; i < fs->clusters+2; i++)
if (fs->fat[i].value >= fs->clusters+2 &&
(fs->fat[i].value < FAT_MIN_BAD(fs))) {
printf("Cluster %ld out of range (%ld > %ld). Setting to EOF.\n",
i-2,fs->fat[i].value,fs->clusters+2-1);
set_fat(fs,i,-1);
}
free(first);
if (second)
free(second);
}
void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new)
{
unsigned char data[4];
int size;
loff_t offs;
if ((long)new == -1)
new = FAT_EOF(fs);
else if ((long)new == -2)
new = FAT_BAD(fs);
switch( fs->fat_bits ) {
case 12:
offs = fs->fat_start+cluster*3/2;
if (cluster & 1) {
data[0] = ((new & 0xf) << 4) | (fs->fat[cluster-1].value >> 8);
data[1] = new >> 4;
}
else {
data[0] = new & 0xff;
data[1] = (new >> 8) | (cluster == fs->clusters-1 ? 0 :
(0xff & fs->fat[cluster+1].value) << 4);
}
size = 2;
break;
case 16:
offs = fs->fat_start+cluster*2;
*(unsigned short *) data = CT_LE_W(new);
size = 2;
break;
case 32:
offs = fs->fat_start+cluster*4;
/* According to M$, the high 4 bits of a FAT32 entry are reserved and
* are not part of the cluster number. So we never touch them. */
*(unsigned long *) data = CT_LE_L( (new & 0xfffffff) |
(fs->fat[cluster].reserved << 28) );
size = 4;
break;
default:
die("Bad FAT entry size: %d bits.",fs->fat_bits);
}
fs->fat[cluster].value = new;
fs_write(offs,size,&data);
fs_write(offs+fs->fat_size,size,&data);
}
int bad_cluster(DOS_FS *fs,unsigned long cluster)
{
return FAT_IS_BAD(fs,fs->fat[cluster].value);
}
unsigned long next_cluster(DOS_FS *fs,unsigned long cluster)
{
unsigned long value;
value = fs->fat[cluster].value;
if (FAT_IS_BAD(fs,value))
die("Internal error: next_cluster on bad cluster");
return FAT_IS_EOF(fs,value) ? -1 : value;
}
loff_t cluster_start(DOS_FS *fs,unsigned long cluster)
{
return fs->data_start+((loff_t)cluster-2)*fs->cluster_size;
}
void set_owner(DOS_FS *fs,unsigned long cluster,DOS_FILE *owner)
{
if (owner && fs->fat[cluster].owner)
die("Internal error: attempt to change file owner");
fs->fat[cluster].owner = owner;
}
DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster)
{
return fs->fat[cluster].owner;
}
void fix_bad(DOS_FS *fs)
{
unsigned long i;
if (verbose)
printf("Checking for bad clusters.\n");
for (i = 2; i < fs->clusters+2; i++)
if (!get_owner(fs,i) && !FAT_IS_BAD(fs,fs->fat[i].value))
if (!fs_test(cluster_start(fs,i),fs->cluster_size)) {
printf("Cluster %lu is unreadable.\n",i);
set_fat(fs,i,-2);
}
}
void reclaim_free(DOS_FS *fs)
{
int reclaimed;
unsigned long i;
if (verbose)
printf("Checking for unused clusters.\n");
reclaimed = 0;
for (i = 2; i < fs->clusters+2; i++)
if (!get_owner(fs,i) && fs->fat[i].value &&
!FAT_IS_BAD(fs,fs->fat[i].value)) {
set_fat(fs,i,0);
reclaimed++;
}
if (reclaimed)
printf("Reclaimed %d unused cluster%s (%d bytes).\n",reclaimed,
reclaimed == 1 ? "" : "s",reclaimed*fs->cluster_size);
}
static void tag_free(DOS_FS *fs,DOS_FILE *ptr)
{
DOS_FILE *owner;
int prev;
unsigned long i,walk;
for (i = 2; i < fs->clusters+2; i++)
if (fs->fat[i].value && !FAT_IS_BAD(fs,fs->fat[i].value) &&
!get_owner(fs,i) && !fs->fat[i].prev) {
prev = 0;
for (walk = i; walk > 0 && walk != -1;
walk = next_cluster(fs,walk)) {
if (!(owner = get_owner(fs,walk))) set_owner(fs,walk,ptr);
else if (owner != ptr)
die("Internal error: free chain collides with file");
else {
set_fat(fs,prev,-1);
break;
}
prev = walk;
}
}
}
void reclaim_file(DOS_FS *fs)
{
DOS_FILE dummy;
int reclaimed,files,changed;
unsigned long i,next,walk;
if (verbose)
printf("Reclaiming unconnected clusters.\n");
for (i = 2; i < fs->clusters+2; i++) fs->fat[i].prev = 0;
for (i = 2; i < fs->clusters+2; i++) {
next = fs->fat[i].value;
if (!get_owner(fs,i) && next && next < fs->clusters+2) {
if (get_owner(fs,next) || !fs->fat[next].value ||
FAT_IS_BAD(fs,fs->fat[next].value)) set_fat(fs,i,-1);
else fs->fat[next].prev++;
}
}
do {
tag_free(fs,&dummy);
changed = 0;
for (i = 2; i < fs->clusters+2; i++)
if (fs->fat[i].value && !FAT_IS_BAD(fs,fs->fat[i].value) &&
!get_owner(fs, i)) {
if (!fs->fat[fs->fat[i].value].prev--)
die("Internal error: prev going below zero");
set_fat(fs,i,-1);
changed = 1;
printf("Broke cycle at cluster %lu in free chain.\n",i);
break;
}
}
while (changed);
files = reclaimed = 0;
for (i = 2; i < fs->clusters+2; i++)
if (get_owner(fs,i) == &dummy && !fs->fat[i].prev) {
DIR_ENT de;
loff_t offset;
files++;
offset = alloc_rootdir_entry(fs,&de,"FSCK%04dREC");
de.start = CT_LE_W(i&0xffff);
if (fs->fat_bits == 32)
de.starthi = CT_LE_W(i>>16);
for (walk = i; walk > 0 && walk != -1;
walk = next_cluster(fs,walk)) {
de.size = CT_LE_L(CF_LE_L(de.size)+fs->cluster_size);
reclaimed++;
}
fs_write(offset,sizeof(DIR_ENT),&de);
}
if (reclaimed)
printf("Reclaimed %d unused cluster%s (%d bytes) in %d chain%s.\n",
reclaimed,reclaimed == 1 ? "" : "s",reclaimed*fs->cluster_size,files,
files == 1 ? "" : "s");
}
unsigned long update_free(DOS_FS *fs)
{
unsigned long i;
unsigned long free = 0;
int do_set = 0;
for (i = 2; i < fs->clusters+2; i++)
if (!get_owner(fs,i) && !FAT_IS_BAD(fs,fs->fat[i].value))
++free;
if (!fs->fsinfo_start)
return free;
if (verbose)
printf("Checking free cluster summary.\n");
if (fs->free_clusters >= 0) {
if (free != fs->free_clusters) {
printf( "Free cluster summary wrong (%ld vs. really %ld)\n",
fs->free_clusters,free);
if (interactive)
printf( "1) Correct\n2) Don't correct\n" );
else printf( " Auto-correcting.\n" );
if (!interactive || get_key("12","?") == '1')
do_set = 1;
}
}
else {
printf( "Free cluster summary uninitialized (should be %ld)\n", free );
if (interactive)
printf( "1) Set it\n2) Leave it uninitialized\n" );
else printf( " Auto-setting.\n" );
if (!interactive || get_key("12","?") == '1')
do_set = 1;
}
if (do_set) {
fs->free_clusters = free;
free = CT_LE_L(free);
fs_write(fs->fsinfo_start+offsetof(struct info_sector,free_clusters),
sizeof(free),&free);
}
return free;
}
/* Local Variables: */
/* tab-width: 8 */
/* End: */

View file

@ -1,64 +0,0 @@
/* fat.h - Read/write access to the FAT */
/* Written 1993 by Werner Almesberger */
#ifndef _FAT_H
#define _FAT_H
void read_fat(DOS_FS *fs);
/* Loads the FAT of the file system described by FS. Initializes the FAT,
replaces broken FATs and rejects invalid cluster entries. */
void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new);
/* Changes the value of the CLUSTERth cluster of the FAT of FS to NEW. Special
values of NEW are -1 (EOF, 0xff8 or 0xfff8) and -2 (bad sector, 0xff7 or
0xfff7) */
int bad_cluster(DOS_FS *fs,unsigned long cluster);
/* Returns a non-zero integer if the CLUSTERth cluster is marked as bad or zero
otherwise. */
unsigned long next_cluster(DOS_FS *fs,unsigned long cluster);
/* Returns the number of the cluster following CLUSTER, or -1 if this is the
last cluster of the respective cluster chain. CLUSTER must not be a bad
cluster. */
loff_t cluster_start(DOS_FS *fs,unsigned long cluster);
/* Returns the byte offset of CLUSTER, relative to the respective device. */
void set_owner(DOS_FS *fs,unsigned long cluster,DOS_FILE *owner);
/* Sets the owner pointer of the respective cluster to OWNER. If OWNER was NULL
before, it can be set to NULL or any non-NULL value. Otherwise, only NULL is
accepted as the new value. */
DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster);
/* Returns the owner of the repective cluster or NULL if the cluster has no
owner. */
void fix_bad(DOS_FS *fs);
/* Scans the disk for currently unused bad clusters and marks them as bad. */
void reclaim_free(DOS_FS *fs);
/* Marks all allocated, but unused clusters as free. */
void reclaim_file(DOS_FS *fs);
/* Scans the FAT for chains of allocated, but unused clusters and creates files
for them in the root directory. Also tries to fix all inconsistencies (e.g.
loops, shared clusters, etc.) in the process. */
unsigned long update_free(DOS_FS *fs);
/* Updates free cluster count in FSINFO sector. */
#endif

View file

@ -1,251 +0,0 @@
/* file.c - Additional file attributes */
/* Written 1993 by Werner Almesberger */
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
//#include <unistd.h>
#define _LINUX_STAT_H /* hack to avoid inclusion of <linux/stat.h> */
#define _LINUX_STRING_H_ /* hack to avoid inclusion of <linux/string.h>*/
#define _LINUX_FS_H /* hack to avoid inclusion of <linux/fs.h> */
//#include <linux/version.h>
//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
//# define __KERNEL__
//# include <asm/types.h>
//# undef __KERNEL__
//#endif
#include "dosfsck.h"
#include "msdos_fs.h"
#include "common.h"
#include "file.h"
FDSC *fp_root = NULL;
static void put_char(char **p,unsigned char c)
{
if ((c >= ' ' && c < 0x7f) || c >= 0xa0) *(*p)++ = c;
else {
*(*p)++ = '\\';
*(*p)++ = '0'+(c >> 6);
*(*p)++ = '0'+((c >> 3) & 7);
*(*p)++ = '0'+(c & 7);
}
}
char *file_name(unsigned char *fixed)
{
static char path[MSDOS_NAME*4+2];
char *p;
int i,j;
p = path;
for (i = j = 0; i < 8; i++)
if (fixed[i] != ' ') {
while (j++ < i) *p++ = ' ';
put_char(&p,fixed[i]);
}
if (strncmp(fixed+8," ",3)) {
*p++ = '.';
for (i = j = 0; i < 3; i++)
if (fixed[i+8] != ' ') {
while (j++ < i) *p++ = ' ';
put_char(&p,fixed[i+8]);
}
}
*p = 0;
return path;
}
int file_cvt(unsigned char *name,unsigned char *fixed)
{
unsigned char c;
int size,ext,cnt;
size = 8;
ext = 0;
while (*name) {
c = *name;
if (c < ' ' || c > 0x7e || strchr("*?<>|\"/",c)) {
printf("Invalid character in name. Use \\ooo for special "
"characters.\n");
return 0;
}
if (c == '.') {
if (ext) {
printf("Duplicate dots in name.\n");
return 0;
}
while (size--) *fixed++ = ' ';
size = 3;
ext = 1;
name++;
continue;
}
if (c == '\\') {
c = 0;
for (cnt = 3; cnt; cnt--) {
if (*name < '0' || *name > '7') {
printf("Invalid octal character.\n");
return 0;
}
c = c*8+*name++-'0';
}
if (cnt < 4) {
printf("Expected three octal digits.\n");
return 0;
}
name += 3;
}
if (islower(c)) c = toupper(c);
if (size) {
*fixed++ = c;
size--;
}
name++;
}
if (*name || size == 8) return 0;
if (!ext) {
while (size--) *fixed++ = ' ';
size = 3;
}
while (size--) *fixed++ = ' ';
return 1;
}
void file_add(char *path,FD_TYPE type)
{
FDSC **current,*walk;
char name[MSDOS_NAME];
char *here;
current = &fp_root;
if (*path != '/') die("%s: Absolute path required.",path);
path++;
while (1) {
if ((here = strchr(path,'/'))) *here = 0;
if (!file_cvt(path,name)) exit(2);
for (walk = *current; walk; walk = walk->next)
if (!here && (!strncmp(name,walk->name,MSDOS_NAME) || (type ==
fdt_undelete && !strncmp(name+1,walk->name+1,MSDOS_NAME-1))))
die("Ambiguous name: \"%s\"",path);
else if (here && !strncmp(name,walk->name,MSDOS_NAME)) break;
if (!walk) {
walk = alloc(sizeof(FDSC));
strncpy(walk->name,name,MSDOS_NAME);
walk->type = here ? fdt_none : type;
walk->first = NULL;
walk->next = *current;
*current = walk;
}
current = &walk->first;
if (!here) break;
*here = '/';
path = here+1;
}
}
FDSC **file_cd(FDSC **curr,char *fixed)
{
FDSC **walk;
if (!curr || !*curr) return NULL;
for (walk = curr; *walk; walk = &(*walk)->next)
if (!strncmp((*walk)->name,fixed,MSDOS_NAME) && (*walk)->first)
return &(*walk)->first;
return NULL;
}
static FDSC **file_find(FDSC **dir,char *fixed)
{
if (!dir || !*dir) return NULL;
if (*(unsigned char *) fixed == DELETED_FLAG) {
while (*dir) {
if (!strncmp((*dir)->name+1,fixed+1,MSDOS_NAME-1) && !(*dir)->first)
return dir;
dir = &(*dir)->next;
}
return NULL;
}
while (*dir) {
if (!strncmp((*dir)->name,fixed,MSDOS_NAME) && !(*dir)->first)
return dir;
dir = &(*dir)->next;
}
return NULL;
}
FD_TYPE file_type(FDSC **curr,char *fixed)
{
FDSC **this;
if ((this = file_find(curr,fixed))) return (*this)->type;
return fdt_none;
}
void file_modify(FDSC **curr,char *fixed)
{
FDSC **this,*next;
if (!(this = file_find(curr,fixed)))
die("Internal error: file_find failed");
switch ((*this)->type) {
case fdt_drop:
printf("Dropping %s\n",file_name(fixed));
*(unsigned char *) fixed = DELETED_FLAG;
break;
case fdt_undelete:
*fixed = *(*this)->name;
printf("Undeleting %s\n",file_name(fixed));
break;
default:
die("Internal error: file_modify");
}
next = (*this)->next;
free(*this);
*this = next;
}
static void report_unused(FDSC *this)
{
FDSC *next;
while (this) {
next = this->next;
if (this->first) report_unused(this->first);
else if (this->type != fdt_none)
printf("Warning: did not %s file %s\n",this->type == fdt_drop ?
"drop" : "undelete",file_name(this->name));
free(this);
this = next;
}
}
void file_unused(void)
{
report_unused(fp_root);
}
/* Local Variables: */
/* tab-width: 8 */
/* End: */

View file

@ -1,55 +0,0 @@
/* file.h - Additional file attributes */
/* Written 1993 by Werner Almesberger */
#ifndef _FILE_H
#define _FILE_H
typedef enum { fdt_none,fdt_drop,fdt_undelete } FD_TYPE;
typedef struct _fptr {
char name[MSDOS_NAME];
FD_TYPE type;
struct _fptr *first; /* first entry */
struct _fptr *next; /* next file in directory */
} FDSC;
extern FDSC *fp_root;
char *file_name(unsigned char *fixed);
/* Returns a pointer to a pretty-printed representation of a fixed MS-DOS file
name. */
int file_cvt(unsigned char *name,unsigned char *fixed);
/* Converts a pretty-printed file name to the fixed MS-DOS format. Returns a
non-zero integer on success, zero on failure. */
void file_add(char *path,FD_TYPE type);
/* Define special attributes for a path. TYPE can be either FDT_DROP or
FDT_UNDELETE. */
FDSC **file_cd(FDSC **curr,char *fixed);
/* Returns a pointer to the directory descriptor of the subdirectory FIXED of
CURR, or NULL if no such subdirectory exists. */
FD_TYPE file_type(FDSC **curr,char *fixed);
/* Returns the attribute of the file FIXED in directory CURR or FDT_NONE if no
such file exists or if CURR is NULL. */
void file_modify(FDSC **curr,char *fixed);
/* Performs the necessary operation on the entry of CURR that is named FIXED. */
void file_unused(void);
/* Displays warnings for all unused file attributes. */
#endif

View file

@ -1,444 +0,0 @@
/* io.c - Virtual disk input/output */
/* Written 1993 by Werner Almesberger */
/*
* Thu Feb 26 01:15:36 CET 1998: Martin Schulze <joey@infodrom.north.de>
* Fixed nasty bug that caused every file with a name like
* xxxxxxxx.xxx to be treated as bad name that needed to be fixed.
*/
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
//#include <unistd.h>
#include <sys/stat.h>
//#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <assert.h>
//#include <linux/fd.h>
#ifdef _WIN32
#include <windows.h>
#include <winioctl.h>
#define __LITTLE_ENDIAN 1234
#define __BIG_ENDIAN 4321
#define __BYTE_ORDER __LITTLE_ENDIAN
#define inline
#define __attribute__(x)
#define BLOCK_SIZE 512
#endif
#include "dosfsck.h"
#include "common.h"
#include "io.h"
typedef struct _change {
void *data;
loff_t pos;
int size;
struct _change *next;
} CHANGE;
static CHANGE *changes,*last;
static int fd,did_change = 0;
unsigned device_no;
static int WIN32open(const char *path, int oflag, ...);
#define open WIN32open
static int WIN32close(int fd);
#define close WIN32close
static int WIN32read(int fd, void *buf, unsigned int len);
#define read WIN32read
static int WIN32write(int fd, void *buf, unsigned int len);
#define write WIN32write
static loff_t WIN32llseek(int fd, loff_t offset, int whence);
#ifdef llseek
#undef llseek
#endif
#define llseek WIN32llseek
//static int is_device = 0;
void fs_open(char *path,int rw)
{
#ifdef _WIN32
static char dev_buf[] = "\\\\.\\X:";
#else
struct stat stbuf;
#endif
if (path[1] == ':' && path[2] == '\0') {
dev_buf[4] = path[0];
path = dev_buf;
// is_device = 1;
}
if ((fd = open(path,rw ? O_RDWR : O_RDONLY)) < 0)
pdie("open %s",path);
changes = last = NULL;
did_change = 0;
#if 0
if (fstat(fd,&stbuf) < 0)
pdie("fstat %s",path);
device_no = S_ISBLK(stbuf.st_mode) ? (stbuf.st_rdev >> 8) & 0xff : 0;
#endif
}
void fs_read(loff_t pos,int size,void *data)
{
CHANGE *walk;
int got;
#if 1 // TMN
const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN:
const loff_t seekpos_aligned = pos - (pos % 512); // TMN:
const size_t seek_delta = (size_t)(pos - seekpos_aligned); // TMN:
const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; // TMN:
char* tmpBuf = malloc(readsize_aligned); // TMN:
if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %I64d",pos);
if ((got = read(fd,tmpBuf,readsize_aligned)) < 0) pdie("Read %d bytes at %I64d",size,pos);
assert(got >= size);
got = size;
assert(seek_delta + size <= readsize);
memcpy(data, tmpBuf+seek_delta, size);
free(tmpBuf);
#else // TMN:
if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
if ((got = read(fd,data,size)) < 0) pdie("Read %d bytes at %lld",size,pos);
#endif // TMN:
if (got != size) die("Got %d bytes instead of %d at %I64d",got,size,pos);
for (walk = changes; walk; walk = walk->next) {
if (walk->pos < pos+size && walk->pos+walk->size > pos) {
if (walk->pos < pos)
memcpy(data,(char *) walk->data+pos-walk->pos,min((size_t)size,
(size_t)(walk->size-pos+walk->pos)));
else memcpy((char *) data+walk->pos-pos,walk->data,min((size_t)walk->size,
(size_t)(size+pos-walk->pos)));
}
}
}
int fs_test(loff_t pos,int size)
{
void *scratch;
int okay;
#if 1 // TMN
const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN:
const loff_t seekpos_aligned = pos - (pos % 512); // TMN:
scratch = alloc(readsize_aligned);
if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos);
okay = read(fd,scratch,readsize_aligned) == (int)readsize_aligned;
free(scratch);
#else // TMN:
if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
scratch = alloc(size);
okay = read(fd,scratch,size) == size;
free(scratch);
#endif // TMN:
return okay;
}
void fs_write(loff_t pos,int size,void *data)
{
CHANGE *new;
int did;
#if 1 //SAE
if (write_immed) {
void *scratch;
const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size;
const loff_t seekpos_aligned = pos - (pos % 512);
const size_t seek_delta = (size_t)(pos - seekpos_aligned);
boolean use_read = (seek_delta != 0) || ((readsize_aligned-size) != 0);
/* Aloc temp buffer if write is not aligned */
if (use_read)
scratch = alloc(readsize_aligned);
else
scratch = data;
did_change = 1;
if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %I64d",seekpos_aligned);
if (use_read)
{
/* Read aligned data */
if (read(fd,scratch,readsize_aligned) < 0) pdie("Read %d bytes at %I64d",size,pos);
/* Patch data in memory */
memcpy((char *)scratch+seek_delta, data, size);
}
/* Write it back */
if ((did = write(fd,scratch,readsize_aligned)) == (int)readsize_aligned)
{
if (use_read) free(scratch);
return;
}
if (did < 0) pdie("Write %d bytes at %I64d",size,pos);
die("Wrote %d bytes instead of %d at %I64d",did,size,pos);
}
new = alloc(sizeof(CHANGE));
new->pos = pos;
memcpy(new->data = alloc(new->size = size),data,size);
new->next = NULL;
if (last) last->next = new;
else changes = new;
last = new;
#else //SAE
if (write_immed) {
did_change = 1;
if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
if ((did = write(fd,data,size)) == size) return;
if (did < 0) pdie("Write %d bytes at %lld",size,pos);
die("Wrote %d bytes instead of %d at %lld",did,size,pos);
}
new = alloc(sizeof(CHANGE));
new->pos = pos;
memcpy(new->data = alloc(new->size = size),data,size);
new->next = NULL;
if (last) last->next = new;
else changes = new;
last = new;
#endif //SAE
}
static void fs_flush(void)
{
CHANGE *this;
//int size;
int old_write_immed = write_immed;
/* Disable writes to the list now */
write_immed = 1;
while (changes) {
this = changes;
changes = changes->next;
#if 0
if (llseek(fd,this->pos,0) != this->pos)
fprintf(stderr,"Seek to %lld failed: %s\n Did not write %d bytes.\n",
(__int64)this->pos,strerror(errno),this->size);
else if ((size = write(fd,this->data,this->size)) < 0)
fprintf(stderr,"Writing %d bytes at %lld failed: %s\n",this->size,
(__int64)this->pos,strerror(errno));
else if (size != this->size)
fprintf(stderr,"Wrote %d bytes instead of %d bytes at %lld."
"\n",size,this->size,(__int64)this->pos);
#else
fs_write(this->pos, this->size, this->data);
#endif
free(this->data);
free(this);
}
/* Restore values */
write_immed = old_write_immed;
}
int fs_close(int write)
{
CHANGE *next;
int changed;
changed = !!changes;
if (write) fs_flush();
else while (changes) {
next = changes->next;
free(changes->data);
free(changes);
changes = next;
}
if (close(fd) < 0) pdie("closing file system");
return changed || did_change;
}
int fs_changed(void)
{
return !!changes || did_change;
}
/* Local Variables: */
/* tab-width: 8 */
/* End: */
#define O_SHORT_LIVED _O_SHORT_LIVED
//#define O_ACCMODE 3
#define O_NONE 3
#define O_BACKUP 0x10000
#define O_SHARED 0x20000
static int WIN32open(const char *path, int oflag, ...)
{
HANDLE fh;
DWORD desiredAccess = 0;
DWORD shareMode = 0;
DWORD creationDisposition = 0;
DWORD flagsAttributes = FILE_ATTRIBUTE_NORMAL;
SECURITY_ATTRIBUTES securityAttributes;
va_list ap;
int pmode;
int trunc = FALSE;
securityAttributes.nLength = sizeof(securityAttributes);
securityAttributes.lpSecurityDescriptor = NULL;
securityAttributes.bInheritHandle = oflag & O_NOINHERIT ? FALSE : TRUE;
switch (oflag & O_ACCMODE) {
case O_RDONLY:
desiredAccess = GENERIC_READ;
// shareMode = FILE_SHARE_READ;
shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE; // TMN:
break;
case O_WRONLY:
desiredAccess = GENERIC_WRITE;
shareMode = 0;
break;
case O_RDWR:
desiredAccess = GENERIC_READ|GENERIC_WRITE;
shareMode = 0;
break;
case O_NONE:
desiredAccess = 0;
shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
}
if (oflag & O_APPEND) {
desiredAccess |= FILE_APPEND_DATA|SYNCHRONIZE;
shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
}
if (oflag & O_SHARED)
shareMode |= FILE_SHARE_READ|FILE_SHARE_WRITE;
switch (oflag & (O_CREAT|O_EXCL|O_TRUNC)) {
case 0:
case O_EXCL:
creationDisposition = OPEN_EXISTING;
break;
case O_CREAT:
creationDisposition = OPEN_ALWAYS;
break;
case O_CREAT|O_EXCL:
case O_CREAT|O_TRUNC|O_EXCL:
creationDisposition = CREATE_NEW;
break;
case O_TRUNC:
case O_TRUNC|O_EXCL:
creationDisposition = TRUNCATE_EXISTING;
break;
case O_CREAT|O_TRUNC:
creationDisposition = OPEN_ALWAYS;
trunc = TRUE;
break;
}
if (oflag & O_CREAT) {
va_start(ap, oflag);
pmode = va_arg(ap, int);
va_end(ap);
if ((pmode & 0222) == 0)
flagsAttributes |= FILE_ATTRIBUTE_READONLY;
}
if (oflag & O_TEMPORARY) {
flagsAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
desiredAccess |= DELETE;
}
if (oflag & O_SHORT_LIVED)
flagsAttributes |= FILE_ATTRIBUTE_TEMPORARY;
if (oflag & O_SEQUENTIAL)
flagsAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
else if (oflag & O_RANDOM)
flagsAttributes |= FILE_FLAG_RANDOM_ACCESS;
if (oflag & O_BACKUP)
flagsAttributes |= FILE_FLAG_BACKUP_SEMANTICS;
if ((fh = CreateFile(path, desiredAccess, shareMode, &securityAttributes,
creationDisposition, flagsAttributes, NULL)) == INVALID_HANDLE_VALUE) {
errno = GetLastError();
return -1;
}
if (trunc) {
if (!SetEndOfFile(fh)) {
errno = GetLastError();
CloseHandle(fh);
DeleteFile(path);
return -1;
}
}
return (int)fh;
}
static int WIN32close(int fd)
{
if (!CloseHandle((HANDLE)fd)) {
errno = GetLastError();
return -1;
}
return 0;
}
static int WIN32read(int fd, void *buf, unsigned int len)
{
DWORD actualLen;
if (!ReadFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {
errno = GetLastError();
if (errno == ERROR_BROKEN_PIPE)
return 0;
else
return -1;
}
return (int)actualLen;
}
static int WIN32write(int fd, void *buf, unsigned int len)
{
DWORD actualLen;
if (!WriteFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {
errno = GetLastError();
return -1;
}
return (int)actualLen;
}
static loff_t WIN32llseek(int fd, loff_t offset, int whence)
{
long lo, hi;
DWORD err;
lo = (long)(offset & 0xffffffff);
hi = (long)(offset >> 32);
lo = SetFilePointer((HANDLE)fd, lo, &hi, whence);
if (lo == 0xFFFFFFFF && (err = GetLastError()) != NO_ERROR) {
errno = err;
return -1;
}
return ((loff_t)hi << 32) | (__u32)lo;
}
int fsctl(int fd, int code)
{
DWORD ret;
if (!DeviceIoControl((HANDLE)fd, code, NULL, 0, NULL, 0, &ret, NULL)) {
errno = GetLastError();
return -1;
}
return 0;
}

View file

@ -1,54 +0,0 @@
/* io.h - Virtual disk input/output */
/* Written 1993 by Werner Almesberger */
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#ifndef _IO_H
#define _IO_H
//#include <sys/types.h> /* for loff_t */
#include "dosfsck.h"
/* In earlier versions, an own llseek() was used, but glibc lseek() is
* sufficient (or even better :) for 64 bit offsets in the meantime */
#define llseek lseek
void fs_open(char *path,int rw);
/* Opens the file system PATH. If RW is zero, the file system is opened
read-only, otherwise, it is opened read-write. */
void fs_read(loff_t pos,int size,void *data);
/* Reads SIZE bytes starting at POS into DATA. Performs all applicable
changes. */
int fs_test(loff_t pos,int size);
/* Returns a non-zero integer if SIZE bytes starting at POS can be read without
errors. Otherwise, it returns zero. */
void fs_write(loff_t pos,int size,void *data);
/* If write_immed is non-zero, SIZE bytes are written from DATA to the disk,
starting at POS. If write_immed is zero, the change is added to a list in
memory. */
int fs_close(int write);
/* Closes the file system, performs all pending changes if WRITE is non-zero
and removes the list of changes. Returns a non-zero integer if the file
system has been changed since the last fs_open, zero otherwise. */
int fs_changed(void);
/* Determines whether the file system has changed. See fs_close. */
extern unsigned device_no;
/* Major number of device (0 if file) and size (in 512 byte sectors) */
#endif

View file

@ -1,480 +0,0 @@
/* lfn.c - Functions for handling VFAT long filenames */
/* Written 1998 by Roman Hodek */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include "common.h"
#include "io.h"
#include "dosfsck.h"
#include "lfn.h"
#include "file.h"
typedef struct {
__u8 id; /* sequence number for slot */
__u8 name0_4[10]; /* first 5 characters in name */
__u8 attr; /* attribute byte */
__u8 reserved; /* always 0 */
__u8 alias_checksum; /* checksum for 8.3 alias */
__u8 name5_10[12]; /* 6 more characters in name */
__u16 start; /* starting cluster number, 0 in long slots */
__u8 name11_12[4]; /* last 2 characters in name */
} LFN_ENT;
#define LFN_ID_START 0x40
#define LFN_ID_SLOTMASK 0x1f
#define CHARS_PER_LFN 13
/* These modul-global vars represent the state of the LFN parser */
unsigned char *lfn_unicode = NULL;
unsigned char lfn_checksum;
int lfn_slot = -1;
loff_t *lfn_offsets = NULL;
int lfn_parts = 0;
static unsigned char fat_uni2esc[64] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z', '+', '-'
};
/* This defines which unicode chars are directly convertable to ISO-8859-1 */
#define UNICODE_CONVERTABLE(cl,ch) (ch == 0 && (cl < 0x80 || cl >= 0xa0))
/* for maxlen param */
#define UNTIL_0 INT_MAX
static void copy_lfn_part( char *dst, LFN_ENT *lfn );
static char *cnv_unicode( const unsigned char *uni, int maxlen, int use_q );
/* Convert name part in 'lfn' from unicode to ASCII */
static __inline char* CNV_THIS_PART(LFN_ENT *lfn)
{ \
char __part_uni[CHARS_PER_LFN*2];
copy_lfn_part( __part_uni, lfn );
cnv_unicode( __part_uni, CHARS_PER_LFN, 0 );
}
/* Convert name parts collected so far (from previous slots) from unicode to
* ASCII */
#define CNV_PARTS_SO_FAR() \
(cnv_unicode( lfn_unicode+(lfn_slot*CHARS_PER_LFN*2), \
lfn_parts*CHARS_PER_LFN, 0 ))
/* This function converts an unicode string to a normal ASCII string, assuming
* ISO-8859-1 charset. Characters not in 8859-1 are converted to the same
* escape notation as used by the kernel, i.e. the uuencode-like ":xxx" */
static char *cnv_unicode( const unsigned char *uni, int maxlen, int use_q )
{
const unsigned char *up;
unsigned char *out, *cp;
int len, val;
for( len = 0, up = uni; (up-uni)/2 < maxlen && (up[0] || up[1]); up += 2 ){
if (UNICODE_CONVERTABLE(up[0],up[1]))
++len;
else
len += 4;
}
cp = out = use_q ? qalloc( &mem_queue, len+1 ) : alloc( len+1 );
for( up = uni; (up-uni)/2 < maxlen && (up[0] || up[1]); up += 2 ) {
if (UNICODE_CONVERTABLE(up[0],up[1]))
*cp++ = up[0];
else {
/* here the same escape notation is used as in the Linux kernel */
*cp++ = ':';
val = (up[1] << 8) + up[0];
cp[2] = fat_uni2esc[val & 0x3f];
val >>= 6;
cp[1] = fat_uni2esc[val & 0x3f];
val >>= 6;
cp[0] = fat_uni2esc[val & 0x3f];
cp += 3;
}
}
*cp = 0;
return( out );
}
static void copy_lfn_part( char *dst, LFN_ENT *lfn )
{
memcpy( dst, lfn->name0_4, 10 );
memcpy( dst+10, lfn->name5_10, 12 );
memcpy( dst+22, lfn->name11_12, 4 );
}
static void clear_lfn_slots( int start, int end )
{
int i;
LFN_ENT empty;
/* New dir entry is zeroed except first byte, which is set to 0xe5.
* This is to avoid that some FAT-reading OSes (not Linux! ;) stop reading
* a directory at the first zero entry...
*/
memset( &empty, 0, sizeof(empty) );
empty.id = DELETED_FLAG;
for( i = start; i <= end; ++i ) {
fs_write( lfn_offsets[i], sizeof(LFN_ENT), &empty );
}
}
void lfn_reset( void )
{
if (lfn_unicode)
free( lfn_unicode );
lfn_unicode = NULL;
if (lfn_offsets)
free( lfn_offsets );
lfn_offsets = NULL;
lfn_slot = -1;
}
/* This function is only called with de->attr == VFAT_LN_ATTR. It stores part
* of the long name. */
void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
{
LFN_ENT *lfn = (LFN_ENT *)de;
unsigned offset;
if (de->attr != VFAT_LN_ATTR)
die("lfn_add_slot called with non-LFN directory entry");
if (lfn->id & LFN_ID_START) {
if (lfn_slot != -1) {
int can_clear = 0;
/* There is already a LFN "in progess", so it is an error that a
* new start entry is here. */
/* Causes: 1) if slot# == expected: start bit set mysteriously, 2)
* old LFN overwritten by new one */
/* Fixes: 1) delete previous LFN 2) if slot# == expected and
* checksum ok: clear start bit */
/* XXX: Should delay that until next LFN known (then can better
* display the name) */
printf( "A new long file name starts within an old one.\n" );
if ((lfn->id & LFN_ID_SLOTMASK) == lfn_slot &&
lfn->alias_checksum == lfn_checksum) {
char *part1 = CNV_THIS_PART(lfn);
char *part2 = CNV_PARTS_SO_FAR();
printf( " It could be that the LFN start bit is wrong here\n"
" if \"%s\" seems to match \"%s\".\n", part1, part2 );
free( part1 );
free( part2 );
can_clear = 1;
}
if (interactive) {
printf( "1: Delete previous LFN\n2: Leave it as it is.\n" );
if (can_clear)
printf( "3: Clear start bit and concatenate LFNs\n" );
}
else printf( " Not auto-correcting this.\n" );
if (interactive) {
switch( get_key( can_clear ? "123" : "12", "?" )) {
case '1':
clear_lfn_slots( 0, lfn_parts-1 );
lfn_reset();
break;
case '2':
break;
case '3':
lfn->id &= ~LFN_ID_START;
fs_write( dir_offset+offsetof(LFN_ENT,id),
sizeof(lfn->id), &lfn->id );
break;
}
}
}
lfn_slot = lfn->id & LFN_ID_SLOTMASK;
lfn_checksum = lfn->alias_checksum;
lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 );
lfn_offsets = alloc( lfn_slot*sizeof(loff_t) );
lfn_parts = 0;
}
else if (lfn_slot == -1) {
/* No LFN in progress, but slot found; start bit missing */
/* Causes: 1) start bit got lost, 2) Previous slot with start bit got
* lost */
/* Fixes: 1) delete LFN, 2) set start bit */
char *part = CNV_THIS_PART(lfn);
printf( "Long filename fragment \"%s\" found outside a LFN "
"sequence.\n (Maybe the start bit is missing on the "
"last fragment)\n", part );
if (interactive) {
printf( "1: Delete fragment\n2: Leave it as it is.\n"
"3: Set start bit\n" );
}
else printf( " Not auto-correcting this.\n" );
if (interactive) {
switch( get_key( "123", "?" )) {
case '1':
if (!lfn_offsets)
lfn_offsets = alloc( sizeof(loff_t) );
lfn_offsets[0] = dir_offset;
clear_lfn_slots( 0, 0 );
lfn_reset();
return;
case '2':
lfn_reset();
return;
case '3':
lfn->id |= LFN_ID_START;
fs_write( dir_offset+offsetof(LFN_ENT,id),
sizeof(lfn->id), &lfn->id );
lfn_slot = lfn->id & LFN_ID_SLOTMASK;
lfn_checksum = lfn->alias_checksum;
lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 );
lfn_offsets = alloc( lfn_slot*sizeof(loff_t) );
lfn_parts = 0;
break;
}
}
}
else if ((lfn->id & LFN_ID_SLOTMASK) != lfn_slot) {
/* wrong sequence number */
/* Causes: 1) seq-no destroyed */
/* Fixes: 1) delete LFN, 2) fix number (maybe only if following parts
* are ok?, maybe only if checksum is ok?) (Attention: space
* for name was allocated before!) */
int can_fix = 0;
printf( "Unexpected long filename sequence number "
"(%d vs. expected %d).\n",
(lfn->id & LFN_ID_SLOTMASK), lfn_slot );
if (lfn->alias_checksum == lfn_checksum) {
char *part1 = CNV_THIS_PART(lfn);
char *part2 = CNV_PARTS_SO_FAR();
printf( " It could be that just the number is wrong\n"
" if \"%s\" seems to match \"%s\".\n", part1, part2 );
free( part1 );
free( part2 );
can_fix = 1;
}
if (interactive) {
printf( "1: Delete LFN\n2: Leave it as it is (and ignore LFN so far)\n" );
if (can_fix)
printf( "3: Correct sequence number\n" );
}
else printf( " Not auto-correcting this.\n" );
if (interactive) {
switch( get_key( can_fix ? "123" : "12", "?" )) {
case '1':
lfn_offsets[lfn_parts++] = dir_offset;
clear_lfn_slots( 0, lfn_parts-1 );
lfn_reset();
return;
case '2':
lfn_reset();
return;
case '3':
lfn->id = (lfn->id & ~LFN_ID_SLOTMASK) | lfn_slot;
fs_write( dir_offset+offsetof(LFN_ENT,id),
sizeof(lfn->id), &lfn->id );
break;
}
}
}
if (lfn->alias_checksum != lfn_checksum) {
/* checksum mismatch */
/* Causes: 1) checksum field here destroyed */
/* Fixes: 1) delete LFN, 2) fix checksum */
printf( "Checksum in long filename part wrong "
"(%02x vs. expected %02x).\n",
lfn->alias_checksum, lfn_checksum );
if (interactive) {
printf( "1: Delete LFN\n2: Leave it as it is.\n"
"3: Correct checksum\n" );
}
else printf( " Not auto-correcting this.\n" );
if (interactive) {
switch( get_key( "123", "?" )) {
case '1':
lfn_offsets[lfn_parts++] = dir_offset;
clear_lfn_slots( 0, lfn_parts-1 );
lfn_reset();
return;
case '2':
break;
case '3':
lfn->alias_checksum = lfn_checksum;
fs_write( dir_offset+offsetof(LFN_ENT,alias_checksum),
sizeof(lfn->alias_checksum), &lfn->alias_checksum );
break;
}
}
}
if (lfn_slot != -1) {
lfn_slot--;
offset = lfn_slot * CHARS_PER_LFN*2;
copy_lfn_part( lfn_unicode+offset, lfn );
if (lfn->id & LFN_ID_START)
lfn_unicode[offset+26] = lfn_unicode[offset+27] = 0;
lfn_offsets[lfn_parts++] = dir_offset;
}
if (lfn->reserved != 0) {
printf( "Reserved field in VFAT long filename slot is not 0 "
"(but 0x%02x).\n", lfn->reserved );
if (interactive)
printf( "1: Fix.\n2: Leave it.\n" );
else printf( "Auto-setting to 0.\n" );
if (!interactive || get_key("12","?") == '1') {
lfn->reserved = 0;
fs_write( dir_offset+offsetof(LFN_ENT,reserved),
sizeof(lfn->reserved), &lfn->reserved );
}
}
if (lfn->start != CT_LE_W(0)) {
printf( "Start cluster field in VFAT long filename slot is not 0 "
"(but 0x%04x).\n", lfn->start );
if (interactive)
printf( "1: Fix.\n2: Leave it.\n" );
else printf( "Auto-setting to 0.\n" );
if (!interactive || get_key("12","?") == '1') {
lfn->start = CT_LE_W(0);
fs_write( dir_offset+offsetof(LFN_ENT,start),
sizeof(lfn->start),&lfn->start );
}
}
}
/* This function is always called when de->attr != VFAT_LN_ATTR is found, to
* retrieve the previously constructed LFN. */
char *lfn_get( DIR_ENT *de )
{
char *lfn;
__u8 sum;
int i;
if (de->attr == VFAT_LN_ATTR)
die("lfn_get called with LFN directory entry");
#if 0
if (de->lcase)
printf( "lcase=%02x\n",de->lcase );
#endif
if (lfn_slot == -1)
/* no long name for this file */
return NULL;
if (lfn_slot != 0) {
/* The long name isn't finished yet. */
/* Causes: 1) LFN slot overwritten by non-VFAT aware tool */
/* Fixes: 1) delete LFN 2) move overwriting entry to somewhere else
* and let user enter missing part of LFN (hard to do :-()
* 3) renumber entries and truncate name */
char *long_name = CNV_PARTS_SO_FAR();
char *short_name = file_name(de->name);
printf( "Unfinished long file name \"%s\".\n"
" (Start may have been overwritten by %s)\n",
long_name, short_name );
free( long_name );
if (interactive) {
printf( "1: Delete LFN\n2: Leave it as it is.\n"
"3: Fix numbering (truncates long name and attaches "
"it to short name %s)\n", short_name );
}
else printf( " Not auto-correcting this.\n" );
if (interactive) {
switch( get_key( "123", "?" )) {
case '1':
clear_lfn_slots( 0, lfn_parts-1 );
lfn_reset();
return NULL;
case '2':
lfn_reset();
return NULL;
case '3':
for( i = 0; i < lfn_parts; ++i ) {
__u8 id = (lfn_parts-i) | (i==0 ? LFN_ID_START : 0);
fs_write( lfn_offsets[i]+offsetof(LFN_ENT,id),
sizeof(id), &id );
}
memmove( lfn_unicode, lfn_unicode+lfn_slot*CHARS_PER_LFN*2,
lfn_parts*CHARS_PER_LFN*2 );
break;
}
}
}
for (sum = 0, i = 0; i < 11; i++)
sum = (((sum&1) << 7) | ((sum&0xfe) >> 1)) + de->name[i];
if (sum != lfn_checksum) {
/* checksum doesn't match, long name doesn't apply to this alias */
/* Causes: 1) alias renamed */
/* Fixes: 1) Fix checksum in LFN entries */
char *long_name = CNV_PARTS_SO_FAR();
char *short_name = file_name(de->name);
printf( "Wrong checksum for long file name \"%s\".\n"
" (Short name %s may have changed without updating the long name)\n",
long_name, short_name );
free( long_name );
if (interactive) {
printf( "1: Delete LFN\n2: Leave it as it is.\n"
"3: Fix checksum (attaches to short name %s)\n",
short_name );
}
else printf( " Not auto-correcting this.\n" );
if (interactive) {
switch( get_key( "123", "?" )) {
case '1':
clear_lfn_slots( 0, lfn_parts-1 );
lfn_reset();
return NULL;
case '2':
lfn_reset();
return NULL;
case '3':
for( i = 0; i < lfn_parts; ++i ) {
fs_write( lfn_offsets[i]+offsetof(LFN_ENT,alias_checksum),
sizeof(sum), &sum );
}
break;
}
}
}
lfn = cnv_unicode( lfn_unicode, UNTIL_0, 1 );
lfn_reset();
return( lfn );
}
void lfn_check_orphaned(void)
{
char *long_name;
if (lfn_slot == -1)
return;
long_name = CNV_PARTS_SO_FAR();
printf("Orphaned long file name part \"%s\"\n", long_name);
if (interactive)
printf( "1: Delete.\n2: Leave it.\n" );
else printf( " Auto-deleting.\n" );
if (!interactive || get_key("12","?") == '1') {
clear_lfn_slots(0, lfn_parts - 1);
}
lfn_reset();
}
/* Local Variables: */
/* tab-width: 8 */
/* End: */

View file

@ -1,20 +0,0 @@
/* lfn.h - Functions for handling VFAT long filenames */
/* Written 1998 by Roman Hodek */
#ifndef _LFN_H
#define _LFN_H
void lfn_reset( void );
/* Reset the state of the LFN parser. */
void lfn_add_slot( DIR_ENT *de, loff_t dir_offset );
/* Process a dir slot that is a VFAT LFN entry. */
char *lfn_get( DIR_ENT *de );
/* Retrieve the long name for the proper dir entry. */
void lfn_check_orphaned(void);
#endif

View file

@ -1,182 +0,0 @@
#ifndef _LINUX_MSDOS_FS_H
#define _LINUX_MSDOS_FS_H
/*
* The MS-DOS filesystem constants/structures
*/
#include "byteorder.h"
#define SECTOR_SIZE 512 /* sector size (bytes) */
#define SECTOR_BITS 9 /* log2(SECTOR_SIZE) */
#define MSDOS_DPB (MSDOS_DPS) /* dir entries per block */
#define MSDOS_DPB_BITS 4 /* log2(MSDOS_DPB) */
#define MSDOS_DPS (SECTOR_SIZE / sizeof(struct msdos_dir_entry))
#define MSDOS_DPS_BITS 4 /* log2(MSDOS_DPS) */
#if 0
#define CF_LE_W(v) le16_to_cpu(v)
#define CF_LE_L(v) le32_to_cpu(v)
#define CT_LE_W(v) cpu_to_le16(v)
#define CT_LE_L(v) cpu_to_le32(v)
#endif
#define MSDOS_SUPER_MAGIC 0x4d44 /* MD */
#define MSDOS_ROOT_INO 1 /* == MINIX_ROOT_INO */
#define MSDOS_DIR_BITS 5 /* log2(sizeof(struct msdos_dir_entry)) */
/* directory limit */
#define FAT_MAX_DIR_ENTRIES (65536)
#define FAT_MAX_DIR_SIZE (FAT_MAX_DIR_ENTRIES << MSDOS_DIR_BITS)
#define ATTR_NONE 0 /* no attribute bits */
#define ATTR_RO 1 /* read-only */
#define ATTR_HIDDEN 2 /* hidden */
#define ATTR_SYS 4 /* system */
#define ATTR_VOLUME 8 /* volume label */
#define ATTR_DIR 16 /* directory */
#define ATTR_ARCH 32 /* archived */
/* attribute bits that are copied "as is" */
#define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN)
/* bits that are used by the Windows 95/Windows NT extended FAT */
#define ATTR_EXT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
#define CASE_LOWER_BASE 8 /* base is lower case */
#define CASE_LOWER_EXT 16 /* extension is lower case */
#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */
#define IS_FREE(n) (!*(n) || *(n) == DELETED_FLAG)
/* valid file mode bits */
#define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)
/* Convert attribute bits and a mask to the UNIX mode. */
#define MSDOS_MKMODE(a, m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO))
#define MSDOS_NAME 11 /* maximum name length */
#define MSDOS_LONGNAME 256 /* maximum name length */
#define MSDOS_SLOTS 21 /* max # of slots for short and long names */
#define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */
#define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */
/* media of boot sector */
#define FAT_VALID_MEDIA(x) ((0xF8 <= (x) && (x) <= 0xFF) || (x) == 0xF0)
#define FAT_FIRST_ENT(s, x) ((MSDOS_SB(s)->fat_bits == 32 ? 0x0FFFFF00 : \
MSDOS_SB(s)->fat_bits == 16 ? 0xFF00 : 0xF00) | (x))
/* start of data cluster's entry (number of reserved clusters) */
#define FAT_START_ENT 2
/* maximum number of clusters */
#define MAX_FAT12 0xFF4
#define MAX_FAT16 0xFFF4
#define MAX_FAT32 0x0FFFFFF6
#define MAX_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? MAX_FAT32 : \
MSDOS_SB(s)->fat_bits == 16 ? MAX_FAT16 : MAX_FAT12)
/* bad cluster mark */
#define BAD_FAT12 0xFF7
#define BAD_FAT16 0xFFF7
#define BAD_FAT32 0x0FFFFFF7
/* standard EOF */
#define EOF_FAT12 0xFFF
#define EOF_FAT16 0xFFFF
#define EOF_FAT32 0x0FFFFFFF
#define FAT_ENT_FREE (0)
#define FAT_ENT_BAD (BAD_FAT32)
#define FAT_ENT_EOF (EOF_FAT32)
#define FAT_FSINFO_SIG1 0x41615252
#define FAT_FSINFO_SIG2 0x61417272
#define IS_FSINFO(x) (le32_to_cpu((x)->signature1) == FAT_FSINFO_SIG1 \
&& le32_to_cpu((x)->signature2) == FAT_FSINFO_SIG2)
/*
* ioctl commands
*/
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
/* <linux/videotext.h> has used 0x72 ('r') in collision, so skip a few */
#define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32)
#define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32)
/*
* vfat shortname flags
*/
#define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */
#define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */
#define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */
#define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */
#define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */
struct fat_boot_sector {
__u8 ignored[3]; /* Boot strap short or near jump */
__u8 system_id[8]; /* Name - can be used to special case
partition manager volumes */
__u8 sector_size[2]; /* bytes per logical sector */
__u8 sec_per_clus; /* sectors/cluster */
__le16 reserved; /* reserved sectors */
__u8 fats; /* number of FATs */
__u8 dir_entries[2]; /* root directory entries */
__u8 sectors[2]; /* number of sectors */
__u8 media; /* media code */
__le16 fat_length; /* sectors/FAT */
__le16 secs_track; /* sectors per track */
__le16 heads; /* number of heads */
__le32 hidden; /* hidden sectors (unused) */
__le32 total_sect; /* number of sectors (if sectors == 0) */
/* The following fields are only used by FAT32 */
__le32 fat32_length; /* sectors/FAT */
__le16 flags; /* bit 8: fat mirroring, low 4: active fat */
__u8 version[2]; /* major, minor filesystem version */
__le32 root_cluster; /* first cluster in root directory */
__le16 info_sector; /* filesystem info sector */
__le16 backup_boot; /* backup boot sector */
__le16 reserved2[6]; /* Unused */
};
struct fat_boot_fsinfo {
__le32 signature1; /* 0x41615252L */
__le32 reserved1[120]; /* Nothing as far as I can tell */
__le32 signature2; /* 0x61417272L */
__le32 free_clusters; /* Free cluster count. -1 if unknown */
__le32 next_cluster; /* Most recently allocated cluster */
__le32 reserved2[4];
};
struct msdos_dir_entry {
__u8 name[8],ext[3]; /* name and extension */
__u8 attr; /* attribute bits */
__u8 lcase; /* Case for base and extension */
__u8 ctime_cs; /* Creation time, centiseconds (0-199) */
__le16 ctime; /* Creation time */
__le16 cdate; /* Creation date */
__le16 adate; /* Last access date */
__le16 starthi; /* High 16 bits of cluster in FAT32 */
__le16 time,date,start;/* time, date and first cluster */
__le32 size; /* file size (in bytes) */
};
/* Up to 13 characters of the name */
struct msdos_dir_slot {
__u8 id; /* sequence number for slot */
__u8 name0_4[10]; /* first 5 characters in name */
__u8 attr; /* attribute byte */
__u8 reserved; /* always 0 */
__u8 alias_checksum; /* checksum for 8.3 alias */
__u8 name5_10[12]; /* 6 more characters in name */
__le16 start; /* starting cluster number, 0 in long slots */
__u8 name11_12[4]; /* last 2 characters in name */
};
struct fat_slot_info {
loff_t i_pos; /* on-disk position of directory entry */
loff_t slot_off; /* offset for slot or de start */
int nr_slots; /* number of slots + 1(de) in filename */
struct msdos_dir_entry *de;
struct buffer_head *bh;
};
#endif

View file

@ -1,192 +0,0 @@
#ifndef _LINUX_BYTEORDER_SWAB_H
#define _LINUX_BYTEORDER_SWAB_H
/*
* linux/byteorder/swab.h
* Byte-swapping, independently from CPU endianness
* swabXX[ps]?(foo)
*
* Francois-Rene Rideau <fare@tunes.org> 19971205
* separated swab functions from cpu_to_XX,
* to clean up support for bizarre-endian architectures.
*
* See asm-i386/byteorder.h and suches for examples of how to provide
* architecture-dependent optimized versions
*
*/
#include "compiler.h"
/* casts are necessary for constants, because we never know how for sure
* how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way.
*/
#define ___swab16(x) \
({ \
__u16 __x = (x); \
((__u16)( \
(((__u16)(__x) & (__u16)0x00ffU) << 8) | \
(((__u16)(__x) & (__u16)0xff00U) >> 8) )); \
})
#define ___swab32(x) \
({ \
__u32 __x = (x); \
((__u32)( \
(((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \
(((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | \
(((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | \
(((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \
})
#define ___swab64(x) \
({ \
__u64 __x = (x); \
((__u64)( \
(__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \
(__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \
(__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \
(__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \
(__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \
(__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
(__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \
(__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \
})
#define ___constant_swab16(x) \
((__u16)( \
(((__u16)(x) & (__u16)0x00ffU) << 8) | \
(((__u16)(x) & (__u16)0xff00U) >> 8) ))
#define ___constant_swab32(x) \
((__u32)( \
(((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
(((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \
(((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \
(((__u32)(x) & (__u32)0xff000000UL) >> 24) ))
#define ___constant_swab64(x) \
((__u64)( \
(__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \
(__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \
(__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \
(__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \
(__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \
(__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
(__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \
(__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) ))
/*
* provide defaults when no architecture-specific optimization is detected
*/
#ifndef __arch__swab16
# define __arch__swab16(x) ({ __u16 __tmp = (x) ; ___swab16(__tmp); })
#endif
#ifndef __arch__swab32
# define __arch__swab32(x) ({ __u32 __tmp = (x) ; ___swab32(__tmp); })
#endif
#ifndef __arch__swab64
# define __arch__swab64(x) ({ __u64 __tmp = (x) ; ___swab64(__tmp); })
#endif
#ifndef __arch__swab16p
# define __arch__swab16p(x) __arch__swab16(*(x))
#endif
#ifndef __arch__swab32p
# define __arch__swab32p(x) __arch__swab32(*(x))
#endif
#ifndef __arch__swab64p
# define __arch__swab64p(x) __arch__swab64(*(x))
#endif
#ifndef __arch__swab16s
# define __arch__swab16s(x) do { *(x) = __arch__swab16p((x)); } while (0)
#endif
#ifndef __arch__swab32s
# define __arch__swab32s(x) do { *(x) = __arch__swab32p((x)); } while (0)
#endif
#ifndef __arch__swab64s
# define __arch__swab64s(x) do { *(x) = __arch__swab64p((x)); } while (0)
#endif
/*
* Allow constant folding
*/
#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
# define __swab16(x) \
(__builtin_constant_p((__u16)(x)) ? \
___swab16((x)) : \
__fswab16((x)))
# define __swab32(x) \
(__builtin_constant_p((__u32)(x)) ? \
___swab32((x)) : \
__fswab32((x)))
# define __swab64(x) \
(__builtin_constant_p((__u64)(x)) ? \
___swab64((x)) : \
__fswab64((x)))
#else
# define __swab16(x) __fswab16(x)
# define __swab32(x) __fswab32(x)
# define __swab64(x) __fswab64(x)
#endif /* OPTIMIZE */
static __inline__ __attribute_const__ __u16 __fswab16(__u16 x)
{
return __arch__swab16(x);
}
static __inline__ __u16 __swab16p(const __u16 *x)
{
return __arch__swab16p(x);
}
static __inline__ void __swab16s(__u16 *addr)
{
__arch__swab16s(addr);
}
static __inline__ __attribute_const__ __u32 __fswab32(__u32 x)
{
return __arch__swab32(x);
}
static __inline__ __u32 __swab32p(const __u32 *x)
{
return __arch__swab32p(x);
}
static __inline__ void __swab32s(__u32 *addr)
{
__arch__swab32s(addr);
}
#ifdef __BYTEORDER_HAS_U64__
static __inline__ __attribute_const__ __u64 __fswab64(__u64 x)
{
# ifdef __SWAB_64_THRU_32__
__u32 h = x >> 32;
__u32 l = x & ((1ULL<<32)-1);
return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h)));
# else
return __arch__swab64(x);
# endif
}
static __inline__ __u64 __swab64p(const __u64 *x)
{
return __arch__swab64p(x);
}
static __inline__ void __swab64s(__u64 *addr)
{
__arch__swab64s(addr);
}
#endif /* __BYTEORDER_HAS_U64__ */
#if defined(__KERNEL__)
#define swab16 __swab16
#define swab32 __swab32
#define swab64 __swab64
#define swab16p __swab16p
#define swab32p __swab32p
#define swab64p __swab64p
#define swab16s __swab16s
#define swab32s __swab32s
#define swab64s __swab64s
#endif
#endif /* _LINUX_BYTEORDER_SWAB_H */

View file

@ -1,8 +0,0 @@
#ifndef _version_h
#define _version_h
#define VERSION "2.8"
#define VERSION_DATE "28 Feb 2001"
#endif /* _version_h */

View file

@ -1,744 +0,0 @@
/* $Id: vfat.h 16656 2005-07-20 02:52:52Z ion $ */
#include <ddk/ntifs.h>
#include <ddk/ntdddisk.h>
#include <ndk/ntndk.h>
#include <reactos/helper.h>
#include <ccros.h>
#include <limits.h>
#include <debug.h>
#define USE_ROS_CC_AND_FS
#include <pshpack1.h>
struct _BootSector
{
unsigned char magic0, res0, magic1;
unsigned char OEMName[8];
unsigned short BytesPerSector;
unsigned char SectorsPerCluster;
unsigned short ReservedSectors;
unsigned char FATCount;
unsigned short RootEntries, Sectors;
unsigned char Media;
unsigned short FATSectors, SectorsPerTrack, Heads;
unsigned long HiddenSectors, SectorsHuge;
unsigned char Drive, Res1, Sig;
unsigned long VolumeID;
unsigned char VolumeLabel[11], SysType[8];
unsigned char Res2[448];
unsigned short Signatur1;
};
struct _BootSector32
{
unsigned char magic0, res0, magic1; // 0
unsigned char OEMName[8]; // 3
unsigned short BytesPerSector; // 11
unsigned char SectorsPerCluster; // 13
unsigned short ReservedSectors; // 14
unsigned char FATCount; // 16
unsigned short RootEntries, Sectors; // 17
unsigned char Media; // 21
unsigned short FATSectors, SectorsPerTrack, Heads; // 22
unsigned long HiddenSectors, SectorsHuge; // 28
unsigned long FATSectors32; // 36
unsigned short ExtFlag; // 40
unsigned short FSVersion; // 42
unsigned long RootCluster; // 44
unsigned short FSInfoSector; // 48
unsigned short BootBackup; // 50
unsigned char Res3[12]; // 52
unsigned char Drive; // 64
unsigned char Res4; // 65
unsigned char ExtBootSignature; // 66
unsigned long VolumeID; // 67
unsigned char VolumeLabel[11], SysType[8]; // 71
unsigned char Res2[420]; // 90
unsigned short Signature1; // 510
};
struct _BootSectorFatX
{
unsigned char SysType[4]; // 0
unsigned long VolumeID; // 4
unsigned long SectorsPerCluster; // 8
unsigned short FATCount; // 12
unsigned long Unknown; // 14
unsigned char Unused[4078]; // 18
};
struct _FsInfoSector
{
unsigned long ExtBootSignature2; // 0
unsigned char Res6[480]; // 4
unsigned long FSINFOSignature; // 484
unsigned long FreeCluster; // 488
unsigned long NextCluster; // 492
unsigned char Res7[12]; // 496
unsigned long Signatur2; // 508
};
typedef struct _BootSector BootSector;
struct _FATDirEntry
{
union
{
struct { unsigned char Filename[8], Ext[3]; };
unsigned char ShortName[11];
};
unsigned char Attrib;
unsigned char lCase;
unsigned char CreationTimeMs;
unsigned short CreationTime,CreationDate,AccessDate;
unsigned short FirstClusterHigh; // higher
unsigned short UpdateTime; //time create/update
unsigned short UpdateDate; //date create/update
unsigned short FirstCluster;
unsigned long FileSize;
};
typedef struct _FATDirEntry FAT_DIR_ENTRY, *PFAT_DIR_ENTRY;
struct _FATXDirEntry
{
unsigned char FilenameLength; // 0
unsigned char Attrib; // 1
unsigned char Filename[42]; // 2
unsigned long FirstCluster; // 44
unsigned long FileSize; // 48
unsigned short UpdateTime; // 52
unsigned short UpdateDate; // 54
unsigned short CreationTime; // 56
unsigned short CreationDate; // 58
unsigned short AccessTime; // 60
unsigned short AccessDate; // 62
};
struct _slot
{
unsigned char id; // sequence number for slot
WCHAR name0_4[5]; // first 5 characters in name
unsigned char attr; // attribute byte
unsigned char reserved; // always 0
unsigned char alias_checksum; // checksum for 8.3 alias
WCHAR name5_10[6]; // 6 more characters in name
unsigned char start[2]; // starting cluster number
WCHAR name11_12[2]; // last 2 characters in name
};
typedef struct _slot slot;
#include <poppack.h>
#define VFAT_CASE_LOWER_BASE 8 // base is lower case
#define VFAT_CASE_LOWER_EXT 16 // extension is lower case
#define LONGNAME_MAX_LENGTH 256 // max length for a long filename
#define ENTRY_DELETED(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_DELETED(&((DirEntry)->FatX)) : FAT_ENTRY_DELETED(&((DirEntry)->Fat)))
#define ENTRY_VOLUME(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat)))
#define ENTRY_END(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_END(&((DirEntry)->FatX)) : FAT_ENTRY_END(&((DirEntry)->Fat)))
#define FAT_ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5)
#define FAT_ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
#define FAT_ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)
#define FAT_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
#define FATX_ENTRY_DELETED(DirEntry) ((DirEntry)->FilenameLength == 0xe5)
#define FATX_ENTRY_END(DirEntry) ((DirEntry)->FilenameLength == 0xff)
#define FATX_ENTRY_LONG(DirEntry) (FALSE)
#define FATX_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
#define FAT_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FAT_DIR_ENTRY))
#define FATX_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATX_DIR_ENTRY))
typedef struct _FATXDirEntry FATX_DIR_ENTRY, *PFATX_DIR_ENTRY;
union _DIR_ENTRY
{
FAT_DIR_ENTRY Fat;
FATX_DIR_ENTRY FatX;
};
typedef union _DIR_ENTRY DIR_ENTRY, *PDIR_ENTRY;
#define BLOCKSIZE 512
#define FAT16 (1)
#define FAT12 (2)
#define FAT32 (3)
#define FATX16 (4)
#define FATX32 (5)
#define VCB_VOLUME_LOCKED 0x0001
#define VCB_DISMOUNT_PENDING 0x0002
#define VCB_IS_FATX 0x0004
#define VCB_IS_DIRTY 0x4000 /* Volume is dirty */
#define VCB_CLEAR_DIRTY 0x8000 /* Clean dirty flag at shutdown */
typedef struct
{
ULONG VolumeID;
ULONG FATStart;
ULONG FATCount;
ULONG FATSectors;
ULONG rootDirectorySectors;
ULONG rootStart;
ULONG dataStart;
ULONG RootCluster;
ULONG SectorsPerCluster;
ULONG BytesPerSector;
ULONG BytesPerCluster;
ULONG NumberOfClusters;
ULONG FatType;
ULONG Sectors;
BOOLEAN FixedMedia;
} FATINFO, *PFATINFO;
struct _VFATFCB;
struct _VFAT_DIRENTRY_CONTEXT;
typedef struct _HASHENTRY
{
ULONG Hash;
struct _VFATFCB* self;
struct _HASHENTRY* next;
}
HASHENTRY;
#define FCB_HASH_TABLE_SIZE 65536
typedef struct DEVICE_EXTENSION *PDEVICE_EXTENSION;
typedef NTSTATUS (*PGET_NEXT_CLUSTER)(PDEVICE_EXTENSION,ULONG,PULONG);
typedef NTSTATUS (*PFIND_AND_MARK_AVAILABLE_CLUSTER)(PDEVICE_EXTENSION,PULONG);
typedef NTSTATUS (*PWRITE_CLUSTER)(PDEVICE_EXTENSION,ULONG,ULONG,PULONG);
typedef NTSTATUS (*PGET_NEXT_DIR_ENTRY)(PVOID*,PVOID*,struct _VFATFCB*,struct _VFAT_DIRENTRY_CONTEXT*,BOOLEAN);
typedef struct DEVICE_EXTENSION
{
ERESOURCE DirResource;
ERESOURCE FatResource;
KSPIN_LOCK FcbListLock;
LIST_ENTRY FcbListHead;
ULONG HashTableSize;
struct _HASHENTRY** FcbHashTable;
PDEVICE_OBJECT StorageDevice;
PFILE_OBJECT FATFileObject;
FATINFO FatInfo;
ULONG LastAvailableCluster;
ULONG AvailableClusters;
BOOLEAN AvailableClustersValid;
ULONG Flags;
struct _VFATFCB * VolumeFcb;
/* Pointers to functions for manipulating FAT. */
PGET_NEXT_CLUSTER GetNextCluster;
PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster;
PWRITE_CLUSTER WriteCluster;
ULONG CleanShutBitMask;
/* Pointers to functions for manipulating directory entries. */
PGET_NEXT_DIR_ENTRY GetNextDirEntry;
ULONG BaseDateYear;
LIST_ENTRY VolumeListEntry;
} DEVICE_EXTENSION, VCB, *PVCB;
typedef struct
{
PDRIVER_OBJECT DriverObject;
PDEVICE_OBJECT DeviceObject;
ULONG Flags;
ERESOURCE VolumeListLock;
LIST_ENTRY VolumeListHead;
NPAGED_LOOKASIDE_LIST FcbLookasideList;
NPAGED_LOOKASIDE_LIST CcbLookasideList;
NPAGED_LOOKASIDE_LIST IrpContextLookasideList;
FAST_IO_DISPATCH FastIoDispatch;
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks;
} VFAT_GLOBAL_DATA, *PVFAT_GLOBAL_DATA;
extern PVFAT_GLOBAL_DATA VfatGlobalData;
#define FCB_CACHE_INITIALIZED 0x0001
#define FCB_DELETE_PENDING 0x0002
#define FCB_IS_FAT 0x0004
#define FCB_IS_PAGE_FILE 0x0008
#define FCB_IS_VOLUME 0x0010
#define FCB_IS_DIRTY 0x0020
#define FCB_IS_FATX_ENTRY 0x0040
typedef struct _VFATFCB
{
/* FCB header required by ROS/NT */
FSRTL_COMMON_FCB_HEADER RFCB;
SECTION_OBJECT_POINTERS SectionObjectPointers;
ERESOURCE MainResource;
ERESOURCE PagingIoResource;
/* end FCB header required by ROS/NT */
/* directory entry for this file or directory */
DIR_ENTRY entry;
/* Pointer to attributes in entry */
PUCHAR Attributes;
/* long file name, points into PathNameBuffer */
UNICODE_STRING LongNameU;
/* short file name */
UNICODE_STRING ShortNameU;
/* directory name, points into PathNameBuffer */
UNICODE_STRING DirNameU;
/* path + long file name 260 max*/
UNICODE_STRING PathNameU;
/* buffer for PathNameU */
PWCHAR PathNameBuffer;
/* buffer for ShortNameU */
WCHAR ShortNameBuffer[13];
/* */
LONG RefCount;
/* List of FCB's for this volume */
LIST_ENTRY FcbListEntry;
/* pointer to the parent fcb */
struct _VFATFCB* parentFcb;
/* Flags for the fcb */
ULONG Flags;
/* pointer to the file object which has initialized the fcb */
PFILE_OBJECT FileObject;
/* Directory index for the short name entry */
ULONG dirIndex;
/* Directory index where the long name starts */
ULONG startIndex;
/* Share access for the file object */
SHARE_ACCESS FCBShareAccess;
/* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP */
ULONG OpenHandleCount;
/* Entry into the hash table for the path + long name */
HASHENTRY Hash;
/* Entry into the hash table for the path + short name */
HASHENTRY ShortHash;
/* List of byte-range locks for this file */
FILE_LOCK FileLock;
/*
* Optimalization: caching of last read/write cluster+offset pair. Can't
* be in VFATCCB because it must be reset everytime the allocated clusters
* change.
*/
FAST_MUTEX LastMutex;
ULONG LastCluster;
ULONG LastOffset;
} VFATFCB, *PVFATFCB;
typedef struct _VFATCCB
{
LARGE_INTEGER CurrentByteOffset;
/* for DirectoryControl */
ULONG Entry;
/* for DirectoryControl */
UNICODE_STRING SearchPattern;
} VFATCCB, *PVFATCCB;
#ifndef TAG
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
#endif
#define TAG_CCB TAG('V', 'C', 'C', 'B')
#define TAG_FCB TAG('V', 'F', 'C', 'B')
#define TAG_IRP TAG('V', 'I', 'R', 'P')
#define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry))
typedef struct __DOSTIME
{
USHORT Second:5;
USHORT Minute:6;
USHORT Hour:5;
}
DOSTIME, *PDOSTIME;
typedef struct __DOSDATE
{
USHORT Day:5;
USHORT Month:4;
USHORT Year:5;
}
DOSDATE, *PDOSDATE;
#define IRPCONTEXT_CANWAIT 0x0001
#define IRPCONTEXT_PENDINGRETURNED 0x0002
typedef struct
{
PIRP Irp;
PDEVICE_OBJECT DeviceObject;
PDEVICE_EXTENSION DeviceExt;
ULONG Flags;
WORK_QUEUE_ITEM WorkQueueItem;
PIO_STACK_LOCATION Stack;
UCHAR MajorFunction;
UCHAR MinorFunction;
PFILE_OBJECT FileObject;
ULONG RefCount;
KEVENT Event;
} VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT;
typedef struct _VFAT_DIRENTRY_CONTEXT
{
ULONG StartIndex;
ULONG DirIndex;
DIR_ENTRY DirEntry;
UNICODE_STRING LongNameU;
UNICODE_STRING ShortNameU;
} VFAT_DIRENTRY_CONTEXT, *PVFAT_DIRENTRY_CONTEXT;
/* ------------------------------------------------------ shutdown.c */
NTSTATUS STDCALL VfatShutdown (PDEVICE_OBJECT DeviceObject,
PIRP Irp);
/* -------------------------------------------------------- volume.c */
NTSTATUS VfatQueryVolumeInformation (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS VfatSetVolumeInformation (PVFAT_IRP_CONTEXT IrpContext);
/* ------------------------------------------------------ blockdev.c */
NTSTATUS VfatReadDisk(IN PDEVICE_OBJECT pDeviceObject,
IN PLARGE_INTEGER ReadOffset,
IN ULONG ReadLength,
IN PUCHAR Buffer,
IN BOOLEAN Override);
NTSTATUS VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext,
IN PLARGE_INTEGER ReadOffset,
IN ULONG ReadLength,
IN ULONG BufferOffset,
IN BOOLEAN Wait);
NTSTATUS VfatWriteDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext,
IN PLARGE_INTEGER WriteOffset,
IN ULONG WriteLength,
IN ULONG BufferOffset,
IN BOOLEAN Wait);
NTSTATUS VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject,
IN ULONG CtlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferSize,
IN OUT PVOID OutputBuffer,
IN OUT PULONG pOutputBufferSize,
IN BOOLEAN Override);
/* ----------------------------------------------------------- dir.c */
NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT);
BOOLEAN FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt,
USHORT DosDate,
USHORT DosTime,
PLARGE_INTEGER SystemTime);
BOOLEAN FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt,
PLARGE_INTEGER SystemTime,
USHORT *pDosDate,
USHORT *pDosTime);
/* -------------------------------------------------------- create.c */
NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS VfatOpenFile (PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject,
PVFATFCB* parentFcb);
NTSTATUS FindFile (PDEVICE_EXTENSION DeviceExt,
PVFATFCB Parent,
PUNICODE_STRING FileToFindU,
PVFAT_DIRENTRY_CONTEXT DirContext,
BOOLEAN First);
VOID vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry,
PUNICODE_STRING NameU);
NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt,
PVPB Vpb);
/* --------------------------------------------------------- close.c */
NTSTATUS VfatClose (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS VfatCloseFile(PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject);
/* ------------------------------------------------------- cleanup.c */
NTSTATUS VfatCleanup (PVFAT_IRP_CONTEXT IrpContext);
/* --------------------------------------------------------- fastio.c */
VOID
VfatInitFastIoRoutines(PFAST_IO_DISPATCH FastIoDispatch);
BOOLEAN NTAPI
VfatAcquireForLazyWrite(IN PVOID Context,
IN BOOLEAN Wait);
VOID NTAPI
VfatReleaseFromLazyWrite(IN PVOID Context);
BOOLEAN NTAPI
VfatAcquireForReadAhead(IN PVOID Context,
IN BOOLEAN Wait);
VOID NTAPI
VfatReleaseFromReadAhead(IN PVOID Context);
/* --------------------------------------------------------- fsctl.c */
NTSTATUS VfatFileSystemControl (PVFAT_IRP_CONTEXT IrpContext);
/* --------------------------------------------------------- finfo.c */
NTSTATUS VfatQueryInformation (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS VfatSetInformation (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS
VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
PVFATFCB Fcb,
PDEVICE_EXTENSION DeviceExt,
PLARGE_INTEGER AllocationSize);
/* --------------------------------------------------------- iface.c */
NTSTATUS STDCALL DriverEntry (PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath);
/* --------------------------------------------------------- dirwr.c */
NTSTATUS VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
PUNICODE_STRING PathNameU,
PVFATFCB* Fcb,
PVFATFCB ParentFcb,
ULONG RequestedOptions,
UCHAR ReqAttr);
NTSTATUS VfatUpdateEntry (PVFATFCB pFcb);
NTSTATUS VfatDelEntry(PDEVICE_EXTENSION, PVFATFCB);
BOOLEAN
vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt,
PVFATFCB pDirFcb,
ULONG nbSlots,
PULONG start);
/* -------------------------------------------------------- string.c */
VOID
vfatSplitPathName(PUNICODE_STRING PathNameU,
PUNICODE_STRING DirNameU,
PUNICODE_STRING FileNameU);
BOOLEAN vfatIsLongIllegal(WCHAR c);
BOOLEAN wstrcmpjoki (PWSTR s1,
PWSTR s2);
/* ----------------------------------------------------------- fat.c */
NTSTATUS FAT12GetNextCluster(PDEVICE_EXTENSION DeviceExt,
ULONG CurrentCluster,
PULONG NextCluster);
NTSTATUS FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt,
PULONG Cluster);
NTSTATUS FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt,
ULONG ClusterToWrite,
ULONG NewValue,
PULONG OldValue);
NTSTATUS FAT16GetNextCluster(PDEVICE_EXTENSION DeviceExt,
ULONG CurrentCluster,
PULONG NextCluster);
NTSTATUS FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt,
PULONG Cluster);
NTSTATUS FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt,
ULONG ClusterToWrite,
ULONG NewValue,
PULONG OldValue);
NTSTATUS FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt,
ULONG CurrentCluster,
PULONG NextCluster);
NTSTATUS FAT32FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt,
PULONG Cluster);
NTSTATUS FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt,
ULONG ClusterToWrite,
ULONG NewValue,
PULONG OldValue);
NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt,
ULONG FirstCluster,
ULONG FileOffset,
PULONG Cluster,
BOOLEAN Extend);
ULONGLONG ClusterToSector (PDEVICE_EXTENSION DeviceExt,
ULONG Cluster);
NTSTATUS GetNextCluster (PDEVICE_EXTENSION DeviceExt,
ULONG CurrentCluster,
PULONG NextCluster);
NTSTATUS GetNextClusterExtend (PDEVICE_EXTENSION DeviceExt,
ULONG CurrentCluster,
PULONG NextCluster);
NTSTATUS CountAvailableClusters (PDEVICE_EXTENSION DeviceExt,
PLARGE_INTEGER Clusters);
NTSTATUS
WriteCluster(PDEVICE_EXTENSION DeviceExt,
ULONG ClusterToWrite,
ULONG NewValue);
/* ------------------------------------------------------ direntry.c */
ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
PDIR_ENTRY pDirEntry);
BOOLEAN VfatIsDirectoryEmpty(PVFATFCB Fcb);
NTSTATUS FATGetNextDirEntry(PVOID * pContext,
PVOID * pPage,
IN PVFATFCB pDirFcb,
IN PVFAT_DIRENTRY_CONTEXT DirContext,
BOOLEAN First);
NTSTATUS FATXGetNextDirEntry(PVOID * pContext,
PVOID * pPage,
IN PVFATFCB pDirFcb,
IN PVFAT_DIRENTRY_CONTEXT DirContext,
BOOLEAN First);
/* ----------------------------------------------------------- fcb.c */
PVFATFCB vfatNewFCB (PDEVICE_EXTENSION pVCB,
PUNICODE_STRING pFileNameU);
VOID vfatDestroyFCB (PVFATFCB pFCB);
VOID vfatDestroyCCB(PVFATCCB pCcb);
VOID vfatGrabFCB (PDEVICE_EXTENSION pVCB,
PVFATFCB pFCB);
VOID vfatReleaseFCB (PDEVICE_EXTENSION pVCB,
PVFATFCB pFCB);
VOID vfatAddFCBToTable (PDEVICE_EXTENSION pVCB,
PVFATFCB pFCB);
PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt,
PUNICODE_STRING pFileNameU);
PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB);
PVFATFCB vfatOpenRootFCB (PDEVICE_EXTENSION pVCB);
BOOLEAN vfatFCBIsDirectory (PVFATFCB FCB);
BOOLEAN vfatFCBIsRoot(PVFATFCB FCB);
NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
PVFATFCB fcb,
PFILE_OBJECT fileObject);
NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB,
PVFATFCB parentFCB,
PUNICODE_STRING FileToFindU,
PVFATFCB * fileFCB);
NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
PVFATFCB *pParentFCB,
PVFATFCB *pFCB,
PUNICODE_STRING pFileNameU);
NTSTATUS vfatMakeFCBFromDirEntry (PVCB vcb,
PVFATFCB directoryFCB,
PVFAT_DIRENTRY_CONTEXT DirContext,
PVFATFCB * fileFCB);
/* ------------------------------------------------------------ rw.c */
NTSTATUS VfatRead (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt,
ULONG FirstCluster,
PULONG CurrentCluster,
BOOLEAN Extend);
/* ----------------------------------------------------------- misc.c */
NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext);
PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject,
PIRP Irp);
VOID VfatFreeIrpContext(PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS STDCALL VfatBuildRequest (PDEVICE_OBJECT DeviceObject,
PIRP Irp);
PVOID VfatGetUserBuffer(IN PIRP);
NTSTATUS VfatLockUserBuffer(IN PIRP, IN ULONG,
IN LOCK_OPERATION);
NTSTATUS
VfatSetExtendedAttributes(PFILE_OBJECT FileObject,
PVOID Ea,
ULONG EaLength);
/* ------------------------------------------------------------- flush.c */
NTSTATUS VfatFlush(PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb);
/* EOF */

View file

@ -12,10 +12,6 @@
<xi:include href="chklib/chklib.rbuild" />
</directory>
<directory name="dosfsck">
<xi:include href="dosfsck/dosfsck.rbuild" />
</directory>
<directory name="gettype">
<xi:include href="gettype/gettype.rbuild" />
</directory>