mirror of
https://github.com/gryf/ADFlib.git
synced 2026-02-07 08:45:55 +01:00
Initial import
This commit is contained in:
13
AUTHORS
Normal file
13
AUTHORS
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
The main developper is
|
||||
Laurent Clévy (laurent.clevy@club-internet.fr)
|
||||
|
||||
Contributors are:
|
||||
Bjarne Viksoe
|
||||
(C++ wrapper, lot of bug fixes)
|
||||
Gary Harris
|
||||
(bug fixes and W32 support)
|
||||
Dan Sutherland
|
||||
(bug fixes and W32 support)
|
||||
|
||||
See CHANGES.txt for detailed contributions.
|
||||
339
COPYING
Normal file
339
COPYING
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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) <year> <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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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 Lesser General
|
||||
Public License instead of this License.
|
||||
101
ChangeLog
Normal file
101
ChangeLog
Normal file
@@ -0,0 +1,101 @@
|
||||
20MAR08
|
||||
ADFlib 0.7.12
|
||||
- use GNU autotools build system
|
||||
- fix building on 64bit architectures but needs C99 compliant compliler
|
||||
- remove some windows specific stuff maybe one should add it again updating it
|
||||
to use the current directory structure
|
||||
20JAN07
|
||||
ADFlib 0.7.11a
|
||||
- Minor Makefile fixes. Works under Fedora Core 5, gcc 4.1.0.
|
||||
- Inclusing of Bjarke Viksoe C++ wrapper (adfwrapper.h). Windows specific for the moment,
|
||||
but good example of C++ wrapper on top of ADFlib.
|
||||
- Inclusion of GPL license and text inside every code source file
|
||||
(requested by Gürkan Sengün to build a Debian package for unadf)
|
||||
|
||||
31MAR06
|
||||
ADFlib 0.7.11
|
||||
Minor Makefile and compilation process changes to work under cygwin and with gcc 3.4.4.
|
||||
|
||||
16OCT02
|
||||
ADFlib 0.7.9d by Gary Harris
|
||||
- changes all occurences of // foo, into /* foo */
|
||||
- updated "Copyright Laurent Clevy" message date up to 2002 intead of 1999
|
||||
- marked all Bjarke changes by the /* BV */ comment
|
||||
|
||||
22JAN01
|
||||
ADFlib 0.7.9c by Bjarke Viksoe
|
||||
- changes : Win32/nt4_dev.c
|
||||
.return RC_ERROR instead of FALSE
|
||||
.return TRUE when input parameter of NT4CloseDrive is NULL
|
||||
- changes : Win32/defendian.h
|
||||
changes printf and putchar into -empty string- for Win32 GUI applications
|
||||
- fix : in adf_hd.c, in adfMountDev(), dumpfiledevice was assumed sometimes, but it could be native.
|
||||
"if (dev->isNativeDev)" when needed
|
||||
- fix : in adf_hd.c, in adfMountDev(), some memory release was forgotten in case of error
|
||||
- change : adf_hd.c, line 36, floppy dump files with 83 sectors are now valid (request by users)
|
||||
- change : adf_hd.c , adfReadRDSKBlock(), ignore checksum error. Win98 modifies this sector
|
||||
|
||||
10SEP00
|
||||
- ADFlib 0.7.9b refixes and Win32 code improvements by Gary Harris
|
||||
27FEB00
|
||||
- ADFlib 0.7.9a bug with hardfiles fixed some months ago by Dan Sutherland
|
||||
05SEP99
|
||||
- ADFlib 0.7.9 released. Docs updated.
|
||||
15AUG99
|
||||
- fix: bug in adfGetHashValue() : must use unsigned char...
|
||||
- unadf 1.0 : with multiple files and recursive extraction, pipe redirection
|
||||
01AUG99
|
||||
- adfGetDelEnt(), adfUndelEntry(), adfCheckEntry()
|
||||
??JUN99
|
||||
- fix: forgot the secType for the cache entry in adfCreateDir()
|
||||
- fix: adfRemoveEntry() with a dir did not remove the related cache blocks
|
||||
26MAY99
|
||||
- 0.7.8a released.
|
||||
- a minor buf was detected in the bootblock checksum checking
|
||||
24MAY99
|
||||
- 0.7.8 released. the 0.7.9 will have some links support. the next unadf version will have extraction (-x).
|
||||
- Win32 dynamic library makefile added
|
||||
- test scripts floppy.sh and bigdev.sh added
|
||||
- small bug fix in adfGetRDirEnt().
|
||||
20MAY99
|
||||
- the ENV_DECLARATION is put in the library (adf_env.c), and must be removed from the main() files.
|
||||
Will be consistent will the .dll version.
|
||||
- unadf.c started : a unzip like utility for the .ADF files. Extraction not provided yet.
|
||||
- adfGetRDirEnt() added, adfFreeDirList() modified : to get recursively the entire directories entries tree.
|
||||
13MAY99
|
||||
- adfSetEntryAccess() and adfSetEntryComment() added
|
||||
- Win32 makefile added for the static library form
|
||||
06MAY99
|
||||
- adfGetVersionNumber() and adfGetVersionDate() added
|
||||
01MAY99
|
||||
- many date and time fields filled
|
||||
- bug fix in adfCreateDir()
|
||||
- adfRenameEntry() already worked with two differents dirs, but it's verified now
|
||||
29APR
|
||||
- Hardfile support added (requested by Dan Sutherland)
|
||||
19APR
|
||||
- bug fix in cache routines
|
||||
- adfRenameEntry() works in the same directory, only
|
||||
6APR99
|
||||
- bug fix in adfWriteBootBlock() : disks can really be made bootable
|
||||
- bug fix around adfCreateDumpDevice()
|
||||
22MAR99
|
||||
- removed the fread() bug : fopen(,"rb")
|
||||
- removed the LSEG checking
|
||||
01FEB99
|
||||
- adfFlushFile()
|
||||
- dir cache support for files and directories
|
||||
- bugfix : adfCloseFile() when filesize==0
|
||||
- bugfix : parent field in file header block
|
||||
28JAN99
|
||||
- safier and proper error handling
|
||||
27JAN99
|
||||
- bugfix : adfGetFreeBlocks(), physical and logical block numbers confused
|
||||
24JAN99
|
||||
- adfRemoveEntry() : delete files and empty directories
|
||||
- modified Makefile : remplace links for Linux/ and
|
||||
adf_nativ.h with gcc flags -I. -I..
|
||||
19JAN99
|
||||
- Remove most of signed/unsigned warning from MSVC
|
||||
- Error handling : test exe
|
||||
- Read only support
|
||||
8
Makefile.am
Normal file
8
Makefile.am
Normal file
@@ -0,0 +1,8 @@
|
||||
SUBDIRS = src doc
|
||||
if EXAMPLES
|
||||
SUBDIRS += examples
|
||||
endif
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = adflib.pc
|
||||
|
||||
146
README
Normal file
146
README
Normal file
@@ -0,0 +1,146 @@
|
||||
|
||||
|
||||
The ADFlib is a free, portable and open implementation of the Amiga filesystem.
|
||||
|
||||
It supports :
|
||||
- floppy dumps
|
||||
- multiple partitions harddisk dumps
|
||||
- UAE hardfiles
|
||||
- WinNT devices with the 'native driver' written by Dan Sutherland
|
||||
- mount/unmount/create a device (real one or a dump file),
|
||||
- mount/unmount/create a volume (partition),
|
||||
- create/open/close/delete/rename/undel a file,
|
||||
- read/write bytes from/to a file,
|
||||
- create/delete/rename/move/undel a directory,
|
||||
- get directory contents, change current directory, get parent directory
|
||||
- use dir cache to get directory contents.
|
||||
|
||||
|
||||
It is written in portable C, and support the WinNT platform to access
|
||||
real drives.
|
||||
|
||||
---
|
||||
|
||||
unADF is a unzip like for .ADF files :
|
||||
|
||||
|
||||
unadf [-lrcsp -v n] dumpname.adf [files-with-path] [-d extractdir]
|
||||
-l : lists root directory contents
|
||||
-r : lists directory tree contents
|
||||
-c : use dircache data (must be used with -l)
|
||||
-s : display entries logical block pointer (must be used with -l)
|
||||
|
||||
-v n : mount volume #n instead of default #0 volume
|
||||
|
||||
-p : send extracted files to pipe (unadf -p dump.adf Pics/pic1.gif | xv -)
|
||||
-d dir : extract to 'dir' directory
|
||||
|
||||
|
||||
|
||||
Credits:
|
||||
--------
|
||||
|
||||
main design and code Laurent Clevy
|
||||
Bug fixes and C++ wrapper Bjarke Viksoe (adfwrapper.h)
|
||||
WinNT native driver Dan Sutherland and Gary Harris
|
||||
|
||||
|
||||
New versions and contact e-mail can be found at :
|
||||
|
||||
http://lclevy.free.fr/adflib
|
||||
|
||||
|
||||
|
||||
COMPILATION
|
||||
-----------
|
||||
|
||||
It had been tested on Intel/Linux with gcc 2.7.2, Solaris 2.6, and
|
||||
Win32.
|
||||
|
||||
Update (march 2006):
|
||||
Makefiles has been modified to compile under Cygwin and gcc 3.4.4. (still 6 ISO C warning : normal)
|
||||
|
||||
The size of long must be 4, the size of short 2.
|
||||
The library reads disk sectors written with the big endian (Motorola) byte
|
||||
ordering.
|
||||
|
||||
You have to type :
|
||||
|
||||
make clean
|
||||
make dep
|
||||
make lib
|
||||
|
||||
A 'lidadf.a' should be created.
|
||||
|
||||
|
||||
* Byte ordering
|
||||
|
||||
'make clean' remove the temporary files and the 'defendian.h'. In this file,
|
||||
LITT_ENDIAN must be defined if the target machine uses the little endian
|
||||
byte ordering, like this :
|
||||
|
||||
#ifndef LITT_ENDIAN
|
||||
#define LITT_ENDIAN 1
|
||||
#endif /* LITT_ENDIAN */
|
||||
|
||||
This should be done automatically by the 'myconf' shell script. myconf
|
||||
autocompiles a C file which detects the byte ordering. The 'defendian.h'
|
||||
is generated in 'myconf'. 'defendian.h' should be included in every .c file
|
||||
which uses the LITT_ENDIAN define is used, otherwise the compiler could think
|
||||
it is not defined, and the target machine is (always) using the big endian
|
||||
byte ordering.
|
||||
|
||||
'myconf' is launched by 'make depend'.
|
||||
|
||||
|
||||
* Native driver
|
||||
|
||||
The NATIV_DIR variable is used to choose the (only one) target platform
|
||||
of the native driver. The default is :
|
||||
|
||||
NATIV_DIR = ./Generic
|
||||
|
||||
This one do not give access to any real device. The other one available is
|
||||
Win32, to access real devices under WinNT.
|
||||
|
||||
|
||||
* Win32DLL
|
||||
|
||||
The 'prefix.h' is used to create the Win32 DLL version of the library.
|
||||
If the WIN32DLL variable is defined in the library code, public functions
|
||||
are preceded by the '__declspec(dllexport)' directive. If this same
|
||||
variable is defined, the '__declspec(dllimport)' is put before the functions
|
||||
prototypes in the 'adflib.h' library include file.
|
||||
|
||||
|
||||
|
||||
|
||||
FILES
|
||||
-----
|
||||
|
||||
AUTHORS Contributors
|
||||
README The file you are reading
|
||||
TODO Future improvements and bugfixes
|
||||
CHANGES Detailed changes
|
||||
src/ main library files
|
||||
src/win32/ WinNT native driver
|
||||
src/generic/ native files templates
|
||||
boot/ Bootblocks that might by used to put on floppy disks
|
||||
doc/ The library developpers documentation
|
||||
doc/FAQ/ The Amiga Filesystem explained
|
||||
examples/ unadf.c
|
||||
|
||||
|
||||
Possible bugs
|
||||
-------------
|
||||
|
||||
- in dircache updates
|
||||
- when a volume is becoming full
|
||||
- lost memory releases
|
||||
|
||||
|
||||
Please report any bugs or mistakes in the documentation !
|
||||
|
||||
|
||||
|
||||
Have fun anyway !
|
||||
13
adflib.pc.in
Normal file
13
adflib.pc.in
Normal file
@@ -0,0 +1,13 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: adflib
|
||||
Description: The ADFlib is a portable C library designed to manage Amiga formatted devices like harddisks and ZIP disks, or dump files of this kind of media via the .ADF format.
|
||||
Version: @VERSION@
|
||||
Requires:
|
||||
Conflicts:
|
||||
Libs: -L${libdir} -ladf
|
||||
Cflags: -I${includedir} -I${includedir}/generic
|
||||
|
||||
7
autogen.sh
Executable file
7
autogen.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
libtoolize --copy --force
|
||||
aclocal
|
||||
autoconf
|
||||
autoheader
|
||||
automake --add-missing
|
||||
|
||||
BIN
boot/stdboot3.bbk
Normal file
BIN
boot/stdboot3.bbk
Normal file
Binary file not shown.
55
configure.ac
Normal file
55
configure.ac
Normal file
@@ -0,0 +1,55 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT(adflib, 0.7.12, lclevy_AT_club-internet.fr)
|
||||
AC_CONFIG_SRCDIR([src/adf_env.c])
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
AM_INIT_AUTOMAKE
|
||||
|
||||
AC_ARG_ENABLE([examples],
|
||||
[ --enable-examples Build exmples],
|
||||
[case "${enableval}" in
|
||||
yes) examples=true ;;
|
||||
no) examples=false ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-examples]) ;;
|
||||
esac],
|
||||
[examples=true])
|
||||
|
||||
AM_CONDITIONAL([EXAMPLES], [test x$examples = xtrue])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([limits.h stdint.h stdlib.h string.h unistd.h])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_TYPE_INT32_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_STRUCT_TM
|
||||
AC_HEADER_STDBOOL
|
||||
AC_TYPE_UINT16_T
|
||||
AC_TYPE_UINT32_T
|
||||
AC_TYPE_UINT8_T
|
||||
|
||||
# Checks for library functions.
|
||||
AC_FUNC_MALLOC
|
||||
AC_FUNC_STAT
|
||||
AC_CHECK_FUNCS([memset strchr strdup strerror strrchr])
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
src/Makefile
|
||||
doc/Makefile
|
||||
examples/Makefile
|
||||
adflib.pc])
|
||||
AC_OUTPUT
|
||||
270
doc/API.txt
Normal file
270
doc/API.txt
Normal file
@@ -0,0 +1,270 @@
|
||||
The ADFlib API quick overview
|
||||
*****************************
|
||||
|
||||
outdated ! But may be useful anyway...
|
||||
|
||||
|
||||
Always read ADFlib structures, never change a value directly, the
|
||||
behaviour of the library could then become unforeseeable.
|
||||
|
||||
|
||||
|
||||
Minimal C program with ADFlib
|
||||
-----------------------------
|
||||
|
||||
#include<stdio.h> /* for puts() */
|
||||
|
||||
#include"adflib.h"
|
||||
|
||||
ENV_DECLARATION;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
adfEnvInitDefault();
|
||||
|
||||
puts("hello world");
|
||||
|
||||
adfEnvCleanUp();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Device
|
||||
------
|
||||
|
||||
struct Device {
|
||||
int devType; /* see adf_str.h */
|
||||
BOOL readOnly;
|
||||
long size; /* in bytes */
|
||||
|
||||
int nVol; /* partitions */
|
||||
struct Volume** volList;
|
||||
|
||||
long cylinders; /* geometry */
|
||||
long heads;
|
||||
long sectors;
|
||||
|
||||
BOOL isNativeDev;
|
||||
void *nativeDev;
|
||||
};
|
||||
|
||||
struct Device* adfMountDev(char* name)
|
||||
mounts and allocates a device (real or dump)
|
||||
|
||||
void adfDeviceInfo(struct Device* dev)
|
||||
prints device info to stdout : must be rewritten for another GUI
|
||||
|
||||
void adfUnMountDev(struct Device* dev)
|
||||
|
||||
void adfCreateHd(struct Device* dev, int nbPartitions, struct Partition** part)
|
||||
create a filesystem for harddisk with one or several partition
|
||||
(see hd_test2.c)
|
||||
|
||||
void adfCreateFlop(struct Device* dev, char* name, int flags)
|
||||
flags are for ffs, dircache or international (see fl_test.c)
|
||||
|
||||
|
||||
Volume
|
||||
------
|
||||
|
||||
struct Volume {
|
||||
struct Device* dev;
|
||||
|
||||
SECTNUM firstBlock; /* first block of data area (from beginning of device) */
|
||||
SECTNUM lastBlock; /* last block of data area (from beginning of device) */
|
||||
SECTNUM rootBlock; /* root block (from firstBlock) */
|
||||
|
||||
char dosType; /* FFS/OFS, DIRCACHE, INTERNATIONAL */
|
||||
BOOL bootCode;
|
||||
int datablockSize; /* 488 or 512 */
|
||||
|
||||
char *volName;
|
||||
|
||||
long bitmapSize; /* in blocks */
|
||||
SECTNUM *bitmapBlocks; /* bitmap blocks pointers */
|
||||
struct bBitmapBlock **bitmapTable;
|
||||
BOOL *bitmapBlocksChg;
|
||||
|
||||
SECTNUM curDirPtr;
|
||||
};
|
||||
|
||||
|
||||
struct Volume* adfMount(struct Device* dev, int partition, BOOL readOnly)
|
||||
The first partition is #0
|
||||
To be called after adfCreateFlop(), adfCreateHd() or adfMountDev().
|
||||
|
||||
void adfVolumeInfo(vol)
|
||||
Display volume info to stdout, must be rewritten for another GUI
|
||||
|
||||
void adfUnMount(struct Volume *vol)
|
||||
|
||||
|
||||
Dump device (.ADF)
|
||||
------------------
|
||||
|
||||
struct adfCreateDumpDevice(char*, int cyl, int heads, int sectors)
|
||||
To be used in place of adfMountDev(). Create a filename of the right size,
|
||||
nothing else
|
||||
|
||||
|
||||
File
|
||||
----
|
||||
|
||||
struct File* adfOpenFile(struct Volume *volume, char* filename, char* mode)
|
||||
mode = "r" or "w"
|
||||
|
||||
void adfCloseFile(struct File* file)
|
||||
|
||||
long adfReadFile(struct File* file, long length, unsigned char* buffer)
|
||||
returns the number of bytes read
|
||||
|
||||
long adfWriteFile(struct File* file, long length, unsigned char* buffer)
|
||||
returns the number of bytes written
|
||||
|
||||
BOOL adfEndOfFile(struct File* file)
|
||||
|
||||
|
||||
Directory
|
||||
---------
|
||||
|
||||
struct List* adfGetDirEnt(struct Volume* vol, SECTNUM nSect)
|
||||
Returns a linked list with the directory entries. Each cell content of the list
|
||||
must be freed with adfFreeEntry()
|
||||
|
||||
void adfFreeEntry(struct Entry *entry)
|
||||
|
||||
SECTNUM adfChangeDir(struct Volume* vol, char* dirname)
|
||||
change current directory
|
||||
|
||||
void adfParentDir(struct Volume* vol)
|
||||
change current directory
|
||||
|
||||
void printEntry(struct Entry* entry)
|
||||
print the cell content to stdout
|
||||
|
||||
void CreateDir(struct Volume* vol, SECTNUM parentSect, char* name)
|
||||
|
||||
|
||||
|
||||
Callbacks mechanism
|
||||
-------------------
|
||||
|
||||
* The library environment : 'struct Env adfEnv'
|
||||
|
||||
This variable is the only global variable of the library. It contains
|
||||
callbacks for error and notification messages, and global variables.
|
||||
By default, adfEnvInitDefault() initialize adfEnv functions that display
|
||||
messages to stderr. You must use adfSetEnv() to use your own defined
|
||||
functions.
|
||||
The environment must be clean up with adfEnvCleanUp().
|
||||
|
||||
Four functions are available :
|
||||
- (*adfEnv.eFct)(char*), called by ADFlib for a fatal error. It STOPS
|
||||
the library : you must redefine yourself a more friendly to handle
|
||||
this kind of error.
|
||||
- (adfEnv.wFct)(char*), called for warnings. It is called when something wrong
|
||||
happens, but processing can continue.
|
||||
- (adfEnv.vFct)(char*), called to display verbose messages.
|
||||
- (*adfEnv.notifyEnv)(SECTNUM p, int t), called to tell that
|
||||
the volume structure has changed. The value p give where the change appeared,
|
||||
t the type of the value (ST_DIR,ST_FILE,...).
|
||||
|
||||
The environment also contains access to nativeFunctions.
|
||||
|
||||
|
||||
* Native device and functions
|
||||
|
||||
By default, the library is compiled to manage .ADF files (dump files) and
|
||||
real devices like harddisk and removable disks (called native devives)
|
||||
on ONE defined plateform (WinNT/Intel or Linux/68k...)
|
||||
|
||||
To add a new plateform to be supported by ADFlib, you must write your
|
||||
own files adf_nativ.h and adf_nativ.c.
|
||||
|
||||
. data types
|
||||
|
||||
adf_nativ.h defines two structures :
|
||||
- 'struct nativeDev'. It contains all the variable necessary for
|
||||
the native device management. You can add here whatever you what to
|
||||
be able to manage your real device on your plateform !
|
||||
- 'struct nativeFunctions'. It defines the minimal API between ADFlib and
|
||||
the specific native part. The functions names and prototypes must not be
|
||||
changed, since they are called by the library. It is possible to add
|
||||
other functions.
|
||||
|
||||
The type device 'struct Device' contains one variable 'void* nativeDev'.
|
||||
It is allocated within adf_nativ.c by adfInitDevice().
|
||||
Another variable 'BOOL isNativeDev' tells if the ADFlib is working with
|
||||
a dump file (.ADF) or a real device.
|
||||
|
||||
'adfEnv' contains one variable 'void *nativeFct'. adfEnvInitDefault()
|
||||
allocates it by calling the function adfInitNativeFct().
|
||||
|
||||
|
||||
. callback functions :
|
||||
|
||||
The structure 'struct nativeFunctions' must have at least :
|
||||
BOOL (*adfInitDevice)(struct Device*, char*)
|
||||
BOOL (*adfNativeReadSector)(struct Device*, long, int, unsigned char*)
|
||||
BOOL (*adfNativeWriteSector)(struct Device*, long, int, unsigned char*)
|
||||
BOOL (*adfIsDevNative)(char*)
|
||||
void (*adfReleaseDevice)()
|
||||
|
||||
|
||||
For example, adfMountDev() calls adfInitDevice() this way :
|
||||
struct nativeFunctions *nFct;
|
||||
|
||||
... /* struct Device* dev allocation */
|
||||
|
||||
nFct = adfEnv.nativeFct; /* was of type void* */
|
||||
|
||||
/* only once ! */
|
||||
dev->isNativeDev = (*nFct->adfIsDevNative)(filename);
|
||||
|
||||
/* choose between dump or a real device */
|
||||
if (dev->isNativeDev)
|
||||
(*nFct->adfInitDevice)(dev, filename);
|
||||
else
|
||||
adfInitDumpDevice(dev, filename);
|
||||
|
||||
|
||||
You must define one function to initialize a device, for example :
|
||||
|
||||
BOOL myInitDevice(struct Device *dev, char* name)
|
||||
{
|
||||
/* allocate and initailize dev->nativeDev */
|
||||
|
||||
/* return TRUE if everything happens right */
|
||||
}
|
||||
|
||||
or
|
||||
|
||||
BOOL myIsDevNative(char* name)
|
||||
{
|
||||
/* for a Unix like platform */
|
||||
return( strncmp("/dev/",name,5)==0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
And so on to read, write a 512 bytes block, and release the native device.
|
||||
|
||||
|
||||
The function 'adfInitNativeFct()', also defined in adf_nativ.c (and .h),
|
||||
makes the names and the ADFlib native API :
|
||||
|
||||
void adfInitNativeFct()
|
||||
{
|
||||
struct nativeFunctions *nFct;
|
||||
|
||||
nFct = (struct nativeFunctions*)adfEnv.nativeFct;
|
||||
|
||||
nFct->adfInitDevice = myInitDevice ;
|
||||
nFct->adfNativeReadSector = myReadSector ;
|
||||
...
|
||||
}
|
||||
|
||||
But the prototypes must stay the same !
|
||||
|
||||
|
||||
2410
doc/FAQ/adf_info.html
Normal file
2410
doc/FAQ/adf_info.html
Normal file
File diff suppressed because it is too large
Load Diff
2121
doc/FAQ/adf_info.txt
Normal file
2121
doc/FAQ/adf_info.txt
Normal file
File diff suppressed because it is too large
Load Diff
1134
doc/FAQ/adf_info_V0_9.txt
Normal file
1134
doc/FAQ/adf_info_V0_9.txt
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/FAQ/image/adf_dir.gif
Normal file
BIN
doc/FAQ/image/adf_dir.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.8 KiB |
BIN
doc/FAQ/image/adf_file.gif
Normal file
BIN
doc/FAQ/image/adf_file.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.9 KiB |
24
doc/Makefile.am
Normal file
24
doc/Makefile.am
Normal file
@@ -0,0 +1,24 @@
|
||||
doc_DATA = $(top_srcdir)/README \
|
||||
$(top_srcdir)/AUTHORS \
|
||||
$(top_srcdir)/COPYING \
|
||||
$(top_srcdir)/ChangeLog \
|
||||
$(top_srcdir)/NEWS
|
||||
|
||||
nobase_doc_DATA = FAQ/image/adf_dir.gif \
|
||||
FAQ/image/adf_file.gif \
|
||||
FAQ/adf_info.html \
|
||||
FAQ/adf_info.txt \
|
||||
FAQ/adf_info_V0_9.txt \
|
||||
api_device.html \
|
||||
api_dir.html \
|
||||
api_env.html \
|
||||
api_file.html \
|
||||
api_index.html \
|
||||
api_native.html \
|
||||
api_salv.html \
|
||||
api_volume.html \
|
||||
API.txt \
|
||||
version0.7.9d_gary.txt
|
||||
|
||||
EXTRA_DIST = doc_DATA nobase_doc_DATA
|
||||
|
||||
334
doc/api_device.html
Normal file
334
doc/api_device.html
Normal file
@@ -0,0 +1,334 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Device</TITLE>
|
||||
</HEAD>
|
||||
|
||||
|
||||
<BODY>
|
||||
|
||||
<H1 ALIGN=CENTER>the Device API</H1>
|
||||
|
||||
<HR>
|
||||
<H1>Use cases</H1>
|
||||
|
||||
<UL>
|
||||
|
||||
<P>
|
||||
<LI>Mounting volume of a existing device (ADF dump or real one) :
|
||||
<OL>
|
||||
<LI>adfMountDev()
|
||||
<LI>adfMount()
|
||||
<LI>adfUnMount()
|
||||
<LI>adfUnMountDev()
|
||||
</OL>
|
||||
|
||||
<P>
|
||||
<LI>Creating an ADF dump of a floppy :
|
||||
<OL>
|
||||
<LI>adfCreateDumpDevice()
|
||||
<LI>adfCreateFlop()
|
||||
<LI>adfMount()
|
||||
<LI>adfUnMount()
|
||||
<LI>adfUnMountDev()
|
||||
</OL>
|
||||
|
||||
<P>
|
||||
<LI>Creating an ADF dump of a harddisk :
|
||||
<OL>
|
||||
<LI>adfCreateDumpDevice()
|
||||
<LI>adfCreateHd()
|
||||
<LI>adfMount()
|
||||
<LI>adfUnMount()
|
||||
<LI>adfUnMountDev()
|
||||
</OL>
|
||||
|
||||
<P>
|
||||
<LI>Creating an new filesystem for an harddisk on a real device :
|
||||
<OL>
|
||||
<LI>adfMountDev()
|
||||
<LI>adfCreateHd()
|
||||
<LI>adfMount()
|
||||
<LI>adfUnMount()
|
||||
<LI>adfUnMountDev()
|
||||
</OL>
|
||||
|
||||
</UL>
|
||||
|
||||
<HR>
|
||||
|
||||
<H1>Data structures</H1>
|
||||
|
||||
<P>
|
||||
<B>
|
||||
Warning ! None of the fields of the structure below must be modified directly. In this case,
|
||||
i can not tell how will behave the library. Unless specified, read access
|
||||
is of course allowed.
|
||||
</B>
|
||||
<P>
|
||||
The dynamic memory allocation/releasing is done by the library (i hope :).
|
||||
<P>
|
||||
|
||||
<PRE>
|
||||
struct Device {
|
||||
int devType; /* DEVTYPE_FLOPDD, DEVTYPE_FLOPHD or DEVTYPE_HARDDISK */
|
||||
long size; /* size in bytes of the media. ADFlib is limited to 4Gb */
|
||||
|
||||
int nVol; /* number of partitions (volumes) */
|
||||
struct Volume* *volList; /* volumes */
|
||||
|
||||
long cylinders, heads, sectors; /* device geometry */
|
||||
|
||||
BOOL isNativeDev;
|
||||
|
||||
void *nativeDev; /* native specific and private structure */
|
||||
}
|
||||
</PRE>
|
||||
|
||||
<P>
|
||||
The Partition structure is used with adfCreateHd().
|
||||
|
||||
|
||||
<PRE>
|
||||
struct Partition{
|
||||
long startCyl; /* starting cylinder of the usable space : should be 2 */
|
||||
long lenCyl; /* length of this area, in cylinders */
|
||||
|
||||
char* volName; /* name of the volume, if any. Instead filled with 0. */
|
||||
|
||||
int volType; /* filesystem caracteristics : use the flags FSMASK_FFS,
|
||||
FSMASK_INTL and FSMASK_DIRCACHE */
|
||||
|
||||
}
|
||||
</PRE>
|
||||
|
||||
|
||||
<HR>
|
||||
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfMountDev() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>struct Device*</B> adfMountDev( <B>char*</B> name)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Mounts a device. The name could be a filename for an ADF dump, or a
|
||||
real device name like "|F:" for the Win32 F: partition. <BR>
|
||||
The real device name is plateform dependent.
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
NULL if an error occurs, a Device structure pointer instead.
|
||||
|
||||
<H2>Internals</H2>
|
||||
<OL>
|
||||
<LI>Allocation of <I>struct Device *dev</I>
|
||||
<LI>Calls <I>adfIsNativeDev()</I> to determine if the name point out
|
||||
a ADF dump or a real (native) device. The field <I>dev->isNativeDev</I> is filled.
|
||||
<LI>Initialize the (real or dump) device. The field <I>dev->size</I> is filled.
|
||||
<LI><I>dev->devType</I> is filled.
|
||||
<LI>The device is mounted : <I>dev->nVol, dev->volList[], dev->cylinders,
|
||||
dev->heads, dev->sectors</I> are filled.
|
||||
<LI><I>dev</I> is returned
|
||||
</OL>
|
||||
Warning, in each <I>dev->volList[i]</I> volumes (vol),
|
||||
only <I>vol->volName</I> (might be NULL), <I>vol->firstBlock, vol->lastBlock</I>
|
||||
and <I>vol->rootBlock</I> are filled !
|
||||
|
||||
<H2>See also</H2>
|
||||
|
||||
struct Device, real (native) devices
|
||||
|
||||
<H2>Files</H2>
|
||||
|
||||
Real devices allocation : adf_nativ.c, adf_nativ.h <BR>
|
||||
ADF allocation : adf_dump.c, adf_dump.h
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfUnMountDev() </FONT></P>
|
||||
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>void</B> adfUnMountDev( <B>struct Device*</B> dev)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Releases a Device and frees related resources.
|
||||
|
||||
<H2>Internals</H2>
|
||||
|
||||
<OL>
|
||||
<LI>Frees <I>dev->volList[]</I>
|
||||
<LI>Releases the ADF dump or real (native) device : call the suited function.
|
||||
</OL>
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfCreateHd() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfCreateHd(<B>struct Device*</B> dev, <B>int</B> nPart,
|
||||
<B>struct Partition*</B> *partList )
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Create the filesystem of a device which will be used as an Harddisk.
|
||||
<I>AdfMount()</I> must be used after to mount
|
||||
a volume (partition).
|
||||
<P>
|
||||
In case of a new ADF dump, <I>adfCreateDumpDevice()</I> must be called before to
|
||||
create an empty media of the right size.
|
||||
<P>
|
||||
An Harddisk ADF dump created with ADFlib -can not be- used back by the AmigaDOS,
|
||||
since some fields of the header structures are missing : they can not be
|
||||
automatically determined.
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
RC_OK, or Something different in case of error.
|
||||
|
||||
<H2>Examples</H2>
|
||||
|
||||
Creation of an ADF Zip disk dump : <BR>
|
||||
|
||||
<PRE>
|
||||
struct Partition part1;
|
||||
struct Partition **partList;
|
||||
struct Device *hd;
|
||||
RETCODE rc;
|
||||
|
||||
/* Env init */
|
||||
|
||||
/* cyl = 2891, heads = 1, sectors = 68 */
|
||||
hd = adfCreateDumpDevice("newdev",2891,1,68);
|
||||
if (!hd) { /* cleanup and exit */ }
|
||||
|
||||
/* allocation of partlist[] */
|
||||
|
||||
/* the filesystem definition : size, FFS with DIRCACHE */
|
||||
part1.startCyl = 2;
|
||||
part1.lenCyl = 2889;
|
||||
part1.volName = strdup("zip");
|
||||
part1.volType = FSMASK_FFS|FSMASK_DIRCACHE;
|
||||
|
||||
partList[0] = &part1;
|
||||
|
||||
/* creates the filesystem */
|
||||
rc = adfCreateHd(hd,1,partList);
|
||||
if (rc!=RC_OK) { /* something wrong, cleaning up and exit */ }
|
||||
|
||||
/* freeing of partList[] and part1.volName */
|
||||
|
||||
/* device usage */
|
||||
|
||||
adfUnMountDev(hd);
|
||||
|
||||
/* Env cleanup */
|
||||
|
||||
</PRE>
|
||||
|
||||
|
||||
<H2>Internals</H2>
|
||||
|
||||
<OL>
|
||||
<LI>Creates and fill <I>dev->volList[]</I>
|
||||
<LI>Creates the Harddisk header structures on the media. It uses usually the
|
||||
2 first cylinders of the device.
|
||||
</OL>
|
||||
|
||||
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfCreateFlop() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfCreateFlop(<B>struct Device*</B> dev,
|
||||
<B>char*</B> volName, <B>int</B> volType )
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Creates the filesystem of a DD or HD floppy.
|
||||
<I>AdfMount()</I> must be used after to mount the only volume.
|
||||
<P>
|
||||
In case of a new ADF dump, <I>adfCreateDumpDevice()</I> must be called before to
|
||||
create an empty media of the right size.
|
||||
<P>
|
||||
An Harddisk ADF dump created with ADFlib -can be- used back by the AmigaDOS.
|
||||
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
RC_OK, or Something different in case of error.
|
||||
|
||||
|
||||
<H2>Examples</H2>
|
||||
|
||||
<PRE>
|
||||
struct Device *flop;
|
||||
|
||||
/* Env init */
|
||||
|
||||
/* creates a DD floppy empty dump */
|
||||
/* cyl = 80, heads = 2, sectors = 11. HD floppies has 22 sectors */
|
||||
flop = adfCreateDumpDevice("newdev", 80, 2, 11);
|
||||
if (!flop) { /* cleanup and exit */ }
|
||||
|
||||
/* create the filesystem : OFS with DIRCACHE */
|
||||
rc = adfCreateFlop( flop, "empty", FSMASK_DIRCACHE );
|
||||
if (rc!=RC_OK) { /* error : cleanup and exit() */
|
||||
|
||||
/* device usage */
|
||||
|
||||
adfUnMountDev(flop);
|
||||
|
||||
/* Env cleanup */
|
||||
|
||||
</PRE>
|
||||
|
||||
<H2>Internals</H2>
|
||||
|
||||
<OL>
|
||||
<LI>Allocation of dev->volList[]. It contains one volume.
|
||||
<LI>Creation of the volume
|
||||
</OL>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> ADF only : adfCreateDumpDevice() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>struct Device*</B> adfCreateDumpDevice(<B>char*</B> filename,
|
||||
<B>long</B> cyl, <B>long</B> heads, <B>long</B> sect)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Create a file of the right size, and fills some fields of the Device
|
||||
structure. Must be followed by adfCreateFlop() and adfCreateHd().
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
the Device, NULL in case of error.
|
||||
|
||||
<H2>Examples</H2>
|
||||
See adfCreateFlop() and adfCreateHd() examples.
|
||||
|
||||
<H2>Internals</H2>
|
||||
|
||||
<OL>
|
||||
<LI>Allocate <I>struct Device* dev</I>
|
||||
<LI>Allocate <I>dev->nativeDev</I>
|
||||
<LI>Create an empty file with a size equals to : cyl*heads*sect*512.
|
||||
<LI>Open this file with "rb+" mode
|
||||
<LI>Fills <I>dev->cylinders, dev->heads, dev->sectors, dev->size,
|
||||
dev->devType</I>, and <I>dev->nVol</I> = 0.
|
||||
<LI>Returns <I>dev</I>
|
||||
</OL>
|
||||
|
||||
</BODY>
|
||||
|
||||
</HTML>
|
||||
274
doc/api_dir.html
Normal file
274
doc/api_dir.html
Normal file
@@ -0,0 +1,274 @@
|
||||
<HTML>
|
||||
<HEAD><TITLE> Directory </TITLE></HEAD>
|
||||
|
||||
<BODY>
|
||||
|
||||
<H1 ALIGN=CENTER>the Directory API</H1>
|
||||
|
||||
<HR>
|
||||
<H1>Data structures</H1>
|
||||
|
||||
<PRE>
|
||||
|
||||
/* entry types */
|
||||
|
||||
#define ST_DIR 2
|
||||
#define ST_FILE -3
|
||||
|
||||
|
||||
struct Entry{
|
||||
int type; /* type of the entry */
|
||||
char *name; /* name */
|
||||
SECTNUM sector; /* sector pointer */
|
||||
char *comment; /* optional comment */
|
||||
unsigned long size; /* file size, 0 for a directory */
|
||||
long access; /* RWEDAPSH access rights */
|
||||
|
||||
int year, month, day; /* date */
|
||||
int hour, min, sec; /* hour */
|
||||
}
|
||||
|
||||
|
||||
/* general purpose list used to stored directory entries */
|
||||
struct List{
|
||||
void *content; /* Filled with struct Entry* type */
|
||||
struct List *subdir; /* If the cell content is a dir, its entries list */
|
||||
/* is stored here, else filled with NULL */
|
||||
struct List *next; /* Next cell */
|
||||
}
|
||||
</PRE>
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfGetDirEnt() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>struct List*</B> adfGetDirEnt(<B>struct Volume*</B> vol, <B>SECTNUM</B> dir )<BR>
|
||||
equivalent to <BR>
|
||||
<B>struct List*</B> adfGetRDirEnt(<B>struct Volume*</B> vol, <B>SECTNUM</B> dir, FALSE )<BR>
|
||||
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Returns a linked list which contains the entries of one directory.
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
The list, NULL in case of error.
|
||||
|
||||
<H2>Examples</H2>
|
||||
|
||||
<PRE>
|
||||
struct List *list, *cell;
|
||||
struct Entry *entry;
|
||||
|
||||
/* saves the head of the list */
|
||||
cell = list = adfGetDirEnt(vol,vol->curDirPtr);
|
||||
|
||||
/* while cell->next is NULL, the last cell */
|
||||
while(cell) {
|
||||
entry = (struct Entry*)cell->content;
|
||||
printf("%s %ld\n", entry->name, entry->sector);
|
||||
cell = cell->next;
|
||||
}
|
||||
|
||||
/* frees the list and the content */
|
||||
adfFreeDirList(list);
|
||||
|
||||
|
||||
|
||||
</PRE>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfGetRDirEnt() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>struct List*</B> adfGetRDirEnt(<B>struct Volume*</B> vol, <B>SECTNUM</B> dir, <B>BOOL</B> recursive )<BR>
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Returns a linked list which contains the entries of one directory.
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
The list, NULL in case of error.
|
||||
|
||||
<H2>Examples</H2>
|
||||
|
||||
<PRE>
|
||||
|
||||
#define TRUE 1
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
struct List *list, *cell;
|
||||
struct Entry *entry;
|
||||
|
||||
...
|
||||
|
||||
/* saves the head of the list */
|
||||
cell = list = adfGetRDirEnt(vol,vol->curDirPtr,TRUE);
|
||||
|
||||
/* prints the tree */
|
||||
printTree(cell);
|
||||
|
||||
/* frees the list and the content */
|
||||
adfFreeDirList(list);
|
||||
|
||||
...
|
||||
|
||||
}
|
||||
|
||||
/* print the directories tree. recursive */
|
||||
printTree(struct List* tree)
|
||||
{
|
||||
while(tree) {
|
||||
entry = (struct Entry*)cell->content;
|
||||
printf("%s %ld\n", entry->name, entry->sector);
|
||||
if (tree->subdir!=NULL)
|
||||
printTree(tree->subdir)
|
||||
tree = tree->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</PRE>
|
||||
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfChangeDir() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfChangeDir(<B>struct Volume*</B> vol, <B>char *</B>dirName)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Change the current working directory to the new one (dirName).
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
RC_OK, something different in case of error.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfParentDir() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfParentDir(<B>struct Volume*</B> vol)
|
||||
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Change the current working directory to its parent directory. If the current
|
||||
directory is the root of the filesystem ('/'), nothing happens.
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
RC_OK, something different in case of error.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfCreateDir() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfCreateDir(<B>struct Volume*</B> vol,
|
||||
<B>SECTNUM</B> parent, <B>char*</B> dirName)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Creates a new directory (dirName) into the specified directory (parent).
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
RC_OK, something different in case of error.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfRemoveEntry() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfRemoveEntry(<B>struct Volume *</B>vol,
|
||||
<B>SECTNUM</B> parent, <B>char *</B>name)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Removes a entry (a file or an empty directory) from one directory (parent).
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
RC_OK, something different in case of error.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfFreeDirList() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>void</B> adfFreeDirList(<B>struct List*</B> list)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Frees a linked list or a tree of directory entries.
|
||||
|
||||
|
||||
<P>
|
||||
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfAccess2String() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>char*</B> adfAccess2String(<B>long</B> access)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Converts the access rights from <I>long</I> to <I>char*</I>.
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
A C string which represents the access rights.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfRenameEntry() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfRenameEntry(<B>struct Volume*</B> vol, <B>SECTNUM</B> oldDir, <B>char*</B> old, <B>SECTNUM</B> newDir, <B>char*</B> new)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Changes the name of the entry <I>old</I> located in the <I>oldDir</I> into
|
||||
the name <I>new</I>, located into the <I>newDir</I> directory.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> printEntry() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>void</B> printEntry(<B>struct Entry*</B> entry)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Do no use this function (not an adf one), but you can use its code to learn
|
||||
how to display a directory entry (in adf_dir.c).
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
</BODY>
|
||||
|
||||
</HTML>
|
||||
187
doc/api_env.html
Normal file
187
doc/api_env.html
Normal file
@@ -0,0 +1,187 @@
|
||||
<HTML>
|
||||
<HEAD><TITLE> Environment </TITLE></HEAD>
|
||||
|
||||
<BODY>
|
||||
|
||||
<H1 ALIGN=CENTER>the Environment API</H1>
|
||||
|
||||
|
||||
<HR>
|
||||
<H1>Typical usage</H1>
|
||||
|
||||
|
||||
<PRE>
|
||||
#include"adflib.h"
|
||||
|
||||
|
||||
void MyVer(char *msg)
|
||||
{
|
||||
fprintf(stderr,"Verbose [%s]\n",msg);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOL boolPr = TRUE;
|
||||
|
||||
adfEnvInitDefault();
|
||||
|
||||
/* to use the dir cache blocks, default is FALSE */
|
||||
adfChgEnvProp(PR_USEDIRC, (void*)&boolPr); // optional
|
||||
|
||||
/* to override the verbose callback */
|
||||
adfChgEnvProp(PR_VFCT, MyVer); // optional
|
||||
|
||||
adfEnvCleanUp();
|
||||
}
|
||||
</PRE>
|
||||
|
||||
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfEnvInitDefault() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>void</B> adfEnvInitDefault()
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Initialise the library data structures and default values.
|
||||
Must be done before any other call to the library.
|
||||
<P>
|
||||
There is 4 callback functions which can be (and must be) overridden,
|
||||
the library must not write anything to the console.
|
||||
<UL>
|
||||
<LI>The verbose messages redirection,
|
||||
<LI>the warning messages redirection,
|
||||
<LI>the error messages redirection (must stop the library)
|
||||
<LI>The notification callback : when the current directory has changed.
|
||||
<LI>The progress bar : this function is called with an int first set to 0.
|
||||
Then the value increases up to 100. It can be used to display a progress bar.
|
||||
</UL>
|
||||
By default, those functions write a message to stderr.
|
||||
<P>
|
||||
Another environment property is the ability to use or not the dir cache
|
||||
blocks to get the content of a directory. By default, it is not used.
|
||||
<P>
|
||||
See <B>adfChgEnvProp()</B> to learn how to change those properties.
|
||||
|
||||
|
||||
<H2>Internals</H2>
|
||||
|
||||
<OL>
|
||||
<LI>Set the default values
|
||||
<LI>Prints the library version with the verbose callback.
|
||||
<LI>Allocate the native functions structure
|
||||
<LI>Calls adfInitNativeFct()
|
||||
</OL>
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfChgEnvProp() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>void</B> adfChgEnvProp(<B>int</B> propertyName, <B>void*</B> new value)
|
||||
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Change the default or lastest value of one of the environment property.
|
||||
The new value has the <B>void*</B>, this is the only way to transmit it
|
||||
for several types. A cast is made depending of the property name inside
|
||||
adfChgEnvProp().
|
||||
<P>
|
||||
Here's the list of the properties, and their types :
|
||||
<UL>
|
||||
<LI>PR_VFCT, displays verbose messages, (void(*)(char*))
|
||||
<LI>PR_WFCT, displays warning messages, (void(*)(char*))
|
||||
<LI>PR_EFCT, displays error messages, (void(*)(char*))
|
||||
</UL>
|
||||
<UL>
|
||||
<LI>PR_NOTFCT, directory object change notification, (void(*)(SECTNUM,int))
|
||||
<LI>PR_USE_NOTFCT, toggle on/off (default=off=false), BOOL
|
||||
</UL>
|
||||
<UL>
|
||||
<LI>PR_PROGBAR, progress bar, (void(*)(int))
|
||||
<LI>PR_USE_PROGBAR, use progress bar (default=off), BOOL<BR>
|
||||
The functions that support 'progress bar' are : adfCreateFlop(),
|
||||
adfCreateHd(), adfCreateHdFile().
|
||||
</UL>
|
||||
<UL>
|
||||
<LI>PR_RWACCESS, read (BOOL=false) or write (BOOL=true) operation, logical block and physical sector accessed, (void(*)(SECTNUM,SECTNUM,BOOL))
|
||||
<LI>PR_USE_RWACCESS, use rwaccess (default=off), BOOL
|
||||
</UL>
|
||||
|
||||
<UL>
|
||||
<LI>PR_USEDIRC, use dircache blocks, BOOL (default=off).
|
||||
</UL>
|
||||
|
||||
For the non pointer types (int with PR_USEDIRC), you have to use a temporary variable.
|
||||
|
||||
To override successfully a function, the easiest is to reuse the default function
|
||||
located in adf_env.c, and to change it for your needs.
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfEnvCleanUp() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>void</B> adfEnvCleanUp()
|
||||
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Cleans up the environment.
|
||||
|
||||
<H2>Internals</H2>
|
||||
|
||||
Frees the native functions structure.
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfEnvCleanUp() : Obsolete </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
<B>void</B> adfSetEnvFct( <B>void(*eFct)(char*)</B> error, <B>void(*wFct)(char*)</B> warning, <B>void(*vFct)(char*)</B> verbose, <B>void(*notFct)(SECTNUM,int)</B> notify )
|
||||
|
||||
<P>
|
||||
Obsolete : use adfChgEnvProp() instead.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfGetVersionNumber() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>char*</B> adfGetVersionNumber()
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Returns the current numeric ADFlib version.
|
||||
|
||||
<P>
|
||||
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfGetVersionDate() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>char*</B> adfGetVersionDate()
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Returns the date of the ADFlib current version.
|
||||
|
||||
<P>
|
||||
|
||||
|
||||
</BODY>
|
||||
|
||||
</HTML>
|
||||
246
doc/api_file.html
Normal file
246
doc/api_file.html
Normal file
@@ -0,0 +1,246 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>File</TITLE>
|
||||
</HEAD>
|
||||
|
||||
|
||||
<BODY>
|
||||
|
||||
<H1 ALIGN=CENTER>the File API</H1>
|
||||
|
||||
|
||||
<H1>Data structures</H1>
|
||||
|
||||
<P>
|
||||
<B>
|
||||
Warning ! None of the fields of the structure below must be modified directly. In this case,
|
||||
i can not tell how will behave the library. Unless specified, read access
|
||||
is of course allowed.
|
||||
</B>
|
||||
<P>
|
||||
The dynamic memory allocation/releasing is done by the library (i hope :).
|
||||
<P>
|
||||
|
||||
<PRE>
|
||||
struct File {
|
||||
struct Volume *volume; // pointer to the volume
|
||||
|
||||
struct bFileHeaderBlock* fileHdr; // the header block
|
||||
void *currentData; // current data block
|
||||
struct bFileExtBlock* currentExt; // current data extension block
|
||||
|
||||
long nDataBlock; // number of current data blocks
|
||||
SECTNUM curDataPtr; // pointer to the current data block
|
||||
unsigned long pos; // file pos
|
||||
|
||||
int posInDataBlk; // index in a datablock
|
||||
int posInExtBlk; // index in a file header or file extension block
|
||||
BOOL eof; // TRUE is the last byte has been read, use adfendOfFile()
|
||||
BOOL writeMode; // if the adfOpenFile() mode is "w"
|
||||
};
|
||||
|
||||
</PRE>
|
||||
|
||||
|
||||
<HR>
|
||||
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfOpenFile() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>struct File*</B> adfOpenFile(<B>struct Volume*</B> vol, <B>char*</B> name, <B>char*</B> mode);
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Opens the file with the name <I>name</I> which is located in the current
|
||||
working directory of the <I>vol</I> volume.<BR>
|
||||
The allowed <I>mode</I> are <I>"r"</I> and <I>"w"</I>. If the mode is <I>"w"</I>, the file
|
||||
mustn't already exists, otherwise an error occurs.
|
||||
<P>
|
||||
Some basic access permissions are just checked for now.
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
The File structure, ready to be read or wrote.<BR>
|
||||
NULL if an error occurs : file not found with "r", or file already exists with "w".
|
||||
|
||||
<H2>Internals</H2>
|
||||
<P>
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfFlushFile() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>void</B> adfFlushFile(<B>struct File*</B> file);
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Flushes the datablocks on disk.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfCloseFile() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>void</B> adfCloseFile(<B>struct File*</B> file)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Calls adfFlushFile() and frees the file structure.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfFileRealSize() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>long</B> adfFileRealSize(<B>unsigned long</B> size, <B>int</B> blockSize, <B>long*</B> dataN, <B>long*</B> extN);
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Returns the real size in blocks of a file which the given size. It does not
|
||||
taking into account the new dircache that -may- be allocated.
|
||||
<P>
|
||||
The <I>blockSize</I> must be 488 or 512. This information is located in the
|
||||
<B>datablockSize</B> of the Volume structure.
|
||||
<P>
|
||||
If the pointers <I>dataN</I> and <I>extN</I> aren't NULL, the number of
|
||||
data blocks and file extension blocks are returned.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfReadFile() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>long</B> adfReadFile(<B>struct File*</B> file, <B>long</B> n, <B>unsigned char*</B> buffer)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Read <I>n</I> bytes from the given <I>file</I> into the buffer <I>buffer</I>.
|
||||
<P>
|
||||
Use adfEndOfFile() to check if the end of the file is reached or not.
|
||||
|
||||
<H2>Example</H2>
|
||||
|
||||
|
||||
<PRE>
|
||||
|
||||
#include"adflib.h"
|
||||
|
||||
|
||||
struct File* file;
|
||||
FILE* out;
|
||||
long n;
|
||||
unsigned char buf[600];
|
||||
|
||||
/* a device and a volume 'vol' has been successfully mounted */
|
||||
|
||||
|
||||
/* opens the Amiga file */
|
||||
file = adfOpenFile(vol, "mod.and.distantcall","r");
|
||||
if (!file) { /* frees resources and exits */ };
|
||||
|
||||
/* opens the output classic file */
|
||||
out = fopen("mod.distant","wb");
|
||||
if (!out) { adfCloseFile(file); /* ... */ };
|
||||
|
||||
/* copy the Amiga file into the standard file, 600 bytes per 600 bytes */
|
||||
len = 600;
|
||||
n = adfReadFile(file, len, buf);
|
||||
while(!adfEndOfFile(file)) {
|
||||
fwrite(buf, sizeof(unsigned char), n, out);
|
||||
n = adfReadFile(file, len, buf);
|
||||
}
|
||||
/* even if the EOF is reached, some bytes may need to be written */
|
||||
if (n>0)
|
||||
fwrite(buf, sizeof(unsigned char), n, out);
|
||||
|
||||
/* closes the standard file */
|
||||
fclose(out);
|
||||
|
||||
/* closes the Amiga file */
|
||||
adfCloseFile(file);
|
||||
|
||||
</PRE>
|
||||
|
||||
<H2>Returned values</H2>
|
||||
|
||||
The number of bytes really read.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfEndOfFile() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>BOOL</B> adfEndOfFile(<B>struct File*</B> file)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
TRUE if the end of the file <I>file</I> is reached.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfWriteFile() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>long</B> adfWriteFile(<B>struct File*</B> file, <B>long</B> n, <B>unsigned char*</B> buffer)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Writes <I>n</I> bytes from the given <I>buffer</I> into the file <I>file</I>.
|
||||
<P>
|
||||
|
||||
<H2>Example</H2>
|
||||
|
||||
|
||||
<PRE>
|
||||
|
||||
#include"adflib.h"
|
||||
|
||||
struct File* file;
|
||||
FILE* in;
|
||||
|
||||
/* a device and a volume 'vol' has been successfully mounted */
|
||||
|
||||
|
||||
file = adfOpenFile(vol, "moon_gif", "w");
|
||||
if (!file) { /* error handling */ };
|
||||
|
||||
in = fopen( argv[2],"rb");
|
||||
if (!out) { adfCloseFile(file); /* error handling */ };
|
||||
|
||||
len = 600;
|
||||
n = fread(buf,sizeof(unsigned char),len,out);
|
||||
while(!feof(out)) {
|
||||
adfWriteFile(file, n, buf);
|
||||
n = fread(buf,sizeof(unsigned char),len,out);
|
||||
}
|
||||
if (n>0)
|
||||
adfWriteFile(file, n, buf);
|
||||
|
||||
fclose(out);
|
||||
|
||||
adfCloseFile(file);
|
||||
|
||||
</PRE>
|
||||
|
||||
<H2>Returned values</H2>
|
||||
|
||||
The number of bytes really wrote.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
</BODY>
|
||||
|
||||
</HTML>
|
||||
28
doc/api_index.html
Normal file
28
doc/api_index.html
Normal file
@@ -0,0 +1,28 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>The ADFlib Developpers documentation</TITLE>
|
||||
</HEAD>
|
||||
|
||||
|
||||
<BODY>
|
||||
|
||||
<H1 ALIGN=CENTER>the ADFlib API</H1>
|
||||
|
||||
<HR>
|
||||
|
||||
|
||||
<UL>
|
||||
<LI><A HREF="api_device.html">Device</A> : create and mount/unmount harddisk, floppydisk, .ADF, hardfiles,
|
||||
<LI><A HREF="api_volume.html">Volume</A> : create and mout/unmount volumes
|
||||
<LI><A HREF="api_dir.html">Directory</A> : list, create, change of directories,
|
||||
<LI><A HREF="api_file.html">File</A> : create, read and write files,
|
||||
<LI><A HREF="api_env.html">Environment</A> : initialize and shutdown the library, control its behaviour,
|
||||
<LI><A HREF="api_salv.html">Salvage</A> : undeletion, recovery,
|
||||
<LI><A HREF="api_native.html">Native API</A> : how to write real devices drivers on your OS,
|
||||
</UL>
|
||||
|
||||
<HR>
|
||||
|
||||
</BODY>
|
||||
|
||||
</HTML>
|
||||
231
doc/api_native.html
Normal file
231
doc/api_native.html
Normal file
@@ -0,0 +1,231 @@
|
||||
<HTML>
|
||||
<HEAD><TITLE> Native </TITLE></HEAD>
|
||||
|
||||
<BODY>
|
||||
|
||||
<H1 ALIGN=CENTER>the Native API</H1>
|
||||
|
||||
<HR>
|
||||
|
||||
<H1>Introduction</H1>
|
||||
|
||||
By default, the library is compiled to manage .ADF files (dump files) and
|
||||
plateform specific real devices like harddisk or removable disks
|
||||
(called native devices).<BR>
|
||||
At compile time, you can choose between available platforms like Win32/Intel
|
||||
for example. At run-time, it is possible to mount a dump device or a real device,
|
||||
several times.
|
||||
<P>
|
||||
To add a new plateform support into ADFlib, you must write your
|
||||
own files adf_nativ.h and adf_nativ.c for that platform. This driver is the link
|
||||
between the native API of the library and the platform specific functions to
|
||||
access the hardware.
|
||||
<P>
|
||||
The templates for those files are in Generic/.
|
||||
<P>
|
||||
The native API consists of :
|
||||
<P>
|
||||
1. The natives functions :
|
||||
|
||||
<UL>
|
||||
<LI><B>RETCODE</B> adfInitDevice(<B>struct Device*</B>, <B>char*</B>)
|
||||
<LI><B>RETCODE</B> adfReleaseDevice(<B>struct Device*</B>)
|
||||
<LI><B>RETCODE</B> adfNativeReadSector(<B>struct Device*</B>, <B>long</B>, <B>int</B>, <B>unsigned char*</B>)
|
||||
<LI><B>RETCODE</B> adfNativeWriteSector(<B>struct Device*</B>, <B>long</B>, <B>int</B>, <B>unsigned char*</B>)
|
||||
<LI><B>BOOL</B> adfIsDevNative(<B>char*</B>)
|
||||
<LI><B>void</B> adfInitNativeFct()
|
||||
</UL>
|
||||
|
||||
2. And two data structures devoted to native devices management :
|
||||
|
||||
<UL>
|
||||
<LI><B>struct nativeFunctions</B> stored in the library environment,
|
||||
<LI><B>struct nativeDevice</B> stored in the <B>struct Device</B> structure.
|
||||
</UL>
|
||||
|
||||
The author of the driver defines the <B>nativeDevice</B> structure
|
||||
and writes the expected functions below, with the expected parameters and the expected behaviours.
|
||||
<P>
|
||||
At the environment initialisation, a pointer of each function is stored in the
|
||||
<B>nativeFunctions</B> structure with adfInitNativeFct().
|
||||
<P>
|
||||
Here's how, for example, adfMountDev() call a native function : adfInitDevice() :
|
||||
<PRE>
|
||||
|
||||
struct Device* adfMountDev(char* filename)
|
||||
{
|
||||
struct nativeFunctions *nFct;
|
||||
struct Device* dev;
|
||||
|
||||
/* 'dev' memory allocation */
|
||||
|
||||
/* gets the native function pointers */
|
||||
nFct = (struct nativeFunctions*)adfEnv.nativeFct; /* was of type void* */
|
||||
|
||||
/* only once ! */
|
||||
dev->isNativeDev = (*nFct->adfIsDevNative)(filename);
|
||||
|
||||
/* choose dump or a real device initialisation */
|
||||
if (dev->isNativeDev)
|
||||
(*nFct->adfInitDevice)(dev, filename);
|
||||
else
|
||||
adfInitDumpDevice(dev, filename);
|
||||
|
||||
...
|
||||
|
||||
|
||||
</PRE>
|
||||
|
||||
<HR>
|
||||
|
||||
<H1>Data structures</H1>
|
||||
|
||||
<PRE>
|
||||
struct nativeFunctions{
|
||||
/* function pointers */
|
||||
RETCODE (*adfInitDevice)(struct Device*, char*);
|
||||
RETCODE (*adfNativeReadSector)(struct Device*, long, int, unsigned char*);
|
||||
RETCODE (*adfNativeWriteSector)(struct Device*, long, int, unsigned char*);
|
||||
BOOL (*adfIsDevNative)(char*);
|
||||
RETCODE (*adfReleaseDevice)();
|
||||
};
|
||||
|
||||
Those functions are detailed above.
|
||||
|
||||
struct nativeDevice{
|
||||
/* private to native functions, never used in the library, only in native functions */
|
||||
/* for the dump devices, this structure contains one field : FILE *fd */
|
||||
};
|
||||
|
||||
</PRE>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfInitDevice() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfInitDevice(<B>struct Device*</B> device, <B>char*</B> name)
|
||||
<P>
|
||||
You can choose another name, but the same parameters types and number, and
|
||||
the same return type.
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Initialise the native device.
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
RC_OK if everything went allright, something else otherwise.
|
||||
|
||||
<H2>Template</H2>
|
||||
|
||||
<PRE>
|
||||
RETCODE adfInitDevice(struct Device* dev, char* name)
|
||||
{
|
||||
struct nativeDevice* nDev;
|
||||
|
||||
/* the type was 'void*' */
|
||||
nDev = (struct nativeDevice*)dev->nativeDev;
|
||||
|
||||
nDev = (struct nativeDevice*)malloc(sizeof(struct nativeDevice));
|
||||
if (!nDev) {
|
||||
(*adfEnv.eFct)("myInitDevice : malloc");
|
||||
return RC_ERROR;
|
||||
}
|
||||
dev->nativeDev = nDev;
|
||||
|
||||
/*
|
||||
* specific device operations
|
||||
*
|
||||
* you MUST set the 'dev->size' field with the length in bytes of the physical media
|
||||
*/
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
</PRE>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfNativeReadSector() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfNativeReadSector(<B>struct Device*</B> device, <B>long</B> n, <B>int</B> size, <B>unsigned char*</B> buf)
|
||||
<P>
|
||||
You can choose another name, but the same parameters types and number, and
|
||||
the same return type.
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Move to 512*<I>n</I> bytes from the beginning of the media,
|
||||
and read <I>size</I> bytes into the <I>buf</I> buffer.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfNativeWriteSector() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfNativeWriteSector(<B>struct Device*</B> device, <B>long</B> n, <B>int</B> size, <B>unsigned char*</B> buf)
|
||||
<P>
|
||||
You can choose another name, but the same parameters types and number, and
|
||||
the same return type.
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Move to 512*<I>n</I> bytes from the beginning of the media,
|
||||
and write <I>size</I> bytes into the <I>buf</I> buffer.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfReleaseDevice() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfReleaseDevice(<B>struct Device*</B> device)
|
||||
<P>
|
||||
You can choose another name, but the same parameters types and number, and
|
||||
the same return type.
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Release the device.
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfIsDevNative() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfIsDevNative(<B>char*</B> name)
|
||||
<P>
|
||||
You can choose another name, but the same parameters types and number, and
|
||||
the same return type.
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
TRUE is the name points out a native device, FALSE otherwise.
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfInitDevice() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfInitDevice(<B>struct Device*</B> device, <B>char*</B> name)
|
||||
<P>
|
||||
You can choose another name, but the same parameters types and number, and
|
||||
the same return type.
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Initialise the nativeFunctions structure with the native functions addresses.
|
||||
|
||||
<HR>
|
||||
|
||||
</BODY>
|
||||
|
||||
</HTML>
|
||||
119
doc/api_salv.html
Normal file
119
doc/api_salv.html
Normal file
@@ -0,0 +1,119 @@
|
||||
<HTML>
|
||||
<HEAD><TITLE> Salvage </TITLE></HEAD>
|
||||
|
||||
<BODY>
|
||||
|
||||
<H1 ALIGN=CENTER>the Salvage API</H1>
|
||||
|
||||
|
||||
<HR>
|
||||
<H1>Typical usage</H1>
|
||||
|
||||
|
||||
<PRE>
|
||||
#include"adflib.h"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
struct List *list, *cell;
|
||||
|
||||
/* initialization */
|
||||
/* the device and volume are mounted */
|
||||
|
||||
cell = list = adfGetDelEnt(vol);
|
||||
while(cell) {
|
||||
block =(struct Block*) cell->content;
|
||||
printf("%s %d %d %ld\n",block->name,block->type,block->secType,
|
||||
block->sect);
|
||||
cell = cell->next;
|
||||
}
|
||||
/* we noted the entry 883 and 885 */
|
||||
adfFreeDelList(list);
|
||||
|
||||
/* 883 is a file */
|
||||
if (adfCheckEntry(vol,883,0)==RC_OK)
|
||||
adfUndelEntry(vol,vol->curDirPtr,883);
|
||||
|
||||
/* 885 is a directory */
|
||||
if (adfCheckEntry(vol,885,0)==RC_OK)
|
||||
adfUndelEntry(vol,vol->curDirPtr,885);
|
||||
|
||||
/* unmounts done */
|
||||
/* cleanup */
|
||||
}
|
||||
</PRE>
|
||||
|
||||
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfGetDelEnt() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>struct List*</B> adfGetDelEnt(<B>struct Volume *</B>vol)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Returns the list of the files/directories that MIGHT be undeleted. The
|
||||
entries must be checked before !
|
||||
<P>
|
||||
See <B>adfFreeDelList()</B> to free this list.<BR>
|
||||
See <B>adfCheckEntry()</B> to check if the entry could be undeleted.
|
||||
|
||||
<H2>Internals</H2>
|
||||
|
||||
Scans all the blocks of the volume to find directory blocks
|
||||
and file header blocks that are not allocated in the bitmap.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfCheckEntry() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfCheckEntry(<B>struct Volume*</B> vol, <B>SECTNUM</B> nSect, <B>int</B> level)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Checks if an entry (directory or file) could be undeleted.
|
||||
<P>
|
||||
The 'level' argument is not used yet. Could be set to 0.
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfUndelEntry()</FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfUndelEntry(<B>struct Volume*</B> vol, <B>SECTNUM</B> parent, <B>SECTNUM</B> nSect)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Undelete a directory or a file. The parent directory of an entry must exist.
|
||||
|
||||
<H2>Internals</H2>
|
||||
|
||||
Add the entry first block pointer in the parent directory list and allocated
|
||||
the related blocks in the bitmap.
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> void adfFreeDelList(struct List* list) </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>void</B> adfFreeDelList(<B>struct List*</B> list)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Free the list of deleted entries.
|
||||
<P>
|
||||
|
||||
|
||||
</BODY>
|
||||
|
||||
</HTML>
|
||||
171
doc/api_volume.html
Normal file
171
doc/api_volume.html
Normal file
@@ -0,0 +1,171 @@
|
||||
<HTML>
|
||||
<HEAD><TITLE> Volume </TITLE></HEAD>
|
||||
|
||||
<BODY>
|
||||
|
||||
<H1 ALIGN=CENTER>the Volume API</H1>
|
||||
|
||||
<HR>
|
||||
<H1>Use cases</H1>
|
||||
|
||||
<P>
|
||||
See Device API use cases.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<H1>Data structures</H1>
|
||||
|
||||
<PRE>
|
||||
struct Volume{
|
||||
struct Device *dev; /* the pointer of the Device structure of which the volume belongs to */
|
||||
|
||||
/* physical sector numbers */
|
||||
SECTNUM firstBlock; /* first block of the data area (from the beginning of the media) */
|
||||
SECTNUM lastBlock; /* last usable block (from the beginning of the media) */
|
||||
|
||||
/* logical sector number */
|
||||
SECTNUM rootBlock; /* root block (from firstBlock) */
|
||||
|
||||
char dosType; /* FFS/OFS, DIRCACHE, INTERNATIONAL */
|
||||
BOOL bootCode; /* TRUE if a floppy is bootable */
|
||||
int dataBlockSize; /* 488 or 512 */
|
||||
|
||||
char* volName;
|
||||
|
||||
/* bitmap */
|
||||
long bitmapSize; /* number of blocks used to store the bitmap
|
||||
(excluding the bitmapExtension blocks) */
|
||||
SECTNUM *bitmapBlocks; /* bitmap blocks pointers (excluding bitmap extensions blocks) */
|
||||
struct bBitmapBlock* *bitmapTable; /* stores the bitmap blocks */
|
||||
BOOL *bitmapBlocksChg; /* bitmapBlocksChg[i] is TRUE if bitmapTable[i} has changed,
|
||||
and need to be written at bitmapBlocks[i] */
|
||||
|
||||
SECTNUM curDirPtr; /* number of the current working directory */
|
||||
}
|
||||
</PRE>
|
||||
|
||||
<P>
|
||||
If <I>vol</I> is one Volume structure returned by adfMount() :
|
||||
<UL>
|
||||
<LI>The devType is <I>vol->dev->devType</I>.
|
||||
<LI>The dosType is OFS or FFS (exclusive), and may have the DIRCACHE and INTERNATIONAL
|
||||
modes enabled. Uses isFFS(vol->dosType), isOFS(), isINTL() and isDIRCACHE()
|
||||
to determine it.
|
||||
<BR>
|
||||
<B>Warning ! Even if isINTL() returns FALSE, if isDIRCACHE()
|
||||
is TRUE, the Volume is considered (like with AmigaDOS) as having the
|
||||
international mode enabled !</B>
|
||||
</UL>
|
||||
|
||||
<HR>
|
||||
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfMount() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>struct Volume*</B> adfMount(<B>struct Device *</B>dev,
|
||||
<B>int</B> nPart, <B>BOOL</B> readOnly)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
<P>
|
||||
Mounts a designed volume (nPart) of the Device (dev), eventually with
|
||||
read only access (readOnly). The first partition is #0.
|
||||
<P>
|
||||
The current working directory is the root block.
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
The Volume, NULL in case of error.
|
||||
|
||||
<H2>Internals</H2>
|
||||
<OL>
|
||||
<LI>Read the bootblock to determine <I>vol->dosType</I>
|
||||
and <I>vol->datablockSize</I>.
|
||||
<LI>Read the rootblock, fills <I>vol->curDirPtr</I>
|
||||
<LI>Read and allocate the bitmap : <I>vol->bitmapBlocks[],
|
||||
vol->bitmapTable[], vol->bitmapSize, vol->bitmapBlocksChg[]</I>.
|
||||
</OL>
|
||||
|
||||
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfUnMount() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>void</B> adfUnMount(<B>struct Volume *</B>vol)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Release a Volume. Free the bitmap structures.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfCountFreeBlocks() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>long</B> adfCountFreeBlocks(<B>struct Volume *</B>vol)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Counts the free blocks of a Volume.
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
The number of free blocks.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfInstallBootBlock() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfInstallBootBlock(<B>struct Volume*</B> vol, <B>unsigned char*</B> code)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Install a bootblock on a floppy disk. Won't work on any other device.
|
||||
<P>
|
||||
You must provide the 1024 bytes large bootblock.<BR>
|
||||
Doesn't modify the initial 'DOS' header and dosType. Recalculates the checksum.
|
||||
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
RC_OK, something different in case of error.
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<P ALIGN=CENTER><FONT SIZE=+2> adfCreateHdFile() </FONT></P>
|
||||
|
||||
<H2>Syntax</H2>
|
||||
|
||||
<B>RETCODE</B> adfCreateHdFile(<B>struct Device*</B> dev, <B>char*</B> volName, <B>int</B> volType)
|
||||
|
||||
<H2>Description</H2>
|
||||
|
||||
Create an hardfile on a dump file. The size of this file must be larger
|
||||
than 1802240 bytes, the size of an high density floppy dump.
|
||||
<P>
|
||||
Use adfCreateDumpDevice() the create the device passed to adfCreateHdFile().
|
||||
|
||||
<H2>Return values</H2>
|
||||
|
||||
RC_OK, something different in case of error.
|
||||
|
||||
<H2>Internals</H2>
|
||||
|
||||
The device is created with one volume, and <I>dev->devType if filled with
|
||||
DEVTYPE_HARDFILE.
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
</BODY>
|
||||
|
||||
</HTML>
|
||||
70
doc/version0.7.9d_gary.txt
Normal file
70
doc/version0.7.9d_gary.txt
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
ADFLib changes - Wednesday 16/10/02
|
||||
-----------------------------------
|
||||
|
||||
Background
|
||||
----------
|
||||
Bjark Viksoe changed ADFLib 0.7.9b in or before December 2001. Experimental
|
||||
version sent to me by Laurent in December 2001, soon to be released as 0.7.9c.
|
||||
Changes tried with ADFOpus then put aside due to difficulties compiling.
|
||||
Successfully tried again in October 2002, having neither heard anything more
|
||||
from Laurent nor seen a later version at the web site.
|
||||
|
||||
Bjark Viksoe's changes removed the dynamic projects and changed a number of
|
||||
parameters such as where compiled files were stored. These were potentially not
|
||||
portable and operated outside the compilation directory e.g. "..\..\AdfLib...",
|
||||
"C:\Temp".
|
||||
|
||||
Laurent's original settings were slightly at odds with common VC++ practice i.e. Win32
|
||||
and Debug directories used for compiled files rather than Release and Debug; Debug
|
||||
executables used Release libs rather than debug versions.
|
||||
|
||||
Enter Gary with a shiny version of ADF Opus to release and a desire to release it with
|
||||
a clean and equally shiny ADFLib 0.7.9c distribution.
|
||||
|
||||
|
||||
Method
|
||||
------
|
||||
I started with a clean installation of ADFLib 0.7.9b. Loading this into VC++ 6 SP5
|
||||
updated the project and workspace files to VC++ 6 versions. Next, I unpacked a clean
|
||||
installation of the potential 0.7.9c version received from Laurent. I then used WinDiff
|
||||
to determine exactly what changes Bjark had made and manually edited the 0.7.9b files
|
||||
to match.
|
||||
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
-Reinstated dynlib, dynunadf and staticunadf by starting with V0.7.9b.
|
||||
|
||||
-Returned to original ADFLib compilation settings as above, then made some subtle changes.
|
||||
|
||||
-Release output files now go to Bin/Win32/Release, rather than Bin/Win32, for
|
||||
symmetry and standardisation. Intermediate files still go to Release and Debug.
|
||||
|
||||
-Debug dynunadf and staticunadf now use the debug libs, not the release ones,
|
||||
to allow full debugger access.
|
||||
|
||||
-Fixed a path setting problem which caused a failure to find adflibd.lib.
|
||||
|
||||
-Changed Bjark's setting of "C7 Compatible" back to "Program Database for Edit and Continue"
|
||||
for consistency with the other projects.
|
||||
|
||||
-Annotated Bjark's changes with /* BV */ for easy identification.
|
||||
|
||||
-Removed C++ comment tags and replaced them with C tags across the board. ADFLib should
|
||||
hopefully be pure C again now.
|
||||
|
||||
-Removed a change implemented for Opus which was inadvertantly left in during earlier updates
|
||||
i.e. a string added to struct nativeDevice in adf_nativ.h.
|
||||
|
||||
-Updated Laurent's copyright on every page to include 2002.
|
||||
|
||||
-Updated the version and date strings to:
|
||||
#define ADFLIB_VERSION "0.7.9c"
|
||||
#define ADFLIB_DATE "16 October, 2002"
|
||||
|
||||
-Everything compiles cleanly with no warnings. :-)
|
||||
|
||||
-Bjark's changes appear to support non-standard FD ADFs up to 83 tracks. Can we confirm this?
|
||||
|
||||
6
examples/Makefile.am
Normal file
6
examples/Makefile.am
Normal file
@@ -0,0 +1,6 @@
|
||||
bin_PROGRAMS = unadf
|
||||
unadf_SOURCES = unadf.c
|
||||
unadf_LDADD = $(top_srcdir)/src/libadf.la
|
||||
unadf_DEPENDENCIES = $(top_srcdir)/src/libadf.la
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/$(NATIVE_DIR)
|
||||
|
||||
567
examples/unadf.c
Normal file
567
examples/unadf.c
Normal file
@@ -0,0 +1,567 @@
|
||||
/*
|
||||
* unadf 1.0
|
||||
*
|
||||
*
|
||||
* tested under Linux and Win32
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#define UNADF_VERSION "1.0"
|
||||
|
||||
|
||||
#include<stdlib.h>
|
||||
#include<errno.h>
|
||||
#include<string.h>
|
||||
|
||||
#include "adflib.h"
|
||||
|
||||
/* The portable way used to create a directory is to call the MKDIR command via the
|
||||
* system() function.
|
||||
* It is used to create the 'dir1' directory, like the 'dir1/dir11' directory
|
||||
*/
|
||||
|
||||
/* the portable way to check if a directory 'dir1' already exists i'm using is to
|
||||
* do fopen('dir1','rb'). NULL is returned if 'dir1' doesn't exists yet, an handle instead
|
||||
*/
|
||||
|
||||
#define MKDIR "mkdir"
|
||||
|
||||
#ifdef WIN32
|
||||
#define DIRSEP '\\'
|
||||
#else
|
||||
#define DIRSEP '/'
|
||||
#endif /* WIN32 */
|
||||
|
||||
#define EXTBUFL 1024*8
|
||||
|
||||
|
||||
void help()
|
||||
{
|
||||
puts("unadf [-lrcsp -v n] dumpname.adf [files-with-path] [-d extractdir]");
|
||||
puts(" -l : lists root directory contents");
|
||||
puts(" -r : lists directory tree contents");
|
||||
puts(" -c : use dircache data (must be used with -l)");
|
||||
puts(" -s : display entries logical block pointer (must be used with -l)");
|
||||
putchar('\n');
|
||||
puts(" -v n : mount volume #n instead of default #0 volume");
|
||||
putchar('\n');
|
||||
puts(" -p : send extracted files to pipe (unadf -p dump.adf Pics/pic1.gif | xv -)");
|
||||
puts(" -d dir : extract to 'dir' directory");
|
||||
}
|
||||
|
||||
void printEnt(struct Volume *vol, struct Entry* entry, char *path, BOOL sect)
|
||||
{
|
||||
/* do not print the links entries, ADFlib do not support them yet properly */
|
||||
if (entry->type==ST_LFILE || entry->type==ST_LDIR || entry->type==ST_LSOFT)
|
||||
return;
|
||||
|
||||
if (entry->type==ST_DIR)
|
||||
printf(" ");
|
||||
else
|
||||
printf("%7ld ",entry->size);
|
||||
|
||||
printf("%4d/%02d/%02d %2d:%02d:%02d ",entry->year, entry->month, entry->days,
|
||||
entry->hour, entry->mins, entry->secs);
|
||||
if (sect)
|
||||
printf(" %06ld ",entry->sector);
|
||||
|
||||
if (strlen(path)>0)
|
||||
printf(" %s/",path);
|
||||
else
|
||||
printf(" ");
|
||||
if (entry->type==ST_DIR)
|
||||
printf("%s/",entry->name);
|
||||
else
|
||||
printf("%s",entry->name);
|
||||
if (entry->comment!=NULL && strlen(entry->comment)>0)
|
||||
printf(", %s",entry->comment);
|
||||
putchar('\n');
|
||||
|
||||
}
|
||||
|
||||
|
||||
void extractFile(struct Volume *vol, char* name, char* path, unsigned char *extbuf,
|
||||
BOOL pflag, BOOL qflag)
|
||||
{
|
||||
struct File *file;
|
||||
FILE* out;
|
||||
long n;
|
||||
char *filename;
|
||||
|
||||
filename = NULL;
|
||||
if (pflag)
|
||||
out = stdout;
|
||||
else {
|
||||
if (strlen(path)>0) {
|
||||
filename=(char*)malloc(sizeof(char)* (strlen(path)+1+strlen(name)+1) );
|
||||
if (!filename) return;
|
||||
sprintf(filename,"%s%c%s",path,DIRSEP,name);
|
||||
out = fopen(filename, "wb");
|
||||
}
|
||||
else
|
||||
out = fopen(name, "wb");
|
||||
if (!out) return;
|
||||
}
|
||||
|
||||
file = adfOpenFile(vol, name, "r");
|
||||
if (!file) { fclose(out); return; }
|
||||
|
||||
n = adfReadFile(file, EXTBUFL, extbuf);
|
||||
while(!adfEndOfFile(file)) {
|
||||
fwrite(extbuf, sizeof(unsigned char), n, out);
|
||||
n = adfReadFile(file, EXTBUFL, extbuf);
|
||||
}
|
||||
if (n>0)
|
||||
fwrite(extbuf, sizeof(unsigned char), n, out);
|
||||
|
||||
if (!pflag)
|
||||
fclose(out);
|
||||
|
||||
adfCloseFile(file);
|
||||
|
||||
if (!qflag) {
|
||||
if (filename!=NULL)
|
||||
printf("x - %s\n", filename);
|
||||
else
|
||||
printf("x - %s\n", name);
|
||||
}
|
||||
|
||||
if (filename!=NULL)
|
||||
free(filename);
|
||||
}
|
||||
|
||||
|
||||
void extractTree(struct Volume *vol, struct List* tree, char *path, unsigned char *extbuf,
|
||||
BOOL pflag, BOOL qflag)
|
||||
{
|
||||
struct Entry* entry;
|
||||
char *buf;
|
||||
char sysbuf[200];
|
||||
|
||||
while(tree) {
|
||||
entry = (struct Entry*)tree->content;
|
||||
if (entry->type==ST_DIR) {
|
||||
buf = NULL;
|
||||
if (strlen(path)>0) {
|
||||
buf=(char*)malloc(strlen(path)+1+strlen(entry->name)+1);
|
||||
if (!buf) return;
|
||||
sprintf(buf,"%s%c%s",path,DIRSEP,entry->name);
|
||||
sprintf(sysbuf,"%s %s",MKDIR,buf);
|
||||
if (!qflag) printf("x - %s%c\n",buf,DIRSEP);
|
||||
}
|
||||
else {
|
||||
sprintf(sysbuf,"%s %s",MKDIR,entry->name);
|
||||
if (!qflag) printf("x - %s%c\n",entry->name,DIRSEP);
|
||||
}
|
||||
|
||||
if (!pflag) system(sysbuf);
|
||||
|
||||
if (tree->subdir!=NULL) {
|
||||
if (adfChangeDir(vol,entry->name)==RC_OK) {
|
||||
if (buf!=NULL)
|
||||
extractTree(vol,tree->subdir,buf,extbuf, pflag, qflag);
|
||||
else
|
||||
extractTree(vol,tree->subdir,entry->name,extbuf, pflag, qflag);
|
||||
adfParentDir(vol);
|
||||
}
|
||||
else {
|
||||
if (strlen(path)>0)
|
||||
fprintf(stderr,"ExtractTree : dir \"%s/%s\" not found.\n",path,entry->name);
|
||||
else
|
||||
fprintf(stderr,"ExtractTree : dir \"%s\" not found.\n",entry->name);
|
||||
}
|
||||
}
|
||||
|
||||
if (buf!=NULL)
|
||||
free(buf);
|
||||
}
|
||||
else if (entry->type==ST_FILE) {
|
||||
extractFile(vol,entry->name,path,extbuf, pflag, qflag);
|
||||
}
|
||||
tree = tree->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printTree(struct Volume *vol, struct List* tree, char* path, BOOL sect)
|
||||
{
|
||||
char *buf;
|
||||
struct Entry* entry;
|
||||
|
||||
while(tree) {
|
||||
printEnt(vol, tree->content, path, sect);
|
||||
if (tree->subdir!=NULL) {
|
||||
entry = (struct Entry*)tree->content;
|
||||
if (strlen(path)>0) {
|
||||
buf=(char*)malloc(sizeof(char)* (strlen(path)+1+strlen(entry->name)+1) );
|
||||
if (!buf) {
|
||||
fprintf(stderr,"printTree : malloc error\n");
|
||||
return;
|
||||
}
|
||||
sprintf(buf,"%s/%s", path, entry->name);
|
||||
printTree(vol, tree->subdir, buf, sect);
|
||||
free(buf);
|
||||
}
|
||||
else
|
||||
printTree(vol, tree->subdir, entry->name, sect);
|
||||
}
|
||||
tree = tree->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printDev(struct Device* dev)
|
||||
{
|
||||
printf("Device : ");
|
||||
|
||||
switch(dev->devType){
|
||||
case DEVTYPE_FLOPDD:
|
||||
printf("Floppy DD"); break;
|
||||
case DEVTYPE_FLOPHD:
|
||||
printf("Floppy HD"); break;
|
||||
case DEVTYPE_HARDDISK:
|
||||
printf("Harddisk"); break;
|
||||
case DEVTYPE_HARDFILE:
|
||||
printf("Hardfile"); break;
|
||||
default:
|
||||
printf("???"); break;
|
||||
}
|
||||
|
||||
printf(". Cylinders = %ld, Heads = %ld, Sectors = %ld",dev->cylinders,dev->heads,dev->sectors);
|
||||
|
||||
printf(". Volumes = %d\n",dev->nVol);
|
||||
}
|
||||
|
||||
|
||||
void printVol(struct Volume* vol, int volNum)
|
||||
{
|
||||
printf("Volume : ");
|
||||
|
||||
switch(vol->dev->devType) {
|
||||
case DEVTYPE_FLOPDD:
|
||||
printf ("Floppy 880 KBytes,");
|
||||
break;
|
||||
case DEVTYPE_FLOPHD:
|
||||
printf ("Floppy 1760 KBytes,");
|
||||
break;
|
||||
case DEVTYPE_HARDDISK:
|
||||
printf ("HD partition #%d %3.1f KBytes,", volNum, (vol->lastBlock - vol->firstBlock +1) * 512.0/1024.0);
|
||||
break;
|
||||
case DEVTYPE_HARDFILE:
|
||||
printf ("HardFile %3.1f KBytes,", (vol->lastBlock - vol->firstBlock +1) * 512.0/1024.0);
|
||||
break;
|
||||
default:
|
||||
printf ("???,");
|
||||
}
|
||||
|
||||
if (vol->volName!=NULL)
|
||||
printf(" \"%s\"", vol->volName);
|
||||
|
||||
printf(" between sectors [%ld-%ld].",vol->firstBlock, vol->lastBlock);
|
||||
|
||||
printf(" %s ",isFFS(vol->dosType) ? "FFS" : "OFS");
|
||||
if (isINTL(vol->dosType))
|
||||
printf ("INTL ");
|
||||
if (isDIRCACHE(vol->dosType))
|
||||
printf ("DIRCACHE ");
|
||||
|
||||
printf(". Filled at %2.1f%%.\n", 100.0-
|
||||
(adfCountFreeBlocks(vol)*100.0)/(vol->lastBlock - vol->firstBlock +1) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void processFile(struct Volume *vol, char* name, char* path, unsigned char *extbuf,
|
||||
BOOL pflag, BOOL qflag)
|
||||
{
|
||||
char *sepptr, *cdstr, *fullname, *filename;
|
||||
char *bigstr;
|
||||
FILE *tfile;
|
||||
|
||||
adfToRootDir(vol);
|
||||
|
||||
sepptr = strchr(name, '/');
|
||||
if (sepptr==NULL) {
|
||||
extractFile(vol, name, path, extbuf, pflag, qflag);
|
||||
}
|
||||
else {
|
||||
/* the all-in-one string : to call system(), to find the filename, the convert dir sep char ... */
|
||||
bigstr=(char*)malloc(strlen(MKDIR)+1+strlen(path)+1+strlen(name)+1);
|
||||
if (!bigstr) { fprintf(stderr,"processFile : malloc"); return; }
|
||||
|
||||
/* to build to extract path */
|
||||
if (strlen(path)>0) {
|
||||
sprintf(bigstr,"%s %s%c%s",MKDIR,path,DIRSEP,name);
|
||||
cdstr = bigstr+strlen(MKDIR)+1+strlen(path)+1;
|
||||
}
|
||||
else {
|
||||
sprintf(bigstr,"%s %s",MKDIR,name);
|
||||
cdstr = bigstr+strlen(MKDIR)+1;
|
||||
}
|
||||
/* the directory in which the file will be extracted */
|
||||
fullname = bigstr+strlen(MKDIR)+1;
|
||||
|
||||
/* finds the filename, and separates it from the path */
|
||||
filename = strrchr(bigstr,'/')+1;
|
||||
filename[-1]='\0';
|
||||
|
||||
sepptr = cdstr;
|
||||
/* find the end of the first dir to create */
|
||||
while(sepptr[0]!='/' && sepptr[0]!='\0')
|
||||
sepptr++;
|
||||
|
||||
while(strlen(cdstr)>0) {
|
||||
if (sepptr[0]=='/') { /* not the last one */
|
||||
sepptr[0]='\0';
|
||||
if (adfChangeDir(vol,cdstr)!=RC_OK)
|
||||
return;
|
||||
tfile = fopen(fullname,"r"); /* the only portable way to test if the dir exists */
|
||||
if (tfile==NULL) { /* does't exist : create it */
|
||||
if (!pflag) system(bigstr);
|
||||
if (!qflag) printf("x - %s%c\n",fullname,DIRSEP);
|
||||
}
|
||||
else
|
||||
fclose(tfile);
|
||||
sepptr[0] = DIRSEP; /* converts the '/' to '/' or '\' */
|
||||
cdstr = sepptr+1; /* next beginning of the next dir to create */
|
||||
/* to find the end of the next dir */
|
||||
sepptr++;
|
||||
while(sepptr[0]!='/' && sepptr[0]!='\0')
|
||||
sepptr++;
|
||||
}
|
||||
else { /* the last one */
|
||||
if (adfChangeDir(vol,cdstr)!=RC_OK)
|
||||
return;
|
||||
tfile = fopen(fullname,"r");
|
||||
if (tfile==NULL) {
|
||||
if (!pflag) system(bigstr);
|
||||
if (!qflag) printf("x - %s%c\n",fullname,DIRSEP);
|
||||
}
|
||||
else
|
||||
fclose(tfile);
|
||||
cdstr = cdstr+strlen(cdstr); /* at the end, ends the while loop */
|
||||
}
|
||||
}
|
||||
extractFile(vol, filename, fullname, extbuf, pflag, qflag);
|
||||
|
||||
free(bigstr);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int i, j;
|
||||
BOOL rflag, lflag, xflag, cflag, vflag, sflag, dflag, pflag, qflag;
|
||||
struct List* files, *rtfiles;
|
||||
char *devname, *dirname;
|
||||
char strbuf[80];
|
||||
unsigned char *extbuf;
|
||||
int vInd, dInd, fInd, aInd;
|
||||
BOOL nextArg;
|
||||
|
||||
struct Device *dev;
|
||||
struct Volume *vol;
|
||||
struct List *list, *cell;
|
||||
int volNum;
|
||||
BOOL true = TRUE;
|
||||
|
||||
if (argc<2) {
|
||||
help();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
rflag = lflag = cflag = vflag = sflag = dflag = pflag = qflag = FALSE;
|
||||
vInd = dInd = fInd = aInd = -1;
|
||||
xflag = TRUE;
|
||||
dirname = NULL;
|
||||
devname = NULL;
|
||||
files = rtfiles = NULL;
|
||||
volNum = 0;
|
||||
|
||||
fprintf(stderr,"unADF v%s : a unzip like for .ADF files, powered by ADFlib (v%s - %s)\n\n",
|
||||
UNADF_VERSION, adfGetVersionNumber(),adfGetVersionDate());
|
||||
|
||||
/* parse options */
|
||||
i=1;
|
||||
while(i<argc) {
|
||||
if (argv[i][0]=='-') {
|
||||
j=1;
|
||||
nextArg = FALSE;
|
||||
while(j<(int)strlen(argv[i]) && !nextArg) {
|
||||
switch(argv[i][j]) {
|
||||
case 'v':
|
||||
vflag = TRUE;
|
||||
if ((i+1)<(argc-1)) {
|
||||
i++;
|
||||
nextArg = TRUE;
|
||||
errno = 0;
|
||||
volNum = atoi(argv[i]);
|
||||
if (errno!=0 || volNum<0) {
|
||||
fprintf(stderr,"invalid volume number, aborting.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
fprintf(stderr,"no volume number, -v option ignored.\n");
|
||||
break;
|
||||
case 'l':
|
||||
lflag = TRUE;
|
||||
xflag = FALSE;
|
||||
break;
|
||||
case 's':
|
||||
sflag = TRUE;
|
||||
break;
|
||||
case 'c':
|
||||
cflag = TRUE;
|
||||
break;
|
||||
case 'r':
|
||||
rflag = TRUE;
|
||||
break;
|
||||
case 'd':
|
||||
if (devname!=NULL && xflag && (i+1)==(argc-1)) {
|
||||
i++;
|
||||
dirname = argv[i];
|
||||
if (dirname[strlen(dirname)-1]==DIRSEP)
|
||||
dirname[strlen(dirname)-1]='\0';
|
||||
nextArg = TRUE;
|
||||
dflag = TRUE;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
if (xflag) {
|
||||
fprintf(stderr,"sending files to pipe.\n");
|
||||
pflag = TRUE;
|
||||
qflag = TRUE;
|
||||
}
|
||||
else
|
||||
fprintf(stderr,"-p option must be used with extraction, ignored.\n");
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
help();
|
||||
exit(0);
|
||||
} /* switch */
|
||||
j++;
|
||||
} /* while */
|
||||
} /* if */
|
||||
else {
|
||||
/* the last non option string is taken as a filename */
|
||||
if (devname==NULL) /* if the device name has been already given */
|
||||
devname = argv[i];
|
||||
else {
|
||||
if (xflag) {
|
||||
if (rtfiles==NULL)
|
||||
rtfiles = files = newCell(NULL, (void*)argv[i]);
|
||||
else
|
||||
files = newCell(files, (void*)argv[i]);
|
||||
}
|
||||
else
|
||||
fprintf(stderr,"Must be used with extraction, ignored.\n");
|
||||
}
|
||||
}
|
||||
i++;
|
||||
} /* while */
|
||||
|
||||
extbuf =(unsigned char*)malloc(EXTBUFL*sizeof(char));
|
||||
if (!extbuf) { fprintf(stderr,"malloc error\n"); exit(1); }
|
||||
|
||||
/* initialize the library */
|
||||
adfEnvInitDefault();
|
||||
|
||||
dev = adfMountDev( devname,TRUE );
|
||||
if (!dev) {
|
||||
sprintf(strbuf,"Can't mount the dump device '%s'.\n", devname);
|
||||
fprintf(stderr, strbuf);
|
||||
adfEnvCleanUp(); exit(1);
|
||||
}
|
||||
if (!qflag)
|
||||
printDev(dev);
|
||||
|
||||
if (volNum>=dev->nVol) {
|
||||
fprintf(stderr,"This device has only %d volume(s), aborting.\n",dev->nVol);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
vol = adfMount(dev, volNum, TRUE);
|
||||
if (!vol) {
|
||||
adfUnMountDev(dev);
|
||||
fprintf(stderr, "Can't mount the volume\n");
|
||||
adfEnvCleanUp(); exit(1);
|
||||
}
|
||||
|
||||
if (!qflag) {
|
||||
printVol(vol, volNum);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
if (cflag && isDIRCACHE(vol->dosType) && lflag) {
|
||||
adfChgEnvProp(PR_USEDIRC,&true);
|
||||
if (!qflag)
|
||||
puts("Using dir cache blocks.");
|
||||
}
|
||||
|
||||
if (lflag) {
|
||||
if (!rflag) {
|
||||
cell = list = adfGetDirEnt(vol,vol->curDirPtr);
|
||||
while(cell) {
|
||||
printEnt(vol,cell->content,"", sflag);
|
||||
cell = cell->next;
|
||||
}
|
||||
adfFreeDirList(list);
|
||||
} else {
|
||||
cell = list = adfGetRDirEnt(vol,vol->curDirPtr,TRUE);
|
||||
printTree(vol,cell,"", sflag);
|
||||
adfFreeDirList(list);
|
||||
}
|
||||
}else if (xflag) {
|
||||
if (rtfiles!=NULL) {
|
||||
files = rtfiles;
|
||||
while(files!=NULL) {
|
||||
if (dirname!=NULL)
|
||||
processFile(vol, (char*)files->content, dirname, extbuf, pflag, qflag);
|
||||
else
|
||||
processFile(vol, (char*)files->content, "", extbuf, pflag, qflag);
|
||||
files = files->next;
|
||||
}
|
||||
freeList(rtfiles);
|
||||
}
|
||||
else {
|
||||
cell = list = adfGetRDirEnt(vol,vol->curDirPtr,TRUE);
|
||||
if (dirname==NULL)
|
||||
extractTree(vol, cell, "", extbuf, pflag, qflag);
|
||||
else
|
||||
extractTree(vol, cell, dirname, extbuf, pflag, qflag);
|
||||
adfFreeDirList(list);
|
||||
}
|
||||
}
|
||||
else
|
||||
help();
|
||||
|
||||
free(extbuf);
|
||||
|
||||
adfUnMount(vol);
|
||||
adfUnMountDev(dev);
|
||||
|
||||
adfEnvCleanUp();
|
||||
|
||||
return(0);
|
||||
}
|
||||
1215
examples/unadf.output
Normal file
1215
examples/unadf.output
Normal file
File diff suppressed because it is too large
Load Diff
10
examples/unadf.usage
Normal file
10
examples/unadf.usage
Normal file
@@ -0,0 +1,10 @@
|
||||
unadf [-lrcsp -v n] dumpname.adf [files-with-path] [-d extractdir]
|
||||
-l : lists root directory contents
|
||||
-r : lists directory tree contents
|
||||
-c : use dircache data (must be used with -l)
|
||||
-s : display entries logical block pointer (must be used with -l)
|
||||
|
||||
-v n : mount volume #n instead of default #0 volume
|
||||
|
||||
-p : send extracted files to pipe (unadf -p dump.adf Pics/pic1.gif | xv -)
|
||||
-d dir : extract to 'dir' directory
|
||||
44
src/Makefile.am
Normal file
44
src/Makefile.am
Normal file
@@ -0,0 +1,44 @@
|
||||
NATIVE_DIR = generic
|
||||
|
||||
lib_LTLIBRARIES = libadf.la
|
||||
|
||||
libadf_la_SOURCES = adf_hd.c \
|
||||
adf_disk.c \
|
||||
adf_raw.c \
|
||||
adf_bitm.c \
|
||||
adf_dump.c \
|
||||
adf_util.c \
|
||||
adf_env.c \
|
||||
$(NATIVE_DIR)/adf_nativ.c \
|
||||
adf_dir.c \
|
||||
adf_file.c \
|
||||
adf_cache.c \
|
||||
adf_link.c \
|
||||
adf_salv.c
|
||||
|
||||
include_HEADERS = adf_defs.h \
|
||||
adf_blk.h \
|
||||
adf_err.h \
|
||||
adf_str.h \
|
||||
adflib.h \
|
||||
adf_bitm.h \
|
||||
adf_cache.h \
|
||||
adf_dir.h \
|
||||
adf_disk.h \
|
||||
adf_dump.h \
|
||||
adf_env.h \
|
||||
adf_file.h \
|
||||
adf_hd.h \
|
||||
adf_link.h \
|
||||
adf_raw.h \
|
||||
adf_salv.h \
|
||||
adf_util.h \
|
||||
defendian.h \
|
||||
hd_blk.h \
|
||||
prefix.h \
|
||||
$(NATIVE_DIR)/adf_nativ.h
|
||||
|
||||
libadf_la_LDFLAGS = -version-info 0:12:0
|
||||
AM_CPPFLAGS = -D_XOPEN_SOURCE -D_SVID_SOURCE -D_BSD_SOURCE -D_GNU_SOURCE -I$(srcdir) -I$(srcdir)/$(NATIVE_DIR)
|
||||
AM_CFLAGS = -std=c99 -pedantic -Wall
|
||||
|
||||
561
src/adf_bitm.c
Normal file
561
src/adf_bitm.c
Normal file
@@ -0,0 +1,561 @@
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_bitm.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* bitmap code
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include"adf_raw.h"
|
||||
#include"adf_bitm.h"
|
||||
#include"adf_err.h"
|
||||
#include"adf_disk.h"
|
||||
#include"adf_util.h"
|
||||
#include"defendian.h"
|
||||
|
||||
extern uint32_t bitMask[32];
|
||||
|
||||
extern struct Env adfEnv;
|
||||
|
||||
/*
|
||||
* adfUpdateBitmap
|
||||
*
|
||||
*/
|
||||
RETCODE adfUpdateBitmap(struct Volume *vol)
|
||||
{
|
||||
int i;
|
||||
struct bRootBlock root;
|
||||
|
||||
/*printf("adfUpdateBitmap\n");*/
|
||||
|
||||
if (adfReadRootBlock(vol, vol->rootBlock,&root)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
root.bmFlag = BM_INVALID;
|
||||
if (adfWriteRootBlock(vol,vol->rootBlock,&root)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
for(i=0; i<vol->bitmapSize; i++)
|
||||
if (vol->bitmapBlocksChg[i]) {
|
||||
if (adfWriteBitmapBlock(vol, vol->bitmapBlocks[i], vol->bitmapTable[i])!=RC_OK)
|
||||
return RC_ERROR;
|
||||
vol->bitmapBlocksChg[i] = FALSE;
|
||||
}
|
||||
|
||||
root.bmFlag = BM_VALID;
|
||||
adfTime2AmigaTime(adfGiveCurrentTime(),&(root.days),&(root.mins),&(root.ticks));
|
||||
if (adfWriteRootBlock(vol,vol->rootBlock,&root)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfCountFreeBlocks
|
||||
*
|
||||
*/
|
||||
int32_t adfCountFreeBlocks(struct Volume* vol)
|
||||
{
|
||||
int32_t freeBlocks;
|
||||
int j;
|
||||
|
||||
freeBlocks = 0L;
|
||||
for(j=vol->firstBlock+2; j<=(vol->lastBlock - vol->firstBlock); j++)
|
||||
if ( adfIsBlockFree(vol,j) )
|
||||
freeBlocks++;
|
||||
|
||||
return freeBlocks;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfReadBitmap
|
||||
*
|
||||
*/
|
||||
RETCODE adfReadBitmap(struct Volume* vol, int32_t nBlock, struct bRootBlock* root)
|
||||
{
|
||||
int32_t mapSize, nSect;
|
||||
int32_t j, i;
|
||||
struct bBitmapExtBlock bmExt;
|
||||
|
||||
mapSize = nBlock / (127*32);
|
||||
if ( (nBlock%(127*32))!=0 )
|
||||
mapSize++;
|
||||
vol->bitmapSize = mapSize;
|
||||
|
||||
vol->bitmapTable = (struct bBitmapBlock**) malloc(sizeof(struct bBitmapBlock*)*mapSize);
|
||||
if (!vol->bitmapTable) {
|
||||
(*adfEnv.eFct)("adfReadBitmap : malloc, vol->bitmapTable");
|
||||
return RC_MALLOC;
|
||||
}
|
||||
vol->bitmapBlocks = (SECTNUM*) malloc(sizeof(SECTNUM)*mapSize);
|
||||
if (!vol->bitmapBlocks) {
|
||||
free(vol->bitmapTable);
|
||||
(*adfEnv.eFct)("adfReadBitmap : malloc, vol->bitmapBlocks");
|
||||
return RC_MALLOC;
|
||||
}
|
||||
vol->bitmapBlocksChg = (BOOL*) malloc(sizeof(BOOL)*mapSize);
|
||||
if (!vol->bitmapBlocksChg) {
|
||||
free(vol->bitmapTable); free(vol->bitmapBlocks);
|
||||
(*adfEnv.eFct)("adfReadBitmap : malloc, vol->bitmapBlocks");
|
||||
return RC_MALLOC;
|
||||
}
|
||||
for(i=0; i<mapSize; i++) {
|
||||
vol->bitmapBlocksChg[i] = FALSE;
|
||||
|
||||
vol->bitmapTable[i] = (struct bBitmapBlock*)malloc(sizeof(struct bBitmapBlock));
|
||||
if (!vol->bitmapTable[i]) {
|
||||
free(vol->bitmapBlocksChg); free(vol->bitmapBlocks);
|
||||
for(j=0; j<i; j++)
|
||||
free(vol->bitmapTable[j]);
|
||||
free(vol->bitmapTable);
|
||||
(*adfEnv.eFct)("adfReadBitmap : malloc, vol->bitmapBlocks");
|
||||
return RC_MALLOC;
|
||||
}
|
||||
}
|
||||
|
||||
j=0; i=0;
|
||||
/* bitmap pointers in rootblock : 0 <= i <BM_SIZE */
|
||||
while(i<BM_SIZE && root->bmPages[i]!=0) {
|
||||
vol->bitmapBlocks[j] = nSect = root->bmPages[i];
|
||||
if ( !isSectNumValid(vol,nSect) ) {
|
||||
(*adfEnv.wFct)("adfReadBitmap : sector out of range");
|
||||
}
|
||||
|
||||
if (adfReadBitmapBlock(vol, nSect, vol->bitmapTable[j])!=RC_OK) {
|
||||
adfFreeBitmap(vol);
|
||||
return RC_ERROR;
|
||||
}
|
||||
j++; i++;
|
||||
}
|
||||
nSect = root->bmExt;
|
||||
while(nSect!=0) {
|
||||
/* bitmap pointers in bitmapExtBlock, j <= mapSize */
|
||||
if (adfReadBitmapExtBlock(vol, nSect, &bmExt)!=RC_OK) {
|
||||
adfFreeBitmap(vol);
|
||||
return RC_ERROR;
|
||||
}
|
||||
i=0;
|
||||
while(i<127 && j<mapSize) {
|
||||
nSect = bmExt.bmPages[i];
|
||||
if ( !isSectNumValid(vol,nSect) )
|
||||
(*adfEnv.wFct)("adfReadBitmap : sector out of range");
|
||||
vol->bitmapBlocks[j] = nSect;
|
||||
|
||||
if (adfReadBitmapBlock(vol, nSect, vol->bitmapTable[j])!=RC_OK) {
|
||||
adfFreeBitmap(vol);
|
||||
return RC_ERROR;
|
||||
}
|
||||
i++; j++;
|
||||
}
|
||||
nSect = bmExt.nextBlock;
|
||||
}
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfIsBlockFree
|
||||
*
|
||||
*/
|
||||
BOOL adfIsBlockFree(struct Volume* vol, SECTNUM nSect)
|
||||
{
|
||||
int sectOfMap = nSect-2;
|
||||
int block = sectOfMap/(127*32);
|
||||
int indexInMap = (sectOfMap/32)%127;
|
||||
|
||||
/*printf("sect=%d block=%d ind=%d, ",sectOfMap,block,indexInMap);
|
||||
printf("bit=%d, ",sectOfMap%32);
|
||||
printf("bitm=%x, ",bitMask[ sectOfMap%32]);
|
||||
printf("res=%x, ",vol->bitmapTable[ block ]->map[ indexInMap ]
|
||||
& bitMask[ sectOfMap%32 ]);
|
||||
*/
|
||||
return ( (vol->bitmapTable[ block ]->map[ indexInMap ]
|
||||
& bitMask[ sectOfMap%32 ])!=0 );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfSetBlockFree OK
|
||||
*
|
||||
*/
|
||||
void adfSetBlockFree(struct Volume* vol, SECTNUM nSect)
|
||||
{
|
||||
uint32_t oldValue;
|
||||
int sectOfMap = nSect-2;
|
||||
int block = sectOfMap/(127*32);
|
||||
int indexInMap = (sectOfMap/32)%127;
|
||||
|
||||
/*printf("sect=%d block=%d ind=%d, ",sectOfMap,block,indexInMap);
|
||||
printf("bit=%d, ",sectOfMap%32);
|
||||
*printf("bitm=%x, ",bitMask[ sectOfMap%32]);*/
|
||||
|
||||
oldValue = vol->bitmapTable[ block ]->map[ indexInMap ];
|
||||
/*printf("old=%x, ",oldValue);*/
|
||||
vol->bitmapTable[ block ]->map[ indexInMap ]
|
||||
= oldValue | bitMask[ sectOfMap%32 ];
|
||||
/*printf("new=%x, ",vol->bitmapTable[ block ]->map[ indexInMap ]);*/
|
||||
|
||||
vol->bitmapBlocksChg[ block ] = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfSetBlockUsed
|
||||
*
|
||||
*/
|
||||
void adfSetBlockUsed(struct Volume* vol, SECTNUM nSect)
|
||||
{
|
||||
uint32_t oldValue;
|
||||
int sectOfMap = nSect-2;
|
||||
int block = sectOfMap/(127*32);
|
||||
int indexInMap = (sectOfMap/32)%127;
|
||||
|
||||
oldValue = vol->bitmapTable[ block ]->map[ indexInMap ];
|
||||
|
||||
vol->bitmapTable[ block ]->map[ indexInMap ]
|
||||
= oldValue & (~bitMask[ sectOfMap%32 ]);
|
||||
vol->bitmapBlocksChg[ block ] = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfGet1FreeBlock
|
||||
*
|
||||
*/
|
||||
SECTNUM adfGet1FreeBlock(struct Volume *vol) {
|
||||
SECTNUM block[1];
|
||||
if (!adfGetFreeBlocks(vol,1,block))
|
||||
return(-1);
|
||||
else
|
||||
return(block[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* adfGetFreeBlocks
|
||||
*
|
||||
*/
|
||||
BOOL adfGetFreeBlocks(struct Volume* vol, int nbSect, SECTNUM* sectList)
|
||||
{
|
||||
int i, j;
|
||||
BOOL diskFull;
|
||||
int32_t block = vol->rootBlock;
|
||||
|
||||
i = 0;
|
||||
diskFull = FALSE;
|
||||
/*printf("lastblock=%ld\n",vol->lastBlock);*/
|
||||
while( i<nbSect && !diskFull ) {
|
||||
if ( adfIsBlockFree(vol, block) ) {
|
||||
sectList[i] = block;
|
||||
i++;
|
||||
}
|
||||
/* if ( block==vol->lastBlock )
|
||||
block = vol->firstBlock+2;*/
|
||||
if ( (block+vol->firstBlock)==vol->lastBlock )
|
||||
block = 2;
|
||||
else if (block==vol->rootBlock-1)
|
||||
diskFull = TRUE;
|
||||
else
|
||||
block++;
|
||||
}
|
||||
|
||||
if (!diskFull)
|
||||
for(j=0; j<nbSect; j++)
|
||||
adfSetBlockUsed( vol, sectList[j] );
|
||||
|
||||
return (i==nbSect);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfCreateBitmap
|
||||
*
|
||||
* create bitmap structure in vol
|
||||
*/
|
||||
RETCODE adfCreateBitmap(struct Volume *vol)
|
||||
{
|
||||
int32_t nBlock, mapSize ;
|
||||
int i, j;
|
||||
|
||||
nBlock = vol->lastBlock - vol->firstBlock +1 - 2;
|
||||
|
||||
mapSize = nBlock / (127*32);
|
||||
if ( (nBlock%(127*32))!=0 )
|
||||
mapSize++;
|
||||
vol->bitmapSize = mapSize;
|
||||
|
||||
vol->bitmapTable = (struct bBitmapBlock**)malloc( sizeof(struct bBitmapBlock*)*mapSize );
|
||||
if (!vol->bitmapTable) {
|
||||
(*adfEnv.eFct)("adfCreateBitmap : malloc, vol->bitmapTable");
|
||||
return RC_MALLOC;
|
||||
}
|
||||
|
||||
vol->bitmapBlocksChg = (BOOL*) malloc(sizeof(BOOL)*mapSize);
|
||||
if (!vol->bitmapBlocksChg) {
|
||||
free(vol->bitmapTable);
|
||||
(*adfEnv.eFct)("adfCreateBitmap : malloc, vol->bitmapBlocksChg");
|
||||
return RC_MALLOC;
|
||||
}
|
||||
|
||||
vol->bitmapBlocks = (SECTNUM*) malloc(sizeof(SECTNUM)*mapSize);
|
||||
if (!vol->bitmapBlocks) {
|
||||
free(vol->bitmapTable); free(vol->bitmapBlocksChg);
|
||||
(*adfEnv.eFct)("adfCreateBitmap : malloc, vol->bitmapBlocks");
|
||||
return RC_MALLOC;
|
||||
}
|
||||
|
||||
for(i=0; i<mapSize; i++) {
|
||||
vol->bitmapTable[i] = (struct bBitmapBlock*)malloc(sizeof(struct bBitmapBlock));
|
||||
if (!vol->bitmapTable[i]) {
|
||||
free(vol->bitmapTable); free(vol->bitmapBlocksChg);
|
||||
for(j=0; j<i; j++)
|
||||
free(vol->bitmapTable[j]);
|
||||
free(vol->bitmapTable);
|
||||
(*adfEnv.eFct)("adfCreateBitmap : malloc");
|
||||
return RC_MALLOC;
|
||||
}
|
||||
}
|
||||
|
||||
for(i=vol->firstBlock+2; i<=(vol->lastBlock - vol->firstBlock); i++)
|
||||
adfSetBlockFree(vol, i);
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfWriteNewBitmap
|
||||
*
|
||||
* write ext blocks and bitmap
|
||||
*
|
||||
* uses vol->bitmapSize,
|
||||
*/
|
||||
RETCODE adfWriteNewBitmap(struct Volume *vol)
|
||||
{
|
||||
struct bBitmapExtBlock bitme;
|
||||
SECTNUM *bitExtBlock;
|
||||
int n, i, k;
|
||||
int nExtBlock;
|
||||
int nBlock;
|
||||
SECTNUM *sectList;
|
||||
struct bRootBlock root;
|
||||
|
||||
sectList=(SECTNUM*)malloc(sizeof(SECTNUM)*vol->bitmapSize);
|
||||
if (!sectList) {
|
||||
(*adfEnv.eFct)("adfCreateBitmap : sectList");
|
||||
return RC_MALLOC;
|
||||
}
|
||||
|
||||
if (!adfGetFreeBlocks(vol, vol->bitmapSize, sectList)) {
|
||||
free(sectList);
|
||||
return RC_ERROR;
|
||||
}
|
||||
|
||||
if (adfReadRootBlock(vol, vol->rootBlock, &root)!=RC_OK) {
|
||||
free(sectList);
|
||||
return RC_ERROR;
|
||||
}
|
||||
nBlock = 0;
|
||||
n = min( vol->bitmapSize, BM_SIZE );
|
||||
for(i=0; i<n; i++) {
|
||||
root.bmPages[i] = vol->bitmapBlocks[i] = sectList[i];
|
||||
}
|
||||
nBlock = n;
|
||||
|
||||
/* for devices with more than 25*127 blocks == hards disks */
|
||||
if (vol->bitmapSize>BM_SIZE) {
|
||||
|
||||
nExtBlock = (vol->bitmapSize-BM_SIZE)/127;
|
||||
if ((vol->bitmapSize-BM_SIZE)%127)
|
||||
nExtBlock++;
|
||||
|
||||
bitExtBlock=(SECTNUM*)malloc(sizeof(SECTNUM)*nExtBlock);
|
||||
if (!bitExtBlock) {
|
||||
free(sectList);
|
||||
adfEnv.eFct("adfWriteNewBitmap : malloc failed");
|
||||
return RC_MALLOC;
|
||||
}
|
||||
|
||||
if (!adfGetFreeBlocks(vol, nExtBlock, bitExtBlock)) {
|
||||
free(sectList); free(bitExtBlock);
|
||||
return RC_MALLOC;
|
||||
}
|
||||
|
||||
k = 0;
|
||||
root.bmExt = bitExtBlock[ k ];
|
||||
while( nBlock<vol->bitmapSize ) {
|
||||
i=0;
|
||||
while( i<127 && nBlock<vol->bitmapSize ) {
|
||||
bitme.bmPages[i] = vol->bitmapBlocks[nBlock] = sectList[i];
|
||||
i++;
|
||||
nBlock++;
|
||||
}
|
||||
if ( k+1<nExtBlock )
|
||||
bitme.nextBlock = bitExtBlock[ k+1 ];
|
||||
else
|
||||
bitme.nextBlock = 0;
|
||||
if (adfWriteBitmapExtBlock(vol, bitExtBlock[ k ], &bitme)!=RC_OK) {
|
||||
free(sectList); free(bitExtBlock);
|
||||
return RC_ERROR;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
free( bitExtBlock );
|
||||
|
||||
}
|
||||
free( sectList);
|
||||
|
||||
if (adfWriteRootBlock(vol,vol->rootBlock,&root)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* adfReadBitmapBlock
|
||||
*
|
||||
* ENDIAN DEPENDENT
|
||||
*/
|
||||
RETCODE
|
||||
adfReadBitmapBlock(struct Volume* vol, SECTNUM nSect, struct bBitmapBlock* bitm)
|
||||
{
|
||||
uint8_t buf[LOGICAL_BLOCK_SIZE];
|
||||
|
||||
/*printf("bitmap %ld\n",nSect);*/
|
||||
if (adfReadBlock(vol, nSect, buf)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
memcpy(bitm, buf, LOGICAL_BLOCK_SIZE);
|
||||
#ifdef LITT_ENDIAN
|
||||
/* big to little = 68000 to x86 */
|
||||
swapEndian((uint8_t*)bitm, SWBL_BITMAP);
|
||||
#endif
|
||||
|
||||
if (bitm->checkSum!=adfNormalSum(buf,0,LOGICAL_BLOCK_SIZE))
|
||||
(*adfEnv.wFct)("adfReadBitmapBlock : invalid checksum");
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfWriteBitmapBlock
|
||||
*
|
||||
* OK
|
||||
*/
|
||||
RETCODE
|
||||
adfWriteBitmapBlock(struct Volume* vol, SECTNUM nSect, struct bBitmapBlock* bitm)
|
||||
{
|
||||
uint8_t buf[LOGICAL_BLOCK_SIZE];
|
||||
uint32_t newSum;
|
||||
|
||||
memcpy(buf,bitm,LOGICAL_BLOCK_SIZE);
|
||||
#ifdef LITT_ENDIAN
|
||||
/* little to big */
|
||||
swapEndian(buf, SWBL_BITMAP);
|
||||
#endif
|
||||
|
||||
newSum = adfNormalSum(buf, 0, LOGICAL_BLOCK_SIZE);
|
||||
swLong(buf,newSum);
|
||||
|
||||
/* dumpBlock((uint8_t*)buf);*/
|
||||
if (adfWriteBlock(vol, nSect, (uint8_t*)buf)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfReadBitmapExtBlock
|
||||
*
|
||||
* ENDIAN DEPENDENT
|
||||
*/
|
||||
RETCODE
|
||||
adfReadBitmapExtBlock(struct Volume* vol, SECTNUM nSect, struct bBitmapExtBlock* bitme)
|
||||
{
|
||||
uint8_t buf[LOGICAL_BLOCK_SIZE];
|
||||
|
||||
if (adfReadBlock(vol, nSect, buf)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
memcpy(bitme, buf, LOGICAL_BLOCK_SIZE);
|
||||
#ifdef LITT_ENDIAN
|
||||
swapEndian((uint8_t*)bitme, SWBL_BITMAP);
|
||||
#endif
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfWriteBitmapExtBlock
|
||||
*
|
||||
*/
|
||||
RETCODE
|
||||
adfWriteBitmapExtBlock(struct Volume* vol, SECTNUM nSect, struct bBitmapExtBlock* bitme)
|
||||
{
|
||||
uint8_t buf[LOGICAL_BLOCK_SIZE];
|
||||
|
||||
memcpy(buf,bitme, LOGICAL_BLOCK_SIZE);
|
||||
#ifdef LITT_ENDIAN
|
||||
/* little to big */
|
||||
swapEndian(buf, SWBL_BITMAPE);
|
||||
#endif
|
||||
|
||||
/* dumpBlock((uint8_t*)buf);*/
|
||||
if (adfWriteBlock(vol, nSect, (uint8_t*)buf)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfFreeBitmap
|
||||
*
|
||||
*/
|
||||
void adfFreeBitmap(struct Volume* vol)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<vol->bitmapSize; i++)
|
||||
free(vol->bitmapTable[i]);
|
||||
vol->bitmapSize = 0;
|
||||
|
||||
free(vol->bitmapTable);
|
||||
vol->bitmapTable = 0;
|
||||
|
||||
free(vol->bitmapBlocks);
|
||||
vol->bitmapBlocks = 0;
|
||||
|
||||
free(vol->bitmapBlocksChg);
|
||||
vol->bitmapBlocksChg = 0;
|
||||
}
|
||||
|
||||
|
||||
/*#######################################################################################*/
|
||||
52
src/adf_bitm.h
Normal file
52
src/adf_bitm.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef ADF_BITM_H
|
||||
#define ADF_BITM_H
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_bitm.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* bitmap code
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include"adf_str.h"
|
||||
#include"prefix.h"
|
||||
|
||||
RETCODE adfReadBitmapBlock(struct Volume*, SECTNUM nSect, struct bBitmapBlock*);
|
||||
RETCODE adfWriteBitmapBlock(struct Volume*, SECTNUM nSect, struct bBitmapBlock*);
|
||||
RETCODE adfReadBitmapExtBlock(struct Volume*, SECTNUM nSect, struct bBitmapExtBlock*);
|
||||
RETCODE adfWriteBitmapExtBlock(struct Volume*, SECTNUM, struct bBitmapExtBlock* );
|
||||
|
||||
SECTNUM adfGet1FreeBlock(struct Volume *vol);
|
||||
RETCODE adfUpdateBitmap(struct Volume *vol);
|
||||
PREFIX int32_t adfCountFreeBlocks(struct Volume* vol);
|
||||
RETCODE adfReadBitmap(struct Volume* , SECTNUM nBlock, struct bRootBlock* root);
|
||||
BOOL adfIsBlockFree(struct Volume* vol, SECTNUM nSect);
|
||||
void adfSetBlockFree(struct Volume* vol, SECTNUM nSect);
|
||||
void adfSetBlockUsed(struct Volume* vol, SECTNUM nSect);
|
||||
BOOL adfGetFreeBlocks(struct Volume* vol, int nbSect, SECTNUM* sectList);
|
||||
RETCODE adfCreateBitmap(struct Volume *vol);
|
||||
RETCODE adfWriteNewBitmap(struct Volume *vol);
|
||||
void adfFreeBitmap(struct Volume *vol);
|
||||
|
||||
#endif /* ADF_BITM_H */
|
||||
|
||||
/*#######################################################################################*/
|
||||
288
src/adf_blk.h
Normal file
288
src/adf_blk.h
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_blk.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* general blocks structures
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ADF_BLK_H
|
||||
#define ADF_BLK_H 1
|
||||
|
||||
#define ULONG uint32_t
|
||||
#define USHORT uint16_t
|
||||
#define UCHAR uint8_t
|
||||
|
||||
#define LOGICAL_BLOCK_SIZE 512
|
||||
|
||||
/* ----- FILE SYSTEM ----- */
|
||||
|
||||
#define FSMASK_FFS 1
|
||||
#define FSMASK_INTL 2
|
||||
#define FSMASK_DIRCACHE 4
|
||||
|
||||
#define isFFS(c) ((c)&FSMASK_FFS)
|
||||
#define isOFS(c) (!((c)&FSMASK_FFS))
|
||||
#define isINTL(c) ((c)&FSMASK_INTL)
|
||||
#define isDIRCACHE(c) ((c)&FSMASK_DIRCACHE)
|
||||
|
||||
|
||||
/* ----- ENTRIES ----- */
|
||||
|
||||
/* access constants */
|
||||
|
||||
#define ACCMASK_D (1<<0)
|
||||
#define ACCMASK_E (1<<1)
|
||||
#define ACCMASK_W (1<<2)
|
||||
#define ACCMASK_R (1<<3)
|
||||
#define ACCMASK_A (1<<4)
|
||||
#define ACCMASK_P (1<<5)
|
||||
#define ACCMASK_S (1<<6)
|
||||
#define ACCMASK_H (1<<7)
|
||||
|
||||
#define hasD(c) ((c)&ACCMASK_D)
|
||||
#define hasE(c) ((c)&ACCMASK_E)
|
||||
#define hasW(c) ((c)&ACCMASK_W)
|
||||
#define hasR(c) ((c)&ACCMASK_R)
|
||||
#define hasA(c) ((c)&ACCMASK_A)
|
||||
#define hasP(c) ((c)&ACCMASK_P)
|
||||
#define hasS(c) ((c)&ACCMASK_S)
|
||||
#define hasH(c) ((c)&ACCMASK_H)
|
||||
|
||||
|
||||
/* ----- BLOCKS ----- */
|
||||
|
||||
/* block constants */
|
||||
|
||||
#define BM_VALID -1
|
||||
#define BM_INVALID 0
|
||||
|
||||
#define HT_SIZE 72
|
||||
#define BM_SIZE 25
|
||||
#define MAX_DATABLK 72
|
||||
|
||||
#define MAXNAMELEN 30
|
||||
#define MAXCMMTLEN 79
|
||||
|
||||
|
||||
/* block primary and secondary types */
|
||||
|
||||
#define T_HEADER 2
|
||||
#define ST_ROOT 1
|
||||
#define ST_DIR 2
|
||||
#define ST_FILE -3
|
||||
#define ST_LFILE -4
|
||||
#define ST_LDIR 4
|
||||
#define ST_LSOFT 3
|
||||
#define T_LIST 16
|
||||
#define T_DATA 8
|
||||
#define T_DIRC 33
|
||||
|
||||
|
||||
/*--- blocks structures --- */
|
||||
|
||||
|
||||
struct bBootBlock {
|
||||
/*000*/ char dosType[4];
|
||||
/*004*/ ULONG checkSum;
|
||||
/*008*/ int32_t rootBlock;
|
||||
/*00c*/ UCHAR data[500+512];
|
||||
};
|
||||
|
||||
|
||||
struct bRootBlock {
|
||||
/*000*/ int32_t type;
|
||||
int32_t headerKey;
|
||||
int32_t highSeq;
|
||||
/*00c*/ int32_t hashTableSize;
|
||||
int32_t firstData;
|
||||
/*014*/ ULONG checkSum;
|
||||
/*018*/ int32_t hashTable[HT_SIZE]; /* hash table */
|
||||
/*138*/ int32_t bmFlag; /* bitmap flag, -1 means VALID */
|
||||
/*13c*/ int32_t bmPages[BM_SIZE];
|
||||
/*1a0*/ int32_t bmExt;
|
||||
/*1a4*/ int32_t cDays; /* creation date FFS and OFS */
|
||||
/*1a8*/ int32_t cMins;
|
||||
/*1ac*/ int32_t cTicks;
|
||||
/*1b0*/ char nameLen;
|
||||
/*1b1*/ char diskName[MAXNAMELEN+1];
|
||||
char r2[8];
|
||||
/*1d8*/ int32_t days; /* last access : days after 1 jan 1978 */
|
||||
/*1dc*/ int32_t mins; /* hours and minutes in minutes */
|
||||
/*1e0*/ int32_t ticks; /* 1/50 seconds */
|
||||
/*1e4*/ int32_t coDays; /* creation date OFS */
|
||||
/*1e8*/ int32_t coMins;
|
||||
/*1ec*/ int32_t coTicks;
|
||||
int32_t nextSameHash; /* == 0 */
|
||||
int32_t parent; /* == 0 */
|
||||
/*1f8*/ int32_t extension; /* FFS: first directory cache block */
|
||||
/*1fc*/ int32_t secType; /* == 1 */
|
||||
};
|
||||
|
||||
|
||||
struct bFileHeaderBlock {
|
||||
/*000*/ int32_t type; /* == 2 */
|
||||
/*004*/ int32_t headerKey; /* current block number */
|
||||
/*008*/ int32_t highSeq; /* number of data block in this hdr block */
|
||||
/*00c*/ int32_t dataSize; /* == 0 */
|
||||
/*010*/ int32_t firstData;
|
||||
/*014*/ ULONG checkSum;
|
||||
/*018*/ int32_t dataBlocks[MAX_DATABLK];
|
||||
/*138*/ int32_t r1;
|
||||
/*13c*/ int32_t r2;
|
||||
/*140*/ int32_t access; /* bit0=del, 1=modif, 2=write, 3=read */
|
||||
/*144*/ uint32_t byteSize;
|
||||
/*148*/ char commLen;
|
||||
/*149*/ char comment[MAXCMMTLEN+1];
|
||||
char r3[91-(MAXCMMTLEN+1)];
|
||||
/*1a4*/ int32_t days;
|
||||
/*1a8*/ int32_t mins;
|
||||
/*1ac*/ int32_t ticks;
|
||||
/*1b0*/ char nameLen;
|
||||
/*1b1*/ char fileName[MAXNAMELEN+1];
|
||||
int32_t r4;
|
||||
/*1d4*/ int32_t real; /* unused == 0 */
|
||||
/*1d8*/ int32_t nextLink; /* link chain */
|
||||
int32_t r5[5];
|
||||
/*1f0*/ int32_t nextSameHash; /* next entry with sane hash */
|
||||
/*1f4*/ int32_t parent; /* parent directory */
|
||||
/*1f8*/ int32_t extension; /* pointer to extension block */
|
||||
/*1fc*/ int32_t secType; /* == -3 */
|
||||
};
|
||||
|
||||
|
||||
/*--- file header extension block structure ---*/
|
||||
|
||||
struct bFileExtBlock {
|
||||
/*000*/ int32_t type; /* == 0x10 */
|
||||
/*004*/ int32_t headerKey;
|
||||
/*008*/ int32_t highSeq;
|
||||
/*00c*/ int32_t dataSize; /* == 0 */
|
||||
/*010*/ int32_t firstData; /* == 0 */
|
||||
/*014*/ ULONG checkSum;
|
||||
/*018*/ int32_t dataBlocks[MAX_DATABLK];
|
||||
int32_t r[45];
|
||||
int32_t info; /* == 0 */
|
||||
int32_t nextSameHash; /* == 0 */
|
||||
/*1f4*/ int32_t parent; /* header block */
|
||||
/*1f8*/ int32_t extension; /* next header extension block */
|
||||
/*1fc*/ int32_t secType; /* -3 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct bDirBlock {
|
||||
/*000*/ int32_t type; /* == 2 */
|
||||
/*004*/ int32_t headerKey;
|
||||
/*008*/ int32_t highSeq; /* == 0 */
|
||||
/*00c*/ int32_t hashTableSize; /* == 0 */
|
||||
int32_t r1; /* == 0 */
|
||||
/*014*/ ULONG checkSum;
|
||||
/*018*/ int32_t hashTable[HT_SIZE]; /* hash table */
|
||||
int32_t r2[2];
|
||||
/*140*/ int32_t access;
|
||||
int32_t r4; /* == 0 */
|
||||
/*148*/ char commLen;
|
||||
/*149*/ char comment[MAXCMMTLEN+1];
|
||||
char r5[91-(MAXCMMTLEN+1)];
|
||||
/*1a4*/ int32_t days; /* last access */
|
||||
/*1a8*/ int32_t mins;
|
||||
/*1ac*/ int32_t ticks;
|
||||
/*1b0*/ char nameLen;
|
||||
/*1b1*/ char dirName[MAXNAMELEN+1];
|
||||
int32_t r6;
|
||||
/*1d4*/ int32_t real; /* ==0 */
|
||||
/*1d8*/ int32_t nextLink; /* link list */
|
||||
int32_t r7[5];
|
||||
/*1f0*/ int32_t nextSameHash;
|
||||
/*1f4*/ int32_t parent;
|
||||
/*1f8*/ int32_t extension; /* FFS : first directory cache */
|
||||
/*1fc*/ int32_t secType; /* == 2 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct bOFSDataBlock{
|
||||
/*000*/ int32_t type; /* == 8 */
|
||||
/*004*/ int32_t headerKey; /* pointer to file_hdr block */
|
||||
/*008*/ int32_t seqNum; /* file data block number */
|
||||
/*00c*/ int32_t dataSize; /* <= 0x1e8 */
|
||||
/*010*/ int32_t nextData; /* next data block */
|
||||
/*014*/ ULONG checkSum;
|
||||
/*018*/ UCHAR data[488];
|
||||
/*200*/ };
|
||||
|
||||
|
||||
/* --- bitmap --- */
|
||||
|
||||
struct bBitmapBlock {
|
||||
/*000*/ ULONG checkSum;
|
||||
/*004*/ ULONG map[127];
|
||||
};
|
||||
|
||||
|
||||
struct bBitmapExtBlock {
|
||||
/*000*/ int32_t bmPages[127];
|
||||
/*1fc*/ int32_t nextBlock;
|
||||
};
|
||||
|
||||
|
||||
struct bLinkBlock {
|
||||
/*000*/ int32_t type; /* == 2 */
|
||||
/*004*/ int32_t headerKey; /* self pointer */
|
||||
int32_t r1[3];
|
||||
/*014*/ ULONG checkSum;
|
||||
/*018*/ char realName[64];
|
||||
int32_t r2[83];
|
||||
/*1a4*/ int32_t days; /* last access */
|
||||
/*1a8*/ int32_t mins;
|
||||
/*1ac*/ int32_t ticks;
|
||||
/*1b0*/ char nameLen;
|
||||
/*1b1*/ char name[MAXNAMELEN+1];
|
||||
int32_t r3;
|
||||
/*1d4*/ int32_t realEntry;
|
||||
/*1d8*/ int32_t nextLink;
|
||||
int32_t r4[5];
|
||||
/*1f0*/ int32_t nextSameHash;
|
||||
/*1f4*/ int32_t parent;
|
||||
int32_t r5;
|
||||
/*1fc*/ int32_t secType; /* == -4, 4, 3 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*--- directory cache block structure ---*/
|
||||
|
||||
struct bDirCacheBlock {
|
||||
/*000*/ int32_t type; /* == 33 */
|
||||
/*004*/ int32_t headerKey;
|
||||
/*008*/ int32_t parent;
|
||||
/*00c*/ int32_t recordsNb;
|
||||
/*010*/ int32_t nextDirC;
|
||||
/*014*/ ULONG checkSum;
|
||||
/*018*/ uint8_t records[488];
|
||||
};
|
||||
|
||||
|
||||
#endif /* ADF_BLK_H */
|
||||
/*##########################################################################*/
|
||||
615
src/adf_cache.c
Normal file
615
src/adf_cache.c
Normal file
@@ -0,0 +1,615 @@
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_cache.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* directory cache code
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include<stdlib.h>
|
||||
#include<string.h>
|
||||
|
||||
#include"adf_defs.h"
|
||||
#include"adf_str.h"
|
||||
#include"adf_err.h"
|
||||
#include"defendian.h"
|
||||
#include"adf_cache.h"
|
||||
#include"adf_raw.h"
|
||||
#include"adf_disk.h"
|
||||
#include"adf_bitm.h"
|
||||
#include"adf_util.h"
|
||||
#include"adf_dir.h"
|
||||
|
||||
|
||||
extern struct Env adfEnv;
|
||||
/*
|
||||
freeEntCache(struct CacheEntry *cEntry)
|
||||
{
|
||||
if (cEntry->name!=NULL)
|
||||
free(cEntry->name);
|
||||
if (cEntry->comm!=NULL)
|
||||
free(cEntry->comm);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* adfGetDirEntCache
|
||||
*
|
||||
* replace 'adfGetDirEnt'. returns a the dir contents based on the dircache list
|
||||
*/
|
||||
struct List* adfGetDirEntCache(struct Volume *vol, SECTNUM dir, BOOL recurs)
|
||||
{
|
||||
struct bEntryBlock parent;
|
||||
struct bDirCacheBlock dirc;
|
||||
int offset, n;
|
||||
struct List *cell, *head;
|
||||
struct CacheEntry caEntry;
|
||||
struct Entry *entry;
|
||||
SECTNUM nSect;
|
||||
|
||||
if (adfReadEntryBlock(vol,dir,&parent)!=RC_OK)
|
||||
return NULL;
|
||||
|
||||
nSect = parent.extension;
|
||||
|
||||
cell = head = NULL;
|
||||
do {
|
||||
/* one loop per cache block */
|
||||
n = offset = 0;
|
||||
if (adfReadDirCBlock(vol, nSect, &dirc)!=RC_OK)
|
||||
return NULL;
|
||||
while (n<dirc.recordsNb) {
|
||||
/* one loop per record */
|
||||
entry = (struct Entry*)malloc(sizeof(struct Entry));
|
||||
if (!entry) {
|
||||
adfFreeDirList(head);
|
||||
return NULL;
|
||||
}
|
||||
adfGetCacheEntry(&dirc, &offset, &caEntry);
|
||||
|
||||
/* converts a cache entry into a dir entry */
|
||||
entry->type = (int)caEntry.type;
|
||||
entry->name = strdup(caEntry.name);
|
||||
if (entry->name==NULL) {
|
||||
free(entry); adfFreeDirList(head);
|
||||
return NULL;
|
||||
}
|
||||
entry->sector = caEntry.header;
|
||||
entry->comment = strdup(caEntry.comm);
|
||||
if (entry->comment==NULL) {
|
||||
free(entry->name); adfFreeDirList(head);
|
||||
return NULL;
|
||||
}
|
||||
entry->size = caEntry.size;
|
||||
entry->access = caEntry.protect;
|
||||
adfDays2Date( caEntry.days, &(entry->year), &(entry->month),
|
||||
&(entry->days) );
|
||||
entry->hour = caEntry.mins/60;
|
||||
entry->mins = caEntry.mins%60;
|
||||
entry->secs = caEntry.ticks/50;
|
||||
|
||||
/* add it into the linked list */
|
||||
if (head==NULL)
|
||||
head = cell = newCell(NULL, (void*)entry);
|
||||
else
|
||||
cell = newCell(cell, (void*)entry);
|
||||
|
||||
if (cell==NULL) {
|
||||
adfFreeEntry(entry);
|
||||
adfFreeDirList(head);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (recurs && entry->type==ST_DIR)
|
||||
cell->subdir = adfGetDirEntCache(vol,entry->sector,recurs);
|
||||
|
||||
n++;
|
||||
}
|
||||
nSect = dirc.nextDirC;
|
||||
}while (nSect!=0);
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* adfGetCacheEntry
|
||||
*
|
||||
* Returns a cache entry, starting from the offset p (the index into records[])
|
||||
* This offset is updated to the end of the returned entry.
|
||||
*/
|
||||
void adfGetCacheEntry(struct bDirCacheBlock *dirc, int *p, struct CacheEntry *cEntry)
|
||||
{
|
||||
int ptr;
|
||||
|
||||
ptr = *p;
|
||||
|
||||
/*printf("p=%d\n",ptr);*/
|
||||
|
||||
#ifdef LITT_ENDIAN
|
||||
cEntry->header = swapLong(dirc->records+ptr);
|
||||
cEntry->size = swapLong(dirc->records+ptr+4);
|
||||
cEntry->protect = swapLong(dirc->records+ptr+8);
|
||||
cEntry->days = swapShort(dirc->records+ptr+16);
|
||||
cEntry->mins = swapShort(dirc->records+ptr+18);
|
||||
cEntry->ticks = swapShort(dirc->records+ptr+20);
|
||||
#else
|
||||
cEntry->header = Long(dirc->records+ptr);
|
||||
cEntry->size = Long(dirc->records+ptr+4);
|
||||
cEntry->protect = Long(dirc->records+ptr+8);
|
||||
cEntry->days = Short(dirc->records+ptr+16);
|
||||
cEntry->mins = Short(dirc->records+ptr+18);
|
||||
cEntry->ticks = Short(dirc->records+ptr+20);
|
||||
#endif
|
||||
cEntry->type =(signed char) dirc->records[ptr+22];
|
||||
|
||||
cEntry->nLen = dirc->records[ptr+23];
|
||||
/* cEntry->name = (char*)malloc(sizeof(char)*(cEntry->nLen+1));
|
||||
if (!cEntry->name)
|
||||
return;
|
||||
*/ memcpy(cEntry->name, dirc->records+ptr+24, cEntry->nLen);
|
||||
cEntry->name[(int)(cEntry->nLen)]='\0';
|
||||
|
||||
cEntry->cLen = dirc->records[ptr+24+cEntry->nLen];
|
||||
if (cEntry->cLen>0) {
|
||||
/* cEntry->comm =(char*)malloc(sizeof(char)*(cEntry->cLen+1));
|
||||
if (!cEntry->comm) {
|
||||
free( cEntry->name ); cEntry->name=NULL;
|
||||
return;
|
||||
}
|
||||
*/ memcpy(cEntry->comm,dirc->records+ptr+24+cEntry->nLen+1,cEntry->cLen);
|
||||
}
|
||||
cEntry->comm[(int)(cEntry->cLen)]='\0';
|
||||
/*printf("cEntry->nLen %d cEntry->cLen %d %s\n",cEntry->nLen,cEntry->cLen,cEntry->name);*/
|
||||
*p = ptr+24+cEntry->nLen+1+cEntry->cLen;
|
||||
|
||||
/* the starting offset of each record must be even (68000 constraint) */
|
||||
if ((*p%2)!=0)
|
||||
*p=(*p)+1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfPutCacheEntry
|
||||
*
|
||||
* remplaces one cache entry at the p offset, and returns its length
|
||||
*/
|
||||
int adfPutCacheEntry( struct bDirCacheBlock *dirc, int *p, struct CacheEntry *cEntry)
|
||||
{
|
||||
int ptr, l;
|
||||
|
||||
ptr = *p;
|
||||
|
||||
#ifdef LITT_ENDIAN
|
||||
swLong(dirc->records+ptr, cEntry->header);
|
||||
swLong(dirc->records+ptr+4, cEntry->size);
|
||||
swLong(dirc->records+ptr+8, cEntry->protect);
|
||||
swShort(dirc->records+ptr+16, cEntry->days);
|
||||
swShort(dirc->records+ptr+18, cEntry->mins);
|
||||
swShort(dirc->records+ptr+20, cEntry->ticks);
|
||||
#else
|
||||
memcpy(dirc->records+ptr,&(cEntry->header),4);
|
||||
memcpy(dirc->records+ptr+4,&(cEntry->size),4);
|
||||
memcpy(dirc->records+ptr+8,&(cEntry->protect),4);
|
||||
memcpy(dirc->records+ptr+16,&(cEntry->days),2);
|
||||
memcpy(dirc->records+ptr+18,&(cEntry->mins),2);
|
||||
memcpy(dirc->records+ptr+20,&(cEntry->ticks),2);
|
||||
#endif
|
||||
dirc->records[ptr+22] =(signed char)cEntry->type;
|
||||
|
||||
dirc->records[ptr+23] = cEntry->nLen;
|
||||
memcpy(dirc->records+ptr+24, cEntry->name, cEntry->nLen);
|
||||
|
||||
dirc->records[ptr+24+cEntry->nLen] = cEntry->cLen;
|
||||
memcpy(dirc->records+ptr+24+cEntry->nLen+1, cEntry->comm, cEntry->cLen);
|
||||
|
||||
/*puts("adfPutCacheEntry");*/
|
||||
|
||||
l = 25+cEntry->nLen+cEntry->cLen;
|
||||
if ((l%2)==0)
|
||||
return l;
|
||||
else {
|
||||
dirc->records[ptr+l] =(char)0;
|
||||
return l+1;
|
||||
}
|
||||
|
||||
/* ptr%2 must be == 0, if l%2==0, (ptr+l)%2==0 */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfEntry2CacheEntry
|
||||
*
|
||||
* converts one dir entry into a cache entry, and return its future length in records[]
|
||||
*/
|
||||
int adfEntry2CacheEntry(struct bEntryBlock *entry, struct CacheEntry *newEntry)
|
||||
{
|
||||
int entryLen;
|
||||
|
||||
/* new entry */
|
||||
newEntry->header = entry->headerKey;
|
||||
if (entry->secType==ST_FILE)
|
||||
newEntry->size = entry->byteSize;
|
||||
else
|
||||
newEntry->size = 0L;
|
||||
newEntry->protect = entry->access;
|
||||
newEntry->days = (short)entry->days;
|
||||
newEntry->mins = (short)entry->mins;
|
||||
newEntry->ticks = (short)entry->ticks;
|
||||
newEntry->type = (signed char)entry->secType;
|
||||
newEntry->nLen = entry->nameLen;
|
||||
memcpy(newEntry->name, entry->name, newEntry->nLen);
|
||||
newEntry->name[(int)(newEntry->nLen)] = '\0';
|
||||
newEntry->cLen = entry->commLen;
|
||||
if (newEntry->cLen>0)
|
||||
memcpy(newEntry->comm, entry->comment, newEntry->cLen);
|
||||
|
||||
entryLen = 24+newEntry->nLen+1+newEntry->cLen;
|
||||
|
||||
/*printf("entry->name %d entry->comment %d\n",entry->nameLen,entry->commLen);
|
||||
printf("newEntry->nLen %d newEntry->cLen %d\n",newEntry->nLen,newEntry->cLen);
|
||||
*/ if ((entryLen%2)==0)
|
||||
return entryLen;
|
||||
else
|
||||
return entryLen+1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfDelFromCache
|
||||
*
|
||||
* delete one cache entry from its block. don't do 'records garbage collecting'
|
||||
*/
|
||||
RETCODE adfDelFromCache(struct Volume *vol, struct bEntryBlock *parent,
|
||||
SECTNUM headerKey)
|
||||
{
|
||||
struct bDirCacheBlock dirc;
|
||||
SECTNUM nSect, prevSect;
|
||||
struct CacheEntry caEntry;
|
||||
int offset, oldOffset, n;
|
||||
BOOL found;
|
||||
int entryLen;
|
||||
int i;
|
||||
RETCODE rc = RC_OK;
|
||||
|
||||
prevSect = -1;
|
||||
nSect = parent->extension;
|
||||
found = FALSE;
|
||||
do {
|
||||
adfReadDirCBlock(vol, nSect, &dirc);
|
||||
offset = 0; n = 0;
|
||||
while(n < dirc.recordsNb && !found) {
|
||||
oldOffset = offset;
|
||||
adfGetCacheEntry(&dirc, &offset, &caEntry);
|
||||
found = (caEntry.header==headerKey);
|
||||
if (found) {
|
||||
entryLen = offset-oldOffset;
|
||||
if (dirc.recordsNb>1 || prevSect==-1) {
|
||||
if (n<dirc.recordsNb-1) {
|
||||
/* not the last of the block : switch the following records */
|
||||
for(i=oldOffset; i<(488-entryLen); i++)
|
||||
dirc.records[i] = dirc.records[i+entryLen];
|
||||
/* and clear the following bytes */
|
||||
for(i=488-entryLen; i<488; i++)
|
||||
dirc.records[i] = 0;
|
||||
}
|
||||
else {
|
||||
/* the last record of this cache block */
|
||||
for(i=oldOffset; i<offset; i++)
|
||||
dirc.records[i] = 0;
|
||||
}
|
||||
dirc.recordsNb--;
|
||||
if (adfWriteDirCBlock(vol, dirc.headerKey, &dirc)!=RC_OK)
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
/* dirc.recordsNb ==1 or == 0 , prevSect!=-1 :
|
||||
* the only record in this dirc block and a previous dirc block exists
|
||||
*/
|
||||
adfSetBlockFree(vol, dirc.headerKey);
|
||||
adfReadDirCBlock(vol, prevSect, &dirc);
|
||||
dirc.nextDirC = 0L;
|
||||
adfWriteDirCBlock(vol, prevSect, &dirc);
|
||||
|
||||
adfUpdateBitmap(vol);
|
||||
}
|
||||
}
|
||||
n++;
|
||||
}
|
||||
prevSect = nSect;
|
||||
nSect = dirc.nextDirC;
|
||||
}while(nSect!=0 && !found);
|
||||
|
||||
if (!found)
|
||||
(*adfEnv.wFct)("adfUpdateCache : entry not found");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfAddInCache
|
||||
*
|
||||
*/
|
||||
RETCODE adfAddInCache(struct Volume *vol, struct bEntryBlock *parent,
|
||||
struct bEntryBlock *entry)
|
||||
{
|
||||
struct bDirCacheBlock dirc, newDirc;
|
||||
SECTNUM nSect, nCache;
|
||||
struct CacheEntry caEntry, newEntry;
|
||||
int offset, n;
|
||||
int entryLen;
|
||||
|
||||
entryLen = adfEntry2CacheEntry(entry, &newEntry);
|
||||
/*printf("adfAddInCache--%4ld %2d %6ld %8lx %4d %2d:%02d:%02d %30s %22s\n",
|
||||
newEntry.header, newEntry.type, newEntry.size, newEntry.protect,
|
||||
newEntry.days, newEntry.mins/60, newEntry.mins%60,
|
||||
newEntry.ticks/50,
|
||||
newEntry.name, newEntry.comm);
|
||||
*/
|
||||
nSect = parent->extension;
|
||||
do {
|
||||
if (adfReadDirCBlock(vol, nSect, &dirc)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
offset = 0; n = 0;
|
||||
/*printf("parent=%4ld\n",dirc.parent);*/
|
||||
while(n < dirc.recordsNb) {
|
||||
adfGetCacheEntry(&dirc, &offset, &caEntry);
|
||||
/*printf("*%4ld %2d %6ld %8lx %4d %2d:%02d:%02d %30s %22s\n",
|
||||
caEntry.header, caEntry.type, caEntry.size, caEntry.protect,
|
||||
caEntry.days, caEntry.mins/60, caEntry.mins%60,
|
||||
caEntry.ticks/50,
|
||||
caEntry.name, caEntry.comm);
|
||||
*/
|
||||
n++;
|
||||
}
|
||||
|
||||
/* if (offset+entryLen<=488) {
|
||||
adfPutCacheEntry(&dirc, &offset, &newEntry);
|
||||
dirc.recordsNb++;
|
||||
adfWriteDirCBlock(vol, dirc.headerKey, &dirc);
|
||||
return rc;
|
||||
}*/
|
||||
nSect = dirc.nextDirC;
|
||||
}while(nSect!=0);
|
||||
|
||||
/* in the last block */
|
||||
if (offset+entryLen<=488) {
|
||||
adfPutCacheEntry(&dirc, &offset, &newEntry);
|
||||
dirc.recordsNb++;
|
||||
/*printf("entry name=%s\n",newEntry.name);*/
|
||||
}
|
||||
else {
|
||||
/* request one new block free */
|
||||
nCache = adfGet1FreeBlock(vol);
|
||||
if (nCache==-1) {
|
||||
(*adfEnv.wFct)("adfCreateDir : nCache==-1");
|
||||
return RC_VOLFULL;
|
||||
}
|
||||
|
||||
/* create a new dircache block */
|
||||
memset(&newDirc,0,512);
|
||||
if (parent->secType==ST_ROOT)
|
||||
newDirc.parent = vol->rootBlock;
|
||||
else if (parent->secType==ST_DIR)
|
||||
newDirc.parent = parent->headerKey;
|
||||
else
|
||||
(*adfEnv.wFct)("adfAddInCache : unknown secType");
|
||||
newDirc.recordsNb = 0L;
|
||||
newDirc.nextDirC = 0L;
|
||||
|
||||
adfPutCacheEntry(&dirc, &offset, &newEntry);
|
||||
newDirc.recordsNb++;
|
||||
if (adfWriteDirCBlock(vol, nCache, &newDirc)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
dirc.nextDirC = nCache;
|
||||
}
|
||||
/*printf("dirc.headerKey=%ld\n",dirc.headerKey);*/
|
||||
if (adfWriteDirCBlock(vol, dirc.headerKey, &dirc)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
/*if (strcmp(entry->name,"file_5u")==0)
|
||||
dumpBlock(&dirc);
|
||||
*/
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfUpdateCache
|
||||
*
|
||||
*/
|
||||
RETCODE adfUpdateCache(struct Volume *vol, struct bEntryBlock *parent,
|
||||
struct bEntryBlock *entry, BOOL entryLenChg)
|
||||
{
|
||||
struct bDirCacheBlock dirc;
|
||||
SECTNUM nSect;
|
||||
struct CacheEntry caEntry, newEntry;
|
||||
int offset, oldOffset, n;
|
||||
BOOL found;
|
||||
int i, oLen, nLen;
|
||||
int sLen; /* shift length */
|
||||
|
||||
nLen = adfEntry2CacheEntry(entry, &newEntry);
|
||||
|
||||
nSect = parent->extension;
|
||||
found = FALSE;
|
||||
do {
|
||||
/*printf("dirc=%ld\n",nSect);*/
|
||||
if (adfReadDirCBlock(vol, nSect, &dirc)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
offset = 0; n = 0;
|
||||
/* search entry to update with its header_key */
|
||||
while(n < dirc.recordsNb && !found) {
|
||||
oldOffset = offset;
|
||||
/* offset is updated */
|
||||
adfGetCacheEntry(&dirc, &offset, &caEntry);
|
||||
oLen = offset-oldOffset;
|
||||
sLen = oLen-nLen;
|
||||
/*printf("olen=%d nlen=%d\n",oLen,nLen);*/
|
||||
found = (caEntry.header==newEntry.header);
|
||||
if (found) {
|
||||
if (!entryLenChg || oLen==nLen) {
|
||||
/* same length : remplace the old values */
|
||||
adfPutCacheEntry(&dirc, &oldOffset, &newEntry);
|
||||
/*if (entryLenChg) puts("oLen==nLen");*/
|
||||
if (adfWriteDirCBlock(vol, dirc.headerKey, &dirc)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
}
|
||||
else if (oLen>nLen) {
|
||||
/*puts("oLen>nLen");*/
|
||||
/* the new record is shorter, write it,
|
||||
* then shift down the following records
|
||||
*/
|
||||
adfPutCacheEntry(&dirc, &oldOffset, &newEntry);
|
||||
for(i=oldOffset+nLen; i<(488-sLen); i++)
|
||||
dirc.records[i] = dirc.records[i+sLen];
|
||||
/* then clear the following bytes */
|
||||
for(i=488-sLen; i<488; i++)
|
||||
dirc.records[i] = (char)0;
|
||||
|
||||
if (adfWriteDirCBlock(vol, dirc.headerKey, &dirc)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
}
|
||||
else {
|
||||
/* the new record is larger */
|
||||
/*puts("oLen<nLen");*/
|
||||
adfDelFromCache(vol,parent,entry->headerKey);
|
||||
adfAddInCache(vol,parent,entry);
|
||||
/*puts("oLen<nLen end");*/
|
||||
|
||||
}
|
||||
}
|
||||
n++;
|
||||
}
|
||||
nSect = dirc.nextDirC;
|
||||
}while(nSect!=0 && !found);
|
||||
|
||||
if (found) {
|
||||
if (adfUpdateBitmap(vol)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
}
|
||||
else
|
||||
(*adfEnv.wFct)("adfUpdateCache : entry not found");
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfCreateEmptyCache
|
||||
*
|
||||
*/
|
||||
RETCODE adfCreateEmptyCache(struct Volume *vol, struct bEntryBlock *parent, SECTNUM nSect)
|
||||
{
|
||||
struct bDirCacheBlock dirc;
|
||||
SECTNUM nCache;
|
||||
|
||||
if (nSect==-1) {
|
||||
nCache = adfGet1FreeBlock(vol);
|
||||
if (nCache==-1) {
|
||||
(*adfEnv.wFct)("adfCreateDir : nCache==-1");
|
||||
return RC_VOLFULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
nCache = nSect;
|
||||
|
||||
if (parent->extension==0)
|
||||
parent->extension = nCache;
|
||||
|
||||
memset(&dirc,0, sizeof(struct bDirCacheBlock));
|
||||
|
||||
if (parent->secType==ST_ROOT)
|
||||
dirc.parent = vol->rootBlock;
|
||||
else if (parent->secType==ST_DIR)
|
||||
dirc.parent = parent->headerKey;
|
||||
else {
|
||||
(*adfEnv.wFct)("adfCreateEmptyCache : unknown secType");
|
||||
/*printf("secType=%ld\n",parent->secType);*/
|
||||
}
|
||||
|
||||
dirc.recordsNb = 0;
|
||||
dirc.nextDirC = 0;
|
||||
|
||||
if (adfWriteDirCBlock(vol, nCache, &dirc)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfReadDirCBlock
|
||||
*
|
||||
*/
|
||||
RETCODE adfReadDirCBlock(struct Volume *vol, SECTNUM nSect, struct bDirCacheBlock *dirc)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
|
||||
if (adfReadBlock(vol, nSect, buf)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
memcpy(dirc,buf,512);
|
||||
#ifdef LITT_ENDIAN
|
||||
swapEndian((uint8_t*)dirc,SWBL_CACHE);
|
||||
#endif
|
||||
if (dirc->checkSum!=adfNormalSum(buf,20,512))
|
||||
(*adfEnv.wFct)("adfReadDirCBlock : invalid checksum");
|
||||
if (dirc->type!=T_DIRC)
|
||||
(*adfEnv.wFct)("adfReadDirCBlock : T_DIRC not found");
|
||||
if (dirc->headerKey!=nSect)
|
||||
(*adfEnv.wFct)("adfReadDirCBlock : headerKey!=nSect");
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfWriteDirCblock
|
||||
*
|
||||
*/
|
||||
RETCODE adfWriteDirCBlock(struct Volume* vol, int32_t nSect, struct bDirCacheBlock* dirc)
|
||||
{
|
||||
uint8_t buf[LOGICAL_BLOCK_SIZE];
|
||||
uint32_t newSum;
|
||||
|
||||
dirc->type = T_DIRC;
|
||||
dirc->headerKey = nSect;
|
||||
|
||||
memcpy(buf, dirc, LOGICAL_BLOCK_SIZE);
|
||||
#ifdef LITT_ENDIAN
|
||||
swapEndian(buf, SWBL_CACHE);
|
||||
#endif
|
||||
|
||||
newSum = adfNormalSum(buf, 20, LOGICAL_BLOCK_SIZE);
|
||||
swLong(buf+20,newSum);
|
||||
/* *(int32_t*)(buf+20) = swapLong((uint8_t*)&newSum);*/
|
||||
|
||||
if (adfWriteBlock(vol, nSect, buf)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
/*puts("adfWriteDirCBlock");*/
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
/*################################################################################*/
|
||||
48
src/adf_cache.h
Normal file
48
src/adf_cache.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef _ADF_CACHE_H
|
||||
#define _ADF_CACHE_H 1
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_cache.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* directory cache code
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "adf_str.h"
|
||||
|
||||
void adfGetCacheEntry(struct bDirCacheBlock *dirc, int *p, struct CacheEntry *cEntry);
|
||||
int adfPutCacheEntry( struct bDirCacheBlock *dirc, int *p, struct CacheEntry *cEntry);
|
||||
|
||||
struct List* adfGetDirEntCache(struct Volume *vol, SECTNUM dir, BOOL recurs);
|
||||
|
||||
RETCODE adfCreateEmptyCache(struct Volume *vol, struct bEntryBlock *parent, SECTNUM nSect);
|
||||
RETCODE adfAddInCache(struct Volume *vol, struct bEntryBlock *parent, struct bEntryBlock *entry);
|
||||
RETCODE adfUpdateCache(struct Volume *vol, struct bEntryBlock *parent, struct bEntryBlock *entry, BOOL);
|
||||
RETCODE adfDelFromCache(struct Volume *vol, struct bEntryBlock *parent, SECTNUM);
|
||||
|
||||
RETCODE adfReadDirCBlock(struct Volume *vol, SECTNUM nSect, struct bDirCacheBlock *dirc);
|
||||
RETCODE adfWriteDirCBlock(struct Volume*, int32_t, struct bDirCacheBlock* dirc);
|
||||
|
||||
#endif /* _ADF_CACHE_H */
|
||||
|
||||
/*##########################################################################*/
|
||||
71
src/adf_defs.h
Normal file
71
src/adf_defs.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_defs.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _ADF_DEFS_H
|
||||
#define _ADF_DEFS_H 1
|
||||
|
||||
#define ADFLIB_VERSION "0.7.11a"
|
||||
#define ADFLIB_DATE "January 20th, 2007"
|
||||
|
||||
#define SECTNUM int32_t
|
||||
#define RETCODE int32_t
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#include <stdint.h>
|
||||
#define ULONG uint32_t
|
||||
#define USHORT uint16_t
|
||||
#define UCHAR uint8_t
|
||||
#define BOOL int
|
||||
|
||||
|
||||
/* defines max and min */
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) (a)>(b) ? (a) : (b)
|
||||
#endif
|
||||
#ifndef min
|
||||
#define min(a,b) (a)<(b) ? (a) : (b)
|
||||
#endif
|
||||
|
||||
|
||||
/* (*byte) to (*short) and (*byte) to (*long) conversion */
|
||||
|
||||
#define Short(p) ((p)[0]<<8 | (p)[1])
|
||||
#define Long(p) (Short(p)<<16 | Short(p+2))
|
||||
|
||||
|
||||
/* swap short and swap long macros for little endian machines */
|
||||
|
||||
#define swapShort(p) ((p)[0]<<8 | (p)[1])
|
||||
#define swapLong(p) (swapShort(p)<<16 | swapShort(p+2))
|
||||
|
||||
|
||||
|
||||
#endif /* _ADF_DEFS_H */
|
||||
/*##########################################################################*/
|
||||
1042
src/adf_dir.c
Normal file
1042
src/adf_dir.c
Normal file
File diff suppressed because it is too large
Load Diff
70
src/adf_dir.h
Normal file
70
src/adf_dir.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#ifndef ADF_DIR_H
|
||||
#define ADF_DIR_H 1
|
||||
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_dir.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include"adf_str.h"
|
||||
#include"adf_err.h"
|
||||
#include"adf_defs.h"
|
||||
|
||||
#include"prefix.h"
|
||||
|
||||
PREFIX RETCODE adfToRootDir(struct Volume *vol);
|
||||
BOOL isDirEmpty(struct bDirBlock *dir);
|
||||
PREFIX RETCODE adfRemoveEntry(struct Volume *vol, SECTNUM pSect, char *name);
|
||||
PREFIX struct List* adfGetDirEnt(struct Volume* vol, SECTNUM nSect );
|
||||
PREFIX struct List* adfGetRDirEnt(struct Volume* vol, SECTNUM nSect, BOOL recurs );
|
||||
PREFIX void adfFreeDirList(struct List* list);
|
||||
|
||||
RETCODE adfEntBlock2Entry(struct bEntryBlock *entryBlk, struct Entry *entry);
|
||||
PREFIX void adfFreeEntry(struct Entry *entry);
|
||||
RETCODE adfCreateFile(struct Volume* vol, SECTNUM parent, char *name,
|
||||
struct bFileHeaderBlock *fhdr);
|
||||
PREFIX RETCODE adfCreateDir(struct Volume* vol, SECTNUM parent, char* name);
|
||||
SECTNUM adfCreateEntry(struct Volume *vol, struct bEntryBlock *dir, char *name, SECTNUM );
|
||||
PREFIX RETCODE adfRenameEntry(struct Volume *vol, SECTNUM, char *old,SECTNUM,char *new);
|
||||
|
||||
|
||||
RETCODE adfReadEntryBlock(struct Volume* vol, SECTNUM nSect, struct bEntryBlock* ent);
|
||||
RETCODE adfWriteDirBlock(struct Volume* vol, SECTNUM nSect, struct bDirBlock *dir);
|
||||
RETCODE adfWriteEntryBlock(struct Volume* vol, SECTNUM nSect, struct bEntryBlock *ent);
|
||||
|
||||
char* adfAccess2String(int32_t acc);
|
||||
uint8_t adfIntlToUpper(uint8_t c);
|
||||
int adfGetHashValue(uint8_t *name, BOOL intl);
|
||||
void myToUpper( uint8_t *ostr, uint8_t *nstr, int,BOOL intl );
|
||||
PREFIX RETCODE adfChangeDir(struct Volume* vol, char *name);
|
||||
PREFIX RETCODE adfParentDir(struct Volume* vol);
|
||||
PREFIX RETCODE adfSetEntryAccess(struct Volume*, SECTNUM, char*, int32_t);
|
||||
PREFIX RETCODE adfSetEntryComment(struct Volume*, SECTNUM, char*, char*);
|
||||
SECTNUM adfNameToEntryBlk(struct Volume *vol, int32_t ht[], char* name,
|
||||
struct bEntryBlock *entry, SECTNUM *);
|
||||
|
||||
PREFIX void printEntry(struct Entry* entry);
|
||||
void adfFreeDirList(struct List* list);
|
||||
|
||||
#endif /* ADF_DIR_H */
|
||||
|
||||
454
src/adf_disk.c
Normal file
454
src/adf_disk.c
Normal file
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_disk.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* logical disk/volume code
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "adf_str.h"
|
||||
#include "adf_disk.h"
|
||||
#include "adf_raw.h"
|
||||
#include "adf_hd.h"
|
||||
#include "adf_bitm.h"
|
||||
#include "adf_util.h"
|
||||
#include "adf_nativ.h"
|
||||
#include "adf_dump.h"
|
||||
#include "adf_err.h"
|
||||
#include "adf_cache.h"
|
||||
|
||||
extern struct Env adfEnv;
|
||||
|
||||
uint32_t bitMask[32] = {
|
||||
0x1, 0x2, 0x4, 0x8,
|
||||
0x10, 0x20, 0x40, 0x80,
|
||||
0x100, 0x200, 0x400, 0x800,
|
||||
0x1000, 0x2000, 0x4000, 0x8000,
|
||||
0x10000, 0x20000, 0x40000, 0x80000,
|
||||
0x100000, 0x200000, 0x400000, 0x800000,
|
||||
0x1000000, 0x2000000, 0x4000000, 0x8000000,
|
||||
0x10000000, 0x20000000, 0x40000000, 0x80000000 };
|
||||
|
||||
|
||||
RETCODE adfInstallBootBlock(struct Volume *vol, uint8_t* code)
|
||||
{
|
||||
int i;
|
||||
struct bBootBlock boot;
|
||||
|
||||
if (vol->dev->devType!=DEVTYPE_FLOPDD && vol->dev->devType!=DEVTYPE_FLOPHD)
|
||||
return RC_ERROR;
|
||||
|
||||
if (adfReadBootBlock(vol, &boot)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
boot.rootBlock = 880;
|
||||
for(i=0; i<1024-12; i++) /* bootcode */
|
||||
boot.data[i] = code[i+12];
|
||||
|
||||
if (adfWriteBootBlock(vol, &boot)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
vol->bootCode = TRUE;
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* isSectNumValid
|
||||
*
|
||||
*/
|
||||
BOOL isSectNumValid(struct Volume *vol, SECTNUM nSect)
|
||||
{
|
||||
return( 0<=nSect && nSect<=(vol->lastBlock - vol->firstBlock) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* adfVolumeInfo
|
||||
*
|
||||
*/
|
||||
void adfVolumeInfo(struct Volume *vol)
|
||||
{
|
||||
struct bRootBlock root;
|
||||
char diskName[35];
|
||||
int days,month,year;
|
||||
|
||||
if (adfReadRootBlock(vol, vol->rootBlock, &root)!=RC_OK)
|
||||
return;
|
||||
|
||||
memset(diskName, 0, 35);
|
||||
memcpy(diskName, root.diskName, root.nameLen);
|
||||
|
||||
printf ("Name : %-30s\n",vol->volName);
|
||||
printf ("Type : ");
|
||||
switch(vol->dev->devType) {
|
||||
case DEVTYPE_FLOPDD:
|
||||
printf ("Floppy Double Density : 880 KBytes\n");
|
||||
break;
|
||||
case DEVTYPE_FLOPHD:
|
||||
printf ("Floppy High Density : 1760 KBytes\n");
|
||||
break;
|
||||
case DEVTYPE_HARDDISK:
|
||||
printf ("Hard Disk partition : %3.1f KBytes\n",
|
||||
(vol->lastBlock - vol->firstBlock +1) * 512.0/1024.0);
|
||||
break;
|
||||
case DEVTYPE_HARDFILE:
|
||||
printf ("HardFile : %3.1f KBytes\n",
|
||||
(vol->lastBlock - vol->firstBlock +1) * 512.0/1024.0);
|
||||
break;
|
||||
default:
|
||||
printf ("Unknown devType!\n");
|
||||
}
|
||||
printf ("Filesystem : ");
|
||||
printf("%s ",isFFS(vol->dosType) ? "FFS" : "OFS");
|
||||
if (isINTL(vol->dosType))
|
||||
printf ("INTL ");
|
||||
if (isDIRCACHE(vol->dosType))
|
||||
printf ("DIRCACHE ");
|
||||
putchar('\n');
|
||||
|
||||
printf("Free blocks = %d\n", adfCountFreeBlocks(vol));
|
||||
if (vol->readOnly)
|
||||
printf("Read only\n");
|
||||
else
|
||||
printf("Read/Write\n");
|
||||
|
||||
/* created */
|
||||
adfDays2Date(root.coDays, &year, &month, &days);
|
||||
printf ("created %d/%02d/%02d %d:%02d:%02d\n",days,month,year,
|
||||
root.coMins/60,root.coMins%60,root.coTicks/50);
|
||||
adfDays2Date(root.days, &year, &month, &days);
|
||||
printf ("last access %d/%02d/%02d %d:%02d:%02d, ",days,month,year,
|
||||
root.mins/60,root.mins%60,root.ticks/50);
|
||||
adfDays2Date(root.cDays, &year, &month, &days);
|
||||
printf ("%d/%02d/%02d %d:%02d:%02d\n",days,month,year,
|
||||
root.cMins/60,root.cMins%60,root.cTicks/50);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* adfMount
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct Volume* adfMount( struct Device *dev, int nPart, BOOL readOnly )
|
||||
{
|
||||
int32_t nBlock;
|
||||
struct bRootBlock root;
|
||||
struct bBootBlock boot;
|
||||
struct Volume* vol;
|
||||
|
||||
if (dev==NULL || nPart<nPart || nPart >= dev->nVol) {
|
||||
(*adfEnv.eFct)("adfMount : invalid parameter(s)");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vol = dev->volList[nPart];
|
||||
vol->dev = dev;
|
||||
vol->mounted = TRUE;
|
||||
|
||||
/*printf("first=%ld last=%ld root=%ld\n",vol->firstBlock,
|
||||
vol->lastBlock, vol->rootBlock);
|
||||
*/
|
||||
if (adfReadBootBlock(vol, &boot)!=RC_OK) {
|
||||
(*adfEnv.wFct)("adfMount : BootBlock invalid");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vol->dosType = boot.dosType[3];
|
||||
if (isFFS(vol->dosType))
|
||||
vol->datablockSize=512;
|
||||
else
|
||||
vol->datablockSize=488;
|
||||
|
||||
if (dev->readOnly /*|| isDIRCACHE(vol->dosType)*/)
|
||||
vol->readOnly = TRUE;
|
||||
else
|
||||
vol->readOnly = readOnly;
|
||||
|
||||
if (adfReadRootBlock(vol, vol->rootBlock, &root)!=RC_OK) {
|
||||
(*adfEnv.wFct)("adfMount : RootBlock invalid");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nBlock = vol->lastBlock - vol->firstBlock +1 - 2;
|
||||
|
||||
adfReadBitmap( vol, nBlock, &root );
|
||||
vol->curDirPtr = vol->rootBlock;
|
||||
|
||||
/*printf("blockSize=%d\n",vol->blockSize);*/
|
||||
|
||||
return( vol );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* adfUnMount
|
||||
*
|
||||
* free bitmap structures
|
||||
* free current dir
|
||||
*/
|
||||
void adfUnMount(struct Volume *vol)
|
||||
{
|
||||
if (!vol) {
|
||||
(*adfEnv.eFct)("adfUnMount : vol is null");
|
||||
return;
|
||||
}
|
||||
|
||||
adfFreeBitmap(vol);
|
||||
|
||||
vol->mounted = FALSE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* adfCreateVol
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct Volume* adfCreateVol( struct Device* dev, int32_t start, int32_t len,
|
||||
char* volName, int volType )
|
||||
{
|
||||
struct bBootBlock boot;
|
||||
struct bRootBlock root;
|
||||
/* struct bDirCacheBlock dirc;*/
|
||||
SECTNUM blkList[2];
|
||||
struct Volume* vol;
|
||||
int nlen;
|
||||
|
||||
if (adfEnv.useProgressBar)
|
||||
(*adfEnv.progressBar)(0);
|
||||
|
||||
vol=(struct Volume*)malloc(sizeof(struct Volume));
|
||||
if (!vol) {
|
||||
(*adfEnv.eFct)("adfCreateVol : malloc vol");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vol->dev = dev;
|
||||
vol->firstBlock = (dev->heads * dev->sectors)*start;
|
||||
vol->lastBlock = (vol->firstBlock + (dev->heads * dev->sectors)*len)-1;
|
||||
vol->rootBlock = (vol->lastBlock - vol->firstBlock+1)/2;
|
||||
/*printf("first=%ld last=%ld root=%ld\n",vol->firstBlock,
|
||||
vol->lastBlock, vol->rootBlock);
|
||||
*/
|
||||
vol->curDirPtr = vol->rootBlock;
|
||||
|
||||
vol->readOnly = dev->readOnly;
|
||||
|
||||
vol->mounted = TRUE;
|
||||
|
||||
nlen = min( MAXNAMELEN, strlen(volName) );
|
||||
vol->volName = (char*)malloc(nlen+1);
|
||||
if (!vol->volName) {
|
||||
(*adfEnv.eFct)("adfCreateVol : malloc");
|
||||
free(vol); return NULL;
|
||||
}
|
||||
memcpy(vol->volName, volName, nlen);
|
||||
vol->volName[nlen]='\0';
|
||||
|
||||
if (adfEnv.useProgressBar)
|
||||
(*adfEnv.progressBar)(25);
|
||||
|
||||
memset(&boot, 0, 1024);
|
||||
boot.dosType[3] = volType;
|
||||
/*printf("first=%d last=%d\n", vol->firstBlock, vol->lastBlock);
|
||||
printf("name=%s root=%d\n", vol->volName, vol->rootBlock);
|
||||
*/
|
||||
if (adfWriteBootBlock(vol, &boot)!=RC_OK) {
|
||||
free(vol->volName); free(vol);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (adfEnv.useProgressBar)
|
||||
(*adfEnv.progressBar)(20);
|
||||
|
||||
if (adfCreateBitmap( vol )!=RC_OK) {
|
||||
free(vol->volName); free(vol);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (adfEnv.useProgressBar)
|
||||
(*adfEnv.progressBar)(40);
|
||||
|
||||
|
||||
/*for(i=0; i<127; i++)
|
||||
printf("%3d %x, ",i,vol->bitmapTable[0]->map[i]);
|
||||
*/
|
||||
if ( isDIRCACHE(volType) )
|
||||
adfGetFreeBlocks( vol, 2, blkList );
|
||||
else
|
||||
adfGetFreeBlocks( vol, 1, blkList );
|
||||
|
||||
|
||||
/*printf("[0]=%d [1]=%d\n",blkList[0],blkList[1]);*/
|
||||
|
||||
memset(&root, 0, LOGICAL_BLOCK_SIZE);
|
||||
|
||||
if (strlen(volName)>MAXNAMELEN)
|
||||
volName[MAXNAMELEN]='\0';
|
||||
root.nameLen = strlen(volName);
|
||||
memcpy(root.diskName,volName,root.nameLen);
|
||||
adfTime2AmigaTime(adfGiveCurrentTime(),&(root.coDays),&(root.coMins),&(root.coTicks));
|
||||
|
||||
/* dircache block */
|
||||
if ( isDIRCACHE(volType) ) {
|
||||
root.extension = 0L;
|
||||
root.secType = ST_ROOT; /* needed by adfCreateEmptyCache() */
|
||||
adfCreateEmptyCache(vol, (struct bEntryBlock*)&root, blkList[1]);
|
||||
}
|
||||
|
||||
if (adfEnv.useProgressBar)
|
||||
(*adfEnv.progressBar)(60);
|
||||
|
||||
if (adfWriteRootBlock(vol, blkList[0], &root)!=RC_OK) {
|
||||
free(vol->volName); free(vol);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fills root->bmPages[] and writes filled bitmapExtBlocks */
|
||||
if (adfWriteNewBitmap(vol)!=RC_OK)
|
||||
return NULL;
|
||||
|
||||
if (adfEnv.useProgressBar)
|
||||
(*adfEnv.progressBar)(80);
|
||||
|
||||
if (adfUpdateBitmap(vol)!=RC_OK)
|
||||
return NULL;
|
||||
|
||||
if (adfEnv.useProgressBar)
|
||||
(*adfEnv.progressBar)(100);
|
||||
/*printf("free blocks %ld\n",adfCountFreeBlocks(vol));*/
|
||||
|
||||
/* will be managed by adfMount() later */
|
||||
adfFreeBitmap(vol);
|
||||
|
||||
vol->mounted = FALSE;
|
||||
|
||||
return(vol);
|
||||
}
|
||||
|
||||
|
||||
/*-----*/
|
||||
|
||||
/*
|
||||
* adfReadBlock
|
||||
*
|
||||
* read logical block
|
||||
*/
|
||||
RETCODE
|
||||
adfReadBlock(struct Volume* vol, int32_t nSect, uint8_t* buf)
|
||||
{
|
||||
/* char strBuf[80];*/
|
||||
int32_t pSect;
|
||||
struct nativeFunctions *nFct;
|
||||
RETCODE rc;
|
||||
|
||||
if (!vol->mounted) {
|
||||
(*adfEnv.eFct)("the volume isn't mounted, adfReadBlock not possible");
|
||||
return RC_ERROR;
|
||||
}
|
||||
|
||||
/* translate logical sect to physical sect */
|
||||
pSect = nSect+vol->firstBlock;
|
||||
|
||||
if (adfEnv.useRWAccess)
|
||||
(*adfEnv.rwhAccess)(pSect,nSect,FALSE);
|
||||
|
||||
/*printf("psect=%ld nsect=%ld\n",pSect,nSect);*/
|
||||
/* sprintf(strBuf,"ReadBlock : accessing logical block #%ld", nSect);
|
||||
(*adfEnv.vFct)(strBuf);
|
||||
*/
|
||||
if (pSect<vol->firstBlock || pSect>vol->lastBlock) {
|
||||
(*adfEnv.wFct)("adfReadBlock : nSect out of range");
|
||||
|
||||
}
|
||||
/*printf("pSect R =%ld\n",pSect);*/
|
||||
nFct = adfEnv.nativeFct;
|
||||
if (vol->dev->isNativeDev)
|
||||
rc = (*nFct->adfNativeReadSector)(vol->dev, pSect, 512, buf);
|
||||
else
|
||||
rc = adfReadDumpSector(vol->dev, pSect, 512, buf);
|
||||
/*printf("rc=%ld\n",rc);*/
|
||||
if (rc!=RC_OK)
|
||||
return RC_ERROR;
|
||||
else
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfWriteBlock
|
||||
*
|
||||
*/
|
||||
RETCODE adfWriteBlock(struct Volume* vol, int32_t nSect, uint8_t *buf)
|
||||
{
|
||||
int32_t pSect;
|
||||
struct nativeFunctions *nFct;
|
||||
RETCODE rc;
|
||||
|
||||
if (!vol->mounted) {
|
||||
(*adfEnv.eFct)("the volume isn't mounted, adfWriteBlock not possible");
|
||||
return RC_ERROR;
|
||||
}
|
||||
|
||||
if (vol->readOnly) {
|
||||
(*adfEnv.wFct)("adfWriteBlock : can't write block, read only volume");
|
||||
return RC_ERROR;
|
||||
}
|
||||
|
||||
pSect = nSect+vol->firstBlock;
|
||||
/*printf("write nsect=%ld psect=%ld\n",nSect,pSect);*/
|
||||
|
||||
if (adfEnv.useRWAccess)
|
||||
(*adfEnv.rwhAccess)(pSect,nSect,TRUE);
|
||||
|
||||
if (pSect<vol->firstBlock || pSect>vol->lastBlock) {
|
||||
(*adfEnv.wFct)("adfWriteBlock : nSect out of range");
|
||||
}
|
||||
|
||||
nFct = adfEnv.nativeFct;
|
||||
/*printf("nativ=%d\n",vol->dev->isNativeDev);*/
|
||||
if (vol->dev->isNativeDev)
|
||||
rc = (*nFct->adfNativeWriteSector)(vol->dev, pSect, 512, buf);
|
||||
else
|
||||
rc = adfWriteDumpSector(vol->dev, pSect, 512, buf);
|
||||
|
||||
if (rc!=RC_OK)
|
||||
return RC_ERROR;
|
||||
else
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*#######################################################################################*/
|
||||
52
src/adf_disk.h
Normal file
52
src/adf_disk.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef _ADF_DISK_H
|
||||
#define _ADF_DISK_H 1
|
||||
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_disk.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prefix.h"
|
||||
|
||||
#include "adf_str.h"
|
||||
#include "adf_defs.h"
|
||||
|
||||
PREFIX RETCODE adfInstallBootBlock(struct Volume *vol,uint8_t*);
|
||||
|
||||
PREFIX BOOL isSectNumValid(struct Volume *vol, SECTNUM nSect);
|
||||
|
||||
PREFIX struct Volume* adfMount( struct Device *dev, int nPart, BOOL readOnly );
|
||||
PREFIX void adfUnMount(struct Volume *vol);
|
||||
PREFIX void adfVolumeInfo(struct Volume *vol);
|
||||
struct Volume* adfCreateVol( struct Device* dev, int32_t start, int32_t len,
|
||||
char* volName, int volType );
|
||||
|
||||
/*void adfReadBitmap(struct Volume* , int32_t nBlock, struct bRootBlock* root);
|
||||
void adfUpdateBitmap(struct Volume*);
|
||||
*/
|
||||
PREFIX RETCODE adfReadBlock(struct Volume* , int32_t nSect, uint8_t* buf);
|
||||
PREFIX RETCODE adfWriteBlock(struct Volume* , int32_t nSect, uint8_t* buf);
|
||||
|
||||
#endif /* _ADF_DISK_H */
|
||||
|
||||
/*##########################################################################*/
|
||||
262
src/adf_dump.c
Normal file
262
src/adf_dump.c
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* ADF Library
|
||||
*
|
||||
* adf_dump.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Amiga Dump File specific routines
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<errno.h>
|
||||
|
||||
#include"adf_defs.h"
|
||||
#include"adf_str.h"
|
||||
#include"adf_disk.h"
|
||||
#include"adf_nativ.h"
|
||||
#include"adf_err.h"
|
||||
|
||||
extern struct Env adfEnv;
|
||||
|
||||
/*
|
||||
* adfInitDumpDevice
|
||||
*
|
||||
*/
|
||||
RETCODE adfInitDumpDevice(struct Device* dev, char* name, BOOL ro)
|
||||
{
|
||||
struct nativeDevice* nDev;
|
||||
int32_t size;
|
||||
|
||||
nDev = (struct nativeDevice*)dev->nativeDev;
|
||||
|
||||
nDev = (struct nativeDevice*)malloc(sizeof(struct nativeDevice));
|
||||
if (!nDev) {
|
||||
(*adfEnv.eFct)("adfInitDumpDevice : malloc");
|
||||
return RC_MALLOC;
|
||||
}
|
||||
dev->nativeDev = nDev;
|
||||
|
||||
dev->readOnly = ro;
|
||||
errno = 0;
|
||||
if (!ro) {
|
||||
nDev->fd = fopen(name,"rb+");
|
||||
/* force read only */
|
||||
if (!nDev->fd && (errno==EACCES || errno==EROFS) ) {
|
||||
nDev->fd = fopen(name,"rb");
|
||||
dev->readOnly = TRUE;
|
||||
if (nDev->fd)
|
||||
(*adfEnv.wFct)("myInitDevice : fopen, read-only mode forced");
|
||||
}
|
||||
}
|
||||
else
|
||||
/* read only requested */
|
||||
nDev->fd = fopen(name,"rb");
|
||||
|
||||
if (!nDev->fd) {
|
||||
free(nDev);
|
||||
(*adfEnv.eFct)("myInitDevice : fopen");
|
||||
return RC_ERROR;
|
||||
}
|
||||
|
||||
/* determines size */
|
||||
fseek(nDev->fd, 0, SEEK_END);
|
||||
size = ftell(nDev->fd);
|
||||
fseek(nDev->fd, 0, SEEK_SET);
|
||||
|
||||
dev->size = size;
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfReadDumpSector
|
||||
*
|
||||
*/
|
||||
RETCODE adfReadDumpSector(struct Device *dev, int32_t n, int size, uint8_t* buf)
|
||||
{
|
||||
struct nativeDevice* nDev;
|
||||
int r;
|
||||
/*puts("adfReadDumpSector");*/
|
||||
nDev = (struct nativeDevice*)dev->nativeDev;
|
||||
r = fseek(nDev->fd, 512*n, SEEK_SET);
|
||||
/*printf("nnn=%ld size=%d\n",n,size);*/
|
||||
if (r==-1)
|
||||
return RC_ERROR;
|
||||
/*puts("123");*/
|
||||
if ((r=fread(buf, 1, size, nDev->fd))!=size) {
|
||||
/*printf("rr=%d\n",r);*/
|
||||
return RC_ERROR;
|
||||
}
|
||||
/*puts("1234");*/
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfWriteDumpSector
|
||||
*
|
||||
*/
|
||||
RETCODE adfWriteDumpSector(struct Device *dev, int32_t n, int size, uint8_t* buf)
|
||||
{
|
||||
struct nativeDevice* nDev;
|
||||
int r;
|
||||
|
||||
nDev = (struct nativeDevice*)dev->nativeDev;
|
||||
|
||||
r=fseek(nDev->fd, 512*n, SEEK_SET);
|
||||
if (r==-1)
|
||||
return RC_ERROR;
|
||||
|
||||
if ( fwrite(buf, 1, size, nDev->fd)!=(unsigned int)(size) )
|
||||
return RC_ERROR;
|
||||
/*puts("adfWriteDumpSector");*/
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfReleaseDumpDevice
|
||||
*
|
||||
*/
|
||||
RETCODE adfReleaseDumpDevice(struct Device *dev)
|
||||
{
|
||||
struct nativeDevice* nDev;
|
||||
|
||||
if (!dev->nativeDev)
|
||||
return RC_ERROR;
|
||||
|
||||
nDev = (struct nativeDevice*)dev->nativeDev;
|
||||
fclose(nDev->fd);
|
||||
|
||||
free(nDev);
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfCreateHdFile
|
||||
*
|
||||
*/
|
||||
RETCODE adfCreateHdFile(struct Device* dev, char* volName, int volType)
|
||||
{
|
||||
|
||||
if (dev==NULL) {
|
||||
(*adfEnv.eFct)("adfCreateHdFile : dev==NULL");
|
||||
return RC_ERROR;
|
||||
}
|
||||
dev->volList =(struct Volume**) malloc(sizeof(struct Volume*));
|
||||
if (!dev->volList) {
|
||||
(*adfEnv.eFct)("adfCreateHdFile : unknown device type");
|
||||
return RC_ERROR;
|
||||
}
|
||||
|
||||
dev->volList[0] = adfCreateVol( dev, 0L, (int32_t)dev->cylinders, volName, volType );
|
||||
if (dev->volList[0]==NULL) {
|
||||
free(dev->volList);
|
||||
return RC_ERROR;
|
||||
}
|
||||
|
||||
dev->nVol = 1;
|
||||
dev->devType = DEVTYPE_HARDFILE;
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfCreateDumpDevice
|
||||
*
|
||||
* returns NULL if failed
|
||||
*/
|
||||
struct Device*
|
||||
adfCreateDumpDevice(char* filename, int32_t cylinders, int32_t heads, int32_t sectors)
|
||||
{
|
||||
struct Device* dev;
|
||||
uint8_t buf[LOGICAL_BLOCK_SIZE];
|
||||
struct nativeDevice* nDev;
|
||||
/* int32_t i;*/
|
||||
int r;
|
||||
|
||||
dev=(struct Device*)malloc(sizeof(struct Device));
|
||||
if (!dev) {
|
||||
(*adfEnv.eFct)("adfCreateDumpDevice : malloc dev");
|
||||
return NULL;
|
||||
}
|
||||
nDev = (struct nativeDevice*)malloc(sizeof(struct nativeDevice));
|
||||
if (!nDev) {
|
||||
free(dev);
|
||||
(*adfEnv.eFct)("adfCreateDumpDevice : malloc nDev");
|
||||
return NULL;
|
||||
}
|
||||
dev->nativeDev = nDev;
|
||||
|
||||
nDev->fd = (FILE*)fopen(filename,"wb");
|
||||
if (!nDev->fd) {
|
||||
free(nDev); free(dev);
|
||||
(*adfEnv.eFct)("adfCreateDumpDevice : fopen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* for(i=0; i<cylinders*heads*sectors; i++)
|
||||
fwrite(buf, sizeof(uint8_t), 512 , nDev->fd);
|
||||
*/
|
||||
r=fseek(nDev->fd, ((cylinders*heads*sectors)-1)*LOGICAL_BLOCK_SIZE, SEEK_SET);
|
||||
if (r==-1) {
|
||||
fclose(nDev->fd); free(nDev); free(dev);
|
||||
(*adfEnv.eFct)("adfCreateDumpDevice : fseek");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fwrite(buf, LOGICAL_BLOCK_SIZE, 1, nDev->fd);
|
||||
|
||||
fclose(nDev->fd);
|
||||
|
||||
nDev->fd=(FILE*)fopen(filename,"rb+");
|
||||
if (!nDev->fd) {
|
||||
free(nDev); free(dev);
|
||||
(*adfEnv.eFct)("adfCreateDumpDevice : fopen");
|
||||
return NULL;
|
||||
}
|
||||
dev->cylinders = cylinders;
|
||||
dev->heads = heads;
|
||||
dev->sectors = sectors;
|
||||
dev->size = cylinders*heads*sectors* LOGICAL_BLOCK_SIZE;
|
||||
|
||||
if (dev->size==80*11*2*LOGICAL_BLOCK_SIZE)
|
||||
dev->devType = DEVTYPE_FLOPDD;
|
||||
else if (dev->size==80*22*2*LOGICAL_BLOCK_SIZE)
|
||||
dev->devType = DEVTYPE_FLOPHD;
|
||||
else
|
||||
dev->devType = DEVTYPE_HARDDISK;
|
||||
|
||||
dev->nVol = 0;
|
||||
dev->isNativeDev = FALSE;
|
||||
dev->readOnly = FALSE;
|
||||
|
||||
return(dev);
|
||||
}
|
||||
|
||||
/*##################################################################################*/
|
||||
|
||||
39
src/adf_dump.h
Normal file
39
src/adf_dump.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef ADF_DUMP_H
|
||||
#define ADF_DUMP_H 1
|
||||
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_dump.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
PREFIX struct Device*
|
||||
adfCreateDumpDevice(char* filename, int32_t cyl, int32_t heads, int32_t sec);
|
||||
PREFIX RETCODE adfCreateHdFile(struct Device* dev, char* volName, int volType);
|
||||
BOOL adfInitDumpDevice(struct Device* dev, char* name,BOOL);
|
||||
BOOL adfReadDumpSector(struct Device *dev, int32_t n, int size, uint8_t* buf);
|
||||
BOOL adfWriteDumpSector(struct Device *dev, int32_t n, int size, uint8_t* buf);
|
||||
void adfReleaseDumpDevice(struct Device *dev);
|
||||
|
||||
|
||||
#endif /* ADF_DUMP_H */
|
||||
/*##########################################################################*/
|
||||
261
src/adf_env.c
Normal file
261
src/adf_env.c
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* ADF Library
|
||||
*
|
||||
* adf_env.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* library context and customization code
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
|
||||
#include"adf_defs.h"
|
||||
#include"adf_str.h"
|
||||
#include"adf_nativ.h"
|
||||
#include"adf_env.h"
|
||||
|
||||
#include"defendian.h"
|
||||
|
||||
union u{
|
||||
int32_t l;
|
||||
char c[4];
|
||||
};
|
||||
|
||||
ENV_DECLARATION;
|
||||
|
||||
void rwHeadAccess(SECTNUM physical, SECTNUM logical, BOOL write)
|
||||
{
|
||||
/* display the physical sector, the logical block, and if the access is read or write */
|
||||
|
||||
fprintf(stderr, "phy %d / log %d : %c\n", physical, logical, write ? 'W' : 'R');
|
||||
}
|
||||
|
||||
void progressBar(int perCentDone)
|
||||
{
|
||||
fprintf(stderr,"%d %% done\n",perCentDone);
|
||||
}
|
||||
|
||||
void Warning(char* msg) {
|
||||
fprintf(stderr,"Warning <%s>\n",msg);
|
||||
}
|
||||
|
||||
void Error(char* msg) {
|
||||
fprintf(stderr,"Error <%s>\n",msg);
|
||||
/* exit(1);*/
|
||||
}
|
||||
|
||||
void Verbose(char* msg) {
|
||||
fprintf(stderr,"Verbose <%s>\n",msg);
|
||||
}
|
||||
|
||||
void Changed(SECTNUM nSect, int changedType)
|
||||
{
|
||||
/* switch(changedType) {
|
||||
case ST_FILE:
|
||||
fprintf(stderr,"Notification : sector %ld (FILE)\n",nSect);
|
||||
break;
|
||||
case ST_DIR:
|
||||
fprintf(stderr,"Notification : sector %ld (DIR)\n",nSect);
|
||||
break;
|
||||
case ST_ROOT:
|
||||
fprintf(stderr,"Notification : sector %ld (ROOT)\n",nSect);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Notification : sector %ld (???)\n",nSect);
|
||||
}
|
||||
*/}
|
||||
|
||||
/*
|
||||
* adfInitEnv
|
||||
*
|
||||
*/
|
||||
void adfEnvInitDefault()
|
||||
{
|
||||
/* char str[80];*/
|
||||
union u val;
|
||||
|
||||
/* internal checking */
|
||||
|
||||
if (sizeof(short)!=2)
|
||||
{ fprintf(stderr,"Compilation error : sizeof(short)!=2\n"); exit(1); }
|
||||
if (sizeof(int32_t)!=4)
|
||||
{ fprintf(stderr,"Compilation error : sizeof(short)!=2\n"); exit(1); }
|
||||
if (sizeof(struct bEntryBlock)!=512)
|
||||
{ fprintf(stderr,"Internal error : sizeof(struct bEntryBlock)!=512\n"); exit(1); }
|
||||
if (sizeof(struct bRootBlock)!=512)
|
||||
{ fprintf(stderr,"Internal error : sizeof(struct bRootBlock)!=512\n"); exit(1); }
|
||||
if (sizeof(struct bDirBlock)!=512)
|
||||
{ fprintf(stderr,"Internal error : sizeof(struct bDirBlock)!=512\n"); exit(1); }
|
||||
if (sizeof(struct bBootBlock)!=1024)
|
||||
{ fprintf(stderr,"Internal error : sizeof(struct bBootBlock)!=1024\n"); exit(1); }
|
||||
if (sizeof(struct bFileHeaderBlock)!=512)
|
||||
{ fprintf(stderr,"Internal error : sizeof(struct bFileHeaderBlock)!=512\n"); exit(1); }
|
||||
if (sizeof(struct bFileExtBlock)!=512)
|
||||
{ fprintf(stderr,"Internal error : sizeof(struct bFileExtBlock)!=512\n"); exit(1); }
|
||||
if (sizeof(struct bOFSDataBlock)!=512)
|
||||
{ fprintf(stderr,"Internal error : sizeof(struct bOFSDataBlock)!=512\n"); exit(1); }
|
||||
if (sizeof(struct bBitmapBlock)!=512)
|
||||
{ fprintf(stderr,"Internal error : sizeof(struct bBitmapBlock)!=512\n"); exit(1); }
|
||||
if (sizeof(struct bBitmapExtBlock)!=512)
|
||||
{ fprintf(stderr,"Internal error : sizeof(struct bBitmapExtBlock)!=512\n"); exit(1); }
|
||||
if (sizeof(struct bLinkBlock)!=512)
|
||||
{ fprintf(stderr,"Internal error : sizeof(struct bLinkBlock)!=512\n"); exit(1); }
|
||||
|
||||
val.l=1L;
|
||||
/* if LITT_ENDIAN not defined : must be BIG endian */
|
||||
#ifndef LITT_ENDIAN
|
||||
if (val.c[3]!=1) /* little endian : LITT_ENDIAN must be defined ! */
|
||||
{ fprintf(stderr,"Compilation error : #define LITT_ENDIAN must exist\n"); exit(1); }
|
||||
#else
|
||||
if (val.c[3]==1) /* big endian : LITT_ENDIAN must not be defined ! */
|
||||
{ fprintf(stderr,"Compilation error : #define LITT_ENDIAN must not exist\n"); exit(1); }
|
||||
#endif
|
||||
|
||||
adfEnv.wFct = Warning;
|
||||
adfEnv.eFct = Error;
|
||||
adfEnv.vFct = Verbose;
|
||||
adfEnv.notifyFct = Changed;
|
||||
adfEnv.rwhAccess = rwHeadAccess;
|
||||
adfEnv.progressBar = progressBar;
|
||||
|
||||
adfEnv.useDirCache = FALSE;
|
||||
adfEnv.useRWAccess = FALSE;
|
||||
adfEnv.useNotify = FALSE;
|
||||
adfEnv.useProgressBar = FALSE;
|
||||
|
||||
/* sprintf(str,"ADFlib %s (%s)",adfGetVersionNumber(),adfGetVersionDate());
|
||||
(*adfEnv.vFct)(str);
|
||||
*/
|
||||
adfEnv.nativeFct=(struct nativeFunctions*)malloc(sizeof(struct nativeFunctions));
|
||||
if (!adfEnv.nativeFct) (*adfEnv.wFct)("adfInitDefaultEnv : malloc");
|
||||
|
||||
adfInitNativeFct();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfEnvCleanUp
|
||||
*
|
||||
*/
|
||||
void adfEnvCleanUp()
|
||||
{
|
||||
free(adfEnv.nativeFct);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfChgEnvProp
|
||||
*
|
||||
* compilation warnings
|
||||
* adf_env.c: In function adfChgEnvProp:
|
||||
* adf_env.c:176: warning: ISO C forbids conversion of object pointer to function pointer type
|
||||
* adf_env.c:179: warning: ISO C forbids conversion of object pointer to function pointer type
|
||||
* adf_env.c:182: warning: ISO C forbids conversion of object pointer to function pointer type
|
||||
* adf_env.c:185: warning: ISO C forbids conversion of object pointer to function pointer type
|
||||
* adf_env.c:192: warning: ISO C forbids conversion of object pointer to function pointer type
|
||||
* adf_env.c:203: warning: ISO C forbids conversion of object pointer to function pointer type
|
||||
*
|
||||
*/
|
||||
void adfChgEnvProp(int prop, void *new)
|
||||
{
|
||||
BOOL *newBool;
|
||||
/* int *newInt;*/
|
||||
|
||||
switch(prop) {
|
||||
case PR_VFCT:
|
||||
adfEnv.vFct = (void(*)(char*))new;
|
||||
break;
|
||||
case PR_WFCT:
|
||||
adfEnv.wFct = (void(*)(char*))new;
|
||||
break;
|
||||
case PR_EFCT:
|
||||
adfEnv.eFct = (void(*)(char*))new;
|
||||
break;
|
||||
case PR_NOTFCT:
|
||||
adfEnv.notifyFct = (void(*)(SECTNUM,int))new;
|
||||
break;
|
||||
case PR_USE_NOTFCT:
|
||||
newBool = (BOOL*)new;
|
||||
adfEnv.useNotify = *newBool;
|
||||
break;
|
||||
case PR_PROGBAR:
|
||||
adfEnv.progressBar = (void(*)(int))new;
|
||||
break;
|
||||
case PR_USE_PROGBAR:
|
||||
newBool = (BOOL*)new;
|
||||
adfEnv.useProgressBar = *newBool;
|
||||
break;
|
||||
case PR_USE_RWACCESS:
|
||||
newBool = (BOOL*)new;
|
||||
adfEnv.useRWAccess = *newBool;
|
||||
break;
|
||||
case PR_RWACCESS:
|
||||
adfEnv.rwhAccess = (void(*)(SECTNUM,SECTNUM,BOOL))new;
|
||||
break;
|
||||
case PR_USEDIRC:
|
||||
newBool = (BOOL*)new;
|
||||
adfEnv.useDirCache = *newBool;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* adfSetEnv
|
||||
*
|
||||
*/
|
||||
void adfSetEnvFct( void(*eFct)(char*), void(*wFct)(char*), void(*vFct)(char*),
|
||||
void(*notFct)(SECTNUM,int) )
|
||||
{
|
||||
if (*eFct!=0)
|
||||
adfEnv.eFct = *eFct;
|
||||
if (*wFct!=0)
|
||||
adfEnv.wFct = *wFct;
|
||||
if (*vFct!=0)
|
||||
adfEnv.vFct = *vFct;
|
||||
if (*notFct!=0)
|
||||
adfEnv.notifyFct = *notFct;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfGetVersionNumber
|
||||
*
|
||||
*/
|
||||
char* adfGetVersionNumber()
|
||||
{
|
||||
return(ADFLIB_VERSION);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfGetVersionDate
|
||||
*
|
||||
*/
|
||||
char* adfGetVersionDate()
|
||||
{
|
||||
return(ADFLIB_DATE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*##################################################################################*/
|
||||
40
src/adf_env.h
Normal file
40
src/adf_env.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef ADF_ENV_H
|
||||
#define ADF_ENV_H 1
|
||||
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_env.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include"prefix.h"
|
||||
|
||||
PREFIX void adfEnvInitDefault();
|
||||
PREFIX void adfSetEnvFct( void(*e)(char*), void(*w)(char*), void(*v)(char*),
|
||||
void(*n)(SECTNUM,int) );
|
||||
PREFIX void adfEnvCleanUp();
|
||||
PREFIX void adfChgEnvProp(int prop, void *new);
|
||||
PREFIX char* adfGetVersionNumber();
|
||||
PREFIX char* adfGetVersionDate();
|
||||
|
||||
#endif /* ADF_ENV_H */
|
||||
/*##########################################################################*/
|
||||
86
src/adf_err.h
Normal file
86
src/adf_err.h
Normal file
@@ -0,0 +1,86 @@
|
||||
#ifndef ADF_ERR_H
|
||||
#define ADF_ERR_H
|
||||
|
||||
/*
|
||||
* adf_err.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* error codes
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#define hasRC(rc,c) ((rc)&(c))
|
||||
|
||||
#define RC_OK 0
|
||||
#define RC_ERROR -1
|
||||
|
||||
#define RC_MALLOC 1
|
||||
#define RC_VOLFULL 2
|
||||
|
||||
|
||||
#define RC_FOPEN 1<<10
|
||||
#define RC_NULLPTR 1<<12
|
||||
|
||||
/* adfRead*Block() */
|
||||
|
||||
#define RC_BLOCKTYPE 1
|
||||
#define RC_BLOCKSTYPE 1<<1
|
||||
#define RC_BLOCKSUM 1<<2
|
||||
#define RC_HEADERKEY 1<<3
|
||||
#define RC_BLOCKREAD 1<<4
|
||||
|
||||
/* adfWrite*Block */
|
||||
#define RC_BLOCKWRITE 1<<4
|
||||
|
||||
|
||||
/* adfReadBlock() */
|
||||
#define RC_BLOCKOUTOFRANGE 1
|
||||
#define RC_BLOCKNATREAD 1<<1
|
||||
|
||||
/* adfWriteBlock() */
|
||||
/* RC_BLOCKOUTOFRANGE */
|
||||
#define RC_BLOCKNATWRITE 1<<1
|
||||
#define RC_BLOCKREADONLY 1<<2
|
||||
|
||||
/* adfInitDumpDevice() */
|
||||
/* RC_FOPEN */
|
||||
/* RC_MALLOC */
|
||||
|
||||
/* adfNativeReadBlock(), adfReadDumpSector() */
|
||||
|
||||
#define RC_BLOCKSHORTREAD 1
|
||||
#define RC_BLOCKFSEEK 1<<1
|
||||
|
||||
/* adfNativeWriteBlock(), adfWriteDumpSector() */
|
||||
|
||||
#define RC_BLOCKSHORTWRITE 1
|
||||
/* RC_BLOCKFSEEK */
|
||||
|
||||
|
||||
/*-- adfReadRDSKblock --*/
|
||||
#define RC_BLOCKID 1<<5
|
||||
|
||||
/*-- adfWriteRDSKblock() --*/
|
||||
/*RC_BLOCKREADONLY*/
|
||||
|
||||
#endif /* ADF_ERR_H */
|
||||
|
||||
/*############################################################################*/
|
||||
781
src/adf_file.c
Normal file
781
src/adf_file.c
Normal file
@@ -0,0 +1,781 @@
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_file.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* file code
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include<stdlib.h>
|
||||
#include<string.h>
|
||||
|
||||
#include"adf_util.h"
|
||||
#include"adf_file.h"
|
||||
#include"adf_str.h"
|
||||
#include"defendian.h"
|
||||
#include"adf_raw.h"
|
||||
#include"adf_disk.h"
|
||||
#include"adf_dir.h"
|
||||
#include"adf_bitm.h"
|
||||
#include"adf_cache.h"
|
||||
|
||||
extern struct Env adfEnv;
|
||||
|
||||
void adfFileTruncate(struct Volume *vol, SECTNUM nParent, char *name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfFileFlush
|
||||
*
|
||||
*/
|
||||
void adfFlushFile(struct File *file)
|
||||
{
|
||||
struct bEntryBlock parent;
|
||||
struct bOFSDataBlock *data;
|
||||
|
||||
if (file->currentExt) {
|
||||
if (file->writeMode)
|
||||
adfWriteFileExtBlock(file->volume, file->currentExt->headerKey,
|
||||
file->currentExt);
|
||||
}
|
||||
if (file->currentData) {
|
||||
if (file->writeMode) {
|
||||
file->fileHdr->byteSize = file->pos;
|
||||
if (isOFS(file->volume->dosType)) {
|
||||
data = (struct bOFSDataBlock *)file->currentData;
|
||||
data->dataSize = file->posInDataBlk;
|
||||
}
|
||||
if (file->fileHdr->byteSize>0)
|
||||
adfWriteDataBlock(file->volume, file->curDataPtr,
|
||||
file->currentData);
|
||||
}
|
||||
}
|
||||
if (file->writeMode) {
|
||||
file->fileHdr->byteSize = file->pos;
|
||||
/*printf("pos=%ld\n",file->pos);*/
|
||||
adfTime2AmigaTime(adfGiveCurrentTime(),
|
||||
&(file->fileHdr->days),&(file->fileHdr->mins),&(file->fileHdr->ticks) );
|
||||
adfWriteFileHdrBlock(file->volume, file->fileHdr->headerKey, file->fileHdr);
|
||||
|
||||
if (isDIRCACHE(file->volume->dosType)) {
|
||||
/*printf("parent=%ld\n",file->fileHdr->parent);*/
|
||||
adfReadEntryBlock(file->volume, file->fileHdr->parent, &parent);
|
||||
adfUpdateCache(file->volume, &parent, (struct bEntryBlock*)file->fileHdr,FALSE);
|
||||
}
|
||||
adfUpdateBitmap(file->volume);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfGetFileBlocks
|
||||
*
|
||||
*/
|
||||
RETCODE adfGetFileBlocks(struct Volume* vol, struct bFileHeaderBlock* entry,
|
||||
struct FileBlocks* fileBlocks)
|
||||
{
|
||||
int32_t n, m;
|
||||
SECTNUM nSect;
|
||||
struct bFileExtBlock extBlock;
|
||||
int32_t i;
|
||||
|
||||
fileBlocks->header = entry->headerKey;
|
||||
adfFileRealSize( entry->byteSize, vol->datablockSize,
|
||||
&(fileBlocks->nbData), &(fileBlocks->nbExtens) );
|
||||
|
||||
fileBlocks->data=(SECTNUM*)malloc(fileBlocks->nbData * sizeof(SECTNUM));
|
||||
if (!fileBlocks->data) {
|
||||
(*adfEnv.eFct)("adfGetFileBlocks : malloc");
|
||||
return RC_MALLOC;
|
||||
}
|
||||
|
||||
fileBlocks->extens=(SECTNUM*)malloc(fileBlocks->nbExtens * sizeof(SECTNUM));
|
||||
if (!fileBlocks->extens) {
|
||||
(*adfEnv.eFct)("adfGetFileBlocks : malloc");
|
||||
return RC_MALLOC;
|
||||
}
|
||||
|
||||
n = m = 0;
|
||||
/* in file header block */
|
||||
for(i=0; i<entry->highSeq; i++)
|
||||
fileBlocks->data[n++] = entry->dataBlocks[MAX_DATABLK-1-i];
|
||||
|
||||
/* in file extension blocks */
|
||||
nSect = entry->extension;
|
||||
while(nSect!=0) {
|
||||
fileBlocks->extens[m++] = nSect;
|
||||
adfReadFileExtBlock(vol, nSect, &extBlock);
|
||||
for(i=0; i<extBlock.highSeq; i++)
|
||||
fileBlocks->data[n++] = extBlock.dataBlocks[MAX_DATABLK-1-i];
|
||||
nSect = extBlock.extension;
|
||||
}
|
||||
if ( (fileBlocks->nbExtens+fileBlocks->nbData) != (n+m) )
|
||||
(*adfEnv.wFct)("adfGetFileBlocks : less blocks than expected");
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* adfFreeFileBlocks
|
||||
*
|
||||
*/
|
||||
RETCODE adfFreeFileBlocks(struct Volume* vol, struct bFileHeaderBlock *entry)
|
||||
{
|
||||
int i;
|
||||
struct FileBlocks fileBlocks;
|
||||
RETCODE rc = RC_OK;
|
||||
|
||||
adfGetFileBlocks(vol,entry,&fileBlocks);
|
||||
|
||||
for(i=0; i<fileBlocks.nbData; i++) {
|
||||
adfSetBlockFree(vol, fileBlocks.data[i]);
|
||||
}
|
||||
for(i=0; i<fileBlocks.nbExtens; i++) {
|
||||
adfSetBlockFree(vol, fileBlocks.extens[i]);
|
||||
}
|
||||
|
||||
free(fileBlocks.data);
|
||||
free(fileBlocks.extens);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfFileRealSize
|
||||
*
|
||||
* Compute and return real number of block used by one file
|
||||
* Compute number of datablocks and file extension blocks
|
||||
*
|
||||
*/
|
||||
int32_t adfFileRealSize(uint32_t size, int blockSize, int32_t *dataN, int32_t *extN)
|
||||
{
|
||||
int32_t data, ext;
|
||||
|
||||
/*--- number of data blocks ---*/
|
||||
data = size / blockSize;
|
||||
if ( size % blockSize )
|
||||
data++;
|
||||
|
||||
/*--- number of header extension blocks ---*/
|
||||
ext = 0;
|
||||
if (data>MAX_DATABLK) {
|
||||
ext = (data-MAX_DATABLK) / MAX_DATABLK;
|
||||
if ( (data-MAX_DATABLK) % MAX_DATABLK )
|
||||
ext++;
|
||||
}
|
||||
|
||||
if (dataN)
|
||||
*dataN = data;
|
||||
if (extN)
|
||||
*extN = ext;
|
||||
|
||||
return(ext+data+1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfWriteFileHdrBlock
|
||||
*
|
||||
*/
|
||||
RETCODE adfWriteFileHdrBlock(struct Volume *vol, SECTNUM nSect, struct bFileHeaderBlock* fhdr)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint32_t newSum;
|
||||
RETCODE rc = RC_OK;
|
||||
/*printf("adfWriteFileHdrBlock %ld\n",nSect);*/
|
||||
fhdr->type = T_HEADER;
|
||||
fhdr->dataSize = 0;
|
||||
fhdr->secType = ST_FILE;
|
||||
|
||||
memcpy(buf, fhdr, sizeof(struct bFileHeaderBlock));
|
||||
#ifdef LITT_ENDIAN
|
||||
swapEndian(buf, SWBL_FILE);
|
||||
#endif
|
||||
newSum = adfNormalSum(buf,20,sizeof(struct bFileHeaderBlock));
|
||||
swLong(buf+20, newSum);
|
||||
/* *(uint32_t*)(buf+20) = swapLong((uint8_t*)&newSum);*/
|
||||
|
||||
adfWriteBlock(vol, nSect, buf);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfFileSeek
|
||||
*
|
||||
*/
|
||||
void adfFileSeek(struct File *file, uint32_t pos)
|
||||
{
|
||||
SECTNUM extBlock, nSect;
|
||||
uint32_t nPos;
|
||||
int i;
|
||||
|
||||
nPos = min(pos, file->fileHdr->byteSize);
|
||||
file->pos = nPos;
|
||||
extBlock = adfPos2DataBlock(nPos, file->volume->datablockSize,
|
||||
&(file->posInExtBlk), &(file->posInDataBlk), &(file->curDataPtr) );
|
||||
if (extBlock==-1) {
|
||||
adfReadDataBlock(file->volume,
|
||||
file->fileHdr->dataBlocks[MAX_DATABLK-1-file->curDataPtr],
|
||||
file->currentData);
|
||||
}
|
||||
else {
|
||||
nSect = file->fileHdr->extension;
|
||||
i = 0;
|
||||
while( i<extBlock && nSect!=0 ) {
|
||||
adfReadFileExtBlock(file->volume, nSect, file->currentExt );
|
||||
nSect = file->currentExt->extension;
|
||||
}
|
||||
if (i!=extBlock)
|
||||
(*adfEnv.wFct)("error");
|
||||
adfReadDataBlock(file->volume,
|
||||
file->currentExt->dataBlocks[file->posInExtBlk], file->currentData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfFileOpen
|
||||
*
|
||||
*/
|
||||
struct File* adfOpenFile(struct Volume *vol, char* name, char *mode)
|
||||
{
|
||||
struct File *file;
|
||||
SECTNUM nSect;
|
||||
struct bEntryBlock entry, parent;
|
||||
BOOL write;
|
||||
char filename[200];
|
||||
|
||||
write=( strcmp("w",mode)==0 || strcmp("a",mode)==0 );
|
||||
|
||||
if (write && vol->dev->readOnly) {
|
||||
(*adfEnv.wFct)("adfFileOpen : device is mounted 'read only'");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
adfReadEntryBlock(vol, vol->curDirPtr, &parent);
|
||||
|
||||
nSect = adfNameToEntryBlk(vol, parent.hashTable, name, &entry, NULL);
|
||||
if (!write && nSect==-1) {
|
||||
sprintf(filename,"adfFileOpen : file \"%s\" not found.",name);
|
||||
(*adfEnv.wFct)(filename);
|
||||
/*fprintf(stdout,"filename %s %d, parent =%d\n",name,strlen(name),vol->curDirPtr);*/
|
||||
return NULL;
|
||||
}
|
||||
if (!write && hasR(entry.access)) {
|
||||
(*adfEnv.wFct)("adfFileOpen : access denied"); return NULL; }
|
||||
/* if (entry.secType!=ST_FILE) {
|
||||
(*adfEnv.wFct)("adfFileOpen : not a file"); return NULL; }
|
||||
if (write && (hasE(entry.access)||hasW(entry.access))) {
|
||||
(*adfEnv.wFct)("adfFileOpen : access denied"); return NULL; }
|
||||
*/ if (write && nSect!=-1) {
|
||||
(*adfEnv.wFct)("adfFileOpen : file already exists"); return NULL; }
|
||||
|
||||
file = (struct File*)malloc(sizeof(struct File));
|
||||
if (!file) { (*adfEnv.wFct)("adfFileOpen : malloc"); return NULL; }
|
||||
file->fileHdr = (struct bFileHeaderBlock*)malloc(sizeof(struct bFileHeaderBlock));
|
||||
if (!file->fileHdr) {
|
||||
(*adfEnv.wFct)("adfFileOpen : malloc");
|
||||
free(file); return NULL;
|
||||
}
|
||||
file->currentData = malloc(512*sizeof(uint8_t));
|
||||
if (!file->currentData) {
|
||||
(*adfEnv.wFct)("adfFileOpen : malloc");
|
||||
free(file->fileHdr); free(file); return NULL;
|
||||
}
|
||||
|
||||
file->volume = vol;
|
||||
file->pos = 0;
|
||||
file->posInExtBlk = 0;
|
||||
file->posInDataBlk = 0;
|
||||
file->writeMode = write;
|
||||
file->currentExt = NULL;
|
||||
file->nDataBlock = 0;
|
||||
|
||||
if (strcmp("w",mode)==0) {
|
||||
memset(file->fileHdr,0,512);
|
||||
adfCreateFile(vol,vol->curDirPtr,name,file->fileHdr);
|
||||
file->eof = TRUE;
|
||||
}
|
||||
else if (strcmp("a",mode)==0) {
|
||||
memcpy(file->fileHdr,&entry,sizeof(struct bFileHeaderBlock));
|
||||
file->eof = TRUE;
|
||||
adfFileSeek(file, file->fileHdr->byteSize);
|
||||
}
|
||||
else if (strcmp("r",mode)==0) {
|
||||
memcpy(file->fileHdr,&entry,sizeof(struct bFileHeaderBlock));
|
||||
file->eof = FALSE;
|
||||
}
|
||||
|
||||
/*puts("adfOpenFile");*/
|
||||
return(file);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfCloseFile
|
||||
*
|
||||
*/
|
||||
void adfCloseFile(struct File *file)
|
||||
{
|
||||
|
||||
if (file==0)
|
||||
return;
|
||||
/*puts("adfCloseFile in");*/
|
||||
|
||||
adfFlushFile(file);
|
||||
|
||||
if (file->currentExt)
|
||||
free(file->currentExt);
|
||||
|
||||
if (file->currentData)
|
||||
free(file->currentData);
|
||||
|
||||
free(file->fileHdr);
|
||||
free(file);
|
||||
|
||||
/*puts("adfCloseFile out");*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfReadFile
|
||||
*
|
||||
*/
|
||||
int32_t adfReadFile(struct File* file, int32_t n, uint8_t *buffer)
|
||||
{
|
||||
int32_t bytesRead;
|
||||
uint8_t *dataPtr, *bufPtr;
|
||||
int blockSize, size;
|
||||
|
||||
if (n==0) return(n);
|
||||
blockSize = file->volume->datablockSize;
|
||||
/*puts("adfReadFile");*/
|
||||
if (file->pos+n > file->fileHdr->byteSize)
|
||||
n = file->fileHdr->byteSize - file->pos;
|
||||
|
||||
if (isOFS(file->volume->dosType))
|
||||
dataPtr = (uint8_t*)(file->currentData)+24;
|
||||
else
|
||||
dataPtr = file->currentData;
|
||||
|
||||
if (file->pos==0 || file->posInDataBlk==blockSize) {
|
||||
adfReadNextFileBlock(file);
|
||||
file->posInDataBlk = 0;
|
||||
}
|
||||
|
||||
bytesRead = 0; bufPtr = buffer;
|
||||
size = 0;
|
||||
while ( bytesRead < n ) {
|
||||
size = min(n-bytesRead, blockSize-file->posInDataBlk);
|
||||
memcpy(bufPtr, dataPtr+file->posInDataBlk, size);
|
||||
bufPtr += size;
|
||||
file->pos += size;
|
||||
bytesRead += size;
|
||||
file->posInDataBlk += size;
|
||||
if (file->posInDataBlk==blockSize && bytesRead<n) {
|
||||
adfReadNextFileBlock(file);
|
||||
file->posInDataBlk = 0;
|
||||
}
|
||||
}
|
||||
file->eof = (file->pos==file->fileHdr->byteSize);
|
||||
return( bytesRead );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfEndOfFile
|
||||
*
|
||||
*/
|
||||
BOOL adfEndOfFile(struct File* file)
|
||||
{
|
||||
return(file->eof);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfReadNextFileBlock
|
||||
*
|
||||
*/
|
||||
RETCODE adfReadNextFileBlock(struct File* file)
|
||||
{
|
||||
SECTNUM nSect;
|
||||
struct bOFSDataBlock *data;
|
||||
RETCODE rc = RC_OK;
|
||||
|
||||
data =(struct bOFSDataBlock *) file->currentData;
|
||||
|
||||
if (file->nDataBlock==0) {
|
||||
nSect = file->fileHdr->firstData;
|
||||
}
|
||||
else if (isOFS(file->volume->dosType)) {
|
||||
nSect = data->nextData;
|
||||
}
|
||||
else {
|
||||
if (file->nDataBlock<MAX_DATABLK)
|
||||
nSect = file->fileHdr->dataBlocks[MAX_DATABLK-1-file->nDataBlock];
|
||||
else {
|
||||
if (file->nDataBlock==MAX_DATABLK) {
|
||||
file->currentExt=(struct bFileExtBlock*)malloc(sizeof(struct bFileExtBlock));
|
||||
if (!file->currentExt) (*adfEnv.eFct)("adfReadNextFileBlock : malloc");
|
||||
adfReadFileExtBlock(file->volume, file->fileHdr->extension,
|
||||
file->currentExt);
|
||||
file->posInExtBlk = 0;
|
||||
}
|
||||
else if (file->posInExtBlk==MAX_DATABLK) {
|
||||
adfReadFileExtBlock(file->volume, file->currentExt->extension,
|
||||
file->currentExt);
|
||||
file->posInExtBlk = 0;
|
||||
}
|
||||
nSect = file->currentExt->dataBlocks[MAX_DATABLK-1-file->posInExtBlk];
|
||||
file->posInExtBlk++;
|
||||
}
|
||||
}
|
||||
adfReadDataBlock(file->volume,nSect,file->currentData);
|
||||
|
||||
if (isOFS(file->volume->dosType) && data->seqNum!=file->nDataBlock+1)
|
||||
(*adfEnv.wFct)("adfReadNextFileBlock : seqnum incorrect");
|
||||
|
||||
file->nDataBlock++;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfWriteFile
|
||||
*
|
||||
*/
|
||||
int32_t adfWriteFile(struct File *file, int32_t n, uint8_t *buffer)
|
||||
{
|
||||
int32_t bytesWritten;
|
||||
uint8_t *dataPtr, *bufPtr;
|
||||
int size, blockSize;
|
||||
struct bOFSDataBlock *dataB;
|
||||
|
||||
bytesWritten = 0;
|
||||
if (n==0) return (n);
|
||||
/*puts("adfWriteFile");*/
|
||||
blockSize = file->volume->datablockSize;
|
||||
if (isOFS(file->volume->dosType)) {
|
||||
dataB =(struct bOFSDataBlock *)file->currentData;
|
||||
dataPtr = dataB->data;
|
||||
}
|
||||
else
|
||||
dataPtr = file->currentData;
|
||||
|
||||
if (file->pos==0 || file->posInDataBlk==blockSize) {
|
||||
if (adfCreateNextFileBlock(file)==-1) {
|
||||
/* bug found by Rikard */
|
||||
(*adfEnv.wFct)("adfWritefile : no more free sector availbale");
|
||||
return bytesWritten;
|
||||
}
|
||||
file->posInDataBlk = 0;
|
||||
}
|
||||
|
||||
bytesWritten = 0; bufPtr = buffer;
|
||||
while( bytesWritten<n ) {
|
||||
size = min(n-bytesWritten, blockSize-file->posInDataBlk);
|
||||
memcpy(dataPtr+file->posInDataBlk, bufPtr, size);
|
||||
bufPtr += size;
|
||||
file->pos += size;
|
||||
bytesWritten += size;
|
||||
file->posInDataBlk += size;
|
||||
if (file->posInDataBlk==blockSize && bytesWritten<n) {
|
||||
if (adfCreateNextFileBlock(file)==-1) {
|
||||
/* bug found by Rikard */
|
||||
(*adfEnv.wFct)("adfWritefile : no more free sector availbale");
|
||||
return bytesWritten;
|
||||
}
|
||||
file->posInDataBlk = 0;
|
||||
}
|
||||
}
|
||||
return( bytesWritten );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfCreateNextFileBlock
|
||||
*
|
||||
*/
|
||||
SECTNUM adfCreateNextFileBlock(struct File* file)
|
||||
{
|
||||
SECTNUM nSect, extSect;
|
||||
struct bOFSDataBlock *data;
|
||||
unsigned int blockSize;
|
||||
int i;
|
||||
/*puts("adfCreateNextFileBlock");*/
|
||||
blockSize = file->volume->datablockSize;
|
||||
data = file->currentData;
|
||||
|
||||
/* the first data blocks pointers are inside the file header block */
|
||||
if (file->nDataBlock<MAX_DATABLK) {
|
||||
nSect = adfGet1FreeBlock(file->volume);
|
||||
if (nSect==-1) return -1;
|
||||
/*printf("adfCreateNextFileBlock fhdr %ld\n",nSect);*/
|
||||
if (file->nDataBlock==0)
|
||||
file->fileHdr->firstData = nSect;
|
||||
file->fileHdr->dataBlocks[MAX_DATABLK-1-file->nDataBlock] = nSect;
|
||||
file->fileHdr->highSeq++;
|
||||
}
|
||||
else {
|
||||
/* one more sector is needed for one file extension block */
|
||||
if ((file->nDataBlock%MAX_DATABLK)==0) {
|
||||
extSect = adfGet1FreeBlock(file->volume);
|
||||
/*printf("extSect=%ld\n",extSect);*/
|
||||
if (extSect==-1) return -1;
|
||||
|
||||
/* the future block is the first file extension block */
|
||||
if (file->nDataBlock==MAX_DATABLK) {
|
||||
file->currentExt=(struct bFileExtBlock*)malloc(sizeof(struct bFileExtBlock));
|
||||
if (!file->currentExt) {
|
||||
adfSetBlockFree(file->volume, extSect);
|
||||
(*adfEnv.eFct)("adfCreateNextFileBlock : malloc");
|
||||
return -1;
|
||||
}
|
||||
file->fileHdr->extension = extSect;
|
||||
}
|
||||
|
||||
/* not the first : save the current one, and link it with the future */
|
||||
if (file->nDataBlock>=2*MAX_DATABLK) {
|
||||
file->currentExt->extension = extSect;
|
||||
/*printf ("write ext=%d\n",file->currentExt->headerKey);*/
|
||||
adfWriteFileExtBlock(file->volume, file->currentExt->headerKey,
|
||||
file->currentExt);
|
||||
}
|
||||
|
||||
/* initializes a file extension block */
|
||||
for(i=0; i<MAX_DATABLK; i++)
|
||||
file->currentExt->dataBlocks[i] = 0L;
|
||||
file->currentExt->headerKey = extSect;
|
||||
file->currentExt->parent = file->fileHdr->headerKey;
|
||||
file->currentExt->highSeq = 0L;
|
||||
file->currentExt->extension = 0L;
|
||||
file->posInExtBlk = 0L;
|
||||
/*printf("extSect=%ld\n",extSect);*/
|
||||
}
|
||||
nSect = adfGet1FreeBlock(file->volume);
|
||||
if (nSect==-1)
|
||||
return -1;
|
||||
|
||||
/*printf("adfCreateNextFileBlock ext %ld\n",nSect);*/
|
||||
|
||||
file->currentExt->dataBlocks[MAX_DATABLK-1-file->posInExtBlk] = nSect;
|
||||
file->currentExt->highSeq++;
|
||||
file->posInExtBlk++;
|
||||
}
|
||||
|
||||
/* builds OFS header */
|
||||
if (isOFS(file->volume->dosType)) {
|
||||
/* writes previous data block and link it */
|
||||
if (file->pos>=blockSize) {
|
||||
data->nextData = nSect;
|
||||
adfWriteDataBlock(file->volume, file->curDataPtr, file->currentData);
|
||||
/*printf ("writedata=%d\n",file->curDataPtr);*/
|
||||
}
|
||||
/* initialize a new data block */
|
||||
for(i=0; i<(int)blockSize; i++)
|
||||
data->data[i]=0;
|
||||
data->seqNum = file->nDataBlock+1;
|
||||
data->dataSize = blockSize;
|
||||
data->nextData = 0L;
|
||||
data->headerKey = file->fileHdr->headerKey;
|
||||
}
|
||||
else
|
||||
if (file->pos>=blockSize) {
|
||||
adfWriteDataBlock(file->volume, file->curDataPtr, file->currentData);
|
||||
/*printf ("writedata=%d\n",file->curDataPtr);*/
|
||||
memset(file->currentData,0,512);
|
||||
}
|
||||
|
||||
/*printf("datablk=%d\n",nSect);*/
|
||||
file->curDataPtr = nSect;
|
||||
file->nDataBlock++;
|
||||
|
||||
return(nSect);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfPos2DataBlock
|
||||
*
|
||||
*/
|
||||
int32_t adfPos2DataBlock(int32_t pos, int blockSize,
|
||||
int *posInExtBlk, int *posInDataBlk, int32_t *curDataN )
|
||||
{
|
||||
int32_t extBlock;
|
||||
|
||||
*posInDataBlk = pos%blockSize;
|
||||
*curDataN = pos/blockSize;
|
||||
if (*posInDataBlk==0)
|
||||
(*curDataN)++;
|
||||
if (*curDataN<72) {
|
||||
*posInExtBlk = 0;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
*posInExtBlk = (pos-72*blockSize)%blockSize;
|
||||
extBlock = (pos-72*blockSize)/blockSize;
|
||||
if (*posInExtBlk==0)
|
||||
extBlock++;
|
||||
return extBlock;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfReadDataBlock
|
||||
*
|
||||
*/
|
||||
RETCODE adfReadDataBlock(struct Volume *vol, SECTNUM nSect, void *data)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
struct bOFSDataBlock *dBlock;
|
||||
RETCODE rc = RC_OK;
|
||||
|
||||
adfReadBlock(vol, nSect,buf);
|
||||
|
||||
memcpy(data,buf,512);
|
||||
|
||||
if (isOFS(vol->dosType)) {
|
||||
#ifdef LITT_ENDIAN
|
||||
swapEndian(data, SWBL_DATA);
|
||||
#endif
|
||||
dBlock = (struct bOFSDataBlock*)data;
|
||||
/*printf("adfReadDataBlock %ld\n",nSect);*/
|
||||
|
||||
if (dBlock->checkSum!=adfNormalSum(buf,20,sizeof(struct bOFSDataBlock)))
|
||||
(*adfEnv.wFct)("adfReadDataBlock : invalid checksum");
|
||||
if (dBlock->type!=T_DATA)
|
||||
(*adfEnv.wFct)("adfReadDataBlock : id T_DATA not found");
|
||||
if (dBlock->dataSize<0 || dBlock->dataSize>488)
|
||||
(*adfEnv.wFct)("adfReadDataBlock : dataSize incorrect");
|
||||
if ( !isSectNumValid(vol,dBlock->headerKey) )
|
||||
(*adfEnv.wFct)("adfReadDataBlock : headerKey out of range");
|
||||
if ( !isSectNumValid(vol,dBlock->nextData) )
|
||||
(*adfEnv.wFct)("adfReadDataBlock : nextData out of range");
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfWriteDataBlock
|
||||
*
|
||||
*/
|
||||
RETCODE adfWriteDataBlock(struct Volume *vol, SECTNUM nSect, void *data)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint32_t newSum;
|
||||
struct bOFSDataBlock *dataB;
|
||||
RETCODE rc = RC_OK;
|
||||
|
||||
newSum = 0L;
|
||||
if (isOFS(vol->dosType)) {
|
||||
dataB = (struct bOFSDataBlock *)data;
|
||||
dataB->type = T_DATA;
|
||||
memcpy(buf,dataB,512);
|
||||
#ifdef LITT_ENDIAN
|
||||
swapEndian(buf, SWBL_DATA);
|
||||
#endif
|
||||
newSum = adfNormalSum(buf,20,512);
|
||||
swLong(buf+20,newSum);
|
||||
/* *(int32_t*)(buf+20) = swapLong((uint8_t*)&newSum);*/
|
||||
adfWriteBlock(vol,nSect,buf);
|
||||
}
|
||||
else {
|
||||
adfWriteBlock(vol,nSect,data);
|
||||
}
|
||||
/*printf("adfWriteDataBlock %ld\n",nSect);*/
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfReadFileExtBlock
|
||||
*
|
||||
*/
|
||||
RETCODE adfReadFileExtBlock(struct Volume *vol, SECTNUM nSect, struct bFileExtBlock* fext)
|
||||
{
|
||||
uint8_t buf[sizeof(struct bFileExtBlock)];
|
||||
RETCODE rc = RC_OK;
|
||||
|
||||
adfReadBlock(vol, nSect,buf);
|
||||
/*printf("read fext=%d\n",nSect);*/
|
||||
memcpy(fext,buf,sizeof(struct bFileExtBlock));
|
||||
#ifdef LITT_ENDIAN
|
||||
swapEndian((uint8_t*)fext, SWBL_FEXT);
|
||||
#endif
|
||||
if (fext->checkSum!=adfNormalSum(buf,20,sizeof(struct bFileExtBlock)))
|
||||
(*adfEnv.wFct)("adfReadFileExtBlock : invalid checksum");
|
||||
if (fext->type!=T_LIST)
|
||||
(*adfEnv.wFct)("adfReadFileExtBlock : type T_LIST not found");
|
||||
if (fext->secType!=ST_FILE)
|
||||
(*adfEnv.wFct)("adfReadFileExtBlock : stype ST_FILE not found");
|
||||
if (fext->headerKey!=nSect)
|
||||
(*adfEnv.wFct)("adfReadFileExtBlock : headerKey!=nSect");
|
||||
if (fext->highSeq<0 || fext->highSeq>MAX_DATABLK)
|
||||
(*adfEnv.wFct)("adfReadFileExtBlock : highSeq out of range");
|
||||
if ( !isSectNumValid(vol, fext->parent) )
|
||||
(*adfEnv.wFct)("adfReadFileExtBlock : parent out of range");
|
||||
if ( fext->extension!=0 && !isSectNumValid(vol, fext->extension) )
|
||||
(*adfEnv.wFct)("adfReadFileExtBlock : extension out of range");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfWriteFileExtBlock
|
||||
*
|
||||
*/
|
||||
RETCODE adfWriteFileExtBlock(struct Volume *vol, SECTNUM nSect, struct bFileExtBlock* fext)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint32_t newSum;
|
||||
RETCODE rc = RC_OK;
|
||||
|
||||
fext->type = T_LIST;
|
||||
fext->secType = ST_FILE;
|
||||
fext->dataSize = 0L;
|
||||
fext->firstData = 0L;
|
||||
|
||||
memcpy(buf,fext,512);
|
||||
#ifdef LITT_ENDIAN
|
||||
swapEndian(buf, SWBL_FEXT);
|
||||
#endif
|
||||
newSum = adfNormalSum(buf,20,512);
|
||||
swLong(buf+20,newSum);
|
||||
/* *(int32_t*)(buf+20) = swapLong((uint8_t*)&newSum);*/
|
||||
|
||||
adfWriteBlock(vol,nSect,buf);
|
||||
|
||||
return rc;
|
||||
}
|
||||
/*###########################################################################*/
|
||||
60
src/adf_file.h
Normal file
60
src/adf_file.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef ADF_FILE_H
|
||||
#define ADF_FILE_H 1
|
||||
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_file.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include"prefix.h"
|
||||
|
||||
#include"adf_str.h"
|
||||
|
||||
RETCODE adfGetFileBlocks(struct Volume* vol, struct bFileHeaderBlock* entry,
|
||||
struct FileBlocks* );
|
||||
RETCODE adfFreeFileBlocks(struct Volume* vol, struct bFileHeaderBlock *entry);
|
||||
PREFIX int32_t adfFileRealSize(uint32_t size, int blockSize, int32_t *dataN, int32_t *extN);
|
||||
|
||||
int32_t adfPos2DataBlock(int32_t pos, int blockSize, int *posInExtBlk, int *posInDataBlk, int32_t *curDataN );
|
||||
|
||||
RETCODE adfWriteFileHdrBlock(struct Volume *vol, SECTNUM nSect, struct bFileHeaderBlock* fhdr);
|
||||
|
||||
RETCODE adfReadDataBlock(struct Volume *vol, SECTNUM nSect, void *data);
|
||||
RETCODE adfWriteDataBlock(struct Volume *vol, SECTNUM nSect, void *data);
|
||||
RETCODE adfReadFileExtBlock(struct Volume *vol, SECTNUM nSect, struct bFileExtBlock* fext);
|
||||
RETCODE adfWriteFileExtBlock(struct Volume *vol, SECTNUM nSect, struct bFileExtBlock* fext);
|
||||
|
||||
PREFIX struct File* adfOpenFile(struct Volume *vol, char* name, char *mode);
|
||||
PREFIX void adfCloseFile(struct File *file);
|
||||
PREFIX int32_t adfReadFile(struct File* file, int32_t n, uint8_t *buffer);
|
||||
PREFIX BOOL adfEndOfFile(struct File* file);
|
||||
PREFIX void adfFileSeek(struct File *file, uint32_t pos); /* BV */
|
||||
RETCODE adfReadNextFileBlock(struct File* file);
|
||||
PREFIX int32_t adfWriteFile(struct File *file, int32_t n, uint8_t *buffer);
|
||||
SECTNUM adfCreateNextFileBlock(struct File* file);
|
||||
PREFIX void adfFlushFile(struct File *file);
|
||||
|
||||
|
||||
|
||||
#endif /* ADF_FILE_H */
|
||||
|
||||
1035
src/adf_hd.c
Normal file
1035
src/adf_hd.c
Normal file
File diff suppressed because it is too large
Load Diff
66
src/adf_hd.h
Normal file
66
src/adf_hd.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifndef _ADF_HD_H
|
||||
#define _ADF_HD_H 1
|
||||
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_hd.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Harddisk and devices code
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include"prefix.h"
|
||||
|
||||
#include "adf_str.h"
|
||||
#include "hd_blk.h"
|
||||
#include "adf_err.h"
|
||||
|
||||
int adfDevType(struct Device *dev);
|
||||
PREFIX void adfDeviceInfo(struct Device *dev);
|
||||
|
||||
RETCODE adfMountHd(struct Device *dev);
|
||||
RETCODE adfMountFlop(struct Device* dev);
|
||||
PREFIX struct Device* adfMountDev( char* filename,BOOL);
|
||||
PREFIX void adfUnMountDev( struct Device* dev);
|
||||
|
||||
RETCODE adfCreateHdHeader(struct Device* dev, int n, struct Partition** partList );
|
||||
PREFIX RETCODE adfCreateFlop(struct Device* dev, char* volName, int volType );
|
||||
PREFIX RETCODE adfCreateHd(struct Device* dev, int n, struct Partition** partList );
|
||||
PREFIX RETCODE adfCreateHdFile(struct Device* dev, char* volName, int volType);
|
||||
|
||||
struct Device* adfCreateDev(char* filename, int32_t cylinders, int32_t heads, int32_t sectors);
|
||||
|
||||
RETCODE adfReadBlockDev( struct Device* dev, int32_t nSect, int32_t size, uint8_t* buf );
|
||||
RETCODE adfWriteBlockDev(struct Device* dev, int32_t nSect, int32_t size, uint8_t* buf );
|
||||
RETCODE adfReadRDSKblock( struct Device* dev, struct bRDSKblock* blk );
|
||||
RETCODE adfWriteRDSKblock(struct Device *dev, struct bRDSKblock* rdsk);
|
||||
RETCODE adfReadPARTblock( struct Device* dev, int32_t nSect, struct bPARTblock* blk );
|
||||
RETCODE adfWritePARTblock(struct Device *dev, int32_t nSect, struct bPARTblock* part);
|
||||
RETCODE adfReadFSHDblock( struct Device* dev, int32_t nSect, struct bFSHDblock* blk);
|
||||
RETCODE adfWriteFSHDblock(struct Device *dev, int32_t nSect, struct bFSHDblock* fshd);
|
||||
RETCODE adfReadLSEGblock(struct Device* dev, int32_t nSect, struct bLSEGblock* blk);
|
||||
RETCODE adfWriteLSEGblock(struct Device *dev, int32_t nSect, struct bLSEGblock* lseg);
|
||||
|
||||
|
||||
#endif /* _ADF_HD_H */
|
||||
|
||||
/*##########################################################################*/
|
||||
86
src/adf_link.c
Normal file
86
src/adf_link.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* ADF Library
|
||||
*
|
||||
* adf_link.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include<string.h>
|
||||
|
||||
#include"adf_defs.h"
|
||||
#include"adf_str.h"
|
||||
#include"adf_link.h"
|
||||
#include"adf_dir.h"
|
||||
|
||||
extern struct Env adfEnv;
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*/
|
||||
char* path(struct Volume *vol, SECTNUM parent)
|
||||
{
|
||||
struct bEntryBlock entryBlk;
|
||||
char *tmpPath;
|
||||
int len;
|
||||
|
||||
tmpPath = NULL;
|
||||
adfReadEntryBlock(vol, parent, &entryBlk);
|
||||
len = min(entryBlk.nameLen, MAXNAMELEN);
|
||||
memcpy(tmpPath,entryBlk.name,len);
|
||||
tmpPath[len]='\0';
|
||||
/* if (entryBlk.parent!=vol->rootBlock) {
|
||||
return(strcat(path(vol,entryBlk.parent), tmpPath));
|
||||
}
|
||||
else
|
||||
*/ return(tmpPath);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*/
|
||||
RETCODE adfBlockPtr2EntryName(struct Volume *vol, SECTNUM nSect, SECTNUM lPar,
|
||||
char **name, int32_t *size)
|
||||
{
|
||||
struct bEntryBlock entryBlk;
|
||||
struct Entry entry;
|
||||
|
||||
if (*name==0) {
|
||||
adfReadEntryBlock(vol, nSect, &entryBlk);
|
||||
*size = entryBlk.byteSize;
|
||||
return RC_OK;
|
||||
adfEntBlock2Entry(&entryBlk, &entry); /*error*/
|
||||
/* if (entryBlk.secType!=ST_ROOT && entry.parent!=lPar)
|
||||
printf("path=%s\n",path(vol,entry.parent));
|
||||
*/
|
||||
*name = strdup("");
|
||||
if (*name==NULL)
|
||||
return RC_MALLOC;
|
||||
return RC_OK;
|
||||
}
|
||||
else
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
/*##################################################################################*/
|
||||
36
src/adf_link.h
Normal file
36
src/adf_link.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef ADF_LINK_H
|
||||
#define ADF_LINK_H 1
|
||||
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_link.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include"prefix.h"
|
||||
#include <stdint.h>
|
||||
PREFIX RETCODE adfBlockPtr2EntryName(struct Volume *vol, SECTNUM nSect, SECTNUM lPar,
|
||||
char **name, int32_t *size);
|
||||
|
||||
|
||||
#endif /* ADF_LINK_H */
|
||||
/*##########################################################################*/
|
||||
337
src/adf_raw.c
Normal file
337
src/adf_raw.c
Normal file
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_raw.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* logical disk/volume code
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "adf_str.h"
|
||||
#include "adf_raw.h"
|
||||
#include "adf_blk.h"
|
||||
#include "adf_disk.h"
|
||||
#include "adf_util.h"
|
||||
#include "adf_err.h"
|
||||
#include "defendian.h"
|
||||
|
||||
extern struct Env adfEnv;
|
||||
|
||||
int swapTable[MAX_SWTYPE+1][15]={
|
||||
{ 4, SW_CHAR, 2, SW_LONG, 1012, SW_CHAR, 0, 1024 }, /* first bytes of boot */
|
||||
{ 108, SW_LONG, 40, SW_CHAR, 10, SW_LONG, 0, 512 }, /* root */
|
||||
{ 6, SW_LONG, 488, SW_CHAR, 0, 512 }, /* data */
|
||||
/* file, dir, entry */
|
||||
{ 82, SW_LONG, 92, SW_CHAR, 3, SW_LONG, 36, SW_CHAR, 11, SW_LONG, 0, 512 },
|
||||
{ 6, SW_LONG, 0, 24 }, /* cache */
|
||||
{ 128, SW_LONG, 0, 512 }, /* bitmap, fext */
|
||||
/* link */
|
||||
{ 6, SW_LONG, 64, SW_CHAR, 86, SW_LONG, 32, SW_CHAR, 12, SW_LONG, 0, 512 },
|
||||
{ 4, SW_CHAR, 39, SW_LONG, 56, SW_CHAR, 10, SW_LONG, 0, 256 }, /* RDSK */
|
||||
{ 4, SW_CHAR, 127, SW_LONG, 0, 512 }, /* BADB */
|
||||
{ 4, SW_CHAR, 8, SW_LONG, 32, SW_CHAR, 31, SW_LONG, 4, SW_CHAR, /* PART */
|
||||
15, SW_LONG, 0, 256 },
|
||||
{ 4, SW_CHAR, 7, SW_LONG, 4, SW_CHAR, 55, SW_LONG, 0, 256 }, /* FSHD */
|
||||
{ 4, SW_CHAR, 4, SW_LONG, 492, SW_CHAR, 0, 512 } /* LSEG */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* swapEndian
|
||||
*
|
||||
* magic :-) endian swap function (big -> little for read, little to big for write)
|
||||
*/
|
||||
|
||||
void
|
||||
swapEndian( uint8_t *buf, int type )
|
||||
{
|
||||
int i,j;
|
||||
int p;
|
||||
|
||||
i=0;
|
||||
p=0;
|
||||
|
||||
if (type>MAX_SWTYPE || type<0)
|
||||
adfEnv.eFct("SwapEndian: type do not exist");
|
||||
|
||||
while( swapTable[type][i]!=0 ) {
|
||||
for(j=0; j<swapTable[type][i]; j++) {
|
||||
switch( swapTable[type][i+1] ) {
|
||||
case SW_LONG:
|
||||
*(uint32_t*)(buf+p)=Long(buf+p);
|
||||
p+=4;
|
||||
break;
|
||||
case SW_SHORT:
|
||||
*(uint32_t*)(buf+p)=Short(buf+p);
|
||||
p+=2;
|
||||
break;
|
||||
case SW_CHAR:
|
||||
p++;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
i+=2;
|
||||
}
|
||||
if (p!=swapTable[type][i+1])
|
||||
(*adfEnv.wFct)("Warning: Endian Swapping length"); /* BV */
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* adfReadRootBlock
|
||||
*
|
||||
* ENDIAN DEPENDENT
|
||||
*/
|
||||
RETCODE
|
||||
adfReadRootBlock(struct Volume* vol, int32_t nSect, struct bRootBlock* root)
|
||||
{
|
||||
uint8_t buf[LOGICAL_BLOCK_SIZE];
|
||||
|
||||
if (adfReadBlock(vol, nSect, buf)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
memcpy(root, buf, LOGICAL_BLOCK_SIZE);
|
||||
#ifdef LITT_ENDIAN
|
||||
swapEndian((uint8_t*)root, SWBL_ROOT);
|
||||
#endif
|
||||
|
||||
if (root->type!=T_HEADER || root->secType!=ST_ROOT) {
|
||||
(*adfEnv.wFct)("adfReadRootBlock : id not found");
|
||||
return RC_ERROR;
|
||||
}
|
||||
if (root->checkSum!=adfNormalSum(buf, 20, LOGICAL_BLOCK_SIZE)) {
|
||||
(*adfEnv.wFct)("adfReadRootBlock : invalid checksum");
|
||||
return RC_ERROR;
|
||||
}
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfWriteRootBlock
|
||||
*
|
||||
*
|
||||
*/
|
||||
RETCODE adfWriteRootBlock(struct Volume* vol, int32_t nSect, struct bRootBlock* root)
|
||||
{
|
||||
uint8_t buf[LOGICAL_BLOCK_SIZE];
|
||||
uint32_t newSum;
|
||||
|
||||
|
||||
root->type = T_HEADER;
|
||||
root->headerKey = 0L;
|
||||
root->highSeq = 0L;
|
||||
root->hashTableSize = HT_SIZE;
|
||||
root->firstData = 0L;
|
||||
/* checkSum, hashTable */
|
||||
/* bmflag */
|
||||
/* bmPages, bmExt */
|
||||
root->nextSameHash = 0L;
|
||||
root->parent = 0L;
|
||||
root->secType = ST_ROOT;
|
||||
|
||||
memcpy(buf, root, LOGICAL_BLOCK_SIZE);
|
||||
#ifdef LITT_ENDIAN
|
||||
swapEndian(buf, SWBL_ROOT);
|
||||
#endif
|
||||
|
||||
newSum = adfNormalSum(buf,20,LOGICAL_BLOCK_SIZE);
|
||||
swLong(buf+20, newSum);
|
||||
/* *(uint32_t*)(buf+20) = swapLong((uint8_t*)&newSum);*/
|
||||
|
||||
/* dumpBlock(buf);*/
|
||||
if (adfWriteBlock(vol, nSect, buf)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
/*printf("adfWriteRootBlock %ld\n",nSect);*/
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfReadBootBlock
|
||||
*
|
||||
* ENDIAN DEPENDENT
|
||||
*/
|
||||
RETCODE
|
||||
adfReadBootBlock(struct Volume* vol, struct bBootBlock* boot)
|
||||
{
|
||||
uint8_t buf[1024];
|
||||
|
||||
/*puts("22");*/
|
||||
if (adfReadBlock(vol, 0, buf)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
/*puts("11");*/
|
||||
if (adfReadBlock(vol, 1, buf+LOGICAL_BLOCK_SIZE)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
memcpy(boot, buf, LOGICAL_BLOCK_SIZE*2);
|
||||
#ifdef LITT_ENDIAN
|
||||
swapEndian((uint8_t*)boot,SWBL_BOOT);
|
||||
#endif
|
||||
if ( strncmp("DOS",boot->dosType,3)!=0 ) {
|
||||
(*adfEnv.wFct)("adfReadBootBlock : DOS id not found");
|
||||
return RC_ERROR;
|
||||
}
|
||||
|
||||
if ( boot->data[0]!=0 && adfBootSum(buf)!=boot->checkSum ) {
|
||||
/*printf("compsum=%lx sum=%lx\n", adfBootSum(buf),boot->checkSum );*/ /* BV */
|
||||
(*adfEnv.wFct)("adfReadBootBlock : incorrect checksum");
|
||||
}
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* adfWriteBootBlock
|
||||
*
|
||||
*
|
||||
* write bootcode ?
|
||||
*/
|
||||
RETCODE
|
||||
adfWriteBootBlock(struct Volume* vol, struct bBootBlock* boot)
|
||||
{
|
||||
uint8_t buf[LOGICAL_BLOCK_SIZE*2];
|
||||
uint32_t newSum;
|
||||
|
||||
boot->dosType[0] = 'D';
|
||||
boot->dosType[1] = 'O';
|
||||
boot->dosType[2] = 'S';
|
||||
memcpy(buf, boot, LOGICAL_BLOCK_SIZE*2);
|
||||
#ifdef LITT_ENDIAN
|
||||
swapEndian(buf, SWBL_BOOT);
|
||||
#endif
|
||||
|
||||
if (boot->rootBlock==880 || boot->data[0]!=0) {
|
||||
newSum = adfBootSum(buf);
|
||||
/*fprintf(stderr,"sum %x %x\n",newSum,adfBootSum2(buf));*/
|
||||
swLong(buf+4,newSum);
|
||||
/* *(uint32_t*)(buf+4) = swapLong((uint8_t*)&newSum);*/
|
||||
}
|
||||
|
||||
/* dumpBlock(buf);
|
||||
dumpBlock(buf+512);
|
||||
*/
|
||||
if (adfWriteBlock(vol, 0, buf)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
if (adfWriteBlock(vol, 1, buf+512)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
/*puts("adfWriteBootBlock");*/
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* NormalSum
|
||||
*
|
||||
* buf = where the block is stored
|
||||
* offset = checksum place (in bytes)
|
||||
* bufLen = buffer length (in bytes)
|
||||
*/
|
||||
uint32_t
|
||||
adfNormalSum( UCHAR* buf, int offset, int bufLen )
|
||||
{
|
||||
int32_t newsum;
|
||||
int i;
|
||||
|
||||
newsum=0L;
|
||||
for(i=0; i < (bufLen/4); i++)
|
||||
if ( i != (offset/4) ) /* old chksum */
|
||||
newsum+=Long(buf+i*4);
|
||||
newsum=(-newsum); /* WARNING */
|
||||
|
||||
return(newsum);
|
||||
}
|
||||
|
||||
/*
|
||||
* adfBitmapSum
|
||||
*
|
||||
*/
|
||||
uint32_t
|
||||
adfBitmapSum(uint8_t *buf)
|
||||
{
|
||||
uint32_t newSum;
|
||||
int i;
|
||||
|
||||
newSum = 0L;
|
||||
for(i=1; i<128; i++)
|
||||
newSum-=Long(buf+i*4);
|
||||
return(newSum);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfBootSum
|
||||
*
|
||||
*/
|
||||
uint32_t
|
||||
adfBootSum(uint8_t *buf)
|
||||
{
|
||||
uint32_t d, newSum;
|
||||
int i;
|
||||
|
||||
newSum=0L;
|
||||
for(i=0; i<256; i++) {
|
||||
if (i!=1) {
|
||||
d = Long(buf+i*4);
|
||||
if ( (ULONG_MAX-newSum)<d )
|
||||
newSum++;
|
||||
newSum+=d;
|
||||
}
|
||||
}
|
||||
newSum = ~newSum; /* not */
|
||||
|
||||
return(newSum);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
adfBootSum2(uint8_t *buf)
|
||||
{
|
||||
uint32_t prevsum, newSum;
|
||||
int i;
|
||||
|
||||
prevsum = newSum=0L;
|
||||
for(i=0; i<1024/sizeof(uint32_t); i++) {
|
||||
if (i!=1) {
|
||||
prevsum = newSum;
|
||||
newSum += Long(buf+i*4);
|
||||
if (newSum < prevsum)
|
||||
newSum++;
|
||||
}
|
||||
}
|
||||
newSum = ~newSum; /* not */
|
||||
|
||||
return(newSum);
|
||||
}
|
||||
|
||||
|
||||
/*#######################################################################################*/
|
||||
68
src/adf_raw.h
Normal file
68
src/adf_raw.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_raw.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* blocks level code
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ADF_RAW_H
|
||||
#define _ADF_RAW_H 1
|
||||
|
||||
#include "adf_str.h"
|
||||
|
||||
#define SW_LONG 4
|
||||
#define SW_SHORT 2
|
||||
#define SW_CHAR 1
|
||||
|
||||
#define MAX_SWTYPE 11
|
||||
|
||||
#define SWBL_BOOT 0
|
||||
#define SWBL_ROOT 1
|
||||
#define SWBL_DATA 2
|
||||
#define SWBL_FILE 3
|
||||
#define SWBL_ENTRY 3
|
||||
#define SWBL_DIR 3
|
||||
#define SWBL_CACHE 4
|
||||
#define SWBL_BITMAP 5
|
||||
#define SWBL_FEXT 5
|
||||
#define SWBL_LINK 6
|
||||
#define SWBL_BITMAPE 5
|
||||
#define SWBL_RDSK 7
|
||||
#define SWBL_BADB 8
|
||||
#define SWBL_PART 9
|
||||
#define SWBL_FSHD 10
|
||||
#define SWBL_LSEG 11
|
||||
|
||||
RETCODE adfReadRootBlock(struct Volume*, int32_t nSect, struct bRootBlock* root);
|
||||
RETCODE adfWriteRootBlock(struct Volume* vol, int32_t nSect, struct bRootBlock* root);
|
||||
RETCODE adfReadBootBlock(struct Volume*, struct bBootBlock* boot);
|
||||
RETCODE adfWriteBootBlock(struct Volume* vol, struct bBootBlock* boot);
|
||||
|
||||
uint32_t adfBootSum(uint8_t *buf);
|
||||
uint32_t adfNormalSum( uint8_t *buf, int offset, int bufLen );
|
||||
|
||||
void swapEndian( uint8_t *buf, int type );
|
||||
|
||||
#endif /* _ADF_RAW_H */
|
||||
|
||||
/*##########################################################################*/
|
||||
399
src/adf_salv.c
Normal file
399
src/adf_salv.c
Normal file
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_salv.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* undelete and salvage code : EXPERIMENTAL !
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include<string.h>
|
||||
#include<stdlib.h>
|
||||
|
||||
#include "adf_salv.h"
|
||||
#include "adf_bitm.h"
|
||||
#include "adf_util.h"
|
||||
#include "adf_disk.h"
|
||||
#include "adf_dir.h"
|
||||
#include "adf_file.h"
|
||||
#include "adf_cache.h"
|
||||
|
||||
extern struct Env adfEnv;
|
||||
|
||||
/*
|
||||
* adfFreeGenBlock
|
||||
*
|
||||
*/
|
||||
void adfFreeGenBlock(struct GenBlock* block)
|
||||
{
|
||||
if (block->name!=NULL)
|
||||
free(block->name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfFreeDelList
|
||||
*
|
||||
*/
|
||||
void adfFreeDelList(struct List* list)
|
||||
{
|
||||
struct List *cell;
|
||||
|
||||
cell = list;
|
||||
while(cell!=NULL) {
|
||||
adfFreeGenBlock((struct GenBlock*)cell->content);
|
||||
cell = cell->next;
|
||||
}
|
||||
freeList(list);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfGetDelEnt
|
||||
*
|
||||
*/
|
||||
struct List* adfGetDelEnt(struct Volume *vol)
|
||||
{
|
||||
struct GenBlock *block;
|
||||
int32_t i;
|
||||
struct List *list, *head;
|
||||
BOOL delEnt;
|
||||
|
||||
list = head = NULL;
|
||||
block = NULL;
|
||||
delEnt = TRUE;
|
||||
for(i=vol->firstBlock; i<=vol->lastBlock; i++) {
|
||||
if (adfIsBlockFree(vol, i)) {
|
||||
if (delEnt) {
|
||||
block = (struct GenBlock*)malloc(sizeof(struct GenBlock));
|
||||
if (!block) return NULL;
|
||||
/*printf("%p\n",block);*/
|
||||
}
|
||||
|
||||
adfReadGenBlock(vol, i, block);
|
||||
|
||||
delEnt = (block->type==T_HEADER
|
||||
&& (block->secType==ST_DIR || block->secType==ST_FILE) );
|
||||
|
||||
if (delEnt) {
|
||||
if (head==NULL)
|
||||
list = head = newCell(NULL, (void*)block);
|
||||
else
|
||||
list = newCell(list, (void*)block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (block!=NULL && list!=NULL && block!=list->content) {
|
||||
free(block);
|
||||
/* printf("%p\n",block);*/
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfReadGenBlock
|
||||
*
|
||||
*/
|
||||
RETCODE adfReadGenBlock(struct Volume *vol, SECTNUM nSect, struct GenBlock *block)
|
||||
{
|
||||
uint8_t buf[LOGICAL_BLOCK_SIZE];
|
||||
int len;
|
||||
char name[MAXNAMELEN+1];
|
||||
|
||||
if (adfReadBlock(vol, nSect, buf)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
block->type =(int) swapLong(buf);
|
||||
block->secType =(int) swapLong(buf+vol->blockSize-4);
|
||||
block->sect = nSect;
|
||||
block->name = NULL;
|
||||
|
||||
if (block->type==T_HEADER) {
|
||||
switch(block->secType) {
|
||||
case ST_FILE:
|
||||
case ST_DIR:
|
||||
case ST_LFILE:
|
||||
case ST_LDIR:
|
||||
len = min(MAXNAMELEN, buf[vol->blockSize-80]);
|
||||
strncpy(name, (char*)buf+vol->blockSize-79, len);
|
||||
name[len] = '\0';
|
||||
block->name = strdup(name);
|
||||
block->parent = swapLong(buf+vol->blockSize-12);
|
||||
break;
|
||||
case ST_ROOT:
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfCheckParent
|
||||
*
|
||||
*/
|
||||
RETCODE adfCheckParent(struct Volume* vol, SECTNUM pSect)
|
||||
{
|
||||
struct GenBlock block;
|
||||
|
||||
if (adfIsBlockFree(vol, pSect)) {
|
||||
(*adfEnv.wFct)("adfCheckParent : parent doesn't exists");
|
||||
return RC_ERROR;
|
||||
}
|
||||
|
||||
/* verify if parent is a DIR or ROOT */
|
||||
adfReadGenBlock(vol, pSect, &block);
|
||||
if ( block.type!=T_HEADER
|
||||
|| (block.secType!=ST_DIR && block.secType!=ST_ROOT) ) {
|
||||
(*adfEnv.wFct)("adfCheckParent : parent secType is incorrect");
|
||||
return RC_ERROR;
|
||||
}
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfUndelDir
|
||||
*
|
||||
*/
|
||||
RETCODE adfUndelDir(struct Volume* vol, SECTNUM pSect, SECTNUM nSect,
|
||||
struct bDirBlock* entry)
|
||||
{
|
||||
RETCODE rc;
|
||||
struct bEntryBlock parent;
|
||||
char name[MAXNAMELEN+1];
|
||||
|
||||
/* check if the given parent sector pointer seems OK */
|
||||
if ( (rc=adfCheckParent(vol,pSect)) != RC_OK)
|
||||
return rc;
|
||||
|
||||
if (pSect!=entry->parent) {
|
||||
(*adfEnv.wFct)("adfUndelDir : the given parent sector isn't the entry parent");
|
||||
return RC_ERROR;
|
||||
}
|
||||
|
||||
if (!adfIsBlockFree(vol, entry->headerKey))
|
||||
return RC_ERROR;
|
||||
if (isDIRCACHE(vol->dosType) && !adfIsBlockFree(vol,entry->extension))
|
||||
return RC_ERROR;
|
||||
|
||||
if (adfReadEntryBlock(vol, pSect, &parent)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
strncpy(name, entry->dirName, entry->nameLen);
|
||||
name[(int)entry->nameLen] = '\0';
|
||||
/* insert the entry in the parent hashTable, with the headerKey sector pointer */
|
||||
adfSetBlockUsed(vol,entry->headerKey);
|
||||
adfCreateEntry(vol, &parent, name, entry->headerKey);
|
||||
|
||||
if (isDIRCACHE(vol->dosType)) {
|
||||
adfAddInCache(vol, &parent, (struct bEntryBlock *)entry);
|
||||
adfSetBlockUsed(vol,entry->extension);
|
||||
}
|
||||
|
||||
adfUpdateBitmap(vol);
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfUndelFile
|
||||
*
|
||||
*/
|
||||
RETCODE adfUndelFile(struct Volume* vol, SECTNUM pSect, SECTNUM nSect, struct bFileHeaderBlock* entry)
|
||||
{
|
||||
int32_t i;
|
||||
char name[MAXNAMELEN+1];
|
||||
struct bEntryBlock parent;
|
||||
RETCODE rc;
|
||||
struct FileBlocks fileBlocks;
|
||||
|
||||
/* check if the given parent sector pointer seems OK */
|
||||
if ( (rc=adfCheckParent(vol,pSect)) != RC_OK)
|
||||
return rc;
|
||||
|
||||
if (pSect!=entry->parent) {
|
||||
(*adfEnv.wFct)("adfUndelFile : the given parent sector isn't the entry parent");
|
||||
return RC_ERROR;
|
||||
}
|
||||
|
||||
adfGetFileBlocks(vol, entry, &fileBlocks);
|
||||
|
||||
for(i=0; i<fileBlocks.nbData; i++)
|
||||
if ( !adfIsBlockFree(vol,fileBlocks.data[i]) )
|
||||
return RC_ERROR;
|
||||
else
|
||||
adfSetBlockUsed(vol, fileBlocks.data[i]);
|
||||
for(i=0; i<fileBlocks.nbExtens; i++)
|
||||
if ( !adfIsBlockFree(vol,fileBlocks.extens[i]) )
|
||||
return RC_ERROR;
|
||||
else
|
||||
adfSetBlockUsed(vol, fileBlocks.extens[i]);
|
||||
|
||||
free(fileBlocks.data);
|
||||
free(fileBlocks.extens);
|
||||
|
||||
if (adfReadEntryBlock(vol, pSect, &parent)!=RC_OK)
|
||||
return RC_ERROR;
|
||||
|
||||
strncpy(name, entry->fileName, entry->nameLen);
|
||||
name[(int)entry->nameLen] = '\0';
|
||||
/* insert the entry in the parent hashTable, with the headerKey sector pointer */
|
||||
adfCreateEntry(vol, &parent, name, entry->headerKey);
|
||||
|
||||
if (isDIRCACHE(vol->dosType))
|
||||
adfAddInCache(vol, &parent, (struct bEntryBlock *)entry);
|
||||
|
||||
adfUpdateBitmap(vol);
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfUndelEntry
|
||||
*
|
||||
*/
|
||||
RETCODE adfUndelEntry(struct Volume* vol, SECTNUM parent, SECTNUM nSect)
|
||||
{
|
||||
struct bEntryBlock entry;
|
||||
|
||||
adfReadEntryBlock(vol,nSect,&entry);
|
||||
|
||||
switch(entry.secType) {
|
||||
case ST_FILE:
|
||||
adfUndelFile(vol, parent, nSect, (struct bFileHeaderBlock*)&entry);
|
||||
break;
|
||||
case ST_DIR:
|
||||
adfUndelDir(vol, parent, nSect, (struct bDirBlock*)&entry);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfCheckFile
|
||||
*
|
||||
*/
|
||||
RETCODE adfCheckFile(struct Volume* vol, SECTNUM nSect,
|
||||
struct bFileHeaderBlock* file, int level)
|
||||
{
|
||||
struct bFileExtBlock extBlock;
|
||||
struct bOFSDataBlock dataBlock;
|
||||
struct FileBlocks fileBlocks;
|
||||
int n;
|
||||
|
||||
adfGetFileBlocks(vol,file,&fileBlocks);
|
||||
/*printf("data %ld ext %ld\n",fileBlocks.nbData,fileBlocks.nbExtens);*/
|
||||
if (isOFS(vol->dosType)) {
|
||||
/* checks OFS datablocks */
|
||||
for(n=0; n<fileBlocks.nbData; n++) {
|
||||
/*printf("%ld\n",fileBlocks.data[n]);*/
|
||||
adfReadDataBlock(vol,fileBlocks.data[n],&dataBlock);
|
||||
if (dataBlock.headerKey!=fileBlocks.header)
|
||||
(*adfEnv.wFct)("adfCheckFile : headerKey incorrect");
|
||||
if (dataBlock.seqNum!=n+1)
|
||||
(*adfEnv.wFct)("adfCheckFile : seqNum incorrect");
|
||||
if (n<fileBlocks.nbData-1) {
|
||||
if (dataBlock.nextData!=fileBlocks.data[n+1])
|
||||
(*adfEnv.wFct)("adfCheckFile : nextData incorrect");
|
||||
if (dataBlock.dataSize!=vol->datablockSize)
|
||||
(*adfEnv.wFct)("adfCheckFile : dataSize incorrect");
|
||||
}
|
||||
else { /* last datablock */
|
||||
if (dataBlock.nextData!=0)
|
||||
(*adfEnv.wFct)("adfCheckFile : nextData incorrect");
|
||||
}
|
||||
}
|
||||
}
|
||||
for(n=0; n<fileBlocks.nbExtens; n++) {
|
||||
adfReadFileExtBlock(vol,fileBlocks.extens[n],&extBlock);
|
||||
if (extBlock.parent!=file->headerKey)
|
||||
(*adfEnv.wFct)("adfCheckFile : extBlock parent incorrect");
|
||||
if (n<fileBlocks.nbExtens-1) {
|
||||
if (extBlock.extension!=fileBlocks.extens[n+1])
|
||||
(*adfEnv.wFct)("adfCheckFile : nextData incorrect");
|
||||
}
|
||||
else
|
||||
if (extBlock.extension!=0)
|
||||
(*adfEnv.wFct)("adfCheckFile : nextData incorrect");
|
||||
}
|
||||
|
||||
free(fileBlocks.data);
|
||||
free(fileBlocks.extens);
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfCheckDir
|
||||
*
|
||||
*/
|
||||
RETCODE adfCheckDir(struct Volume* vol, SECTNUM nSect, struct bDirBlock* dir,
|
||||
int level)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfCheckEntry
|
||||
*
|
||||
*/
|
||||
RETCODE adfCheckEntry(struct Volume* vol, SECTNUM nSect, int level)
|
||||
{
|
||||
struct bEntryBlock entry;
|
||||
RETCODE rc;
|
||||
|
||||
adfReadEntryBlock(vol,nSect,&entry);
|
||||
|
||||
switch(entry.secType) {
|
||||
case ST_FILE:
|
||||
rc = adfCheckFile(vol, nSect, (struct bFileHeaderBlock*)&entry, level);
|
||||
break;
|
||||
case ST_DIR:
|
||||
rc = adfCheckDir(vol, nSect, (struct bDirBlock*)&entry, level);
|
||||
break;
|
||||
default:
|
||||
/* printf("adfCheckEntry : not supported\n");*/ /* BV */
|
||||
rc = RC_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*#############################################################################*/
|
||||
42
src/adf_salv.h
Normal file
42
src/adf_salv.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef _ADF_SALV_H
|
||||
#define _ADF_SALV_H 1
|
||||
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_salv.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include"prefix.h"
|
||||
|
||||
#include "adf_str.h"
|
||||
|
||||
RETCODE adfReadGenBlock(struct Volume *vol, SECTNUM nSect, struct GenBlock *block);
|
||||
PREFIX RETCODE adfCheckEntry(struct Volume* vol, SECTNUM nSect, int level);
|
||||
PREFIX RETCODE adfUndelEntry(struct Volume* vol, SECTNUM parent, SECTNUM nSect);
|
||||
PREFIX struct List* adfGetDelEnt(struct Volume *vol);
|
||||
PREFIX void adfFreeDelList(struct List* list);
|
||||
|
||||
|
||||
/*##########################################################################*/
|
||||
#endif /* _ADF_SALV_H */
|
||||
|
||||
235
src/adf_str.h
Normal file
235
src/adf_str.h
Normal file
@@ -0,0 +1,235 @@
|
||||
#ifndef _ADF_STR_H
|
||||
#define _ADF_STR_H 1
|
||||
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_str.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* structures/constants definitions
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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
|
||||
* aint32_t with Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include<stdio.h>
|
||||
|
||||
#include"adf_defs.h"
|
||||
#include"adf_blk.h"
|
||||
#include"adf_err.h"
|
||||
|
||||
/* ----- VOLUME ----- */
|
||||
|
||||
struct Volume {
|
||||
struct Device* dev;
|
||||
|
||||
SECTNUM firstBlock; /* first block of data area (from beginning of device) */
|
||||
SECTNUM lastBlock; /* last block of data area (from beginning of device) */
|
||||
SECTNUM rootBlock; /* root block (from firstBlock) */
|
||||
|
||||
char dosType; /* FFS/OFS, DIRCACHE, INTERNATIONAL */
|
||||
BOOL bootCode;
|
||||
BOOL readOnly;
|
||||
int datablockSize; /* 488 or 512 */
|
||||
int blockSize; /* 512 */
|
||||
|
||||
char *volName;
|
||||
|
||||
BOOL mounted;
|
||||
|
||||
int32_t bitmapSize; /* in blocks */
|
||||
SECTNUM *bitmapBlocks; /* bitmap blocks pointers */
|
||||
struct bBitmapBlock **bitmapTable;
|
||||
BOOL *bitmapBlocksChg;
|
||||
|
||||
SECTNUM curDirPtr;
|
||||
};
|
||||
|
||||
|
||||
struct Partition {
|
||||
int32_t startCyl;
|
||||
int32_t lenCyl;
|
||||
char* volName;
|
||||
int volType;
|
||||
};
|
||||
|
||||
/* ----- DEVICES ----- */
|
||||
|
||||
#define DEVTYPE_FLOPDD 1
|
||||
#define DEVTYPE_FLOPHD 2
|
||||
#define DEVTYPE_HARDDISK 3
|
||||
#define DEVTYPE_HARDFILE 4
|
||||
|
||||
struct Device {
|
||||
int devType; /* see below */
|
||||
BOOL readOnly;
|
||||
int32_t size; /* in bytes */
|
||||
|
||||
int nVol; /* partitions */
|
||||
struct Volume** volList;
|
||||
|
||||
int32_t cylinders; /* geometry */
|
||||
int32_t heads;
|
||||
int32_t sectors;
|
||||
|
||||
BOOL isNativeDev;
|
||||
void *nativeDev;
|
||||
};
|
||||
|
||||
|
||||
/* ----- FILE ----- */
|
||||
|
||||
struct File {
|
||||
struct Volume *volume;
|
||||
|
||||
struct bFileHeaderBlock* fileHdr;
|
||||
void *currentData;
|
||||
struct bFileExtBlock* currentExt;
|
||||
|
||||
int32_t nDataBlock;
|
||||
SECTNUM curDataPtr;
|
||||
uint32_t pos;
|
||||
|
||||
int posInDataBlk;
|
||||
int posInExtBlk;
|
||||
BOOL eof, writeMode;
|
||||
};
|
||||
|
||||
|
||||
/* ----- ENTRY ---- */
|
||||
|
||||
struct Entry{
|
||||
int type;
|
||||
char* name;
|
||||
SECTNUM sector;
|
||||
SECTNUM real;
|
||||
SECTNUM parent;
|
||||
char* comment;
|
||||
uint32_t size;
|
||||
int32_t access;
|
||||
int year, month, days;
|
||||
int hour, mins, secs;
|
||||
};
|
||||
|
||||
struct CacheEntry{
|
||||
int32_t header, size, protect;
|
||||
short days, mins, ticks;
|
||||
signed char type;
|
||||
char nLen, cLen;
|
||||
char name[MAXNAMELEN+1], comm[MAXCMMTLEN+1];
|
||||
/* char *name, *comm;*/
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
struct DateTime{
|
||||
int year,mon,day,hour,min,sec;
|
||||
};
|
||||
|
||||
/* ----- ENVIRONMENT ----- */
|
||||
|
||||
#define PR_VFCT 1
|
||||
#define PR_WFCT 2
|
||||
#define PR_EFCT 3
|
||||
#define PR_NOTFCT 4
|
||||
#define PR_USEDIRC 5
|
||||
#define PR_USE_NOTFCT 6
|
||||
#define PR_PROGBAR 7
|
||||
#define PR_USE_PROGBAR 8
|
||||
#define PR_RWACCESS 9
|
||||
#define PR_USE_RWACCESS 10
|
||||
|
||||
struct Env{
|
||||
void (*vFct)(char*); /* verbose callback function */
|
||||
void (*wFct)(char*); /* warning callback function */
|
||||
void (*eFct)(char*); /* error callback function */
|
||||
|
||||
void (*notifyFct)(SECTNUM, int);
|
||||
BOOL useNotify;
|
||||
|
||||
void (*rwhAccess)(SECTNUM,SECTNUM,BOOL);
|
||||
BOOL useRWAccess;
|
||||
|
||||
void (*progressBar)(int);
|
||||
BOOL useProgressBar;
|
||||
|
||||
BOOL useDirCache;
|
||||
|
||||
void *nativeFct;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct List{ /* generic linked tree */
|
||||
void *content;
|
||||
struct List* subdir;
|
||||
struct List* next;
|
||||
};
|
||||
|
||||
struct GenBlock{
|
||||
SECTNUM sect;
|
||||
SECTNUM parent;
|
||||
int type;
|
||||
int secType;
|
||||
char *name; /* if (type == 2 and (secType==2 or secType==-3)) */
|
||||
};
|
||||
|
||||
struct FileBlocks{
|
||||
SECTNUM header;
|
||||
int32_t nbExtens;
|
||||
SECTNUM* extens;
|
||||
int32_t nbData;
|
||||
SECTNUM* data;
|
||||
};
|
||||
|
||||
struct bEntryBlock {
|
||||
/*000*/ int32_t type; /* T_HEADER == 2 */
|
||||
/*004*/ int32_t headerKey; /* current block number */
|
||||
int32_t r1[3];
|
||||
/*014*/ uint32_t checkSum;
|
||||
/*018*/ int32_t hashTable[HT_SIZE];
|
||||
int32_t r2[2];
|
||||
/*140*/ int32_t access; /* bit0=del, 1=modif, 2=write, 3=read */
|
||||
/*144*/ int32_t byteSize;
|
||||
/*148*/ char commLen;
|
||||
/*149*/ char comment[MAXCMMTLEN+1];
|
||||
char r3[91-(MAXCMMTLEN+1)];
|
||||
/*1a4*/ int32_t days;
|
||||
/*1a8*/ int32_t mins;
|
||||
/*1ac*/ int32_t ticks;
|
||||
/*1b0*/ char nameLen;
|
||||
/*1b1*/ char name[MAXNAMELEN+1];
|
||||
int32_t r4;
|
||||
/*1d4*/ int32_t realEntry;
|
||||
/*1d8*/ int32_t nextLink;
|
||||
int32_t r5[5];
|
||||
/*1f0*/ int32_t nextSameHash;
|
||||
/*1f4*/ int32_t parent;
|
||||
/*1f8*/ int32_t extension;
|
||||
/*1fc*/ int32_t secType;
|
||||
};
|
||||
|
||||
|
||||
#define ENV_DECLARATION struct Env adfEnv
|
||||
|
||||
|
||||
#endif /* _ADF_STR_H */
|
||||
/*##########################################################################*/
|
||||
254
src/adf_util.c
Normal file
254
src/adf_util.c
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_util.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include<stdlib.h>
|
||||
#include<time.h>
|
||||
|
||||
#include "adf_util.h"
|
||||
#include "adf_err.h"
|
||||
#include "adf_disk.h"
|
||||
|
||||
extern struct Env adfEnv;
|
||||
|
||||
|
||||
/*
|
||||
* swLong
|
||||
*
|
||||
* write an uint32_t value (val) (in)
|
||||
* to an uint8_t* buffer (buf) (out)
|
||||
*
|
||||
* used in adfWrite----Block() functions
|
||||
*/
|
||||
void swLong(uint8_t* buf, uint32_t val)
|
||||
{
|
||||
buf[0]= (uint8_t)((val & 0xff000000) >>24UL);
|
||||
buf[1]= (uint8_t)((val & 0x00ff0000) >>16UL);
|
||||
buf[2]= (uint8_t)((val & 0x0000ff00) >>8UL);
|
||||
buf[3]= (uint8_t)(val & 0x000000ff);
|
||||
}
|
||||
|
||||
void swShort(uint8_t* buf, uint16_t val)
|
||||
{
|
||||
buf[0]= (val & 0xff00) >>8UL;
|
||||
buf[1]= (val & 0x00ff) ;
|
||||
}
|
||||
|
||||
/*
|
||||
* newCell
|
||||
*
|
||||
* adds a cell at the end the list
|
||||
*/
|
||||
struct List* newCell(struct List* list, void* content)
|
||||
{
|
||||
struct List* cell;
|
||||
|
||||
cell=(struct List*)malloc(sizeof(struct List));
|
||||
if (!cell) {
|
||||
(*adfEnv.eFct)("newCell : malloc");
|
||||
return NULL;
|
||||
}
|
||||
cell->content = content;
|
||||
cell->next = cell->subdir = 0;
|
||||
if (list!=NULL)
|
||||
list->next = cell;
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* freeList
|
||||
*
|
||||
*/
|
||||
void freeList(struct List* list)
|
||||
{
|
||||
if (list==NULL)
|
||||
return;
|
||||
|
||||
if (list->next)
|
||||
freeList(list->next);
|
||||
free(list);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Days2Date
|
||||
*
|
||||
* amiga disk date format (days) to normal dd/mm/yy format (out)
|
||||
*/
|
||||
|
||||
void
|
||||
adfDays2Date(int32_t days, int *yy, int *mm, int *dd)
|
||||
{
|
||||
int y,m;
|
||||
int nd;
|
||||
int jm[12]={ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
/* 0 = 1 Jan 1978, 6988 = 18 feb 1997 */
|
||||
|
||||
/*--- year ---*/
|
||||
y=1978;
|
||||
if (adfIsLeap(y))
|
||||
nd=366;
|
||||
else
|
||||
nd=365;
|
||||
while( days >= nd ) {
|
||||
days-=nd;
|
||||
y++;
|
||||
if (adfIsLeap(y))
|
||||
nd=366;
|
||||
else
|
||||
nd=365;
|
||||
}
|
||||
|
||||
|
||||
/*--- month ---*/
|
||||
m=1;
|
||||
if (adfIsLeap(y))
|
||||
jm[2-1]=29;
|
||||
while( days >= jm[m-1] ) {
|
||||
days-=jm[m-1];
|
||||
m++;
|
||||
}
|
||||
|
||||
*yy=y;
|
||||
*mm=m;
|
||||
*dd=days+1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* IsLeap
|
||||
*
|
||||
* true if a year (y) is leap
|
||||
*/
|
||||
|
||||
BOOL
|
||||
adfIsLeap(int y)
|
||||
{
|
||||
return( (BOOL) ( !(y%100) ? !(y%400) : !(y%4) ) );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfCurrentDateTime
|
||||
*
|
||||
* return the current system date and time
|
||||
*/
|
||||
struct DateTime
|
||||
adfGiveCurrentTime( void )
|
||||
{
|
||||
struct tm *local;
|
||||
time_t cal;
|
||||
struct DateTime r;
|
||||
|
||||
time(&cal);
|
||||
local=localtime(&cal);
|
||||
|
||||
r.year=local->tm_year; /* since 1900 */
|
||||
r.mon=local->tm_mon+1;
|
||||
r.day=local->tm_mday;
|
||||
r.hour=local->tm_hour;
|
||||
r.min=local->tm_min;
|
||||
r.sec=local->tm_sec;
|
||||
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfTime2AmigaTime
|
||||
*
|
||||
* converts date and time (dt) into Amiga format : day, min, ticks
|
||||
*/
|
||||
void
|
||||
adfTime2AmigaTime(struct DateTime dt, int32_t *day, int32_t *min, int32_t *ticks )
|
||||
{
|
||||
int jm[12]={ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
|
||||
|
||||
*min= dt.hour*60 + dt.min; /* mins */
|
||||
*ticks= dt.sec*50; /* ticks */
|
||||
|
||||
/*--- days ---*/
|
||||
|
||||
*day= dt.day-1; /* current month days */
|
||||
|
||||
/* previous months days downto january */
|
||||
if (dt.mon>1) { /* if previous month exists */
|
||||
dt.mon--;
|
||||
if (dt.mon>2 && adfIsLeap(dt.year)) /* months after a leap february */
|
||||
jm[2-1]=29;
|
||||
while(dt.mon>0) {
|
||||
*day=*day+jm[dt.mon-1];
|
||||
dt.mon--;
|
||||
}
|
||||
}
|
||||
|
||||
/* years days before current year downto 1978 */
|
||||
if (dt.year>78) {
|
||||
dt.year--;
|
||||
while(dt.year>=78) {
|
||||
if (adfIsLeap(dt.year))
|
||||
*day=*day+366;
|
||||
else
|
||||
*day=*day+365;
|
||||
dt.year--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* dumpBlock
|
||||
*
|
||||
* debug function : to dump a block before writing the check its contents
|
||||
*
|
||||
*/
|
||||
void dumpBlock(uint8_t *buf)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for(i=0; i<32; i++) {
|
||||
printf("%5x ",i*16);
|
||||
for (j=0; j<4; j++) {
|
||||
printf("%08x ",Long(buf+j*4+i*16));
|
||||
}
|
||||
printf(" ");
|
||||
for (j=0; j<16; j++)
|
||||
if (buf[i*16+j]<32 || buf[i*16+j]>127)
|
||||
putchar('.');
|
||||
else
|
||||
putchar(buf[i*16+j]);
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*################################################################################*/
|
||||
50
src/adf_util.h
Normal file
50
src/adf_util.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef _ADF_UTIL_H
|
||||
#define _ADF_UTIL_H 1
|
||||
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adf_util.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include"prefix.h"
|
||||
|
||||
#include "adf_str.h"
|
||||
|
||||
|
||||
void swLong(uint8_t* buf, uint32_t val);
|
||||
void swShort(uint8_t* buf, uint16_t val);
|
||||
|
||||
PREFIX struct List* newCell(struct List* list, void* content);
|
||||
PREFIX void freeList(struct List* list);
|
||||
void adfDays2Date(int32_t days, int *yy, int *mm, int *dd);
|
||||
BOOL adfIsLeap(int y);
|
||||
void
|
||||
adfTime2AmigaTime(struct DateTime dt, int32_t *day, int32_t *min, int32_t *ticks );
|
||||
struct DateTime
|
||||
adfGiveCurrentTime( void );
|
||||
|
||||
void dumpBlock(uint8_t *buf);
|
||||
|
||||
/*##########################################################################*/
|
||||
#endif /* _ADF_UTIL_H */
|
||||
|
||||
127
src/adflib.h
Normal file
127
src/adflib.h
Normal file
@@ -0,0 +1,127 @@
|
||||
#ifndef ADFLIB_H
|
||||
#define ADFLIB_H 1
|
||||
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* adflib.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* general include file
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/* Visual C++ DLL specific, define WIN32DLL or not in the makefile */
|
||||
|
||||
#ifdef WIN32DLL
|
||||
#define PREFIX __declspec(dllimport)
|
||||
#else
|
||||
#define PREFIX
|
||||
#endif /* WIN32DLL */
|
||||
|
||||
#include "adf_defs.h"
|
||||
#include "adf_str.h"
|
||||
|
||||
/* util */
|
||||
PREFIX struct List* newCell(struct List* list, void* content);
|
||||
PREFIX void freeList(struct List* list);
|
||||
|
||||
/* dir */
|
||||
PREFIX RETCODE adfToRootDir(struct Volume *vol);
|
||||
PREFIX RETCODE adfCreateDir(struct Volume* vol, SECTNUM parent, char* name);
|
||||
PREFIX RETCODE adfChangeDir(struct Volume* vol, char *name);
|
||||
PREFIX RETCODE adfParentDir(struct Volume* vol);
|
||||
PREFIX RETCODE adfRemoveEntry(struct Volume *vol, SECTNUM pSect, char *name);
|
||||
PREFIX struct List* adfGetDirEnt(struct Volume* vol, SECTNUM nSect );
|
||||
PREFIX struct List* adfGetRDirEnt(struct Volume* vol, SECTNUM nSect, BOOL recurs );
|
||||
PREFIX void printEntry(struct Entry* entry);
|
||||
PREFIX void adfFreeDirList(struct List* list);
|
||||
PREFIX void adfFreeEntry(struct Entry *);
|
||||
PREFIX RETCODE adfRenameEntry(struct Volume *vol, SECTNUM, char *old,SECTNUM,char *pNew); /* BV */
|
||||
PREFIX RETCODE adfSetEntryAccess(struct Volume*, SECTNUM, char*, int32_t);
|
||||
PREFIX RETCODE adfSetEntryComment(struct Volume*, SECTNUM, char*, char*);
|
||||
|
||||
/* file */
|
||||
PREFIX int32_t adfFileRealSize(uint32_t size, int blockSize, int32_t *dataN, int32_t *extN);
|
||||
PREFIX struct File* adfOpenFile(struct Volume *vol, char* name, char *mode);
|
||||
PREFIX void adfCloseFile(struct File *file);
|
||||
PREFIX int32_t adfReadFile(struct File* file, int32_t n, uint8_t *buffer);
|
||||
PREFIX BOOL adfEndOfFile(struct File* file);
|
||||
PREFIX int32_t adfWriteFile(struct File *file, int32_t n, uint8_t *buffer);
|
||||
PREFIX void adfFlushFile(struct File *file);
|
||||
PREFIX void adfFileSeek(struct File *file, uint32_t pos);
|
||||
|
||||
/* volume */
|
||||
PREFIX RETCODE adfInstallBootBlock(struct Volume *vol,uint8_t*);
|
||||
PREFIX struct Volume* adfMount( struct Device *dev, int nPart, BOOL readOnly );
|
||||
PREFIX void adfUnMount(struct Volume *vol);
|
||||
PREFIX void adfVolumeInfo(struct Volume *vol);
|
||||
|
||||
/* device */
|
||||
PREFIX void adfDeviceInfo(struct Device *dev);
|
||||
PREFIX struct Device* adfMountDev( char* filename,BOOL ro);
|
||||
PREFIX void adfUnMountDev( struct Device* dev);
|
||||
PREFIX RETCODE adfCreateHd(struct Device* dev, int n, struct Partition** partList );
|
||||
PREFIX RETCODE adfCreateFlop(struct Device* dev, char* volName, int volType );
|
||||
PREFIX RETCODE adfCreateHdFile(struct Device* dev, char* volName, int volType);
|
||||
|
||||
/* dump device */
|
||||
PREFIX struct Device* adfCreateDumpDevice(char* filename, int32_t cyl, int32_t heads, int32_t sec);
|
||||
|
||||
/* env */
|
||||
PREFIX void adfEnvInitDefault();
|
||||
PREFIX void adfEnvCleanUp();
|
||||
PREFIX void adfChgEnvProp(int prop, void *pNew); /* BV */
|
||||
PREFIX char* adfGetVersionNumber();
|
||||
PREFIX char* adfGetVersionDate();
|
||||
/* obsolete */
|
||||
PREFIX void adfSetEnvFct( void(*e)(char*), void(*w)(char*), void(*v)(char*) );
|
||||
|
||||
/* link */
|
||||
PREFIX RETCODE adfBlockPtr2EntryName(struct Volume *, SECTNUM, SECTNUM,char **, int32_t *);
|
||||
|
||||
/* salv */
|
||||
PREFIX struct List* adfGetDelEnt(struct Volume *vol);
|
||||
PREFIX RETCODE adfUndelEntry(struct Volume* vol, SECTNUM parent, SECTNUM nSect);
|
||||
PREFIX void adfFreeDelList(struct List* list);
|
||||
PREFIX RETCODE adfCheckEntry(struct Volume* vol, SECTNUM nSect, int level);
|
||||
|
||||
/* middle level API */
|
||||
|
||||
PREFIX BOOL isSectNumValid(struct Volume *vol, SECTNUM nSect);
|
||||
|
||||
/* low level API */
|
||||
|
||||
PREFIX RETCODE adfReadBlock(struct Volume* , int32_t nSect, uint8_t* buf);
|
||||
PREFIX RETCODE adfWriteBlock(struct Volume* , int32_t nSect, uint8_t* buf);
|
||||
PREFIX int32_t adfCountFreeBlocks(struct Volume* vol);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ADFLIB_H */
|
||||
/*##########################################################################*/
|
||||
13
src/defendian.h
Normal file
13
src/defendian.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "config.h"
|
||||
|
||||
#ifndef LITT_ENDIAN
|
||||
#if defined(__hppa__) || \
|
||||
defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
|
||||
(defined(__MIPS__) && defined(__MISPEB__)) || \
|
||||
defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
|
||||
defined(__sparc__)
|
||||
#else
|
||||
#define LITT_ENDIAN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
126
src/generic/adf_nativ.c
Normal file
126
src/generic/adf_nativ.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* adf_nativ.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<string.h>
|
||||
#include"adf_str.h"
|
||||
#include"adf_nativ.h"
|
||||
#include"adf_err.h"
|
||||
|
||||
extern struct Env adfEnv;
|
||||
|
||||
/*
|
||||
* myInitDevice
|
||||
*
|
||||
* must fill 'dev->size'
|
||||
*/
|
||||
RETCODE myInitDevice(struct Device* dev, char* name,BOOL ro)
|
||||
{
|
||||
struct nativeDevice* nDev;
|
||||
|
||||
nDev = (struct nativeDevice*)dev->nativeDev;
|
||||
|
||||
nDev = (struct nativeDevice*)malloc(sizeof(struct nativeDevice));
|
||||
if (!nDev) {
|
||||
(*adfEnv.eFct)("myInitDevice : malloc");
|
||||
return RC_ERROR;
|
||||
}
|
||||
dev->nativeDev = nDev;
|
||||
if (!ro)
|
||||
/* check if device is writable, if not, force readOnly to TRUE */
|
||||
dev->readOnly = FALSE;
|
||||
else
|
||||
/* mount device as read only */
|
||||
dev->readOnly = TRUE;
|
||||
|
||||
dev->size = 0;
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* myReadSector
|
||||
*
|
||||
*/
|
||||
RETCODE myReadSector(struct Device *dev, int32_t n, int size, uint8_t* buf)
|
||||
{
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* myWriteSector
|
||||
*
|
||||
*/
|
||||
RETCODE myWriteSector(struct Device *dev, int32_t n, int size, uint8_t* buf)
|
||||
{
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* myReleaseDevice
|
||||
*
|
||||
* free native device
|
||||
*/
|
||||
RETCODE myReleaseDevice(struct Device *dev)
|
||||
{
|
||||
struct nativeDevice* nDev;
|
||||
|
||||
nDev = (struct nativeDevice*)dev->nativeDev;
|
||||
|
||||
free(nDev);
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adfInitNativeFct
|
||||
*
|
||||
*/
|
||||
void adfInitNativeFct()
|
||||
{
|
||||
struct nativeFunctions *nFct;
|
||||
|
||||
nFct = (struct nativeFunctions*)adfEnv.nativeFct;
|
||||
|
||||
nFct->adfInitDevice = myInitDevice ;
|
||||
nFct->adfNativeReadSector = myReadSector ;
|
||||
nFct->adfNativeWriteSector = myWriteSector ;
|
||||
nFct->adfReleaseDevice = myReleaseDevice ;
|
||||
nFct->adfIsDevNative = myIsDevNative;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* myIsDevNative
|
||||
*
|
||||
*/
|
||||
BOOL myIsDevNative(char *devName)
|
||||
{
|
||||
return (strncmp(devName,"/dev/",5)==0);
|
||||
}
|
||||
/*##########################################################################*/
|
||||
68
src/generic/adf_nativ.h
Normal file
68
src/generic/adf_nativ.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* adf_nativ.h
|
||||
*
|
||||
* $ID$
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ADF_NATIV_H
|
||||
#define ADF_NATIV_H
|
||||
|
||||
#include<stdio.h>
|
||||
#include"adf_str.h"
|
||||
|
||||
#define NATIVE_FILE 8001
|
||||
|
||||
#ifndef BOOL
|
||||
#define BOOL int
|
||||
#endif
|
||||
|
||||
#ifndef RETCODE
|
||||
#define RETCODE int32_t
|
||||
#endif
|
||||
|
||||
struct nativeDevice{
|
||||
FILE* fd;
|
||||
};
|
||||
|
||||
struct nativeFunctions{
|
||||
/* called by adfMount() */
|
||||
RETCODE (*adfInitDevice)(struct Device*, char*,BOOL);
|
||||
/* called by adfReadBlock() */
|
||||
RETCODE (*adfNativeReadSector)(struct Device*, int32_t, int, uint8_t*);
|
||||
/* called by adfWriteBlock() */
|
||||
RETCODE (*adfNativeWriteSector)(struct Device*, int32_t, int, uint8_t*);
|
||||
/* called by adfMount() */
|
||||
BOOL (*adfIsDevNative)(char*);
|
||||
/* called by adfUnMount() */
|
||||
RETCODE (*adfReleaseDevice)();
|
||||
};
|
||||
|
||||
void adfInitNativeFct();
|
||||
|
||||
|
||||
RETCODE myReadSector(struct Device *dev, int32_t n, int size, uint8_t* buf);
|
||||
RETCODE myWriteSector(struct Device *dev, int32_t n, int size, uint8_t* buf);
|
||||
RETCODE myInitDevice(struct Device *dev, char* name,BOOL);
|
||||
RETCODE myReleaseDevice(struct Device *dev);
|
||||
BOOL myIsDevNative(char*);
|
||||
|
||||
#endif /* ADF_NATIV_H */
|
||||
|
||||
/*#######################################################################################*/
|
||||
167
src/hd_blk.h
Normal file
167
src/hd_blk.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* ADF Library. (C) 1997-2002 Laurent Clevy
|
||||
*
|
||||
* hd_blk.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* hard disk blocks structures
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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
|
||||
* aint32_t with Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _HD_BLK_H
|
||||
#define _HD_BLK_H 1
|
||||
|
||||
#include "adf_str.h"
|
||||
|
||||
/* ------- RDSK ---------*/
|
||||
|
||||
struct bRDSKblock {
|
||||
/*000*/ char id[4]; /* RDSK */
|
||||
/*004*/ int32_t size; /* 64 int32_ts */
|
||||
/*008*/ ULONG checksum;
|
||||
/*00c*/ int32_t hostID; /* 7 */
|
||||
/*010*/ int32_t blockSize; /* 512 bytes */
|
||||
/*014*/ int32_t flags; /* 0x17 */
|
||||
/*018*/ int32_t badBlockList;
|
||||
/*01c*/ int32_t partitionList;
|
||||
/*020*/ int32_t fileSysHdrList;
|
||||
/*024*/ int32_t driveInit;
|
||||
/*028*/ int32_t r1[6]; /* -1 */
|
||||
/*040*/ int32_t cylinders;
|
||||
/*044*/ int32_t sectors;
|
||||
/*048*/ int32_t heads;
|
||||
/*04c*/ int32_t interleave;
|
||||
/*050*/ int32_t parkingZone;
|
||||
/*054*/ int32_t r2[3]; /* 0 */
|
||||
/*060*/ int32_t writePreComp;
|
||||
/*064*/ int32_t reducedWrite;
|
||||
/*068*/ int32_t stepRate;
|
||||
/*06c*/ int32_t r3[5]; /* 0 */
|
||||
/*080*/ int32_t rdbBlockLo;
|
||||
/*084*/ int32_t rdbBlockHi;
|
||||
/*088*/ int32_t loCylinder;
|
||||
/*08c*/ int32_t hiCylinder;
|
||||
/*090*/ int32_t cylBlocks;
|
||||
/*094*/ int32_t autoParkSeconds;
|
||||
/*098*/ int32_t highRDSKBlock;
|
||||
/*09c*/ int32_t r4; /* 0 */
|
||||
/*0a0*/ char diskVendor[8];
|
||||
/*0a8*/ char diskProduct[16];
|
||||
/*0b8*/ char diskRevision[4];
|
||||
/*0bc*/ char controllerVendor[8];
|
||||
/*0c4*/ char controllerProduct[16];
|
||||
/*0d4*/ char controllerRevision[4];
|
||||
/*0d8*/ int32_t r5[10]; /* 0 */
|
||||
/*100*/
|
||||
};
|
||||
|
||||
|
||||
struct bBADBentry {
|
||||
/*000*/ int32_t badBlock;
|
||||
/*004*/ int32_t goodBlock;
|
||||
};
|
||||
|
||||
|
||||
struct bBADBblock {
|
||||
/*000*/ char id[4]; /* BADB */
|
||||
/*004*/ int32_t size; /* 128 int32_ts */
|
||||
/*008*/ ULONG checksum;
|
||||
/*00c*/ int32_t hostID; /* 7 */
|
||||
/*010*/ int32_t next;
|
||||
/*014*/ int32_t r1;
|
||||
/*018*/ struct bBADBentry blockPairs[61];
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct bPARTblock {
|
||||
/*000*/ char id[4]; /* PART */
|
||||
/*004*/ int32_t size; /* 64 int32_ts */
|
||||
/*008*/ ULONG checksum;
|
||||
/*00c*/ int32_t hostID; /* 7 */
|
||||
/*010*/ int32_t next;
|
||||
/*014*/ int32_t flags;
|
||||
/*018*/ int32_t r1[2];
|
||||
/*020*/ int32_t devFlags;
|
||||
/*024*/ char nameLen;
|
||||
/*025*/ char name[31];
|
||||
/*044*/ int32_t r2[15];
|
||||
|
||||
/*080*/ int32_t vectorSize; /* often 16 int32_ts */
|
||||
/*084*/ int32_t blockSize; /* 128 int32_ts */
|
||||
/*088*/ int32_t secOrg;
|
||||
/*08c*/ int32_t surfaces;
|
||||
/*090*/ int32_t sectorsPerBlock; /* == 1 */
|
||||
/*094*/ int32_t blocksPerTrack;
|
||||
/*098*/ int32_t dosReserved;
|
||||
/*09c*/ int32_t dosPreAlloc;
|
||||
/*0a0*/ int32_t interleave;
|
||||
/*0a4*/ int32_t lowCyl;
|
||||
/*0a8*/ int32_t highCyl;
|
||||
/*0ac*/ int32_t numBuffer;
|
||||
/*0b0*/ int32_t bufMemType;
|
||||
/*0b4*/ int32_t maxTransfer;
|
||||
/*0b8*/ int32_t mask;
|
||||
/*0bc*/ int32_t bootPri;
|
||||
/*0c0*/ char dosType[4];
|
||||
/*0c4*/ int32_t r3[15];
|
||||
};
|
||||
|
||||
|
||||
struct bLSEGblock {
|
||||
/*000*/ char id[4]; /* LSEG */
|
||||
/*004*/ int32_t size; /* 128 int32_ts */
|
||||
/*008*/ ULONG checksum;
|
||||
/*00c*/ int32_t hostID; /* 7 */
|
||||
/*010*/ int32_t next;
|
||||
/*014*/ char loadData[123*4];
|
||||
};
|
||||
|
||||
|
||||
struct bFSHDblock {
|
||||
/*000*/ char id[4]; /* FSHD */
|
||||
/*004*/ int32_t size; /* 64 */
|
||||
/*008*/ ULONG checksum;
|
||||
/*00c*/ int32_t hostID; /* 7 */
|
||||
/*010*/ int32_t next;
|
||||
/*014*/ int32_t flags;
|
||||
/*018*/ int32_t r1[2];
|
||||
/*020*/ char dosType[4];
|
||||
/*024*/ short majVersion;
|
||||
/*026*/ short minVersion;
|
||||
/*028*/ int32_t patchFlags;
|
||||
|
||||
/*02c*/ int32_t type;
|
||||
/*030*/ int32_t task;
|
||||
/*034*/ int32_t lock;
|
||||
/*038*/ int32_t handler;
|
||||
/*03c*/ int32_t stackSize;
|
||||
/*040*/ int32_t priority;
|
||||
/*044*/ int32_t startup;
|
||||
/*048*/ int32_t segListBlock;
|
||||
/*04c*/ int32_t globalVec;
|
||||
/*050*/ int32_t r2[23];
|
||||
/*0ac*/ int32_t r3[21];
|
||||
};
|
||||
|
||||
|
||||
#endif /* _HD_BLK_H */
|
||||
/*##########################################################################*/
|
||||
36
src/prefix.h
Normal file
36
src/prefix.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef _PREFIX_H
|
||||
#define _PREFIX_H 1
|
||||
|
||||
/*
|
||||
* prefix.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* adds symbol export directive under windows
|
||||
* does nothing under Linux
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef WIN32DLL
|
||||
#define PREFIX __declspec(dllexport)
|
||||
#else
|
||||
#define PREFIX
|
||||
#endif /* WIN32DLL */
|
||||
|
||||
#endif /* _PREFIX_H */
|
||||
141
src/win32/adf_nativ.c
Normal file
141
src/win32/adf_nativ.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/* Win32/adf_nativ.c - Win32 specific drive-access routines for ADFLib
|
||||
*
|
||||
* Modified for Win32 by Dan Sutherland <dan@chromerhino.demon.co.uk>
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* Modified 29/8/00 by Gary Harris.
|
||||
** - Added a third, Boolean argument to Win32InitDevice() to avoid a compilation warning
|
||||
** caused by the mismatch with the number of arguments in ADFLib's adfInitDevice().
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../adf_str.h"
|
||||
#include "../adf_err.h"
|
||||
|
||||
#include "adf_nativ.h"
|
||||
#include "nt4_dev.h"
|
||||
|
||||
extern struct Env adfEnv;
|
||||
|
||||
RETCODE Win32InitDevice(struct Device* dev, char* lpstrName, BOOL ro)
|
||||
{
|
||||
struct nativeDevice* nDev;
|
||||
char strTempName[3];
|
||||
|
||||
nDev = (struct nativeDevice*)dev->nativeDev;
|
||||
|
||||
nDev = (struct nativeDevice*)malloc(sizeof(struct nativeDevice));
|
||||
if (!nDev) {
|
||||
(*adfEnv.eFct)("Win32InitDevice : malloc");
|
||||
return RC_ERROR; /* BV */
|
||||
}
|
||||
|
||||
/* convert device name to something usable by Win32 functions */
|
||||
if (strlen(lpstrName) != 3) {
|
||||
(*adfEnv.eFct)("Win32InitDevice : invalid drive specifier");
|
||||
return RC_ERROR; /* BV */
|
||||
}
|
||||
|
||||
strTempName[0] = lpstrName[1];
|
||||
strTempName[1] = lpstrName[2];
|
||||
strTempName[2] = '\0';
|
||||
|
||||
nDev->hDrv = NT4OpenDrive(strTempName);
|
||||
|
||||
if (nDev->hDrv == NULL) {
|
||||
(*adfEnv.eFct)("Win32InitDevice : NT4OpenDrive");
|
||||
return RC_ERROR; /* BV */
|
||||
}
|
||||
|
||||
dev->size = NT4GetDriveSize(nDev->hDrv);
|
||||
|
||||
dev->nativeDev = nDev;
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
RETCODE Win32ReadSector(struct Device *dev, long n, int size, unsigned char* buf)
|
||||
{
|
||||
struct nativeDevice* tDev;
|
||||
|
||||
tDev = (struct nativeDevice*)dev->nativeDev;
|
||||
|
||||
if (! NT4ReadSector(tDev->hDrv, n, size, buf)) {
|
||||
(*adfEnv.eFct)("Win32InitDevice : NT4ReadSector");
|
||||
return RC_ERROR; /* BV */
|
||||
}
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
RETCODE Win32WriteSector(struct Device *dev, long n, int size, unsigned char* buf)
|
||||
{
|
||||
struct nativeDevice* tDev;
|
||||
|
||||
tDev = (struct nativeDevice*)dev->nativeDev;
|
||||
|
||||
if (! NT4WriteSector(tDev->hDrv, n, size, buf)) {
|
||||
(*adfEnv.eFct)("Win32InitDevice : NT4WriteSector");
|
||||
return RC_ERROR; /* BV */
|
||||
}
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
RETCODE Win32ReleaseDevice(struct Device *dev)
|
||||
{
|
||||
struct nativeDevice* nDev;
|
||||
|
||||
nDev = (struct nativeDevice*)dev->nativeDev;
|
||||
|
||||
if (! NT4CloseDrive(nDev->hDrv))
|
||||
return RC_ERROR; /* BV */
|
||||
|
||||
free(nDev);
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
|
||||
void adfInitNativeFct()
|
||||
{
|
||||
struct nativeFunctions *nFct;
|
||||
|
||||
nFct = (struct nativeFunctions*)adfEnv.nativeFct;
|
||||
|
||||
nFct->adfInitDevice = Win32InitDevice;
|
||||
nFct->adfNativeReadSector = Win32ReadSector;
|
||||
nFct->adfNativeWriteSector = Win32WriteSector;
|
||||
nFct->adfReleaseDevice = Win32ReleaseDevice;
|
||||
nFct->adfIsDevNative = Win32IsDevNative;
|
||||
}
|
||||
|
||||
|
||||
BOOL Win32IsDevNative(char *devName)
|
||||
{
|
||||
return devName[0] == '|';
|
||||
}
|
||||
61
src/win32/adf_nativ.h
Normal file
61
src/win32/adf_nativ.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* Win32/adf_nativ.h
|
||||
*
|
||||
* Win32 specific drive access routines for ADFLib
|
||||
* Copyright 1999 by Dan Sutherland <dan@chromerhino.demon.co.uk>
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
*/
|
||||
|
||||
#ifndef ADF_NATIV_H
|
||||
#define ADF_NATIV_H
|
||||
|
||||
#include "../adf_str.h"
|
||||
|
||||
#define NATIVE_FILE 8001
|
||||
|
||||
#ifndef BOOL
|
||||
#define BOOL int
|
||||
#endif
|
||||
|
||||
#ifndef RETCODE
|
||||
#define RETCODE long
|
||||
#endif
|
||||
|
||||
struct nativeDevice{
|
||||
FILE *fd; /* needed by adf_dump.c */
|
||||
void *hDrv;
|
||||
};
|
||||
|
||||
struct nativeFunctions{
|
||||
RETCODE (*adfInitDevice)(struct Device*, char*, BOOL);
|
||||
RETCODE (*adfNativeReadSector)(struct Device*, long, int, unsigned char*);
|
||||
RETCODE (*adfNativeWriteSector)(struct Device*, long, int, unsigned char*);
|
||||
BOOL (*adfIsDevNative)(char*);
|
||||
RETCODE (*adfReleaseDevice)();
|
||||
};
|
||||
|
||||
void adfInitNativeFct();
|
||||
|
||||
RETCODE Win32ReadSector(struct Device *dev, long n, int size, unsigned char* buf);
|
||||
RETCODE Win32WriteSector(struct Device *dev, long n, int size, unsigned char* buf);
|
||||
RETCODE Win32InitDevice(struct Device *dev, char* name, BOOL ro);
|
||||
RETCODE Win32ReleaseDevice(struct Device *dev);
|
||||
BOOL Win32IsDevNative(char*);
|
||||
|
||||
#endif /* ndef ADF_NATIV_H */
|
||||
104
src/win32/adfvolinfo.c
Normal file
104
src/win32/adfvolinfo.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/* An ADFLib function for Windows which displays a dialogue box containing details about
|
||||
** the current disk file.
|
||||
** Converted from adfVolumeInfo(), part of ADFLib by Laurent Clevy.
|
||||
**
|
||||
** Gary Harris
|
||||
** 30/8/00
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "../ADF_raw.h"
|
||||
#include "../ADF_Util.h"
|
||||
|
||||
|
||||
void adfVolumeInfoWin(HWND hWnd, struct Volume *vol)
|
||||
/* Windows version of adfVolumeInfo().
|
||||
** Input: Receives a handle to the window on which to display the dialogue and a pointer
|
||||
** to a ADFLib Volume structure.
|
||||
** Output: Nil. Displays a windows dialogue containing the disk file data.
|
||||
*/
|
||||
{
|
||||
char szTemp[50], szAdfInfo[500]; /* Info string. */
|
||||
|
||||
struct bRootBlock root;
|
||||
char diskName[35];
|
||||
int days,month,year;
|
||||
|
||||
if (adfReadRootBlock(vol, vol->rootBlock, &root)!=RC_OK)
|
||||
return;
|
||||
|
||||
memset(diskName, 0, 35);
|
||||
memcpy(diskName, root.diskName, root.nameLen);
|
||||
|
||||
sprintf(szAdfInfo, "Name : %-30s\n", vol->volName);
|
||||
strcat(szAdfInfo, "Type : ");
|
||||
switch(vol->dev->devType) {
|
||||
case DEVTYPE_FLOPDD:
|
||||
strcat(szAdfInfo, "Floppy Double Density : 880 KBytes\n");
|
||||
break;
|
||||
case DEVTYPE_FLOPHD:
|
||||
strcat(szAdfInfo, "Floppy High Density : 1760 KBytes\n");
|
||||
break;
|
||||
case DEVTYPE_HARDDISK:
|
||||
sprintf(szTemp, "Hard Disk partition : %3.1f KBytes\n",
|
||||
(vol->lastBlock - vol->firstBlock +1) * 512.0/1024.0);
|
||||
strcat(szAdfInfo, szTemp);
|
||||
break;
|
||||
case DEVTYPE_HARDFILE:
|
||||
sprintf(szTemp, "HardFile : %3.1f KBytes\n",
|
||||
(vol->lastBlock - vol->firstBlock +1) * 512.0/1024.0);
|
||||
strcat(szAdfInfo, szTemp);
|
||||
break;
|
||||
default:
|
||||
strcat(szAdfInfo, "Unknown devType!\n");
|
||||
}
|
||||
strcat(szAdfInfo, "Filesystem : ");
|
||||
sprintf(szTemp, "%s ",isFFS(vol->dosType) ? "FFS" : "OFS");
|
||||
strcat(szAdfInfo, szTemp);
|
||||
if (isINTL(vol->dosType))
|
||||
strcat(szAdfInfo, "INTL ");
|
||||
if (isDIRCACHE(vol->dosType))
|
||||
strcat(szAdfInfo, "DIRCACHE ");
|
||||
strcat(szAdfInfo, "\n");
|
||||
|
||||
sprintf(szTemp, "Free blocks = %ld\n", adfCountFreeBlocks(vol));
|
||||
strcat(szAdfInfo, szTemp);
|
||||
if (vol->readOnly)
|
||||
strcat(szAdfInfo, "Read only\n");
|
||||
else
|
||||
strcat(szAdfInfo, "Read/Write\n");
|
||||
|
||||
/* created */
|
||||
adfDays2Date(root.coDays, &year, &month, &days);
|
||||
sprintf(szTemp, "created %d/%02d/%02d %ld:%02ld:%02ld\n",days,month,year,
|
||||
root.coMins/60,root.coMins%60,root.coTicks/50);
|
||||
strcat(szAdfInfo, szTemp);
|
||||
adfDays2Date(root.days, &year, &month, &days);
|
||||
sprintf(szTemp, "last access %d/%02d/%02d %ld:%02ld:%02ld, ",days,month,year,
|
||||
root.mins/60,root.mins%60,root.ticks/50);
|
||||
strcat(szAdfInfo, szTemp);
|
||||
adfDays2Date(root.cDays, &year, &month, &days);
|
||||
sprintf(szTemp, "%d/%02d/%02d %ld:%02ld:%02ld\n",days,month,year,
|
||||
root.cMins/60,root.cMins%60,root.cTicks/50);
|
||||
strcat(szAdfInfo, szTemp);
|
||||
|
||||
MessageBox(hWnd, szAdfInfo, "Adf Info", MB_OK);
|
||||
}
|
||||
|
||||
31
src/win32/defendian.h
Normal file
31
src/win32/defendian.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef DEFENDIAN_H
|
||||
#define DEFENDIAN_H
|
||||
#define LITT_ENDIAN 1
|
||||
/*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#undef printf
|
||||
#define printf
|
||||
|
||||
#undef putchar
|
||||
#define putchar
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* DEFENDIAN_H */
|
||||
140
src/win32/nt4_dev.c
Normal file
140
src/win32/nt4_dev.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/* nt4_dev.c - routines for direct drive access in Windows NT 4.0
|
||||
*
|
||||
* Copyright 1999 by Dan Sutherland <dan@chromerhino.demon.co.uk>
|
||||
*
|
||||
* These routines only currently work with drives <2GB and 512 bytes per sector
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
#include <stdio.h>
|
||||
#include "nt4_dev.h"
|
||||
|
||||
HANDLE NT4OpenDrive(char *lpstrDrive)
|
||||
{
|
||||
char strDriveFile[40];
|
||||
HANDLE hDrv;
|
||||
DWORD dwRet;
|
||||
|
||||
switch (lpstrDrive[0]) {
|
||||
case 'H':
|
||||
sprintf(strDriveFile, "\\\\.\\PhysicalDrive%c", lpstrDrive[1]);
|
||||
break;
|
||||
/* add support for other device types here */
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hDrv = CreateFile(strDriveFile, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||
0, NULL);
|
||||
|
||||
if (hDrv == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
|
||||
if (! DeviceIoControl(hDrv, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0,
|
||||
&dwRet, NULL))
|
||||
return NULL;
|
||||
|
||||
return hDrv;
|
||||
}
|
||||
|
||||
BOOL NT4CloseDrive(HANDLE hDrv)
|
||||
{
|
||||
DWORD dwRet;
|
||||
|
||||
if( hDrv==NULL ) return TRUE; /* BV */
|
||||
|
||||
if (! DeviceIoControl(hDrv, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0,
|
||||
&dwRet, NULL))
|
||||
return FALSE;
|
||||
|
||||
if (! CloseHandle(hDrv))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL NT4ReadSector(HANDLE hDrv, long iSect, int iSize, void *lpvoidBuf)
|
||||
{
|
||||
void *lpvoidTempBuf;
|
||||
DWORD dwActual;
|
||||
|
||||
lpvoidTempBuf = VirtualAlloc(NULL, 512, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
if (SetFilePointer(hDrv, iSect * 512, NULL, FILE_BEGIN) == 0xFFFFFFFF) {
|
||||
VirtualFree(lpvoidTempBuf, 0, MEM_RELEASE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (! ReadFile(hDrv, lpvoidTempBuf, 512, &dwActual, NULL)) {
|
||||
VirtualFree(lpvoidTempBuf, 0, MEM_RELEASE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(lpvoidBuf, lpvoidTempBuf, iSize);
|
||||
VirtualFree(lpvoidTempBuf, 0, MEM_RELEASE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL NT4WriteSector(HANDLE hDrv, long iSect, int iSize, void *lpvoidBuf)
|
||||
{
|
||||
void *lpvoidTempBuf;
|
||||
DWORD dwActual;
|
||||
|
||||
if (iSize != 512)
|
||||
return FALSE;
|
||||
|
||||
lpvoidTempBuf = VirtualAlloc(NULL, 512, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
if (SetFilePointer(hDrv, iSect * 512, NULL, FILE_BEGIN) == 0xFFFFFFFF) {
|
||||
VirtualFree(lpvoidTempBuf, 0, MEM_RELEASE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(lpvoidTempBuf, lpvoidBuf, iSize);
|
||||
|
||||
if (! WriteFile(hDrv, lpvoidTempBuf, 512, &dwActual, NULL)) {
|
||||
VirtualFree(lpvoidTempBuf, 0, MEM_RELEASE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VirtualFree(lpvoidTempBuf, 0, MEM_RELEASE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ULONG NT4GetDriveSize(HANDLE hDrv)
|
||||
{
|
||||
DWORD dwActual;
|
||||
DISK_GEOMETRY dgGeom;
|
||||
long size;
|
||||
|
||||
DeviceIoControl(hDrv, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
|
||||
&dgGeom, sizeof(DISK_GEOMETRY), &dwActual, NULL);
|
||||
|
||||
size = dgGeom.Cylinders.LowPart * dgGeom.TracksPerCylinder *
|
||||
dgGeom.SectorsPerTrack * dgGeom.BytesPerSector;
|
||||
/* BV */
|
||||
/* printf("Total sectors: %i\n", dgGeom.Cylinders.LowPart * dgGeom.TracksPerCylinder * dgGeom.SectorsPerTrack);
|
||||
** printf("Byte size: %i\n", size);
|
||||
*/
|
||||
return size;
|
||||
}
|
||||
26
src/win32/nt4_dev.h
Normal file
26
src/win32/nt4_dev.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* nt4_dev.h - prototypes for NT4 direct drive access functions
|
||||
*
|
||||
* Copyright 1999 by Dan Sutherland
|
||||
*
|
||||
* This file is part of ADFLib.
|
||||
*
|
||||
* ADFLib 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.
|
||||
*
|
||||
* ADFLib 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 Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
HANDLE NT4OpenDrive(char *strDrive);
|
||||
BOOL NT4CloseDrive(HANDLE hDrv);
|
||||
BOOL NT4ReadSector(HANDLE hDrv, long iSect, int iSize, void *lpvoidBuf);
|
||||
BOOL NT4WriteSector(HANDLE hDrv, long iSect, int iSize, void *lpvoidBuf);
|
||||
ULONG NT4GetDriveSize(HANDLE hDrv);
|
||||
40
src/win32/readme_win32.html
Normal file
40
src/win32/readme_win32.html
Normal file
@@ -0,0 +1,40 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Untitled Document</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF">
|
||||
<h1>Readme file for ADFLib on Win32</h1>
|
||||
<p>
|
||||
<p>This file contains additional information on using ADFLib under 32-bit Windows.
|
||||
See the main library documentation for more general info.
|
||||
<h2>Compiling the library on Win32 platforms</h2>
|
||||
<p>The ADFLib distribution contains a two makefiles for nmake:
|
||||
<p><b>Win32Lib.mak</b><br>
|
||||
Compiles the ADFLib as a static library. To use it, simply link your program
|
||||
with adflib.lib and #include adflibusr.h.
|
||||
<p><b>Win32DLL.mak</b><br>
|
||||
Compiles ADFLib as a DLL. This will produce the files ADFLib.dll, ADFLib.lib
|
||||
(the import library to link with your
|
||||
<p>Both makefiles contain debug and release targets. To specify which one to use,
|
||||
use a command line like this:
|
||||
<pre>NMAKE /f "ADFLib.mak" CFG="ADFLib - Win32 Release"</pre>
|
||||
<p>The makefiles will produce a debug version of the library by default if no
|
||||
configuration is specified.
|
||||
<h2>The Win32 native functions</h2>
|
||||
<p>When ADFLib is compiled under Win32, the Win32 native functions will be linked,
|
||||
allowing you to access Amiga harddisks directly in Windows. Current only Windows
|
||||
NT is supported - support for Windows 95 and 98 is in the pipeline.
|
||||
<p>For the direct drive access routines to work under Windows NT, you need administrative
|
||||
priviledges. This is a security feature of Windows NT and there is no way around
|
||||
it.
|
||||
<p>To open a physical device, simply use the following format as the filname:
|
||||
<pre>|Hx</pre>
|
||||
<p>Where x is the ID of the drive to mount. Example:
|
||||
<pre>hd = adfMountDev("|H1");</pre>
|
||||
<p>Your system boot device always has an ID of 0. Attempting to mount it is not
|
||||
a good idea!
|
||||
<p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user