Codebase list gpart / cec0304
Adding upstream version 0.1h. Daniel Baumann 15 years ago
44 changed file(s) with 6401 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0
1 GNU GENERAL PUBLIC LICENSE
2 Version 2, June 1991
3
4 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 675 Mass Ave, Cambridge, MA 02139, USA
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9 Preamble
10
11 The licenses for most software are designed to take away your
12 freedom to share and change it. By contrast, the GNU General Public
13 License is intended to guarantee your freedom to share and change free
14 software--to make sure the software is free for all its users. This
15 General Public License applies to most of the Free Software
16 Foundation's software and to any other program whose authors commit to
17 using it. (Some other Free Software Foundation software is covered by
18 the GNU Library General Public License instead.) You can apply it to
19 your programs, too.
20
21 When we speak of free software, we are referring to freedom, not
22 price. Our General Public Licenses are designed to make sure that you
23 have the freedom to distribute copies of free software (and charge for
24 this service if you wish), that you receive source code or can get it
25 if you want it, that you can change the software or use pieces of it
26 in new free programs; and that you know you can do these things.
27
28 To protect your rights, we need to make restrictions that forbid
29 anyone to deny you these rights or to ask you to surrender the rights.
30 These restrictions translate to certain responsibilities for you if you
31 distribute copies of the software, or if you modify it.
32
33 For example, if you distribute copies of such a program, whether
34 gratis or for a fee, you must give the recipients all the rights that
35 you have. You must make sure that they, too, receive or can get the
36 source code. And you must show them these terms so they know their
37 rights.
38
39 We protect your rights with two steps: (1) copyright the software, and
40 (2) offer you this license which gives you legal permission to copy,
41 distribute and/or modify the software.
42
43 Also, for each author's protection and ours, we want to make certain
44 that everyone understands that there is no warranty for this free
45 software. If the software is modified by someone else and passed on, we
46 want its recipients to know that what they have is not the original, so
47 that any problems introduced by others will not reflect on the original
48 authors' reputations.
49
50 Finally, any free program is threatened constantly by software
51 patents. We wish to avoid the danger that redistributors of a free
52 program will individually obtain patent licenses, in effect making the
53 program proprietary. To prevent this, we have made it clear that any
54 patent must be licensed for everyone's free use or not licensed at all.
55
56 The precise terms and conditions for copying, distribution and
57 modification follow.
58
59 GNU GENERAL PUBLIC LICENSE
60 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62 0. This License applies to any program or other work which contains
63 a notice placed by the copyright holder saying it may be distributed
64 under the terms of this General Public License. The "Program", below,
65 refers to any such program or work, and a "work based on the Program"
66 means either the Program or any derivative work under copyright law:
67 that is to say, a work containing the Program or a portion of it,
68 either verbatim or with modifications and/or translated into another
69 language. (Hereinafter, translation is included without limitation in
70 the term "modification".) Each licensee is addressed as "you".
71
72 Activities other than copying, distribution and modification are not
73 covered by this License; they are outside its scope. The act of
74 running the Program is not restricted, and the output from the Program
75 is covered only if its contents constitute a work based on the
76 Program (independent of having been made by running the Program).
77 Whether that is true depends on what the Program does.
78
79 1. You may copy and distribute verbatim copies of the Program's
80 source code as you receive it, in any medium, provided that you
81 conspicuously and appropriately publish on each copy an appropriate
82 copyright notice and disclaimer of warranty; keep intact all the
83 notices that refer to this License and to the absence of any warranty;
84 and give any other recipients of the Program a copy of this License
85 along with the Program.
86
87 You may charge a fee for the physical act of transferring a copy, and
88 you may at your option offer warranty protection in exchange for a fee.
89
90 2. You may modify your copy or copies of the Program or any portion
91 of it, thus forming a work based on the Program, and copy and
92 distribute such modifications or work under the terms of Section 1
93 above, provided that you also meet all of these conditions:
94
95 a) You must cause the modified files to carry prominent notices
96 stating that you changed the files and the date of any change.
97
98 b) You must cause any work that you distribute or publish, that in
99 whole or in part contains or is derived from the Program or any
100 part thereof, to be licensed as a whole at no charge to all third
101 parties under the terms of this License.
102
103 c) If the modified program normally reads commands interactively
104 when run, you must cause it, when started running for such
105 interactive use in the most ordinary way, to print or display an
106 announcement including an appropriate copyright notice and a
107 notice that there is no warranty (or else, saying that you provide
108 a warranty) and that users may redistribute the program under
109 these conditions, and telling the user how to view a copy of this
110 License. (Exception: if the Program itself is interactive but
111 does not normally print such an announcement, your work based on
112 the Program is not required to print an announcement.)
113
114 These requirements apply to the modified work as a whole. If
115 identifiable sections of that work are not derived from the Program,
116 and can be reasonably considered independent and separate works in
117 themselves, then this License, and its terms, do not apply to those
118 sections when you distribute them as separate works. But when you
119 distribute the same sections as part of a whole which is a work based
120 on the Program, the distribution of the whole must be on the terms of
121 this License, whose permissions for other licensees extend to the
122 entire whole, and thus to each and every part regardless of who wrote it.
123
124 Thus, it is not the intent of this section to claim rights or contest
125 your rights to work written entirely by you; rather, the intent is to
126 exercise the right to control the distribution of derivative or
127 collective works based on the Program.
128
129 In addition, mere aggregation of another work not based on the Program
130 with the Program (or with a work based on the Program) on a volume of
131 a storage or distribution medium does not bring the other work under
132 the scope of this License.
133
134 3. You may copy and distribute the Program (or a work based on it,
135 under Section 2) in object code or executable form under the terms of
136 Sections 1 and 2 above provided that you also do one of the following:
137
138 a) Accompany it with the complete corresponding machine-readable
139 source code, which must be distributed under the terms of Sections
140 1 and 2 above on a medium customarily used for software interchange; or,
141
142 b) Accompany it with a written offer, valid for at least three
143 years, to give any third party, for a charge no more than your
144 cost of physically performing source distribution, a complete
145 machine-readable copy of the corresponding source code, to be
146 distributed under the terms of Sections 1 and 2 above on a medium
147 customarily used for software interchange; or,
148
149 c) Accompany it with the information you received as to the offer
150 to distribute corresponding source code. (This alternative is
151 allowed only for noncommercial distribution and only if you
152 received the program in object code or executable form with such
153 an offer, in accord with Subsection b above.)
154
155 The source code for a work means the preferred form of the work for
156 making modifications to it. For an executable work, complete source
157 code means all the source code for all modules it contains, plus any
158 associated interface definition files, plus the scripts used to
159 control compilation and installation of the executable. However, as a
160 special exception, the source code distributed need not include
161 anything that is normally distributed (in either source or binary
162 form) with the major components (compiler, kernel, and so on) of the
163 operating system on which the executable runs, unless that component
164 itself accompanies the executable.
165
166 If distribution of executable or object code is made by offering
167 access to copy from a designated place, then offering equivalent
168 access to copy the source code from the same place counts as
169 distribution of the source code, even though third parties are not
170 compelled to copy the source along with the object code.
171
172 4. You may not copy, modify, sublicense, or distribute the Program
173 except as expressly provided under this License. Any attempt
174 otherwise to copy, modify, sublicense or distribute the Program is
175 void, and will automatically terminate your rights under this License.
176 However, parties who have received copies, or rights, from you under
177 this License will not have their licenses terminated so long as such
178 parties remain in full compliance.
179
180 5. You are not required to accept this License, since you have not
181 signed it. However, nothing else grants you permission to modify or
182 distribute the Program or its derivative works. These actions are
183 prohibited by law if you do not accept this License. Therefore, by
184 modifying or distributing the Program (or any work based on the
185 Program), you indicate your acceptance of this License to do so, and
186 all its terms and conditions for copying, distributing or modifying
187 the Program or works based on it.
188
189 6. Each time you redistribute the Program (or any work based on the
190 Program), the recipient automatically receives a license from the
191 original licensor to copy, distribute or modify the Program subject to
192 these terms and conditions. You may not impose any further
193 restrictions on the recipients' exercise of the rights granted herein.
194 You are not responsible for enforcing compliance by third parties to
195 this License.
196
197 7. If, as a consequence of a court judgment or allegation of patent
198 infringement or for any other reason (not limited to patent issues),
199 conditions are imposed on you (whether by court order, agreement or
200 otherwise) that contradict the conditions of this License, they do not
201 excuse you from the conditions of this License. If you cannot
202 distribute so as to satisfy simultaneously your obligations under this
203 License and any other pertinent obligations, then as a consequence you
204 may not distribute the Program at all. For example, if a patent
205 license would not permit royalty-free redistribution of the Program by
206 all those who receive copies directly or indirectly through you, then
207 the only way you could satisfy both it and this License would be to
208 refrain entirely from distribution of the Program.
209
210 If any portion of this section is held invalid or unenforceable under
211 any particular circumstance, the balance of the section is intended to
212 apply and the section as a whole is intended to apply in other
213 circumstances.
214
215 It is not the purpose of this section to induce you to infringe any
216 patents or other property right claims or to contest validity of any
217 such claims; this section has the sole purpose of protecting the
218 integrity of the free software distribution system, which is
219 implemented by public license practices. Many people have made
220 generous contributions to the wide range of software distributed
221 through that system in reliance on consistent application of that
222 system; it is up to the author/donor to decide if he or she is willing
223 to distribute software through any other system and a licensee cannot
224 impose that choice.
225
226 This section is intended to make thoroughly clear what is believed to
227 be a consequence of the rest of this License.
228
229 8. If the distribution and/or use of the Program is restricted in
230 certain countries either by patents or by copyrighted interfaces, the
231 original copyright holder who places the Program under this License
232 may add an explicit geographical distribution limitation excluding
233 those countries, so that distribution is permitted only in or among
234 countries not thus excluded. In such case, this License incorporates
235 the limitation as if written in the body of this License.
236
237 9. The Free Software Foundation may publish revised and/or new versions
238 of the General Public License from time to time. Such new versions will
239 be similar in spirit to the present version, but may differ in detail to
240 address new problems or concerns.
241
242 Each version is given a distinguishing version number. If the Program
243 specifies a version number of this License which applies to it and "any
244 later version", you have the option of following the terms and conditions
245 either of that version or of any later version published by the Free
246 Software Foundation. If the Program does not specify a version number of
247 this License, you may choose any version ever published by the Free Software
248 Foundation.
249
250 10. If you wish to incorporate parts of the Program into other free
251 programs whose distribution conditions are different, write to the author
252 to ask for permission. For software which is copyrighted by the Free
253 Software Foundation, write to the Free Software Foundation; we sometimes
254 make exceptions for this. Our decision will be guided by the two goals
255 of preserving the free status of all derivatives of our free software and
256 of promoting the sharing and reuse of software generally.
257
258 NO WARRANTY
259
260 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 REPAIR OR CORRECTION.
269
270 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 POSSIBILITY OF SUCH DAMAGES.
279
280 END OF TERMS AND CONDITIONS
281
282 Appendix: How to Apply These Terms to Your New Programs
283
284 If you develop a new program, and you want it to be of the greatest
285 possible use to the public, the best way to achieve this is to make it
286 free software which everyone can redistribute and change under these terms.
287
288 To do so, attach the following notices to the program. It is safest
289 to attach them to the start of each source file to most effectively
290 convey the exclusion of warranty; and each file should have at least
291 the "copyright" line and a pointer to where the full notice is found.
292
293 <one line to give the program's name and a brief idea of what it does.>
294 Copyright (C) 19yy <name of author>
295
296 This program is free software; you can redistribute it and/or modify
297 it under the terms of the GNU General Public License as published by
298 the Free Software Foundation; either version 2 of the License, or
299 (at your option) any later version.
300
301 This program is distributed in the hope that it will be useful,
302 but WITHOUT ANY WARRANTY; without even the implied warranty of
303 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 GNU General Public License for more details.
305
306 You should have received a copy of the GNU General Public License
307 along with this program; if not, write to the Free Software
308 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
309
310 Also add information on how to contact you by electronic and paper mail.
311
312 If the program is interactive, make it output a short notice like this
313 when it starts in an interactive mode:
314
315 Gnomovision version 69, Copyright (C) 19yy name of author
316 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 This is free software, and you are welcome to redistribute it
318 under certain conditions; type `show c' for details.
319
320 The hypothetical commands `show w' and `show c' should show the appropriate
321 parts of the General Public License. Of course, the commands you use may
322 be called something other than `show w' and `show c'; they could even be
323 mouse-clicks or menu items--whatever suits your program.
324
325 You should also get your employer (if you work as a programmer) or your
326 school, if any, to sign a "copyright disclaimer" for the program, if
327 necessary. Here is a sample; alter the names:
328
329 Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
332 <signature of Ty Coon>, 1 April 1989
333 Ty Coon, President of Vice
334
335 This General Public License does not permit incorporating your program into
336 proprietary programs. If your program is a subroutine library, you may
337 consider it more useful to permit linking proprietary applications with the
338 library. If this is what you want to do, use the GNU Library General
339 Public License instead of this License.
0 v0.1h
1 - New support for the following filesystems: BeOS, QNX 4.x & SGI XFS.
2 - Updated Reiser filesystem support (Francis Devereux <francis@devereux.tc>).
3 - Updated LVM support.
4 - Several small fixes from contributors.
5
6 v0.1g
7 - For access via raw devices: made writing of guessed table also aligned
8 (reading has been aligned since 0.1f).
9 - Fixed stupid copy&paste bug in the partition table check routine.
10
11 v0.1f
12 - Default scan increment 'h' again.
13 - Fixed wrong head-boundary condition.
14 - Introduced possibility to edit guessed partitions.
15 - Scan now starts on (sectors/head) unless -k <start> was given.
16 - Length of guessed NTFS partitions now includes NTFS backup boot
17 sector.
18
19 v0.1e
20 - Default scan increment now 's', extended ptbl boundary condition
21 now depends on scan increment (head if 's', else cylinder boundary).
22 - Added LVM physical volume module (LVM by Heinz Mauelshagen).
23
24 v0.1d
25 - Cope with short reads/read errors from disk (corrupted sectors etc.).
26 - When flagging probable partitions 'invalid' give a reason why.
27 - Fixed buggy ext2 spare superblock location calculation.
28
29 v0.1c
30 - Don't flag partitions 'invalid' which are smaller than their
31 partition table entry.
32 - Fixed buggy rejection of some valid ext2 superblocks.
33 - Fixed linux swap partition size calculation.
34 - Added ReiserFS module.
35
36 v0.1b
37 - First public version.
38 - Made 'fast' scan the default behaviour (-f enables the complete scan).
39 - Increased tolerance in recognizing extended partition tables.
40
41 v0.1a
42 - Initial version.
0
1 gpart Compilation and Installation
2
3
4 Up to now a configure script for gpart does not seem necessary,
5 it should compile under Linux and FreeBSD using GNU cc and GNU
6 make.
7
8 Steps to compile and install:
9
10 - change the installation directory prefix "prefix" in the
11 file "inst.defs". The default is "/usr/local".
12
13 - type "make".
14 - if no errors were encountered, type "make install".
15
16 It is a good idea to read the man page before starting to
17 play around.
+21
-0
LSM less more
0 Begin4
1 Title: gpart
2 Version: 0.1h
3 Entered-date: 2000-02-09
4 Description: A tool which tries to guess the primary partition
5 table of a PC-type hard disk in case the primary
6 partition table in sector 0 is damaged, incorrect
7 or deleted. The guessed table can be written to a
8 file or device. Supported (guessable) filesystem or
9 partition types: DOS/Windows FAT, Linux ext2 and
10 swap, OS/2 HPFS, Windows NTFS, FreeBSD and Solaris/x86
11 disklabels, Minix FS, QNX 4 FS, Reiser FS, LVM physical
12 volumes, BeOS FS, SGI XFS.
13 Keywords: hard disk primary partition table reconstruction
14 Author: michail@brzitwa.de (Michail Brzitwa)
15 Maintained-by: michail@brzitwa.de (Michail Brzitwa)
16 Primary-site: http://home.pages.de/~michab/gpart/
17 ~51k gpart-0.1h.tar.gz
18 Alternate-site: metalab.unc.edu /pub/Linux/system/filesystems
19 Copying-policy: GPL
20 End
0 #
1 # gpart Makefile
2 #
3 include inst.defs
4 include make.defs
5
6 all: gpart
7
8 gpart:
9 $(MAKE) -C src
10 $(MAKE) -C man
11
12 install:
13 $(MAKE) -C src install
14 $(MAKE) -C man install
15
16 uninstall:
17 $(MAKE) -C src uninstall
18 $(MAKE) -C man uninstall
19
20 clean:
21 $(MAKE) -C src clean
22 $(MAKE) -C man clean
0
1 gpart README
2
3
4 Gpart is a small tool which tries to guess what partitions
5 are on a PC type harddisk in case the primary partition table
6 was damaged.
7
8 Gpart works by scanning through the device (or file) given on
9 the command line on a sector basis. Each guessing module is
10 asked if it thinks a file system it knows about could start at
11 a given sector. Several file system guessing modules are built
12 in, others can be added dynamically.
13
14 Consult the manual page for command line options and usage.
15
16
17
18 - Installation ----------------------------------------------------------
19
20 See file INSTALL.
21
22
23
24 - Currently recognized partitions/filesystems types ---------------------
25
26 Modname Typ Description
27 fat 0x01 "Primary DOS with 12 bit FAT"
28 0x04 "Primary DOS with 16 bit FAT (<= 32MB)"
29 0x06 "Primary 'big' DOS (> 32MB)"
30 0x0B "DOS or Windows 95 with 32 bit FAT"
31 0x0C "DOS or Windows 95 with 32 bit FAT, LBA"
32 ntfs 0x07 "OS/2 HPFS, NTFS, QNX or Advanced UNIX"
33 hpfs 0x07 "OS/2 HPFS, NTFS, QNX or Advanced UNIX"
34 ext2 0x83 "Linux ext2 filesystem"
35 lswap 0x82 "Linux swap"
36 bsddl 0xA5 "FreeBSD/NetBSD/386BSD"
37 s86dl 0x82 "Solaris/x86 disklabel"
38 minix 0x80 "Minix V1"
39 0x81 "Minix V2"
40 rfs 0x83 "Reiser filesystem"
41 hmlvm 0xFE "Linux LVM physical volumes"
42 qnx4 0x4F "QNX 4.x"
43 beos 0xEB "BeOS fs"
44 xfs 0x83 "SGI XFS filesystem"
45
46
47
48 - External guessing modules ---------------------------------------------
49
50 gpart allows external partition type guessing modules to be
51 added dynamically. An external module of type "xxx" must be
52 compiled into a shared object file called "gm_xxx.so".
53
54 External modules must provide three functions callable from
55 gpart:
56
57 int xxx_init(disk_desc *d,g_module *m)
58 Initialisation function. Will be called before a scan.
59 It should return the minimum number of bytes it wants
60 to receive for a test. The module should set the
61 description of the filesystem/partition type it handles
62 in g_module.m_desc. If the filesystem/partition type
63 included a partition table like first sector (like the
64 *BSD disklabels do), the flag m_hasptbl should be set.
65 Another flag is m_notinext which means the tested type
66 cannot reside in a logical partition.
67
68 int xxx_term(disk_desc *d)
69 Termination/cleanup function, called after the scanning
70 of the device has been done.
71
72 int xxx_gfun(disk_desc *d,g_module *m)
73 The actual guessing function, called from within the
74 scan loop. It should test the plausibility of the
75 given sectors, and return its guess in m->m_guess (a
76 probability between 0 and 1). See existing modules
77 for examples.
78
79 The given file descriptor d->d_fd can be used for seeking
80 and reading (see e.g. gm_ext2.c which tries to read
81 the first spare superblock). If a module is convinced
82 that it has found a filesystem/partition start it should
83 fill in the assumed begin and size of the partition.
84
85 The test performed should not be too pedantic, for
86 instance it should not be relied upon that the file-
87 system is clean/was properly unmounted. On the other
88 hand too much tolerance leads to misguided guesses,
89 so a golden middle way must be found.
90
91 To create a shared object file from C source, compile the
92 module via
93
94 gcc -Wall -fPIC -shared gm_xxx.c -o gm_xxx.so
95
96 Then install the shared object in a directory searched by
97 the dynamic linker, or set LD_LIBRARY_PATH accordingly.
98 The new external module can then be included by calling
99 gpart like
100
101 gpart -t xxx <other options>
102
103
104
105 - Output explanation ----------------------------------------------------
106
107 Here is a sample 'gpart -v' run on my first IDE hard disk
108 (comments in brackets):
109
110 dev(/dev/hda) mss(512) chs(1232/255/63)(LBA) #s(19792080) size(9664mb)
111 [
112 mss is the medium sector size, chs the geometry retrieved
113 from the OS (or from the command line), #s is the total
114 sector count.
115 ]
116
117 Primary partition(1)
118 type: 006(0x06)(Primary 'big' DOS (> 32MB)) (BOOT)
119 size: 502mb #s(1028097) s(63-1028159)
120 chs: (0/1/1)-(63/254/63)d (0/1/1)-(63/254/63)r
121 hex: 80 01 01 00 06 FE 3F 3F 3F 00 00 00 01 B0 0F 00
122 [
123 size: the size of the partition in megabytes, number of
124 sectors and the sector range.
125 chs: the partition table chs range (d) and the real one.
126 If the number of cylinders is less than 1024 both are
127 identical.
128 hex: the hexadecimal representation of the partition entry
129 as found in the partition table.
130 ]
131
132 ...
133
134 Begin scan...
135 Possible partition(DOS FAT), size(502mb), offset(0mb)
136 type: 006(0x06)(Primary 'big' DOS (> 32MB))
137 size: 502mb #s(1028097) s(63-1028159)
138 chs: (0/1/1)-(63/254/63)d (0/1/1)-(63/254/63)r
139 hex: 00 01 01 00 06 FE 3F 3F 3F 00 00 00 01 B0 0F 00
140
141 Possible extended partition at offset(502mb)
142 Possible partition(Linux ext2), size(31mb), offset(502mb)
143 type: 131(0x83)(Linux ext2 filesystem)
144 size: 31mb #s(64196) s(1028223-1092418)
145 chs: (64/1/1)-(67/254/62)d (64/1/1)-(67/254/62)r
146 hex: 00 01 01 40 83 FE 3E 43 7F B0 0F 00 C4 FA 00 00
147
148 Possible partition(Linux swap), size(125mb), offset(533mb)
149 type: 130(0x82)(Linux swap or Solaris/x86)
150 size: 125mb #s(256976) s(1092483-1349458)
151 chs: (68/1/1)-(83/254/62)d (68/1/1)-(83/254/62)r
152 hex: 00 01 01 44 82 FE 3E 53 83 AB 10 00 D0 EB 03 00
153 [
154 During the scan phase all found partitions are listed by
155 their real type names. The Linux swap partition above is
156 recognized as Linux swap but will get the 0x82 partition
157 identifier which can be both a Solaris disklabel or a
158 Linux swap partition.
159
160 When examing the hex values of the first primary partition
161 it can be seen that they are identical to the values of the
162 actual partition table (good guess) except for the first
163 value (0x80 vs. 0x00). This entry denotes the partition
164 'boot' flag which cannot be guessed.
165 ]
166 ...
167 End scan.
168
169 Checking partitions...
170 Partition(Primary 'big' DOS (> 32MB)): primary
171 Partition(Linux ext2 filesystem): logical
172 Partition(Linux swap or Solaris/x86): logical
173 Partition(Linux LVM physical volume): logical
174 Partition(Linux ext2 filesystem): logical
175 Partition(DOS or Windows 95 with 32 bit FAT, LBA): logical
176 Partition(FreeBSD/NetBSD/386BSD): primary
177 Partition(Linux LVM physical volume): primary
178 Ok.
179 [
180 During the scan phase gpart gathers a simple list of possible
181 partitions, the check phase now tries to decide if found
182 extended partitions seem consistent, if partitions do not
183 overlap etc. Overlapping partitions are silently discarded,
184 all remaining ones are given an attribute 'primary', 'logical',
185 'orphaned' or 'invalid'. If gpart is called like 'gpart -vv ...',
186 it also tells why it thinks a partition guess is invalid.
187
188 If any inconsistencies are found, gpart prints the number
189 of remaining inconsistencies, otherwise it says 'Ok.'
190 ]
191
192 Guessed primary partition table:
193 Primary partition(1)
194 type: 006(0x06)(Primary 'big' DOS (> 32MB))
195 size: 502mb #s(1028097) s(63-1028159)
196 chs: (0/1/1)-(63/254/63)d (0/1/1)-(63/254/63)r
197 hex: 00 01 01 00 06 FE 3F 3F 3F 00 00 00 01 B0 0F 00
198
199 Primary partition(2)
200 type: 005(0x05)(Extended DOS)
201 size: 6157mb #s(12611025) s(1028160-13639184)
202 chs: (64/0/1)-(848/254/63)d (64/0/1)-(848/254/63)r
203 hex: 00 00 01 40 05 FE FF 50 40 B0 0F 00 D1 6D C0 00
204
205 Primary partition(3)
206 type: 165(0xA5)(FreeBSD/NetBSD/386BSD)
207 size: 1396mb #s(2859570) s(13639185-16498754)
208 chs: (849/0/1)-(1023/254/63)d (849/0/1)-(1026/254/63)r
209 hex: 00 00 C1 51 A5 FE FF FF 11 1E D0 00 32 A2 2B 00
210
211 Primary partition(4)
212 type: 254(0xFE)(Linux LVM physical volume)
213 size: 1608mb #s(3293325) s(16498755-19792079)
214 chs: (1023/254/63)-(1023/254/63)d (1027/0/1)-(1231/254/63)r
215 hex: 00 FE FF FF FE FE FF FF 43 C0 FB 00 8D 40 32 00
216 [
217 This is a resulting primary partition table. Note that
218 the logical partition guesses were only used to create
219 the extended partition entry. Up to now gpart cannot
220 reconstruct a damaged logical partition chain itself.
221
222 If a guessed primary partition table should be written to
223 some file or device the user must specify (via the '-W'
224 option) which partition gets the active (bootable) one.
225 ]
226
227
228
229 gpart README, Aug 1999, Michail Brzitwa <mb@ichabod.han.de>
0 #
1 # installation directories for gpart
2 #
3 prefix=/usr/local
4 bindir=$(prefix)/bin
5 libdir=$(prefix)/lib
6 mandir=$(prefix)/man
7 manext=8
8 sharedir=$(prefix)/share
0 #
1 #
2 #
3 CC = gcc
4 CFLAGS = -Wall -O2 -pedantic
5 LDFLAGS =
6 MAKEDEP = gcc -M
7 INSTALL = install
8 RM = rm -f
9 #
10 prg = gpart
11 version = 0.1h
0 #
1 # gpart man Makefile
2 #
3 include ../inst.defs
4 include ../make.defs
5
6
7 all: $(prg).$(manext)
8
9 $(prg).$(manext): $(prg).man
10 @sed -e 's/%MANEXT%/$(manext)/g' \
11 -e 's/%VERSION%/$(version)/g' < $< > $@
12
13 $(prg).$(manext).ps: $(prg).$(manext)
14 @groff -man $< > $@
15
16 clean:
17 @$(RM) $(prg).$(manext) $(prg).$(manext).ps
18
19 install: $(prg).$(manext)
20 $(INSTALL) -d $(mandir)
21 $(INSTALL) -d $(mandir)/man$(manext)
22 $(INSTALL) -m 0444 $(prg).$(manext) $(mandir)/man$(manext)
23
24 uninstall:
25 $(RM) $(mandir)/man$(manext)/$(prg).$(manext)
0 .\"
1 .\" gpart v%VERSION% man page (c) Jan 1999 Michail Brzitwa
2 .\"
3 .TH GPART %MANEXT% "January 2001" "Administration Tools"
4 .SH NAME
5 gpart \- guess PC-type hard disk partitions
6 .SH SYNOPSIS
7 .B gpart
8 [options]
9 .I device
10
11 Options: [-b <backup MBR>][-C c,h,s][-c][-d][-E][-e][-f]
12 [-g][-h][-i][-K <last-sector>][-k <# of sectors>] [-L]
13 [-l <log file>][-n <increment>] [-q][-s <sector-size>]
14 [-t <module-name>][-V][-v] [-W <device>][-w <module-name,
15 weight>]
16 .SH DESCRIPTION
17 .B gpart
18 tries to guess which partitions are on a hard disk.
19 If the primary partition table has been lost, overwritten
20 or destroyed the partitions still exist on the disk but
21 the operating system cannot access them.
22
23 .B gpart
24 ignores the primary partition table and scans the disk
25 (or disk image, file) sector after sector for several
26 filesystem/partition types. It does so by "asking" filesystem
27 recognition modules if they think a given sequence of
28 sectors resembles the beginning of a filesystem or partition
29 type. Currently the following filesystem types are known to
30 .B gpart
31 (listed by module names) :
32
33 .TP
34 .I beos
35 BeOS filesystem type.
36 .TP
37 .I bsddl
38 FreeBSD/NetBSD/386BSD disklabel sub-partitioning
39 scheme used on Intel platforms.
40 .TP
41 .I ext2
42 Linux second extended filesystem.
43 .TP
44 .I fat
45 MS-DOS FAT12/16/32 "filesystems".
46 .TP
47 .I hpfs
48 IBM OS/2 High Performance filesystem.
49 .TP
50 .I hmlvm
51 Linux LVM physical volumes (LVM by Heinz Mauelshagen).
52 .TP
53 .I lswap
54 Linux swap partitions (versions 0 and 1).
55 .TP
56 .I minix
57 The Minix operating system filesystem type.
58 .TP
59 .I ntfs
60 MS Windows NT/2000 filesystem.
61 .TP
62 .I qnx4
63 QNX 4.x filesystem.
64 .TP
65 .I rfs
66 The Reiser filesystem (version 3.5.X, X > 11).
67 .TP
68 .I s86dl
69 Sun Solaris on Intel platforms uses a sub-partitioning
70 scheme on PC hard disks similar to the BSD disklabels.
71 .TP
72 .I xfs
73 Silicon Graphic's journalling filesystem for Linux.
74 .PP
75 More filesystem guessing modules can be added at
76 runtime (see the
77 .I -t
78 option). Please consult the
79 .B gpart
80 README file for detailed explanations on how to create
81 guessing modules. All modules are accompanied by a guessing
82 weight factor which denotes how "educated" their guesses
83 are compared to other modules. This weight can be
84 changed if a certain module keeps on mis-identifying
85 a partition.
86
87 Naturally only partitions which have been formatted in
88 some way can be recognized. If the type of a partition
89 entry in the primary partition table is changed from
90 x to y while the filesystem is still of type x,
91 .B gpart
92 will also still guess a type x.
93
94 No checks are performed whether a found filesystem
95 is clean or even consistent/mountable, so it is quite
96 possible that
97 .B gpart
98 may identify partitions which existed prior to the current
99 partitioning scheme of the disk. Especially on large
100 disks old file system headers/superblocks may be present
101 a long time until they are finally overwritten with
102 user data.
103
104 It should be stressed that
105 .B gpart
106 does a very heuristic job, never believe its output
107 without any plausability checks. It can be easily right
108 in its guesswork but it can also be terribly wrong. You
109 have been warned.
110
111 After having found a list of possible partition types,
112 the list is checked for consistency. For example, a
113 partition which overlaps with the previous one will be
114 discarded. All remaining partitions are labelled with
115 one of the following attributes: "primary", "logical",
116 "orphaned" or "invalid".
117
118 A partition labelled "orphaned" is a logical partition
119 which seems ok but is missed in the chain of logical
120 partitions. This may occur if a logical partition is
121 deleted from the extended partition table without
122 overwriting the actual disk space.
123
124 An "invalid" partition is one that cannot be accepted
125 because of various reasons. If a consistent primary partition
126 table was created in this process it is printed and
127 can be written to a file or device.
128
129 .SH EXTENDED PARTITIONS
130 If the disk/file to be examined consists of primary
131 partitions only,
132 .B gpart
133 has quite a good chance to identify them. Extended
134 partitions on the other hand can result in a lot of
135 problems.
136
137 Extended partitions are realized as a linked list of
138 extended partition tables, each of which include an
139 entry pointing to a logical partition. The size of an
140 extended partition depends on where the last logical
141 partition ends. This means that extended partitions
142 may include "holes", unallocated disk space which
143 should only be assigned to logical, not primary partitions.
144
145 .B gpart
146 tries to do its best to check a found chain of logical
147 partitions but there are very many possible points of
148 failure. If "good" fdisk programs are used to create
149 extended partitions, the resulting tables consist of
150 a zeroed boot record and the four partition entries
151 of which at least two should be marked unused. Unfortunately
152 e.g. the fdisk program shipped with Windows NT does
153 not seem to zero out the boot record area so
154 .B gpart
155 has to be overly tolerant in recognizing extended partition
156 tables. This tolerance may result in quite stupid
157 guesses.
158
159 .SH DISK TRANSFERS
160 If you want to investigate hard disks from other systems
161 you should note down the geometry (number of cylinders,
162 heads per cylinder and sectors per head) used for that
163 disk, and tell
164 .B gpart
165 about this geometry.
166
167 Investigating disks from machines with a different
168 endianness than the scanning one has not been tested
169 at all, and is currently not recommended.
170
171 .SH LARGE DISKS
172 .B gpart
173 relies on the OS reporting the correct disk geometry.
174 Unfortunately sometimes the OS may report a geometry
175 smaller the the actual one (e.g. disks with more than
176 1024 or 16384 cylinder).
177
178 .B gpart
179 checks if guessed partitions extend beyond the disk
180 size and marks those "invalid", but may be mistaken
181 in case the disk size is calculated from an incorrect
182 geometry. For instance if a disk with the geometry
183 1028/255/63 should be scanned, and the OS reports
184 1024/255/63
185 .B gpart
186 should be called like
187
188 .RS
189 gpart -C 1028,255,63 <other options> <device>
190 .RE
191
192 .SH PRECAUTIONS
193 .B gpart
194 may be of some help when the primary partition table was
195 lost or destroyed but it can under
196 .B no
197 circumstances replace proper disk/partition table backups.
198 To save the master boot record (MBR) including the primary
199 partition table to a file type
200
201 .RS
202 dd if=/dev/hda of=mbr bs=512 count=1
203 .RE
204
205 exchanging /dev/hda with the block device name of the
206 disk in question. This should be done for all disks
207 in the system. To restore the primary partition table
208 without overwriting the MBR type
209
210 .RS
211 dd if=mbr of=/dev/hda bs=1 count=64 skip=446 seek=446
212 .RE
213
214 .B Warning:
215 make sure that all parameters are typed as shown and
216 that the disk device is correct. Failing to do so may
217 result in severe filesystem corruption. The saved file
218 should be stored in a safe place like a floppy disk.
219
220 .SH OPTIONS
221 .IP "-b backupfile"
222 If the guessed primary partition table seems consistent
223 and should be written (see the
224 .I
225 -W
226 option) backup the current MBR into the specified file.
227 .IP "-C c,h,s"
228 Set the disk geometry (cylinders, heads, sectors) for
229 the scan. This is useful if a disk should be scanned
230 which was partitioned using a different geometry, if the
231 .I device
232 is a disk-image or if the disk geometry cannot be retrieved
233 through the PCs BIOS. No spaces are allowed between the
234 numbers, unless all three are enclosed in quotes.
235 .IP -c
236 Check/compare mode (implies the
237 .I -q
238 quiet option). After the scan is done, the resulting
239 primary partition table is compared to the existing
240 one. The return code of
241 .B gpart
242 then contains the number of differences (0 if they
243 are identical except for the boot/active flag which
244 cannot be guessed). This option has no effect if
245 .I -d
246 is given on the command line.
247 .IP -d
248 Do not start the guessing loop. Useful if the partition
249 table should be printed (in combination with the
250 .I -v
251 option) without actually scanning for partitions.
252 .IP -E
253 Do not try to identify extended partition tables. If
254 there are extended partitions on the given device
255 .B gpart
256 will most certainly complain about too many primary
257 partitions because there can be only four primary
258 partitions. Existing logical partitions will be listed
259 as primary ones.
260 .IP -e
261 Do not skip disk read errors. If this option is given,
262 and short disk reads or general disk read errors (EIO)
263 are encountered,
264 .B gpart
265 will exit. If not given, the program tries to continue.
266 .IP -f
267 Full scan. When a possible partition is found,
268 .B gpart
269 normally skips all sectors this entry seems to occupy
270 and continues the scan from the end of the last possible
271 partition. The disk scan can take quite a while if
272 this option is given, be patient.
273 .IP -g
274 Do not try to get the disk geometry from the OS. If the
275 .I device
276 is no block or character device but a plain file this
277 option should be supplied. If the file to be scanned is
278 an image of a disk, the geometry can be given by the
279 .I -C
280 option.
281 .IP -h
282 Show some help.
283 .IP -i
284 Run interactively. Each time a possible partition is
285 identified the user is asked for confirmation.
286 .IP "-K last sector"
287 Scan only up to the given sector or the end of the file
288 or device whichever comes first.
289 .IP "-k sectors"
290 Skip given number of sectors before the scan. Potentially
291 useful if a partition is looked for at the end of a
292 large disk.
293 .IP -L
294 List available filesystem/partition type modules and
295 their weights, then exit.
296 .IP "-l logfile"
297 Log output to the given file (even if
298 .I -q
299 was supplied).
300 .IP "-n increment"
301 Scan increment: number of sectors or "s" for single
302 sector increment, "h" for an increment of sectors
303 per head (depends on geometry) or "c" for cylinder
304 increment.
305
306 The increment also influences the condition where extended
307 partition tables are searched: if the scan increment
308 is "s" (i.e. 1) extended partition tables are required
309 to be on a head boundary, otherwise they must be on a
310 cylinder boundary.
311
312 If the disk geometry could not be retrieved and no
313 geometry was given on the command line, the default
314 increment is one sector.
315 .IP -q
316 Quiet/no output mode. However if a logfile was
317 specified (see
318 .I -l
319 option) all output is written to that file. This
320 option overrides the
321 .I -i
322 interactive mode.
323 .IP "-s sector size"
324 Preset medium sector size.
325 .B gpart
326 tries to find out the sector size but may fail in
327 doing so. Probed sector sizes are 2^i, i=9..14
328 (512 to 16384 bytes). The default medium sector
329 size is 512 bytes.
330 .IP "-t module name"
331 Plug in another guessing module. The module to
332 be dynamically linked in must be a shared object
333 file named "gm_<modname>.so".
334 .IP -V
335 Show version number.
336 .IP -v
337 Be verbose. This option can be given more than
338 once resulting in quite a lot of information.
339 .IP "-W device"
340 Write partition table. If a consistent primary
341 partition table has been guessed it can be written
342 to the specified file or device. The supplied device
343 can be the same as the scanned one.
344
345 Additionally the guessed partition entries can
346 be edited. No checks are performed on the entered
347 values, thus the resulting table is allowed to
348 be highly inconsistent. Please beware.
349
350 .B Warning:
351 The guessed partition table should be checked
352 very carefully before writing it back. You can
353 always write the guessed partition table into a
354 plain file and write this into sector 0 using
355 .BR dd (1)
356 (see section PRECAUTIONS above).
357
358 .IP "-w module name,weight"
359 Put the given module at the head of the module chain
360 and assign a new weight to that module. All modules
361 are given an initial weight of 1.0. Again no spaces
362 are allowed.
363
364
365 .PP
366 Default settings are "-n h".
367
368 .SH EXAMPLES
369 \-\ To scan the first IDE hard disk under Linux using default
370 settings type
371
372 .RS
373 gpart /dev/hda
374 .RE
375
376 \-\ To print the primary partition table of the third IDE
377 drive without starting the scan loop in FreeBSD type
378
379 .RS
380 gpart -vvd /dev/wd2
381 .RE
382 .RE
383
384 \-\ If
385 .BR lilo(8)
386 was installed in the master boot record (MBR) of a
387 hard disk it saves the contents of the first sector
388 in a file called /boot/boot.<major/minor>. To list
389 the partitions contained in such a file type e.g.
390
391 .RS
392 gpart -vdg /boot/boot.0300
393 .RE
394
395 If the partition table contains an extended partition,
396 .B gpart
397 will complain about invalid extended partition tables
398 because the extended entry points to sectors not within
399 that file.
400
401 \-\ Usually the first primary partition starts on the
402 second head. If
403 .B gpart
404 cannot identify the first partition properly this may
405 not be the case.
406 .B gpart
407 can be told to start the scan directly from sector one
408 of the disk, using the sector-wise scan mode:
409
410 .RS
411 gpart -k 1 -n s /dev/hdb
412 .RE
413
414 \-\ Suppose
415 .B gpart
416 identifies an NTFS partition as FAT on a certain
417 disk. In this situation the "ntfs" module should be
418 made the first module to be probed and given a
419 weight higher than the usual weight of 1.0:
420
421 .RS
422 gpart -w ntfs,1.5 /dev/hdb
423 .RE
424
425 To list the available modules and their weights use
426 the
427 .I -L
428 option.
429
430 \-\ After having checked the output of
431 .B gpart
432 at least thrice, the primary partition table can
433 be written back to the device this way:
434
435 .RS
436 gpart -W /dev/sdc /dev/sdc
437 .RE
438
439 This of course may be extremely dangerous to your health
440 and social security, so beware.
441
442 \-\ A hard disk with 63 sectors per head is scanned in
443 steps of 63 sectors. To perform the scan on every second
444 head while skipping the first 1008 sectors type
445
446 .RS
447 gpart -k 1008 -n 126 /dev/sda
448 .RE
449
450 \-\ If you want to see how easily
451 .B gpart
452 can be mislead, and how many probable partition starts
453 are on a disk, search the whole disk really sector by
454 sector, writing all output to a logfile:
455
456 .RS
457 gpart -vvfn s -ql /tmp/gpart.log /dev/sd2 &
458 .RE
459
460 Usually
461 .B gpart
462 will not be able to produce an educated guess of the
463 primary partition table in this mode. The logfile
464 however may contain enough hints to manually reconstruct
465 the partition table.
466
467 .SH FILES
468 .I /dev/*
469 .RS
470 Hard disk block devices. The naming scheme of hard disk
471 block devices is OS dependent, consult your system manuals
472 for more information.
473 .RE
474
475 .SH DIAGNOSTICS
476 There are many error message types, all of them should
477 be self-explanatory. Complain if they are not.
478
479 .SH BUGS
480 .B gpart
481 is beta software, so expect buggy behaviour.
482
483 \-\
484 .B gpart
485 only accepts extended partition links with one logical
486 partition. There may be
487 .B fdisk
488 variants out there creating links with up to three
489 logical partition entries but these are not accepted.
490
491 .SH TO DO
492 .br
493 \-\ Support big-endian architectures.
494 .br
495 \-\ Test on 64-bit architectures.
496 .br
497 \-\ Look for boot manager partitions (e.g. OS/2 BM).
498 .br
499 \-\ Think about reconstructing logical partition chains.
500
501 .SH AUTHOR
502 Please send bug reports, suggestions, comments etc. to
503
504 .RS
505 Michail Brzitwa <michail@brzitwa.de>
506 .RE
507
508 .SH "SEE ALSO"
509 .BR fdisk (8).
0 #
1 # gpart src Makefile
2 #
3 include ../inst.defs
4 include ../make.defs
5
6 CFLAGS+=-DVERSION=\"$(version)\"
7 ifeq ($(shell uname),Linux)
8 LIBS=-ldl
9 endif
10
11 ifdef DEBUG
12 CFLAGS+=-g
13 LDFLAGS+=-g
14 endif
15
16 ifdef GPART_LANG
17 CFLAGS+=-DGPART_LANG=\'$(GPART_LANG)\'
18 endif
19
20
21 mod=ext2 lswap fat bsddl ntfs hpfs s86dl minix rfs hmlvm qnx4 beos xfs
22 modobj=$(foreach m,$(mod),gm_$(m).o)
23 obj=gpart.o gmodules.o disku.o l64seek.o $(modobj)
24 src=$(obj:.o=.c)
25 hdr=$(wildcard *.h)
26 allsrc=Makefile $(src) $(hdr)
27
28 all: $(prg)
29
30 $(prg): $(obj)
31 $(CC) -o $@ $(LDFLAGS) $(obj) $(LIBS)
32
33 install: $(prg)
34 $(INSTALL) -d $(bindir)
35 $(INSTALL) -s $(prg) $(bindir)
36
37 uninstall:
38 $(RM) $(bindir)/$(prg)
39
40 clean:
41 @$(RM) $(obj) $(prg) .depend
42
43 static:
44 @$(MAKE) LDFLAGS=-static
45
46 rcscheck:
47 @for f in $(allsrc); do \
48 rcsdiff $$f >/dev/null 2>&1 || echo "Please checkin $$f"; \
49 done
50
51 checkin:
52 @for f in $(allsrc); do \
53 rcsdiff $$f >/dev/null 2>&1 || ci -m"v$(version)" -l $$f; \
54 done
55
56
57 .depend: $(src)
58 @$(MAKEDEP) $(src) > $@
59
60 -include .depend
0 /*
1 * disku.c -- gpart disk util routines
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified: 13.12.2000 <mb@ichabod.han.de>
13 * Calculation of disk cylinder count changed for Linux.
14 *
15 */
16
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <sys/ioctl.h>
21 #include "gpart.h"
22
23 #if defined(__linux__)
24 #include <sys/mount.h>
25 #include <linux/hdreg.h>
26 #endif
27
28 #if defined(__FreeBSD__)
29 #include <errno.h>
30 #include <sys/disklabel.h>
31 #endif
32
33
34
35 /*
36 * get disk geometry. The medium is opened for reading,
37 * descriptor in d_fd.
38 */
39
40 struct disk_geom *disk_geometry(disk_desc *d)
41 {
42 static struct disk_geom g;
43
44 #if defined(__linux__)
45 struct hd_geometry hg;
46 long nsects;
47
48 if (ioctl(d->d_fd,HDIO_GETGEO,&hg) == -1)
49 pr(FATAL,EM_IOCTLFAILED,"HDIO_GETGEO",strerror(errno));
50 #ifdef BLKGETSIZE
51 if (ioctl(d->d_fd,BLKGETSIZE,&nsects) == -1)
52 pr(FATAL,EM_IOCTLFAILED,"BLKGETSIZE",strerror(errno));
53 g.d_c = nsects / (hg.heads * hg.sectors);
54 #else
55 g.d_c = hg.cylinders;
56 #endif
57 g.d_h = hg.heads;
58 g.d_s = hg.sectors;
59
60 #endif
61
62 #if defined(__FreeBSD__)
63 struct disklabel dl;
64 if (ioctl(d->d_fd,DIOCGDINFO,&dl) == -1)
65 pr(FATAL,EM_IOCTLFAILED,"DIOCGDINFO",strerror(errno));
66 g.d_c = dl.d_ncylinders;
67 g.d_h = dl.d_ntracks;
68 g.d_s = dl.d_nsectors;
69 #endif
70
71 return (&g);
72 }
73
74
75 /*
76 * tell the OS to reread a changed partition table. Do
77 * nothing if there is no such possibility.
78 */
79
80 int reread_partition_table(int fd)
81 {
82 #if defined(__linux__) && defined(BLKRRPART)
83 if (ioctl(fd,BLKRRPART) == -1)
84 {
85 pr(ERROR,"rereading partition table: %s",strerror(errno));
86 return (0);
87 }
88 #endif
89
90 return (1);
91 }
0 /*
1 * errmsgs.h -- gpart error/warning messages header file
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _ERRMSGS_H
17 #define _ERRMSGS_H
18
19
20 /* dialog messages */
21 #define DM_YESNO "(y,n)"
22 #define DM_YES "yY"
23 #define DM_NUMORQUIT " (%d..%d, q to quit) : "
24 #define DM_QUIT "qQ"
25 #define DM_STARTSCAN "\nBegin scan...\n"
26 #define DM_ENDSCAN "End scan.\n"
27 #define DM_EDITPTBL "Edit this table"
28 #define DM_ACCEPTGUESS "\nAccept this guess"
29 #define DM_ACTWHICHPART "Activate which partition"
30 #define DM_EDITWHICHPART "Edit which partition"
31 #define DM_WRITEIT "Write this partition table"
32 #define DM_ASKTOREBOOT "partition table written, you should reboot now"
33 #define DM_NOTWRITTEN "Partition table not written\n"
34 #define DM_STARTCHECK "\nChecking partitions...\n"
35 #define DM_NOOFINCONS "Number of inconsistencies found: %d.\n"
36 #define DM_GUESSEDPTBL "\nGuessed primary partition table:\n"
37 #define DM_NOCHECKWARNING "\nWarning: entered values will not be checked; enter at your own risk!\n"
38 #define DM_EDITWHICHITEM "\nEdit which value"
39
40 /* partition list messages */
41 #define PM_DEVDESC1 "\ndev(%s) mss(%d)"
42 #define PM_DEVDESC2 " chs(%d/%d/%d)%s#s(%qd) size(%qdmb)"
43 #define PM_MBRPRINT "\ndev(%s) master boot record (w/o partition table):\n"
44 #define PM_PRIMPART "Primary partition(%d)\n"
45 #define PM_EXTPART " Logical partition\n"
46 #define PM_POSSIBLEPART "Possible partition(%s), size(%qdmb), offset(%qdmb)\n"
47 #define PM_POSSIBLEEXTPART "Possible extended partition at offset(%qdmb)\n"
48 #define PM_PT_TYPE " type: %03d(0x%02X)(%s)"
49 #define PM_PT_SIZE " size: %qdmb #s(%qd)"
50 #define PM_PT_CHS " chs: (%d/%d/%d)-(%d/%d/%d)d"
51 #define PM_PT_HEX " hex: "
52 #define PM_G_PRIMARY "primary "
53 #define PM_G_LOGICAL "logical "
54 #define PM_G_INVALID "invalid "
55 #define PM_G_ORPHANED "orphaned "
56 #define PM_EDITITEM1 "1 - Absolute start sector (%12lu)\n"
57 #define PM_EDITITEM2 "2 - Absolute sector count (%12lu)\n"
58 #define PM_EDITITEM3 "3 - Partition type (%12d)(%s)\n"
59
60 /* error/warning messages */
61 #define EM_FATALERROR "\n*** Fatal error: %s.\n"
62 #define EM_SIMPLEERROR "\n** Error: %s.\n"
63 #define EM_WARNING "\n* Warning: %s.\n"
64 #define EM_PINVALID "\n* Partition invalid(%s):\n"
65 #define EM_MALLOCFAILED "malloc(%d) failed"
66 #define EM_IOCTLFAILED "ioctl(%s) failed: %s"
67 #define EM_OPENFAIL "open(%s): %s"
68 #define EM_STRANGEPTBLMAGIC "strange partition table magic 0x%04X"
69 #define EM_WRONGSECTSIZE "sector size must be > 0 and <= %d"
70 #define EM_FAILSSIZEATTEMPT "failed trying to use sector size %d"
71 #define EM_SEEKFAILURE "dev(%s): seek failure"
72 #define EM_STATFAILURE "stat(%s): %s"
73 #define EM_READERROR "dev(%s): read error near sector(%qd): %s"
74 #define EM_CANTGETSSIZE "cannot get sector size on dev(%s)"
75 #define EM_CANTGETGEOM "cannot get disk geometry"
76 #define EM_MINITFAILURE "module(%s) failed to init"
77 #define EM_INVVALUE "invalid number value"
78 #define EM_PSTART2BIG "partition(%s) starts beyond disk end"
79 #define EM_PSIZE2BIG "partition(%s) is bigger than the disk"
80 #define EM_PEND2BIG "partition(%s) ends beyond disk end"
81 #define EM_STRANGEPTYPE "partition(%s) contains strange flag"
82 #define EM_PTBLREAD "failed to read partition table"
83 #define EM_PTBLWRITE "could not write partition table"
84 #define EM_MBRWRITE "could not write master boot record"
85 #define EM_TOOMANYEXTP "found more than one extended partition, skipping"
86 #define EM_TOOMANYLOGP "more than %d logical partitions encountered"
87 #define EM_EPILLEGALOFS "extended ptbl illegal sector offset"
88 #define EM_INVXPTBL "invalid extended ptbl found at sector(%qd)"
89 #define EM_DISCARDOVLP "Discarded %d overlapping partition guesses"
90 #define EM_TOOMANYXPTS "more than one extended partition: %d"
91 #define EM_TOOMANYPPTS "more than %d primary partitions: %d"
92 #define EM_OPENLOG "cannot open logfile %s"
93 #define EM_NOSUCHMOD "no such module: %s"
94 #define EM_SHORTBREAD "short read near sector(%qd), %d bytes instead of %d. Skipping.."
95 #define EM_BADREADIO "read error (EIO) near sector(%qd), skipping.."
96 #define EM_PINCONS "partition still overlaps with previous one or seems invalid:"
97 #define EM_P_EATEND "extended ptbl without any following partitions"
98 #define EM_P_EWLP "extended ptbl without logical partition"
99 #define EM_P_MTOE "encountered a second extended ptbl"
100 #define EM_P_LISAE "logical partition is an extended partition"
101 #define EM_P_UTS "wrong size, no valid type or (ptbl,link) type mismatch"
102 #define EM_P_2MANYPP "too many primary partitions"
103 #define EM_P_NOTSANE "invalid partition entry (see comments above)"
104 #define EM_P_ENDNOTF "primary partition within extended ptbl link"
105
106
107 #endif /* _ERRMSGS_H */
0 /*
1 * gm_beos.c -- gpart BeOS filesystem guessing module
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 29.01.2001 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include "gpart.h"
20 #include "gm_beos.h"
21
22 #include <stdio.h>
23
24 static const char rcsid[] = "$Id: gm_beos.c,v 1.2 2001/02/07 18:08:08 mb Exp mb $";
25
26
27 int beos_init(disk_desc *d,g_module *m)
28 {
29 if ((d == 0) || (m == 0))
30 return (0);
31 m->m_desc = "BeOS filesystem";
32 return (2 * 512);
33 }
34
35
36
37 int beos_term(disk_desc *d)
38 {
39 return (1);
40 }
41
42
43
44 int beos_gfun(disk_desc *d,g_module *m)
45 {
46 beos_super_block *sb;
47 s64_t size;
48
49 m->m_guess = GM_NO;
50
51 /*
52 * BeOS superblock without little/big endian conversions
53 */
54
55 sb = (beos_super_block *)(d->d_sbuf + 512);
56 if ((sb->magic1 != BEOS_SUPER_BLOCK_MAGIC1) ||
57 (sb->magic2 != BEOS_SUPER_BLOCK_MAGIC2) ||
58 (sb->magic3 != BEOS_SUPER_BLOCK_MAGIC3))
59 return (1);
60
61 /*
62 * some consistency checks
63 */
64
65 if ((sb->block_size != 1024) && (sb->block_size != 2048) &&
66 (sb->block_size != 4096) && (sb->block_size != 8192))
67 return (1);
68
69 if (sb->block_size != 1 << sb->block_shift)
70 return (1);
71
72 if (sb->num_blocks < sb->used_blocks)
73 return (1);
74
75 if ((sb->flags != BEOS_CLEAN) && (sb->flags != BEOS_DIRTY))
76 return (1);
77
78 /*
79 * I hope this is enough, if not I have to read the root dir
80 * as well later.
81 */
82
83 size = sb->num_blocks; size *= sb->block_size; size /= d->d_ssize;
84 m->m_guess = GM_YES;
85 m->m_part.p_typ = 0xEB;
86 m->m_part.p_start = d->d_nsb;
87 m->m_part.p_size = (unsigned long)size;
88
89 return (1);
90 }
0 /*
1 * gm_beos.h -- gpart BeOS filesystem guessing module header
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 29.01.2001 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _GM_BEOS_H
17 #define _GM_BEOS_H
18
19 /* imported from asm/types.h */
20 typedef __signed__ char __s8;
21 typedef unsigned char __u8;
22
23 typedef __signed__ short __s16;
24 typedef unsigned short __u16;
25
26 typedef __signed__ int __s32;
27 typedef unsigned int __u32;
28
29 /*
30 * BeOS filesystem structures, taken from "BEOS filesystem for Linux 1999-05-28"
31 * by Makoto Kato <m_kato@ga2.so-net.ne.jp>
32 */
33
34 /*
35 * Flags of superblock
36 */
37
38 #define BEOS_CLEAN 0x434c454e
39 #define BEOS_DIRTY 0x44495254
40
41 /*
42 * Magic headers of BEOS's superblock, inode and index
43 */
44
45 #define BEOS_SUPER_BLOCK_MAGIC1 0x42465331 /* BEOS1 */
46 #define BEOS_SUPER_BLOCK_MAGIC2 0xdd121031
47 #define BEOS_SUPER_BLOCK_MAGIC3 0x15b6830e
48 #define BEOS_INODE_MAGIC1 0x3bbe0ad9
49 #define BEOS_INDEX_MAGIC 0x69f6c2e8
50 #define BEOS_SUPER_MAGIC BEOS_SUPER_BLOCK_MAGIC1
51 #define BEOS_NUM_DIRECT_BLOCKS 12
52 #define BEOS_NAME_LENGTH 32
53
54 /*
55 * BEOS filesystem type
56 */
57
58 #define BEOS_PPC 1
59 #define BEOS_X86 2
60
61 /*
62 * special type of BEOS
63 */
64
65 typedef s64_t beos_off_t;
66 typedef s64_t beos_bigtime_t;
67 typedef void beos_binode_etc;
68
69 typedef struct _beos_block_run {
70 __u32 allocation_group;
71 __u16 start;
72 __u16 len;
73 } beos_block_run;
74
75 typedef beos_block_run beos_inode_addr;
76
77 /*
78 * The Superblock Structure
79 */
80
81 typedef struct _beos_super_block {
82 char name[BEOS_NAME_LENGTH];
83 __u32 magic1;
84 __u32 fs_byte_order;
85
86 __u32 block_size;
87 __u32 block_shift;
88
89 beos_off_t num_blocks;
90 beos_off_t used_blocks;
91
92 __u32 inode_size;
93
94 __u32 magic2;
95 __u32 blocks_per_ag;
96 __u32 ag_shift;
97 __u32 num_ags;
98
99 __u32 flags;
100
101 beos_block_run log_blocks;
102 beos_off_t log_start;
103 beos_off_t log_end;
104
105 __u32 magic3;
106 beos_inode_addr root_dir;
107 beos_inode_addr indices;
108
109 __u32 pad[8];
110 } __attribute__ ((packed)) beos_super_block;
111
112
113 #endif /* _GM_BEOS_H */
0 /*
1 * gm_bsddl.c -- gpart BSD disk label guessing module
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #include "gpart.h"
17 #include "gm_bsddl.h"
18
19 static const char rcsid[] = "$Id: gm_bsddl.c,v 1.6 2001/02/07 18:08:08 mb Exp mb $";
20
21
22 int bsddl_init(disk_desc *d,g_module *m)
23 {
24 if ((d == 0) || (m == 0))
25 return (0);
26 m->m_desc = "*BSD disklabel";
27 m->m_hasptbl = 1; m->m_notinext = 1;
28 return (BBSIZE);
29 }
30
31
32
33 int bsddl_term(disk_desc *d)
34 {
35 return (1);
36 }
37
38
39
40 int bsddl_gfun(disk_desc *d,g_module *m)
41 {
42 struct disklabel *dl;
43 struct partition *bsdpt;
44 unsigned short *cp, *ep, cs1, cs2;
45
46 m->m_guess = GM_NO;
47 dl = (struct disklabel *)(d->d_sbuf + LABELSECTOR * d->d_ssize);
48 if ((dl->d_magic == le32(DISKMAGIC)) && (dl->d_magic2 == le32(DISKMAGIC)))
49 {
50 /*
51 * partition RAW_PART(2) usually denotes the whole disk (slice)
52 */
53
54 if (dl->d_npartitions <= RAW_PART)
55 return (1);
56 bsdpt = &dl->d_partitions[RAW_PART];
57
58 /*
59 * some sanity checks: disklabel checksum and start
60 * of partition.
61 */
62
63 cs1 = 0; cs2 = le16(dl->d_checksum); dl->d_checksum = 0;
64 cp = (unsigned short *)dl;
65 ep = (unsigned short *)&dl->d_partitions[dl->d_npartitions];
66 for ( ; cp < ep; cp++)
67 cs1 ^= le16(*cp);
68 dl->d_checksum = le16(cs2);
69
70 if ((le32(bsdpt->p_offset) == d->d_nsb) && (cs1 == cs2))
71 {
72 m->m_part.p_typ = 0xA5;
73 m->m_part.p_start = le32(bsdpt->p_offset);
74 m->m_part.p_size = le32(bsdpt->p_size);
75 m->m_guess = GM_YES;
76 }
77 }
78 return (1);
79 }
0 /*
1 * gm_bsddl.h -- gpart BSD disk label guessing module header
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _GM_BSDDL_H
17 #define _GM_BSDDL_H
18
19 /*
20 * BSD 4.4 disklabel support. Copied from the sources of the
21 * FreeBSD (2.2.7) disklabel(8) program sources. These sources
22 * are under the BSD licence, not the GPL. Please see http://
23 * www.freebsd.org/ for copyright/licence notes.
24 */
25
26 #define STANDALONE
27
28 #define BBSIZE 8192 /* size of boot area, with label */
29
30 #ifdef __i386__
31 #define LABELSECTOR 1 /* sector containing label */
32 #define LABELOFFSET 0 /* offset of label in sector */
33 #endif
34
35 #ifndef LABELSECTOR
36 #define LABELSECTOR 0 /* sector containing label */
37 #endif
38
39 #ifndef LABELOFFSET
40 #define LABELOFFSET 64 /* offset of label in sector */
41 #endif
42
43 #define DISKMAGIC ((u_int32_t)0x82564557) /* The disk magic number */
44 #ifndef MAXPARTITIONS
45 #define MAXPARTITIONS 8
46 #endif
47
48 #define LABEL_PART 2 /* partition containing label */
49 #define RAW_PART 2 /* partition containing whole disk */
50 #define SWAP_PART 1 /* partition normally containing swap */
51
52 struct disklabel {
53 u_int32_t d_magic; /* the magic number */
54 u_int16_t d_type; /* drive type */
55 u_int16_t d_subtype; /* controller/d_type specific */
56 char d_typename[16]; /* type name, e.g. "eagle" */
57
58 /*
59 * d_packname contains the pack identifier and is returned when
60 * the disklabel is read off the disk or in-core copy.
61 * d_boot0 and d_boot1 are the (optional) names of the
62 * primary (block 0) and secondary (block 1-15) bootstraps
63 * as found in /usr/mdec. These are returned when using
64 * getdiskbyname(3) to retrieve the values from /etc/disktab.
65 */
66 #if defined(KERNEL) || defined(STANDALONE)
67 char d_packname[16]; /* pack identifier */
68 #else
69 union {
70 char un_d_packname[16]; /* pack identifier */
71 struct {
72 char *un_d_boot0; /* primary bootstrap name */
73 char *un_d_boot1; /* secondary bootstrap name */
74 } un_b;
75 } d_un;
76 #define d_packname d_un.un_d_packname
77 #define d_boot0 d_un.un_b.un_d_boot0
78 #define d_boot1 d_un.un_b.un_d_boot1
79 #endif /* ! KERNEL or STANDALONE */
80
81 /* disk geometry: */
82 u_int32_t d_secsize; /* # of bytes per sector */
83 u_int32_t d_nsectors; /* # of data sectors per track */
84 u_int32_t d_ntracks; /* # of tracks per cylinder */
85 u_int32_t d_ncylinders; /* # of data cylinders per unit */
86 u_int32_t d_secpercyl; /* # of data sectors per cylinder */
87 u_int32_t d_secperunit; /* # of data sectors per unit */
88
89 /*
90 * Spares (bad sector replacements) below are not counted in
91 * d_nsectors or d_secpercyl. Spare sectors are assumed to
92 * be physical sectors which occupy space at the end of each
93 * track and/or cylinder.
94 */
95 u_int16_t d_sparespertrack; /* # of spare sectors per track */
96 u_int16_t d_sparespercyl; /* # of spare sectors per cylinder */
97 /*
98 * Alternate cylinders include maintenance, replacement, configuration
99 * description areas, etc.
100 */
101 u_int32_t d_acylinders; /* # of alt. cylinders per unit */
102
103 /* hardware characteristics: */
104 /*
105 * d_interleave, d_trackskew and d_cylskew describe perturbations
106 * in the media format used to compensate for a slow controller.
107 * Interleave is physical sector interleave, set up by the
108 * formatter or controller when formatting. When interleaving is
109 * in use, logically adjacent sectors are not physically
110 * contiguous, but instead are separated by some number of
111 * sectors. It is specified as the ratio of physical sectors
112 * traversed per logical sector. Thus an interleave of 1:1
113 * implies contiguous layout, while 2:1 implies that logical
114 * sector 0 is separated by one sector from logical sector 1.
115 * d_trackskew is the offset of sector 0 on track N relative to
116 * sector 0 on track N-1 on the same cylinder. Finally, d_cylskew
117 * is the offset of sector 0 on cylinder N relative to sector 0
118 * on cylinder N-1.
119 */
120 u_int16_t d_rpm; /* rotational speed */
121 u_int16_t d_interleave; /* hardware sector interleave */
122 u_int16_t d_trackskew; /* sector 0 skew, per track */
123 u_int16_t d_cylskew; /* sector 0 skew, per cylinder */
124 u_int32_t d_headswitch; /* head switch time, usec */
125 u_int32_t d_trkseek; /* track-to-track seek, usec */
126 u_int32_t d_flags; /* generic flags */
127 #define NDDATA 5
128 u_int32_t d_drivedata[NDDATA]; /* drive-type specific information */
129 #define NSPARE 5
130 u_int32_t d_spare[NSPARE]; /* reserved for future use */
131 u_int32_t d_magic2; /* the magic number (again) */
132 u_int16_t d_checksum; /* xor of data incl. partitions */
133
134 /* filesystem and partition information: */
135 u_int16_t d_npartitions; /* number of partitions in following */
136 u_int32_t d_bbsize; /* size of boot area at sn0, bytes */
137 u_int32_t d_sbsize; /* max size of fs superblock, bytes */
138 struct partition { /* the partition table */
139 u_int32_t p_size; /* number of sectors in partition */
140 u_int32_t p_offset; /* starting sector */
141 u_int32_t p_fsize; /* filesystem basic fragment size */
142 u_int8_t p_fstype; /* filesystem type, see below */
143 u_int8_t p_frag; /* filesystem fragments per block */
144 union {
145 u_int16_t cpg; /* UFS: FS cylinders per group */
146 u_int16_t sgs; /* LFS: FS segment shift */
147 } __partition_u1;
148 #define p_cpg __partition_u1.cpg
149 #define p_sgs __partition_u1.sgs
150 } d_partitions[MAXPARTITIONS]; /* actually may be more */
151 };
152
153
154 #endif /* _GM_BSDDL_H */
0 /*
1 * gm_ext2.c -- gpart ext2 guessing module
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified: 30.04.1999 <mb@ichabod.han.de>
13 * Added suggestions from Andries.Brouwer@cwi.nl
14 *
15 * 18.06.1999 <mb@ichabod.han.de>
16 * Fixed buggy ext2 spare superblock location calculation.
17 *
18 * 29.06.1999 <mb@ichabod.han.de>
19 * Made every disk read/write buffer aligned to pagesize.
20 *
21 */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include "gpart.h"
27 #include "gm_ext2.h"
28
29 static const char rcsid[] = "$Id: gm_ext2.c,v 1.8 2001/02/07 18:08:08 mb Exp mb $";
30
31
32 int ext2_init(disk_desc *d,g_module *m)
33 {
34 int bsize = SUPERBLOCK_SIZE;
35
36 if ((d == 0) || (m == 0))
37 return (0);
38
39 /*
40 * the medium sector size must either be a multiple
41 * of the superblock size or vice versa.
42 */
43
44 if (((d->d_ssize > bsize) && (d->d_ssize % bsize)) ||
45 ((d->d_ssize < bsize) && (bsize % d->d_ssize)))
46 {
47 pr(ERROR,"ext2_init: cannot work on that sector size");
48 return (0);
49 }
50 m->m_desc = "Linux ext2";
51 return (SUPERBLOCK_OFFSET + SUPERBLOCK_SIZE);
52 }
53
54
55
56 int ext2_term(disk_desc *d)
57 {
58 return (1);
59 }
60
61
62
63 int ext2_gfun(disk_desc *d,g_module *m)
64 {
65 struct ext2fs_sb *sb, *sparesb;
66 int psize, bsize = 1024;
67 s64_t ls, ofs;
68 dos_part_entry *pt = &m->m_part;
69 byte_t *ubuf, *sbuf;
70
71 m->m_guess = GM_NO;
72 sb = (struct ext2fs_sb *)(d->d_sbuf + SUPERBLOCK_OFFSET);
73 if (sb->s_magic != le16(EXT2_SUPER_MAGIC))
74 return (1);
75
76 /*
77 * first some plausability checks.
78 */
79
80 if (sb->s_free_blocks_count >= sb->s_blocks_count) return (1);
81 if (sb->s_free_inodes_count >= sb->s_inodes_count) return (1);
82 if (sb->s_errors &&
83 (sb->s_errors != EXT2_ERRORS_CONTINUE) &&
84 (sb->s_errors != EXT2_ERRORS_RO) &&
85 (sb->s_errors != EXT2_ERRORS_PANIC))
86 return (1);
87 if (sb->s_state & ~(EXT2_VALID_FS | EXT2_ERROR_FS))
88 return (1);
89
90 /*
91 * empty filesystems seem unlikely to me.
92 */
93
94 if (sb->s_blocks_count == 0)
95 return (1);
96
97 /*
98 * yet they also shouldn't be too large.
99 */
100
101 if (d->d_nsecs)
102 {
103 ls = sb->s_blocks_count; ls *= bsize;
104 ls /= d->d_ssize; ls += d->d_nsb;
105 if (ls > d->d_nsecs)
106 return (1);
107 }
108
109 /*
110 * ext2fs supports 1024, 2048 and 4096b blocks.
111 */
112
113 switch (sb->s_log_block_size)
114 {
115 case BSIZE_1024 : bsize = 1024; break;
116 case BSIZE_2048 : bsize = 2048; break;
117 case BSIZE_4096 : bsize = 4096; break;
118 default: return (1);
119 }
120
121 /*
122 * current mount count shouldn't be greater than max+20
123 */
124
125 if (sb->s_mnt_count > sb->s_max_mnt_count + 20)
126 return (1);
127
128 /*
129 * up to here this looks like a valid ext2 sb, now try to read
130 * the first spare super block to be sure.
131 */
132
133 if ((ls = l64tell(d->d_fd)) == -1)
134 pr(FATAL,"ext2: cannot seek: %s",strerror(errno));
135 ls /= d->d_ssize; ls -= d->d_nsb; ls *= d->d_ssize;
136 ofs = sb->s_blocks_per_group + sb->s_first_data_block; ofs *= bsize;
137 if (l64seek(d->d_fd,ofs - ls,SEEK_CUR) == -1)
138 pr(FATAL,"ext2: cannot seek: %s",strerror(errno));
139
140 psize = getpagesize();
141 ubuf = alloc(SUPERBLOCK_SIZE + psize);
142 sbuf = align(ubuf,psize);
143 if (read(d->d_fd,sbuf,SUPERBLOCK_SIZE) != SUPERBLOCK_SIZE)
144 pr(FATAL,"ext2: cannot read spare super block");
145 sparesb = (struct ext2fs_sb *)sbuf;
146
147 /*
148 * test only some values of the spare sb.
149 */
150
151 if (sparesb->s_magic != le16(EXT2_SUPER_MAGIC))
152 goto out;
153 if (sparesb->s_log_block_size != sb->s_log_block_size)
154 goto out;
155
156 /*
157 * seems ok.
158 */
159
160 m->m_guess = GM_YES;
161 pt->p_typ = 0x83;
162 pt->p_start = d->d_nsb;
163 pt->p_size = bsize / d->d_ssize;
164 pt->p_size *= sb->s_blocks_count;
165
166 out:
167 free((void *)ubuf);
168 return (1);
169 }
0 /*
1 * gm_ext2.h -- gpart ext2 guessing module header
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _GM_EXT2_H
17 #define _GM_EXT2_H
18
19 /*
20 * Ext2 filesystem structures, taken from the ext2 utilities v1.10.
21 */
22
23 /* imported from asm/types.h */
24 typedef __signed__ char __s8;
25 typedef unsigned char __u8;
26
27 typedef __signed__ short __s16;
28 typedef unsigned short __u16;
29
30 typedef __signed__ int __s32;
31 typedef unsigned int __u32;
32
33 /* imported from ext2fs/ext2_fs.h */
34
35 #define SUPERBLOCK_OFFSET 1024
36 #define SUPERBLOCK_SIZE 1024
37 #define BSIZE_1024 0
38 #define BSIZE_2048 1
39 #define BSIZE_4096 2
40 #define EXT2_LIB_CURRENT_REV 0
41 #define EXT2_SUPER_MAGIC 0xEF53
42 #define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
43 #define EXT2_ERROR_FS 0x0002 /* Errors detected */
44 #define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
45 #define EXT2_DFL_CHECKINTERVAL 15552000 /* Don't use interval check */
46 #define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
47 #define EXT2_ERRORS_RO 2 /* Remount fs read-only */
48 #define EXT2_ERRORS_PANIC 3 /* Panic */
49 #define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
50 #define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
51 #define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
52
53 struct ext2fs_sb {
54 __u32 s_inodes_count; /* Inodes count */
55 __u32 s_blocks_count; /* Blocks count */
56 __u32 s_r_blocks_count; /* Reserved blocks count */
57 __u32 s_free_blocks_count; /* Free blocks count */
58 __u32 s_free_inodes_count; /* Free inodes count */
59 __u32 s_first_data_block; /* First Data Block */
60 __u32 s_log_block_size; /* Block size */
61 __s32 s_log_frag_size; /* Fragment size */
62 __u32 s_blocks_per_group; /* # Blocks per group */
63 __u32 s_frags_per_group; /* # Fragments per group */
64 __u32 s_inodes_per_group; /* # Inodes per group */
65 __u32 s_mtime; /* Mount time */
66 __u32 s_wtime; /* Write time */
67 __u16 s_mnt_count; /* Mount count */
68 __s16 s_max_mnt_count; /* Maximal mount count */
69 __u16 s_magic; /* Magic signature */
70 __u16 s_state; /* File system state */
71 __u16 s_errors; /* Behaviour when detecting errors */
72 __u16 s_minor_rev_level; /* minor revision level */
73 __u32 s_lastcheck; /* time of last check */
74 __u32 s_checkinterval; /* max. time between checks */
75 __u32 s_creator_os; /* OS */
76 __u32 s_rev_level; /* Revision level */
77 __u16 s_def_resuid; /* Default uid for reserved blocks */
78 __u16 s_def_resgid; /* Default gid for reserved blocks */
79 /*
80 * These fields are for EXT2_DYNAMIC_REV superblocks only.
81 *
82 * Note: the difference between the compatible feature set and
83 * the incompatible feature set is that if there is a bit set
84 * in the incompatible feature set that the kernel doesn't
85 * know about, it should refuse to mount the filesystem.
86 *
87 * e2fsck's requirements are more strict; if it doesn't know
88 * about a feature in either the compatible or incompatible
89 * feature set, it must abort and not try to meddle with
90 * things it doesn't understand...
91 */
92 __u32 s_first_ino; /* First non-reserved inode */
93 __u16 s_inode_size; /* size of inode structure */
94 __u16 s_block_group_nr; /* block group # of this superblock */
95 __u32 s_feature_compat; /* compatible feature set */
96 __u32 s_feature_incompat; /* incompatible feature set */
97 __u32 s_feature_ro_compat; /* readonly-compatible feature set */
98 __u8 s_uuid[16]; /* 128-bit uuid for volume */
99 char s_volume_name[16]; /* volume name */
100 char s_last_mounted[64]; /* directory where last mounted */
101 __u32 s_reserved[206]; /* Padding to the end of the block */
102 };
103
104 #endif /* _GM_EXT2_H */
0 /*
1 * gm_fat.c -- gpart fat guessing module
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #include "gpart.h"
17 #include "gm_fat.h"
18
19 static const char rcsid[] = "$Id: gm_fat.c,v 1.6 2001/02/07 18:08:08 mb Exp mb $";
20
21
22 int fat_init(disk_desc *d,g_module *m)
23 {
24 if ((d == 0) || (m == 0))
25 return (0);
26 m->m_desc = "DOS FAT";
27 m->m_align = 'h';
28 return (sizeof(struct fat_boot_sector));
29 }
30
31
32
33 int fat_term(disk_desc *d)
34 {
35 return (1);
36 }
37
38
39
40 int fat_gfun(disk_desc *d,g_module *m)
41 {
42 struct fat_boot_sector *sb = (struct fat_boot_sector *)d->d_sbuf;
43 dos_part_entry *pt = &m->m_part;
44 unsigned long nsecs = 0;
45 unsigned char ig1, ig2, media;
46 int sectsize, fat32 = 0, fat12 = 0;
47 s64_t size = 0;
48
49 m->m_guess = GM_NO;
50 ig1 = sb->ignored[0]; ig2 = sb->ignored[2]; media = sb->media;
51 if ((ig1 == 0xeb) && (ig2 == 0x90) && ((media == 0xf8) || (media == 0xfc)))
52 {
53 if (*((unsigned short *)d->d_sbuf + 255) != le16(DOSPTMAGIC))
54 return (1);
55
56 /*
57 * looks like a standard FAT boot sector. Now find out,
58 * which one of the numerous versions this could be.
59 */
60
61 pt->p_start = d->d_nsb;
62 nsecs = le16(*(unsigned short *)sb->sectors);
63 if (nsecs == 0)
64 nsecs = le32(sb->total_sect);
65 if (nsecs == 0)
66 return (1);
67 sectsize = le16(*(unsigned short *)sb->sector_size);
68 if ((d->d_sbuf[0x39] == '1') && (d->d_sbuf[0x3a] == '2'))
69 fat12 = 1;
70 if (sb->fat_length == 0)
71 fat32 = 1;
72 if (fat32 && (*(d->d_sbuf + 0x26) == 0x29))
73 return (1);
74 if (!fat32 && (*(d->d_sbuf + 0x26) != 0x29))
75 return (1);
76 if (fat12 && fat32)
77 return (1);
78 m->m_guess = GM_YES;
79
80
81 /*
82 * what happens when the fat sectsize != medium sectsize?
83 * I don't know. I just say no now.
84 */
85
86 if (sectsize != d->d_ssize)
87 m->m_guess = GM_NO;
88 size = nsecs; size *= sectsize; size /= 1024;
89 if (size >= 32768)
90 {
91 pt->p_typ = 0x06;
92 if (fat32)
93 pt->p_typ = d->d_lba ? 0x0C : 0x0B;
94 }
95 else
96 pt->p_typ = fat12 ? 0x01 : 0x04;
97 pt->p_size = nsecs;
98 }
99 return (1);
100 }
0 /*
1 * gm_fat.h -- gpart fat guessing module header
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _GM_FAT_H
17 #define _GM_FAT_H
18
19
20 /*
21 * FAT partition boot sector information, taken from the Linux
22 * kernel sources.
23 */
24
25
26 /* imported from asm/types.h */
27 typedef __signed__ char __s8;
28 typedef unsigned char __u8;
29
30 typedef __signed__ short __s16;
31 typedef unsigned short __u16;
32
33 typedef __signed__ int __s32;
34 typedef unsigned int __u32;
35
36
37 struct fat_boot_sector {
38 __s8 ignored[3]; /* Boot strap short or near jump */
39 __s8 system_id[8]; /* Name - can be used to special case
40 partition manager volumes */
41 __u8 sector_size[2]; /* bytes per logical sector */
42 __u8 cluster_size; /* sectors/cluster */
43 __u16 reserved; /* reserved sectors */
44 __u8 fats; /* number of FATs */
45 __u8 dir_entries[2]; /* root directory entries */
46 __u8 sectors[2]; /* number of sectors */
47 __u8 media; /* media code (unused) */
48 __u16 fat_length; /* sectors/FAT */
49 __u16 secs_track; /* sectors per track */
50 __u16 heads; /* number of heads */
51 __u32 hidden; /* hidden sectors (unused) */
52 __u32 total_sect; /* number of sectors (if sectors == 0) */
53
54 /* The following fields are only used by FAT32 */
55 __u32 fat32_length; /* sectors/FAT */
56 __u16 flags; /* bit 8: fat mirroring, low 4: active fat */
57 __u8 version[2]; /* major, minor filesystem version */
58 __u32 root_cluster; /* first cluster in root directory */
59 __u16 info_sector; /* filesystem info sector */
60 __u16 backup_boot; /* backup boot sector */
61 __u16 reserved2[6]; /* Unused */
62 };
63
64 #endif /* _GM_FAT_H */
0 /*
1 * gm_hmlvm.c -- gpart Linux LVM physical volume guessing module
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 29.08.1999 <mb@ichabod.han.de>
12 * Modified: 29.01.2001 <mb@ichabod.han.de>
13 * Minor update to LVM 0.9.
14 *
15 */
16
17 #include <string.h>
18 #include <errno.h>
19 #include "gpart.h"
20 #include "gm_hmlvm.h"
21
22 static const char rcsid[] = "$Id: gm_hmlvm.c,v 1.3 2001/02/07 18:08:08 mb Exp mb $";
23
24
25 int hmlvm_init(disk_desc *d,g_module *m)
26 {
27 if ((d == 0) || (m == 0))
28 return (0);
29
30 m->m_desc = "Linux LVM physical volume";
31 return (LVM_PV_DISK_BASE + LVM_PV_DISK_SIZE);
32 }
33
34
35
36 int hmlvm_term(disk_desc *d)
37 {
38 return (1);
39 }
40
41
42
43 int hmlvm_gfun(disk_desc *d,g_module *m)
44 {
45 pv_disk_t *pv;
46 dos_part_entry *pt = &m->m_part;
47 unsigned int size;
48 s64_t s;
49
50 m->m_guess = GM_NO;
51 pv = (pv_disk_t *)&d->d_sbuf[LVM_PV_DISK_BASE];
52 if ((strncmp((char *)pv->id,LVM_ID,sizeof(pv->id)) == 0) &&
53 ((pv->version == 1) || (pv->version == 2)))
54 {
55 /*
56 * looks like a physical volume header. Do the usual
57 * consistency checks.
58 */
59
60 if (pv->pv_size > LVM_MAX_SIZE)
61 return (1);
62 if ((pv->pv_status != 0) && (pv->pv_status != PV_ACTIVE))
63 return (1);
64 if ((pv->pv_allocatable != 0) && (pv->pv_allocatable != PV_ALLOCATABLE))
65 return (1);
66 if (pv->lv_cur > MAX_LV)
67 return (1);
68 if (strlen((char *)pv->vg_name) > NAME_LEN / 2)
69 return (1);
70
71 size = pv->pe_size / LVM_MIN_PE_SIZE * LVM_MIN_PE_SIZE;
72 if ((pv->pe_size != size) ||
73 (pv->pe_size < LVM_MIN_PE_SIZE) ||
74 (pv->pe_size > LVM_MAX_PE_SIZE))
75 return (1);
76
77 if (pv->pe_total > ( pv->pe_on_disk.size / sizeof ( disk_pe_t)))
78 return (1);
79 if (pv->pe_allocated > pv->pe_total)
80 return (1);
81
82 /*
83 * Ok.
84 */
85
86 m->m_guess = GM_YES;
87 pt->p_start = d->d_nsb;
88 s = pv->pv_size; s *= 512; s /= d->d_ssize;
89 pt->p_size = s;
90 pt->p_typ = 0x8E;
91 }
92
93 return (1);
94 }
0 /*
1 * gm_hmlvm.h -- gpart Linux LVM physical volume guessing module header
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 29.08.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _GM_HMLVM_H
17 #define _GM_HMLVM_H
18
19 /*
20 * structs & defines gathered from LVM 0.7/0.9 lvm.h and liblvm.h
21 */
22
23 #if !defined(__FreeBSD__)
24 typedef unsigned char uint8_t;
25 typedef unsigned short uint16_t;
26 typedef unsigned int uint32_t;
27 #endif
28
29
30 /*
31 * Status flags
32 */
33
34 /* physical volume */
35 #define PV_ACTIVE 0x01 /* pv_status */
36 #define PV_ALLOCATABLE 0x02 /* pv_allocatable */
37
38
39 #define LVM_PV_DISK_BASE 0L
40 #define LVM_PV_DISK_SIZE 1024L
41 #define NAME_LEN 128 /* don't change!!! */
42 #define UUID_LEN 16 /* don't change!!! */
43 #define LVM_MAX_SIZE ( 1024LU * 1024 * 1024 * 2) /* 1TB[sectors] */
44 #define LVM_ID "HM"
45 #define LVM_DIR_PREFIX "/dev/"
46 #define MAX_LV 256
47 #define LVM_MIN_PE_SIZE ( 8L * 2) /* 8 KB in sectors */
48 #define LVM_MAX_PE_SIZE ( 16L * 1024L * 1024L * 2) /* 16GB in sectors */
49
50 /* disk stored pe information */
51 typedef struct {
52 uint16_t lv_num;
53 uint16_t le_num;
54 } disk_pe_t;
55
56 /* disk stored PV, VG, LV and PE size and offset information */
57 typedef struct {
58 uint32_t base;
59 uint32_t size;
60 } lvm_disk_data_t;
61
62 /*
63 * Structure Physical Volume (PV) Version 2
64 */
65
66 /* disk */
67 typedef struct {
68 uint8_t id[2]; /* Identifier */
69 uint16_t version; /* HM lvm version */
70 lvm_disk_data_t pv_on_disk;
71 lvm_disk_data_t vg_on_disk;
72 lvm_disk_data_t pv_uuidlist_on_disk;
73 lvm_disk_data_t lv_on_disk;
74 lvm_disk_data_t pe_on_disk;
75 uint8_t pv_uuid[NAME_LEN];
76 uint8_t vg_name[NAME_LEN];
77 uint8_t system_id[NAME_LEN]; /* for vgexport/vgimport */
78 uint32_t pv_major;
79 uint32_t pv_number;
80 uint32_t pv_status;
81 uint32_t pv_allocatable;
82 uint32_t pv_size; /* HM */
83 uint32_t lv_cur;
84 uint32_t pe_size;
85 uint32_t pe_total;
86 uint32_t pe_allocated;
87 } pv_disk_v2_t;
88
89 #define pv_disk_t pv_disk_v2_t
90
91 #endif /* _GM_HMLVM_H */
0 /*
1 * gm_hpfs.c -- gpart hpfs guessing module
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified: 29.06.1999 <mb@ichabod.han.de>
13 * Made every disk read/write buffer aligned to pagesize.
14 *
15 *
16 */
17
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21 #include "gpart.h"
22 #include "gm_hpfs.h"
23
24 static const char rcsid[] = "$Id: gm_hpfs.c,v 1.8 2001/02/07 18:08:08 mb Exp mb $";
25
26 #define OS2SECTSIZE 512
27
28
29
30 int hpfs_init(disk_desc *d,g_module *m)
31 {
32 if ((d == 0) || (m == 0))
33 return (0);
34
35 m->m_desc = "OS/2 HPFS";
36 return (OS2SECTSIZE);
37 }
38
39
40
41 int hpfs_term(disk_desc *d)
42 {
43 return (1);
44 }
45
46
47
48 int hpfs_gfun(disk_desc *d,g_module *m)
49 {
50 struct hpfs_boot_block *bb = (struct hpfs_boot_block *)d->d_sbuf;
51 struct hpfs_super_block *sb;
52 s64_t s;
53 size_t psize;
54 byte_t *ubuf, *sbuf;
55
56 m->m_guess = GM_NO;
57 if ( (bb->sig_28h == 0x28) &&
58 (strncmp((char *)bb->sig_hpfs,"HPFS ",8) == 0) &&
59 (bb->magic == le16(0xaa55)) &&
60 (*(unsigned short *)bb->bytes_per_sector == le16(OS2SECTSIZE)))
61 {
62 /*
63 * looks like a hpfs boot sector. Test hpfs superblock
64 * at sector offset 16 (from start of partition).
65 */
66
67 if ((s = l64tell(d->d_fd)) == -1)
68 pr(FATAL,"hpfs: cannot seek: %s",strerror(errno));
69 s /= d->d_ssize; s -= d->d_nsb; s *= d->d_ssize;
70 if (l64seek(d->d_fd,16 * OS2SECTSIZE - s,SEEK_CUR) == -1)
71 pr(FATAL,"hpfs: cannot seek: %s",strerror(errno));
72
73 psize = getpagesize();
74 ubuf = alloc(OS2SECTSIZE + psize);
75 sbuf = align(ubuf,psize);
76 if (read(d->d_fd,sbuf,OS2SECTSIZE) != OS2SECTSIZE)
77 pr(FATAL,"hpfs: cannot read super block");
78 sb = (struct hpfs_super_block *)sbuf;
79 if (sb->magic != le32(SB_MAGIC))
80 goto out;
81
82 /*
83 * ok, fill in sizes.
84 */
85
86 s = sb->n_sectors;
87 s *= OS2SECTSIZE;
88 s /= d->d_ssize;
89 m->m_part.p_start = d->d_nsb;
90 m->m_part.p_size = s;
91 m->m_guess = GM_YES;
92 out:
93 free((void *)ubuf);
94 }
95 return (1);
96 }
0 /*
1 * gm_hpfs.h -- gpart hpfs guessing module header
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _GM_HPFS_H
17 #define _GM_HPFS_H
18
19
20 /*
21 * hpfs information/macros, taken from the Linux kernel sources.
22 */
23
24
25 /* Notation */
26
27 typedef unsigned secno; /* sector number, partition relative */
28
29 typedef secno dnode_secno; /* sector number of a dnode */
30 typedef secno fnode_secno; /* sector number of an fnode */
31 typedef secno anode_secno; /* sector number of an anode */
32
33
34
35 /* sector 0 */
36
37 /* The boot block is very like a FAT boot block, except that the
38 29h signature byte is 28h instead, and the ID string is "HPFS". */
39
40 struct hpfs_boot_block
41 {
42 unsigned char jmp[3];
43 unsigned char oem_id[8];
44 unsigned char bytes_per_sector[2]; /* 512 */
45 unsigned char sectors_per_cluster;
46 unsigned char n_reserved_sectors[2];
47 unsigned char n_fats;
48 unsigned char n_rootdir_entries[2];
49 unsigned char n_sectors_s[2];
50 unsigned char media_byte;
51 unsigned short sectors_per_fat;
52 unsigned short sectors_per_track;
53 unsigned short heads_per_cyl;
54 unsigned int n_hidden_sectors;
55 unsigned int n_sectors_l; /* size of partition */
56 unsigned char drive_number;
57 unsigned char mbz;
58 unsigned char sig_28h; /* 28h */
59 unsigned char vol_serno[4];
60 unsigned char vol_label[11];
61 unsigned char sig_hpfs[8]; /* "HPFS " */
62 unsigned char pad[448];
63 unsigned short magic; /* aa55 */
64 };
65
66
67 /* sector 16 */
68
69 /* The super block has the pointer to the root directory. */
70
71 #define SB_MAGIC 0xf995e849
72
73 struct hpfs_super_block
74 {
75 unsigned magic; /* f995 e849 */
76 unsigned magic1; /* fa53 e9c5, more magic? */
77 unsigned huh202; /* ?? 202 = N. of B. in 1.00390625 S.*/
78 fnode_secno root; /* fnode of root directory */
79 secno n_sectors; /* size of filesystem */
80 unsigned n_badblocks; /* number of bad blocks */
81 secno bitmaps; /* pointers to free space bit maps */
82 unsigned zero1; /* 0 */
83 secno badblocks; /* bad block list */
84 unsigned zero3; /* 0 */
85 time_t last_chkdsk; /* date last checked, 0 if never */
86 unsigned zero4; /* 0 */
87 secno n_dir_band; /* number of sectors in dir band */
88 secno dir_band_start; /* first sector in dir band */
89 secno dir_band_end; /* last sector in dir band */
90 secno dir_band_bitmap; /* free space map, 1 dnode per bit */
91 unsigned zero5[8]; /* 0 */
92 secno scratch_dnodes; /* ?? 8 preallocated sectors near dir
93 band, 4-aligned. */
94 unsigned zero6[103]; /* 0 */
95 };
96
97
98
99 #endif /* _GM_HPFS_H */
0 /*
1 * gm_lswap.c -- gpart linux swap guessing module
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified: 22.01.1999 <mb@ichabod.han.de>
13 * Calculation of old swap-partition was wrong.
14 *
15 */
16
17 #include <string.h>
18 #include "gpart.h"
19
20
21 static const char rcsid[] = "$Id: gm_lswap.c,v 1.8 2001/02/07 18:08:08 mb Exp mb $";
22 static char *sigs[] = { "SWAP-SPACE", "SWAPSPACE2" };
23 static int pszs[] = { 4096, 8192 };
24 static int siglen = 10;
25
26
27
28 int lswap_init(disk_desc *d,g_module *m)
29 {
30 if ((d == 0) || (m == 0))
31 return (0);
32
33 m->m_desc = "Linux swap";
34
35 /*
36 * return the max. pagesize of platforms running Linux.
37 * Seems to be 8k (Alpha).
38 */
39
40 return (8192);
41 }
42
43
44
45 int lswap_term(disk_desc *d)
46 {
47 return (1);
48 }
49
50
51
52 int lswap_gfun(disk_desc *d,g_module *m)
53 {
54 char *sig = 0;
55 int i, j, pagesize, vers;
56 byte_t *p, b;
57 s64_t np = 0;
58 dos_part_entry *pt = &m->m_part;
59
60 m->m_guess = GM_NO; pagesize = vers = 0;
61 for (i = 0; (pagesize == 0) && (i < sizeof(sigs)/sizeof(char *)); i++)
62 for (j = 0; j < sizeof(pszs)/sizeof(int); j++)
63 {
64 sig = (char *)(d->d_sbuf + pszs[j] - siglen);
65 if (strncmp(sig,sigs[i],siglen) == 0)
66 {
67 pagesize = pszs[j]; vers = i;
68 break;
69 }
70 }
71
72 if (pagesize == 0)
73 return (1);
74
75 if (vers == 0) /* old (<128mb) style swap */
76 {
77 if (*d->d_sbuf != 0xFE)
78 return (1);
79
80 for (p = (byte_t *)(sig - 1); p >= d->d_sbuf; p--)
81 if (*p)
82 break;
83 np = (p - d->d_sbuf) * 8;
84 for (b = *p; (b & 0x01) == 1; b >>= 1)
85 np++;
86 }
87 else if (vers == 1) /* Linux > 2.2.X swap partitions */
88 {
89 struct swapinfo
90 {
91 char bootbits[1024];
92 unsigned int version;
93 unsigned int last_page;
94 unsigned int nr_badpages;
95 unsigned int padding[125];
96 unsigned int badpages[1];
97 } *info = (struct swapinfo *)d->d_sbuf;
98
99 if (info->version != 1)
100 return (1);
101 np = 1 + info->last_page;
102 }
103 else
104 return (1);
105
106 if (np >= 10) /* mkswap(8) says this */
107 {
108 np *= pagesize; np /= d->d_ssize;
109 m->m_guess = GM_YES; pt->p_typ = 0x82;
110 pt->p_start = d->d_nsb; pt->p_size = np;
111 }
112 return (1);
113 }
0 /*
1 * gm_minix.c -- gpart minix guessing module
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #include "gpart.h"
17 #include "gm_minix.h"
18
19 static const char rcsid[] = "$Id: gm_minix.c,v 1.5 2001/02/07 18:08:08 mb Exp mb $";
20
21
22 int minix_init(disk_desc *d,g_module *m)
23 {
24 if ((d == 0) || (m == 0))
25 return (0);
26 m->m_desc = "Minix filesystem";
27 return (2 * BLOCK_SIZE);
28 }
29
30
31
32 int minix_term(disk_desc *d)
33 {
34 return (1);
35 }
36
37
38
39 int minix_gfun(disk_desc *d,g_module *m)
40 {
41 long version = 0;
42 struct minix_super_block *ms;
43 byte_t *p;
44 unsigned long zones, size;
45
46 ms = (struct minix_super_block *)(d->d_sbuf + BLOCK_SIZE);
47 m->m_guess = GM_NO;
48
49 if (ms->s_magic == le16(MINIX_SUPER_MAGIC))
50 version = MINIX_V1;
51 if (ms->s_magic == le16(MINIX_SUPER_MAGIC2))
52 version = MINIX_V1;
53 if (ms->s_magic == le16(MINIX2_SUPER_MAGIC))
54 version = MINIX_V2;
55 if (ms->s_magic == le16(MINIX2_SUPER_MAGIC2))
56 version = MINIX_V2;
57
58 if (version == 0)
59 return (1);
60 if ((ms->s_state != MINIX_VALID_FS) && (ms->s_state != MINIX_ERROR_FS))
61 return (1);
62
63 /*
64 * the rest of the disk block where the superblock
65 * was found should be zeroed out.
66 */
67
68 for (p = d->d_sbuf + BLOCK_SIZE + sizeof(struct minix_super_block);
69 p < d->d_sbuf + 2 * BLOCK_SIZE; p++)
70 if (*p)
71 return (1);
72
73 zones = (version == MINIX_V2) ? ms->s_zones : ms->s_nzones;
74 size = zones << ms->s_log_zone_size; size *= BLOCK_SIZE;
75
76 m->m_guess = GM_YES;
77 m->m_part.p_typ = (version == MINIX_V2) ? 0x81 : 0x80;
78 m->m_part.p_start = d->d_nsb;
79 m->m_part.p_size = size / d->d_ssize;
80
81 return (1);
82 }
0 /*
1 * gm_minix.h -- gpart minix guessing module header
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _GM_MINIX_H
17 #define _GM_MINIX_H
18
19
20 /*
21 * Minix filesystem structures, taken from the Linux kernel.
22 */
23
24
25 /* imported from asm/types.h */
26 typedef __signed__ char __s8;
27 typedef unsigned char __u8;
28
29 typedef __signed__ short __s16;
30 typedef unsigned short __u16;
31
32 typedef __signed__ int __s32;
33 typedef unsigned int __u32;
34
35
36 #define BLOCK_SIZE 1024
37 #define MINIX_ROOT_INO 1
38
39 /* Not the same as the bogus LINK_MAX in <linux/limits.h>. Oh well. */
40 #define MINIX_LINK_MAX 250
41 #define MINIX2_LINK_MAX 65530
42
43 #define MINIX_I_MAP_SLOTS 8
44 #define MINIX_Z_MAP_SLOTS 64
45 #define MINIX_SUPER_MAGIC 0x137F /* original minix fs */
46 #define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */
47 #define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */
48 #define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */
49 #define MINIX_VALID_FS 0x0001 /* Clean fs. */
50 #define MINIX_ERROR_FS 0x0002 /* fs has errors. */
51
52 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
53 #define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
54
55 #define MINIX_V1 0x0001 /* original minix fs */
56 #define MINIX_V2 0x0002 /* minix V2 fs */
57
58 #define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version
59
60 /*
61 * This is the original minix inode layout on disk.
62 * Note the 8-bit gid and atime and ctime.
63 */
64 struct minix_inode {
65 __u16 i_mode;
66 __u16 i_uid;
67 __u32 i_size;
68 __u32 i_time;
69 __u8 i_gid;
70 __u8 i_nlinks;
71 __u16 i_zone[9];
72 };
73
74 /*
75 * The new minix inode has all the time entries, as well as
76 * long block numbers and a third indirect block (7+1+1+1
77 * instead of 7+1+1). Also, some previously 8-bit values are
78 * now 16-bit. The inode is now 64 bytes instead of 32.
79 */
80 struct minix2_inode {
81 __u16 i_mode;
82 __u16 i_nlinks;
83 __u16 i_uid;
84 __u16 i_gid;
85 __u32 i_size;
86 __u32 i_atime;
87 __u32 i_mtime;
88 __u32 i_ctime;
89 __u32 i_zone[10];
90 };
91
92 /*
93 * minix super-block data on disk
94 */
95 struct minix_super_block {
96 __u16 s_ninodes;
97 __u16 s_nzones;
98 __u16 s_imap_blocks;
99 __u16 s_zmap_blocks;
100 __u16 s_firstdatazone;
101 __u16 s_log_zone_size;
102 __u32 s_max_size;
103 __u16 s_magic;
104 __u16 s_state;
105 __u32 s_zones;
106 };
107
108
109 #endif /* _GM_MINIX_H */
0 /*
1 * gm_ntfs.c -- gpart ntfs guessing module
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified: 26.02.2000 <mb@ichabod.han.de>
13 * Length of guessed partition incremented to include NT4 backup
14 * boot sector.
15 *
16 */
17
18 #include <stdlib.h>
19 #include <string.h>
20 #include "gpart.h"
21 #include "gm_ntfs.h"
22
23 static const char rcsid[] = "$Id: gm_ntfs.c,v 1.6 2001/02/07 18:08:08 mb Exp mb $";
24
25 #define NTFS_SECTSIZE 512
26
27 int ntfs_init(disk_desc *d,g_module *m)
28 {
29 if ((d == 0) || (m == 0))
30 return (0);
31
32 m->m_desc = "Windows NT/W2K FS";
33 m->m_hasptbl = 1;
34 return (NTFS_SECTSIZE); /* The ntfs driver in Linux just assumes so */
35 }
36
37
38
39 int ntfs_term(disk_desc *d)
40 {
41 return (1);
42 }
43
44
45
46 int ntfs_gfun(disk_desc *d,g_module *m)
47 {
48 int blocksize, clusterfactor, clustersize;
49 int mft_clusters_per_record;
50 s64_t size, ls;
51 byte_t *ubuf, *sbuf;
52
53
54 m->m_guess = GM_NO;
55 if (IS_NTFS_VOLUME(d->d_sbuf))
56 {
57 /*
58 * ntfs detection is quite weak, should come before
59 * fat or hpfs.
60 */
61
62 if (NTFS_GETU32(d->d_sbuf + 0x40) > 256UL)
63 return (1);
64 if (NTFS_GETU32(d->d_sbuf + 0x44) > 256UL)
65 return (1);
66
67 blocksize = NTFS_GETU16(d->d_sbuf + 0x0B);
68 clusterfactor = NTFS_GETU8(d->d_sbuf + 0x0D);
69 clustersize = blocksize * clusterfactor;
70 mft_clusters_per_record = NTFS_GETS8(d->d_sbuf + 0x40);
71 if ((mft_clusters_per_record < 0) && (mft_clusters_per_record != -10))
72 return (1);
73 size = NTFS_GETU64(d->d_sbuf + 0x28);
74
75 size /= clusterfactor;
76 size *= clustersize;
77 size /= d->d_ssize;
78
79 /*
80 * look for an additional backup boot sector at the end of
81 * this FS (NT4 puts this backup sector after the FS, this
82 * sector must be counted).
83 */
84
85 ls = d->d_nsb + size; ls *= d->d_ssize;
86 if (l64seek(d->d_fd,ls,SEEK_SET) >= 0)
87 {
88 ubuf = alloc(NTFS_SECTSIZE + getpagesize());
89 sbuf = align(ubuf,getpagesize());
90 if (read(d->d_fd,sbuf,NTFS_SECTSIZE) != NTFS_SECTSIZE)
91 pr(FATAL,"ntfs: cannot read backup boot sector");
92 if (memcmp(d->d_sbuf,sbuf,NTFS_SECTSIZE) == 0)
93 size += 1;
94 free((void *)ubuf);
95 }
96
97 m->m_part.p_start = d->d_nsb;
98 m->m_part.p_size = (unsigned long)size;
99 m->m_part.p_typ = 0x07;
100 m->m_guess = GM_YES;
101 }
102 return (1);
103 }
0 /*
1 * gm_ntfs.h -- gpart ntfs guessing module header
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _GM_NTFS_H
17 #define _GM_NTFS_H
18
19 /*
20 * ntfs information/macros, taken from the Linux kernel sources.
21 */
22
23 #define IS_MAGIC(a,b) (*(int*)(a)==*(int*)(b))
24 #define IS_MFT_RECORD(a) IS_MAGIC((a),"FILE")
25 #define IS_NTFS_VOLUME(a) IS_MAGIC((a)+3,"NTFS")
26 #define IS_INDEX_RECORD(a) IS_MAGIC((a),"INDX")
27
28 /* 'NTFS' in little endian */
29 #define NTFS_SUPER_MAGIC 0x5346544E
30
31 #if defined(i386) || defined(__i386__) || defined(__alpha__)
32
33 /* unsigned integral types */
34 #ifndef NTFS_INTEGRAL_TYPES
35 #define NTFS_INTEGRAL_TYPES
36 typedef unsigned char ntfs_u8;
37 typedef unsigned short ntfs_u16;
38 typedef unsigned int ntfs_u32;
39 typedef s64_t ntfs_u64;
40 #endif /* NTFS_INTEGRAL_TYPES */
41 #endif /* defined(i386) || defined(__i386__) || defined(__alpha__) */
42
43
44 /* Macros reading unsigned integers from a byte pointer */
45 /* these should work for all little endian machines */
46 #define NTFS_GETU8(p) (*(ntfs_u8*)(p))
47 #define NTFS_GETU16(p) (*(ntfs_u16*)(p))
48 #define NTFS_GETU24(p) (NTFS_GETU32(p) & 0xFFFFFF)
49 #define NTFS_GETU32(p) (*(ntfs_u32*)(p))
50 #define NTFS_GETU64(p) (*(ntfs_u64*)(p))
51
52 /* Macros reading signed integers, returning int */
53 #define NTFS_GETS8(p) ((int)(*(char*)(p)))
54 #define NTFS_GETS16(p) ((int)(*(short*)(p)))
55 #define NTFS_GETS24(p) (NTFS_GETU24(p) < 0x800000 ? (int)NTFS_GETU24(p) :
56
57
58
59 #endif /* _GM_NTFS_H */
0 /*
1 * gm_qnx4.c -- gpart qnx4 guessing module
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.2001 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include "gpart.h"
20 #include "gm_qnx4.h"
21
22 #include <stdio.h>
23
24 static const char rcsid[] = "$Id: gm_qnx4.c,v 1.1 2001/01/29 17:11:34 mb Exp mb $";
25
26
27 int qnx4_init(disk_desc *d,g_module *m)
28 {
29 if ((d == 0) || (m == 0))
30 return (0);
31 m->m_desc = "QNX4 filesystem";
32 m->m_notinext = 1;
33 return (2 * QNX4_BLOCK_SIZE);
34 }
35
36
37
38 int qnx4_term(disk_desc *d)
39 {
40 return (1);
41 }
42
43
44
45 int qnx4_gfun(disk_desc *d,g_module *m)
46 {
47 struct qnx4_super_block *sb;
48 struct qnx4_inode_entry *rootdir, bitmap;
49 int rd, rl, i, j, psize, found;
50 s64_t ls, ofs, size;
51 byte_t *ubuf, *sbuf;
52
53 m->m_guess = GM_NO;
54
55 /*
56 * check QNX signature
57 */
58
59 if (memcmp(d->d_sbuf + 4,QNX4_BOOTSECT_SIG,strlen(QNX4_BOOTSECT_SIG)))
60 return (1);
61 sb = (struct qnx4_super_block *)(d->d_sbuf + QNX4_BLOCK_SIZE);
62 if (*sb->RootDir.di_fname != '/')
63 return (1);
64
65 /*
66 * read root directory
67 */
68
69 psize = getpagesize();
70 ubuf = alloc(QNX4_BLOCK_SIZE + psize);
71 sbuf = align(ubuf,psize);
72
73 found = 0;
74
75 rd = le32(sb->RootDir.di_first_xtnt.xtnt_blk) - 1;
76 rl = le32(sb->RootDir.di_first_xtnt.xtnt_size);
77
78 for (j = 0; j < rl; j++)
79 {
80 if ((ls = l64tell(d->d_fd)) == -1)
81 pr(FATAL,"qnx4: cannot seek: %s",strerror(errno));
82 ls /= d->d_ssize; ls -= d->d_nsb; ls *= d->d_ssize;
83 ofs = rd + j; ofs *= QNX4_BLOCK_SIZE;
84 if (l64seek(d->d_fd,ofs - ls,SEEK_CUR) == -1)
85 pr(FATAL,"qnx4: cannot seek: %s",strerror(errno));
86 if (read(d->d_fd,sbuf,QNX4_BLOCK_SIZE) != QNX4_BLOCK_SIZE)
87 pr(FATAL,"qnx4: cannot read root dir entry");
88
89 /*
90 * find the ".bitmap" entry
91 */
92
93 for (i = 0; i < QNX4_INODES_PER_BLOCK; i++)
94 {
95 rootdir = (struct qnx4_inode_entry *) (sbuf + i * QNX4_DIR_ENTRY_SIZE);
96 if (rootdir->di_fname && !strncmp(rootdir->di_fname,QNX4_BITMAP_NAME,strlen(QNX4_BITMAP_NAME)))
97 {
98 memcpy(&bitmap,rootdir,sizeof(struct qnx4_inode_entry));
99 found = 1;
100 }
101 }
102 }
103
104 if (! found)
105 return (1);
106
107 size = le32(bitmap.di_size) * 8 - 6;
108 size *= QNX4_BLOCK_SIZE;
109 size /= d->d_ssize;
110
111 m->m_guess = GM_YES;
112 m->m_part.p_typ = 0x4F;
113 m->m_part.p_start = d->d_nsb;
114 m->m_part.p_size = size;
115
116 free((void *)ubuf);
117 return (1);
118 }
0 /*
1 * gm_qnx4.h -- gpart qnx4 guessing module header
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.2001 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _GM_QNX4_H
17 #define _GM_QNX4_H
18
19 /* imported from asm/types.h */
20 typedef __signed__ char __s8;
21 typedef unsigned char __u8;
22
23 typedef __signed__ short __s16;
24 typedef unsigned short __u16;
25
26 typedef __signed__ int __s32;
27 typedef unsigned int __u32;
28
29
30 #define QNX4_BOOTSECT_SIG "QNX4FS"
31 #define QNX4_BITMAP_NAME ".bitmap"
32
33 /*
34 * QNX4 filesystem structures, taken from the Linux kernel.
35 */
36
37 #define QNX4_VALID_FS 0x0001 /* Clean fs. */
38 #define QNX4_ERROR_FS 0x0002 /* fs has errors. */
39 #define QNX4_BLOCK_SIZE 0x200 /* blocksize of 512 bytes */
40 #define QNX4_INODES_PER_BLOCK 0x08 /* 512 / 64 */
41 #define QNX4_DIR_ENTRY_SIZE 0x040 /* dir entry size of 64 bytes */
42
43 /* for filenames */
44 #define QNX4_SHORT_NAME_MAX 16
45 #define QNX4_NAME_MAX 48
46
47 typedef __u16 qnx4_nxtnt_t;
48 typedef __u8 qnx4_ftype_t;
49
50 typedef struct {
51 __u32 xtnt_blk;
52 __u32 xtnt_size;
53 } qnx4_xtnt_t;
54
55 typedef __u16 qnx4_mode_t;
56 typedef __u16 qnx4_muid_t;
57 typedef __u16 qnx4_mgid_t;
58 typedef __u32 qnx4_off_t;
59 typedef __u16 qnx4_nlink_t;
60
61 /*
62 * This is the original qnx4 inode layout on disk.
63 */
64 struct qnx4_inode_entry {
65 char di_fname[QNX4_SHORT_NAME_MAX];
66 qnx4_off_t di_size;
67 qnx4_xtnt_t di_first_xtnt;
68 __u32 di_xblk;
69 __s32 di_ftime;
70 __s32 di_mtime;
71 __s32 di_atime;
72 __s32 di_ctime;
73 qnx4_nxtnt_t di_num_xtnts;
74 qnx4_mode_t di_mode;
75 qnx4_muid_t di_uid;
76 qnx4_mgid_t di_gid;
77 qnx4_nlink_t di_nlink;
78 __u8 di_zero[4];
79 qnx4_ftype_t di_type;
80 __u8 di_status;
81 };
82
83 struct qnx4_super_block {
84 struct qnx4_inode_entry RootDir;
85 struct qnx4_inode_entry Inode;
86 struct qnx4_inode_entry Boot;
87 struct qnx4_inode_entry AltBoot;
88 };
89
90
91 #endif /* _GM_QNX4_H */
0 /*
1 * gm_rfs.c -- gpart ReiserFS guessing module
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 21.01.1999 <mb@ichabod.han.de>
12 * Modified: 26.12.2000 Francis Devereux <francis@devereux.tc>
13 * Added reiserfs 3.5.28 support.
14 *
15 */
16
17 #include <string.h>
18 #include <errno.h>
19 #include "gpart.h"
20 #include "gm_rfs.h"
21
22 static const char rcsid[] = "$Id: gm_rfs.c,v 1.5 2001/02/07 18:08:08 mb Exp mb $";
23
24
25 int rfs_init(disk_desc *d,g_module *m)
26 {
27 if ((d == 0) || (m == 0))
28 return (0);
29
30 m->m_desc = "Reiser filesystem";
31 return (REISERFS_FIRST_BLOCK * 1024 + SB_SIZE);
32 }
33
34
35
36 int rfs_term(disk_desc *d)
37 {
38 return (1);
39 }
40
41
42
43 int rfs_gfun(disk_desc *d,g_module *m)
44 {
45 struct reiserfs_super_block *sb;
46 dos_part_entry *pt = &m->m_part;
47 s64_t size;
48
49 m->m_guess = GM_NO;
50 sb = (struct reiserfs_super_block *)(d->d_sbuf + REISERFS_FIRST_BLOCK * 1024);
51 if (strncmp(sb->s_magic,REISERFS_SUPER_MAGIC,12) == 0)
52 {
53 /*
54 * sanity checks.
55 */
56
57 if (sb->s_block_count < sb->s_free_blocks)
58 return (1);
59
60 if (sb->s_block_count < REISERFS_MIN_BLOCK_AMOUNT)
61 return (1);
62
63 if ((sb->s_state != REISERFS_VALID_FS) &&
64 (sb->s_state != REISERFS_ERROR_FS))
65 return (1);
66
67 if (sb->s_oid_maxsize % 2) /* must be even */
68 return (1);
69
70 if (sb->s_oid_maxsize < sb->s_oid_cursize)
71 return (1);
72
73 if ((sb->s_blocksize != 4096) && (sb->s_blocksize != 8192))
74 return (1);
75
76 /*
77 * ok.
78 */
79
80 m->m_guess = GM_YES;
81 pt->p_start = d->d_nsb;
82 size = sb->s_block_count; size *= sb->s_blocksize; size /= d->d_ssize;
83 pt->p_size = (unsigned long)size;
84 pt->p_typ = 0x83;
85 }
86 return (1);
87 }
0 /*
1 * gm_rfs.h -- gpart ReiserFS guessing module header
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 21.01.1999 <mb@ichabod.han.de>
12 * Modified: 26.12.2000 Francis Devereux <francis@devereux.tc>
13 * Update support reiserfs version 3.5.28
14 *
15 */
16
17 #ifndef _GM_RFS_H
18 #define _GM_RFS_H
19
20 /* imported from asm/types.h */
21 typedef __signed__ char __s8;
22 typedef unsigned char __u8;
23
24 typedef __signed__ short __s16;
25 typedef unsigned short __u16;
26
27 typedef __signed__ int __s32;
28 typedef unsigned int __u32;
29
30 /*
31 * taken from ReiserFS v3.5.28. Reiserfs Copyright 1996-2000 Hans Reiser
32 */
33
34 #define REISERFS_SUPER_MAGIC "ReIsErFs"
35 #define REISERFS_FIRST_BLOCK 64
36 #define REISERFS_VALID_FS 1
37 #define REISERFS_ERROR_FS 2
38 #define REISERFS_MIN_BLOCK_AMOUNT 100
39
40 struct reiserfs_super_block
41 {
42 __u32 s_block_count; /* blocks count */
43 __u32 s_free_blocks; /* free blocks count */
44 __u32 s_root_block; /* root block number */
45 __u32 s_journal_block; /* journal block number */
46 __u32 s_journal_dev; /* journal device number */
47 __u32 s_orig_journal_size; /* size of the journal on FS creation. used to make sure they don't overflow it */
48 __u32 s_journal_trans_max; /* max number of blocks in a transaction. */
49 __u32 s_journal_block_count; /* total size of the journal. can change over time */
50 __u32 s_journal_max_batch; /* max number of blocks to batch into a trans */
51 __u32 s_journal_max_commit_age; /* in seconds, how old can an async commit be */
52 __u32 s_journal_max_trans_age; /* in seconds, how old can a transaction be */
53 __u16 s_blocksize; /* block size */
54 __u16 s_oid_maxsize; /* max size of object id array, see get_objectid() commentary */
55 __u16 s_oid_cursize; /* current size of object id array */
56 __u16 s_state; /* valid or error */
57 char s_magic[12]; /* reiserfs magic string indicates that file system is reiserfs */
58 __u32 s_hash_function_code; /* indicate, what hash fuction is being use to sort names in a directory*/
59 __u16 s_tree_height; /* height of disk tree */
60 __u16 s_bmap_nr; /* amount of bitmap blocks needed to address each block of file system */
61 __u16 s_reserved;
62 };
63
64 #define SB_SIZE (sizeof(struct reiserfs_super_block))
65
66
67 #endif /* _GM_RFS_H */
0 /*
1 * gm_s86dl.c -- gpart solaris/x86 disklabel guessing module
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #include "gpart.h"
17 #include "gm_s86dl.h"
18
19 static const char rcsid[] = "$Id: gm_s86dl.c,v 1.6 2001/02/07 18:08:08 mb Exp mb $";
20
21
22 int s86dl_init(disk_desc *d,g_module *m)
23 {
24 if ((d == 0) || (m == 0))
25 return (0);
26 m->m_desc = "Solaris/x86 disklabel";
27 m->m_notinext = 1;
28 return (512 + sizeof(struct solaris_x86_vtoc));
29 }
30
31
32
33 int s86dl_term(disk_desc *d)
34 {
35 return (1);
36 }
37
38
39
40 int s86dl_gfun(disk_desc *d,g_module *m)
41 {
42 struct solaris_x86_vtoc *svtoc;
43 struct solaris_x86_slice *ws = 0, *rs = 0;
44 int i;
45
46 m->m_guess = GM_NO;
47 svtoc = (struct solaris_x86_vtoc *)(d->d_sbuf + 512);
48 if ((svtoc->v_sanity != SOLARIS_X86_VTOC_SANE) ||
49 (svtoc->v_version != SOLARIS_X86_V_VERSION))
50 return (1);
51
52 for (i = 0; i < SOLARIS_X86_NUMSLICE; i++)
53 switch (svtoc->v_slice[i].s_tag)
54 {
55 case SOLARIS_X86_V_ROOT :
56 rs = &svtoc->v_slice[i];
57 break;
58 case SOLARIS_X86_V_BACKUP :
59 ws = &svtoc->v_slice[i];
60 break;
61 }
62
63 /*
64 * some simple sanity checks.
65 */
66
67 if ((ws == 0) || (rs == 0))
68 return (1);
69 if (svtoc->v_sectorsz != d->d_ssize)
70 return (1);
71 if (d->d_nsb + ws->s_start + ws->s_size > d->d_nsecs)
72 return (1);
73 if (d->d_nsb + rs->s_start + rs->s_size > d->d_nsecs)
74 return (1);
75 if ((rs->s_start < ws->s_start) || (rs->s_size > ws->s_size))
76 return (1);
77 if (ws->s_flag && (ws->s_flag != SOLARIS_X86_V_UNMNT) &&
78 (ws->s_flag != SOLARIS_X86_V_RONLY))
79 return (1);
80 if (rs->s_flag && (rs->s_flag != SOLARIS_X86_V_UNMNT) &&
81 (rs->s_flag != SOLARIS_X86_V_RONLY))
82 return (1);
83
84 /*
85 * If the recognition of the solaris vtoc isn't
86 * enough, I'll have to read a ufs sb, but for
87 * now the vtoc must suffice.
88 */
89
90 m->m_part.p_typ = 0x82;
91 m->m_part.p_start = d->d_nsb + le32(ws->s_start);
92 m->m_part.p_size = le32(ws->s_size);
93 m->m_guess = GM_YES;
94
95 return (1);
96 }
0 /*
1 * gm_s86dl.h -- gpart solaris/x86 disklabel guessing module header
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _GM_S86DL_H
17 #define _GM_S86DL_H
18
19
20 #define SOLARIS_X86_NUMSLICE 8
21 #define SOLARIS_X86_VTOC_SANE (0x600DDEEEUL)
22 #define SOLARIS_X86_V_VERSION (0x01)
23 #define SOLARIS_X86_V_UNASSIGNED 0x00 /* unassigned partition */
24 #define SOLARIS_X86_V_BOOT 0x01 /* Boot partition */
25 #define SOLARIS_X86_V_ROOT 0x02 /* Root filesystem */
26 #define SOLARIS_X86_V_SWAP 0x03 /* Swap filesystem */
27 #define SOLARIS_X86_V_USR 0x04 /* Usr filesystem */
28 #define SOLARIS_X86_V_BACKUP 0x05 /* full disk */
29 #define SOLARIS_X86_V_STAND 0x06 /* Stand partition */
30 #define SOLARIS_X86_V_VAR 0x07 /* Var partition */
31 #define SOLARIS_X86_V_HOME 0x08 /* Home partition */
32 #define SOLARIS_X86_V_ALTSCTR 0x09 /* Alternate sector partition */
33 #define SOLARIS_X86_V_CACHE 0x0a /* Cache (cachefs) partition */
34 #define SOLARIS_X86_V_UNMNT 0x01 /* Unmountable partition */
35 #define SOLARIS_X86_V_RONLY 0x10 /* Read only */
36
37
38
39 struct solaris_x86_slice {
40 ushort s_tag; /* ID tag of partition */
41 ushort s_flag; /* permision flags */
42 daddr_t s_start; /* start sector no of partition */
43 long s_size; /* # of blocks in partition */
44 };
45
46 struct solaris_x86_vtoc {
47 unsigned long v_bootinfo[3]; /* info needed by mboot (unsupported) */
48 unsigned long v_sanity; /* to verify vtoc sanity */
49 unsigned long v_version; /* layout version */
50 char v_volume[8]; /* volume name */
51 ushort v_sectorsz; /* sector size in bytes */
52 ushort v_nparts; /* number of partitions */
53 unsigned long v_reserved[10]; /* free space */
54 struct solaris_x86_slice
55 v_slice[SOLARIS_X86_NUMSLICE]; /* slice headers */
56 time_t timestamp[SOLARIS_X86_NUMSLICE]; /* timestamp (unsupported) */
57 char v_asciilabel[128]; /* for compatibility */
58 };
59
60
61 #endif /* _GM_S86DL_H */
0 /*
1 * gm_xfs.c -- gpart SGI xfs guessing module
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 30.01.2001 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #include <string.h>
17 #include "gpart.h"
18 #include "gm_xfs.h"
19
20 static const char rcsid[] = "$Id: gm_xfs.c,v 1.1 2001/02/07 18:08:08 mb Exp mb $";
21
22
23 int xfs_init(disk_desc *d,g_module *m)
24 {
25 if ((d == 0) || (m == 0))
26 return (0);
27
28 m->m_desc = "SGI XFS filesystem";
29 return (512);
30 }
31
32
33
34 int xfs_term(disk_desc *d)
35 {
36 return (1);
37 }
38
39
40
41 int xfs_gfun(disk_desc *d,g_module *m)
42 {
43 xfs_sb_t *sb;
44 s64_t size;
45
46 m->m_guess = GM_NO;
47 sb = (xfs_sb_t *)d->d_sbuf;
48
49 /*
50 * Sanity checks from xfs_mount.c
51 */
52
53 if (be32(sb->sb_magicnum) != XFS_SB_MAGIC)
54 return (1);
55
56 if (be32(sb->sb_blocksize) != getpagesize())
57 return (1);
58
59 if ((sb->sb_imax_pct > 100) || (sb->sb_sectsize <= 0))
60 return (1);
61
62 if ((be16(sb->sb_inodesize) < XFS_DINODE_MIN_SIZE) ||
63 (be16(sb->sb_inodesize) > XFS_DINODE_MAX_SIZE))
64 return (1);
65
66 if (be32(sb->sb_blocksize) != 1 << sb->sb_blocklog)
67 return (1);
68
69 size = be64(sb->sb_logstart) ? (s64_t)be32(sb->sb_logblocks) : 0LL;
70 size = be64(sb->sb_dblocks) - size;
71 size *= be32(sb->sb_blocksize);
72 size /= d->d_ssize;
73
74 m->m_guess = GM_YES;
75 m->m_part.p_start = d->d_nsb;
76 m->m_part.p_size = (unsigned long)size;
77 m->m_part.p_typ = 0x83;
78
79 return (1);
80 }
0 /*
1 * gm_xfs.h -- gpart SGI xfs guessing module header
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 30.01.2001 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _GM_XFS_H
17 #define _GM_XFS_H
18
19 /* imported from asm/types.h */
20 typedef __signed__ char __s8;
21 typedef unsigned char __u8;
22
23 typedef __signed__ short __s16;
24 typedef unsigned short __u16;
25
26 typedef __signed__ int __s32;
27 typedef unsigned int __u32;
28
29 typedef __signed__ long long int __s64;
30 typedef unsigned long long int __u64;
31
32 /*
33 * Taken from SGI's Jan192001prerelease.patch for Linux kernel 2.4.0
34 */
35
36 typedef __u32 xfs_agblock_t; /* blockno in alloc. group */
37 typedef __u32 xfs_extlen_t; /* extent length in blocks */
38 typedef __u32 xfs_agnumber_t; /* allocation group number */
39 typedef __s32 xfs_extnum_t; /* # of extents in a file */
40 typedef __s16 xfs_aextnum_t; /* # extents in an attribute fork */
41 typedef __s64 xfs_fsize_t; /* bytes in a file */
42 typedef __u64 xfs_ufsize_t; /* unsigned bytes in a file */
43
44 typedef __s32 xfs_suminfo_t; /* type of bitmap summary info */
45 typedef __s32 xfs_rtword_t; /* word type for bitmap manipulations */
46
47 typedef __s64 xfs_lsn_t; /* log sequence number */
48 typedef __s32 xfs_tid_t; /* transaction identifier */
49
50 typedef __u32 xfs_dablk_t; /* dir/attr block number (in file) */
51 typedef __u32 xfs_dahash_t; /* dir/attr hash value */
52
53 typedef __u16 xfs_prid_t; /* prid_t truncated to 16bits in XFS */
54
55 /*
56 * These types are 64 bits on disk but are either 32 or 64 bits in memory.
57 * Disk based types:
58 */
59 typedef __u64 xfs_dfsbno_t; /* blockno in filesystem (agno|agbno) */
60 typedef __u64 xfs_drfsbno_t; /* blockno in filesystem (raw) */
61 typedef __u64 xfs_drtbno_t; /* extent (block) in realtime area */
62 typedef __u64 xfs_dfiloff_t; /* block number in a file */
63 typedef __u64 xfs_dfilblks_t; /* number of blocks in a file */
64
65 typedef __u64 xfs_off_t;
66 typedef __s32 xfs32_off_t;
67 typedef __u64 xfs_ino_t; /* <inode> type */
68 typedef __s32 xfs_daddr_t; /* <disk address> type */
69 typedef char * xfs_caddr_t; /* <core address> type */
70 typedef __u32 xfs_dev_t;
71
72 typedef struct {
73 unsigned char __u_bits[16];
74 } uuid_t;
75
76 #define XFS_SB_MAGIC 0x58465342 /* 'XFSB' */
77 #define XFS_SB_VERSION_1 1 /* 5.3, 6.0.1, 6.1 */
78 #define XFS_SB_VERSION_2 2 /* 6.2 - attributes */
79 #define XFS_SB_VERSION_3 3 /* 6.2 - new inode version */
80 #define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */
81
82 /*
83 * Inode minimum and maximum sizes.
84 */
85 #define XFS_DINODE_MIN_LOG 8
86 #define XFS_DINODE_MAX_LOG 11
87 #define XFS_DINODE_MIN_SIZE (1 << XFS_DINODE_MIN_LOG)
88 #define XFS_DINODE_MAX_SIZE (1 << XFS_DINODE_MAX_LOG)
89
90 typedef struct xfs_sb
91 {
92 __u32 sb_magicnum; /* magic number == XFS_SB_MAGIC */
93 __u32 sb_blocksize; /* logical block size, bytes */
94 xfs_drfsbno_t sb_dblocks; /* number of data blocks */
95 xfs_drfsbno_t sb_rblocks; /* number of realtime blocks */
96 xfs_drtbno_t sb_rextents; /* number of realtime extents */
97 uuid_t sb_uuid; /* file system unique id */
98 xfs_dfsbno_t sb_logstart; /* starting block of log if internal */
99 xfs_ino_t sb_rootino; /* root inode number */
100 xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */
101 xfs_ino_t sb_rsumino; /* summary inode for rt bitmap */
102 xfs_agblock_t sb_rextsize; /* realtime extent size, blocks */
103 xfs_agblock_t sb_agblocks; /* size of an allocation group */
104 xfs_agnumber_t sb_agcount; /* number of allocation groups */
105 xfs_extlen_t sb_rbmblocks; /* number of rt bitmap blocks */
106 xfs_extlen_t sb_logblocks; /* number of log blocks */
107 __u16 sb_versionnum; /* header version == XFS_SB_VERSION */
108 __u16 sb_sectsize; /* volume sector size, bytes */
109 __u16 sb_inodesize; /* inode size, bytes */
110 __u16 sb_inopblock; /* inodes per block */
111 char sb_fname[12]; /* file system name */
112 __u8 sb_blocklog; /* log2 of sb_blocksize */
113 __u8 sb_sectlog; /* log2 of sb_sectsize */
114 __u8 sb_inodelog; /* log2 of sb_inodesize */
115 __u8 sb_inopblog; /* log2 of sb_inopblock */
116 __u8 sb_agblklog; /* log2 of sb_agblocks (rounded up) */
117 __u8 sb_rextslog; /* log2 of sb_rextents */
118 __u8 sb_inprogress; /* mkfs is in progress, don't mount */
119 __u8 sb_imax_pct; /* max % of fs for inode space */
120 /* statistics */
121 /*
122 * These fields must remain contiguous. If you really
123 * want to change their layout, make sure you fix the
124 * code in xfs_trans_apply_sb_deltas().
125 */
126 __u64 sb_icount; /* allocated inodes */
127 __u64 sb_ifree; /* free inodes */
128 __u64 sb_fdblocks; /* free data blocks */
129 __u64 sb_frextents; /* free realtime extents */
130 /*
131 * End contiguous fields.
132 */
133 xfs_ino_t sb_uquotino; /* user quota inode */
134 xfs_ino_t sb_pquotino; /* project quota inode */
135 __u16 sb_qflags; /* quota flags */
136 __u8 sb_flags; /* misc. flags */
137 __u8 sb_shared_vn; /* shared version number */
138 xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */
139 __u32 sb_unit; /* stripe or raid unit */
140 __u32 sb_width; /* stripe or raid width */
141 __u8 sb_dirblklog; /* log2 of dir block size (fsbs) */
142 __u8 sb_dummy[7]; /* padding */
143 } xfs_sb_t;
144
145 #endif /* _GM_XFS_H */
0 /*
1 * gmodules.c -- gpart module functions
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified: 29.01.2001 <mb@ichabod.han.de>
13 * New modules: qnx & beos.
14 *
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <dlfcn.h>
21 #include "gpart.h"
22
23
24 static g_module *g_head;
25 static int g_count;
26
27
28
29 g_module *g_mod_head()
30 {
31 return (g_head);
32 }
33
34
35
36 int g_mod_count()
37 {
38 return (g_count);
39 }
40
41
42
43 void g_mod_list()
44 {
45 g_module *m;
46
47 pr(MSG,"Module\tWeight\n");
48 for (m = g_head; m; m = m->m_next)
49 pr(MSG,"%s\t(%3.1f)\n",m->m_name,m->m_weight);
50 pr(MSG,"\n");
51 }
52
53
54
55 void g_mod_delete(g_module *m)
56 {
57 if (m)
58 {
59 if (m->m_hd) dlclose(m->m_hd);
60 if (m->m_name) free((void *)m->m_name);
61 free(m);
62 g_count--;
63 }
64 }
65
66
67
68 void g_mod_deleteall()
69 {
70 g_module *m;
71
72 while (g_head)
73 {
74 m = g_head->m_next; g_mod_delete(g_head); g_head = m;
75 }
76 }
77
78
79
80 /*
81 * set weight of module and re-insert as head.
82 */
83
84 g_module *g_mod_setweight(char *name,float weight)
85 {
86 g_module *m, *prev = 0;
87
88 for (m = g_head; m; m = m->m_next)
89 if (strcmp(m->m_name,name) == 0)
90 break;
91 else
92 prev = m;
93 if (m == 0)
94 return (0);
95 if (prev)
96 {
97 prev->m_next = m->m_next;
98 m->m_next = g_head;
99 g_head = m;
100 }
101 g_head->m_weight = weight;
102 return (g_head);
103 }
104
105
106
107 g_module *g_mod_lookup(int how,char *name)
108 {
109 g_module *m;
110
111 if (g_head == 0)
112 {
113 if (how == GM_LOOKUP)
114 return (0);
115 g_head = (g_module *)alloc(sizeof(g_module));
116 m = g_head;
117 }
118 else
119 {
120 for (m = g_head; m->m_next; m = m->m_next)
121 if (strcmp(m->m_name,name) == 0)
122 return (m);
123 if (how == GM_LOOKUP)
124 return (0);
125 m->m_next = (g_module *)alloc(sizeof(g_module));
126 m = m->m_next;
127 }
128 if ((m->m_name = strdup(name)) == 0)
129 pr(FATAL,"out of memory in strdup");
130 m->m_weight = 1.0; g_count++;
131 return (m);
132 }
133
134
135
136 /*
137 * preloaded modules
138 */
139
140 void g_mod_addinternals()
141 {
142 g_module *m;
143
144 #define GMODINS(mod) if(!(m = g_mod_lookup(GM_INSERT,#mod))->m_hd){ \
145 m->m_init=mod##_init; m->m_term=mod##_term; \
146 m->m_gfun=mod##_gfun; }
147
148 /*
149 * If no weights are given on the command line, the order
150 * is somehow important.
151 */
152
153 GMODINS(bsddl);
154 GMODINS(lswap);
155 GMODINS(qnx4);
156 GMODINS(rfs);
157 GMODINS(ntfs);
158 GMODINS(hpfs);
159 GMODINS(minix);
160 GMODINS(beos);
161 GMODINS(ext2);
162 GMODINS(fat);
163 GMODINS(s86dl);
164 GMODINS(hmlvm);
165 GMODINS(xfs);
166 }
167
168
169
170 int g_mod_addexternal(char *name)
171 {
172 g_module *m;
173 char buf[FILENAME_MAX];
174
175 /*
176 * external modules are named 'gm_' name '.so', and will
177 * be searched in the standard ld.so library directories
178 * or those explicitly given by LD_LIBRARY_PATH.
179 */
180
181 snprintf(buf,FILENAME_MAX-1,"gm_%s.so",name);
182 buf[FILENAME_MAX-1] = 0;
183
184 m = g_mod_lookup(GM_INSERT,name);
185 if (m->m_hd)
186 dlclose(m->m_hd);
187
188 if ((m->m_hd = dlopen(buf,RTLD_NOW)) == 0)
189 pr(FATAL,(char *)dlerror());
190
191 snprintf(buf,FILENAME_MAX-1,"%s_init",name);
192 m->m_init = (int (*)())dlsym(m->m_hd,buf);
193 snprintf(buf,FILENAME_MAX-1,"%s_term",name);
194 m->m_term = (int (*)())dlsym(m->m_hd,buf);
195 snprintf(buf,FILENAME_MAX-1,"%s_gfun",name);
196 m->m_gfun = (int (*)())dlsym(m->m_hd,buf);
197 if ((m->m_gfun == 0))
198 pr(FATAL,"module %s: missing vital functions",name);
199
200 return (1);
201 }
0 /*
1 * gmodules.h -- gpart module header file
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified: 29.01.2001 <mb@ichabod.han.de>
13 * New modules: qnx & beos.
14 *
15 */
16
17 #ifndef _GMODULES_H
18 #define _GMODULES_H
19
20
21 #define GM_NO (0.0) /* predefined probabilities */
22 #define GM_PERHAPS (0.5)
23 #define GM_YES (0.8)
24 #define GM_UNDOUBTEDLY (1.0)
25
26 typedef struct g_mod
27 {
28 char *m_name; /* name of module */
29 char *m_desc; /* readable description */
30 int (*m_init)(disk_desc *,struct g_mod *);
31 int (*m_term)(disk_desc *);
32 int (*m_gfun)(disk_desc *,struct g_mod *);
33 float m_guess;
34 float m_weight; /* probability weight */
35 void *m_hd; /* dlopen() descriptor */
36 dos_part_entry m_part; /* a guessed partition entry */
37 long m_align; /* alignment of partition */
38 struct g_mod *m_next;
39 unsigned int m_hasptbl : 1; /* has a ptbl like entry in sec 0 */
40 unsigned int m_notinext : 1; /* cannot exist in an ext part. */
41 unsigned int m_skip : 1; /* skip this module this time */
42 } g_module;
43
44 #define GM_LOOKUP 0
45 #define GM_INSERT 1
46
47 void g_mod_list(), g_mod_delete(g_module *), g_mod_deleteall();
48 g_module *g_mod_head(), *g_mod_lookup(int,char *);
49 void g_mod_addinternals();
50 int g_mod_count(), g_mod_addexternal(char *);
51 g_module *g_mod_setweight(char *,float);
52
53
54
55 /*
56 * preloaded guessing modules
57 */
58
59 #define GMODDECL(mod) int mod##_init(disk_desc *,g_module *), \
60 mod##_term(disk_desc *), \
61 mod##_gfun(disk_desc *,g_module *)
62
63 GMODDECL(bsddl); GMODDECL(ext2); GMODDECL(fat);
64 GMODDECL(hpfs); GMODDECL(lswap); GMODDECL(ntfs);
65 GMODDECL(s86dl); GMODDECL(minix); GMODDECL(rfs);
66 GMODDECL(hmlvm); GMODDECL(qnx4); GMODDECL(beos);
67 GMODDECL(xfs);
68
69
70 #endif /* _GMODULES_H */
0 /*
1 * gpart.c -- gpart main
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified: 11.06.1999 <mb@ichabod.han.de>
13 * Handle disk read errors.
14 * Minor fixes.
15 *
16 * 29.06.1999 <mb@ichabod.han.de>
17 * Made every disk read/write buffer aligned to pagesize.
18 *
19 * 29.08.1999 <mb@ichabod.han.de>
20 * Default scan increment now 's'.
21 * Extended ptbl boundary condition now depends on scan
22 * increment.
23 *
24 * 26.02.2000 <mb@ichabod.han.de>
25 * Default scan increment 'h' again.
26 * Fixed faulty head boundary condition.
27 * Introduced ptbl entry editing after guess loop.
28 * First scanned sector is no of sects/head, if no start
29 * sector was given.
30 * m_notinext now honoured.
31 * Make a MBR backup.
32 * Interactive mode now somehow works.
33 *
34 * 14.05.2000 <mb@ichabod.han.de>
35 * Made writing of guessed table also aligned.
36 * Fixed stupid copy&paste bug in the check routine
37 * (found by Bruno Bozza <brunobozza@hotmail.com>.
38 *
39 * 29.01.2001 <mb@ichabod.han.de>
40 * Extended partition type on an LBA disk now 0x0f instead
41 * of 0x05. Changed some partition types (get_part_type).
42 * When comparing partition types in extptbl links, try
43 * to compare similarity, not equality (is_same_partition_type).
44 *
45 */
46
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <stdarg.h>
51 #include <fcntl.h>
52 #include <unistd.h>
53 #include <string.h>
54 #include <ctype.h>
55 #include <errno.h>
56 #include <sys/stat.h>
57 #include <sys/types.h>
58 #include "gpart.h"
59
60
61 static const char rcsid[] = "$Id: gpart.c,v 1.11 2001/02/07 18:08:08 mb Exp mb $";
62 static const char *gpart_version = PROGRAM " v" VERSION;
63
64
65 int f_check = 0, f_verbose = 0, f_dontguess = 0, f_fast = 1;
66 int f_getgeom = 1, f_interactive = 0, f_quiet = 0, f_testext = 1;
67 int f_skiperrors = 1, berrno = 0;
68 int (*boundary_fun)(disk_desc *,s64_t);
69 unsigned long increment = 'h', gc = 0, gh = 0, gs = 0;
70 s64_t skipsec = 0, maxsec = 0;
71 FILE *log = 0;
72
73
74
75 void usage()
76 {
77 FILE *fp = stderr;
78
79 fprintf(fp,"Usage: %s [options] device\n",PROGRAM);
80 fprintf(fp,"Options: [-b <backup MBR>][-C c,h,s][-c][-d][-E][-e][-f][-g][-h][-i]\n");
81 fprintf(fp," [-K <last sector>][-k <# of sectors>][-L][-l <log file>]\n");
82 fprintf(fp," [-n <increment>][-q][-s <sector-size>][-t <module-name>]\n");
83 fprintf(fp," [-V][-v][-W <device>][-w <module-name,weight>]\n");
84 fprintf(fp,"%s (c) 1999-2001 Michail Brzitwa <michail@brzitwa.de>.\n",gpart_version);
85 fprintf(fp,"Guess PC-type hard disk partitions.\n\n");
86 if (! f_verbose)
87 return;
88 fprintf(fp,"Options:\n");
89 fprintf(fp," -b Save a backup of the original MBR to specified file.\n");
90 fprintf(fp," -C Set c/h/s to be used in the scan.\n");
91 fprintf(fp," -c Check/compare mode.\n");
92 fprintf(fp," -d Do not start the guessing loop.\n");
93 fprintf(fp," -E Do not try to identify extended partition tables.\n");
94 fprintf(fp," -e Do not skip disk read errors.\n");
95 fprintf(fp," -f Full scan.\n");
96 fprintf(fp," -g Do not try to get the disk geometry.\n");
97 fprintf(fp," -h Show this help.\n");
98 fprintf(fp," -i Run interactively (ask for confirmation).\n");
99 fprintf(fp," -K Scan only up to given sector.\n");
100 fprintf(fp," -k Skip sectors before scan.\n");
101 fprintf(fp," -L List available modules and their weights, then exit.\n");
102 fprintf(fp," -l Logfile name.\n");
103 fprintf(fp," -n Scan increment: number or 's' sector, 'h' head, 'c' cylinder.\n");
104 fprintf(fp," -q Run quiet (however log file is written if specified).\n");
105 fprintf(fp," -s Sector size to use (disable sector size probing).\n");
106 fprintf(fp," -t Name of a guessing module to be added.\n");
107 fprintf(fp," -V Show version.\n");
108 fprintf(fp," -v Verbose mode. Can be given more than once.\n");
109 fprintf(fp," -W Write guessed primary partition table to given device or file.\n");
110 fprintf(fp," -w Weight factor of module.\n");
111 fprintf(fp,"\n");
112 }
113
114
115
116 void pr(int type,char *fmt,...)
117 {
118 va_list vl;
119 static char msg[512];
120
121 va_start(vl,fmt); vsnprintf(msg,511,fmt,vl); va_end(vl); msg[511] = 0;
122 switch (type)
123 {
124 case FATAL :
125 g_mod_deleteall();
126 if (! f_quiet) fprintf(stderr,EM_FATALERROR,msg);
127 if (log)
128 {
129 fprintf(log,EM_FATALERROR,msg);
130 fclose(log);
131 }
132 exit(1);
133 case ERROR :
134 if (! f_quiet) fprintf(stderr,EM_SIMPLEERROR,msg);
135 if (log) fprintf(log,EM_SIMPLEERROR,msg);
136 break;
137 case WARN :
138 if (! f_quiet) fprintf(stderr,EM_WARNING,msg);
139 if (log) fprintf(log,EM_WARNING,msg);
140 break;
141 case MSG :
142 if (! f_quiet) fputs(msg,stdout); fflush(stdout);
143 if (log) fputs(msg,log);
144 break;
145 }
146 if (log) fflush(log);
147 }
148
149
150
151 byte_t *alloc(ssize_t s)
152 {
153 byte_t *p = (byte_t *)malloc(s);
154
155 if (p == 0)
156 pr(FATAL,EM_MALLOCFAILED,s);
157 memset(p,0,s);
158 return (p);
159 }
160
161
162
163 /*
164 * read nsecs blocks of ssize bytes from fd
165 */
166
167 ssize_t bread(int fd,byte_t *buf,size_t ssize,size_t nsecs)
168 {
169 ssize_t cs = 0, nr = 0;
170
171 for ( ; nsecs > 0; nsecs--)
172 {
173 if ((nr = read(fd,buf,ssize)) == -1)
174 {
175 berrno = errno;
176 return ((cs == 0) ? -1 : cs);
177 }
178 cs += nr; buf += nr;
179 if (nr < ssize)
180 break;
181 }
182 return (cs);
183 }
184
185
186
187 static int yesno(char *q)
188 {
189 int ch = 0;
190 char buf[3];
191
192 pr(MSG,q); pr(MSG," %s : ",DM_YESNO);
193 if (fgets(buf,3,stdin)) ch = *buf; pr(MSG,"\n");
194 return (strchr(DM_YES,ch) == 0 ? 0 : 1);
195 }
196
197
198
199 static long number_or_quit(char *m,long lo,long up)
200 {
201 char buf[32];
202 long num = -1;
203
204 pr(MSG,m); pr(MSG,DM_NUMORQUIT,lo,up);
205 if (fgets(buf,32,stdin))
206 {
207 if (strchr(DM_QUIT,*buf))
208 return (-1);
209 num = strtoul(buf,0,0);
210 if (errno == ERANGE)
211 return (-1);
212 }
213 return (num);
214 }
215
216
217
218 /*
219 * get three comma separated strings.
220 */
221
222 static int get_csep_arg(char *arg,char **p1,char **p2,char **p3)
223 {
224 char *p;
225
226 if (p1) *p1 = arg; else return (0);
227 if ((p = strchr(arg,',')) == 0) return (0);
228 *p = 0; arg = p + 1;
229 if (p2) *p2 = arg; else return (1);
230 if (p3)
231 {
232 if ((p = strchr(arg,',')) == 0) return (0);
233 *p = 0; *p3 = p + 1;
234 }
235 return (1);
236 }
237
238
239
240 /*
241 * partition type list, taken from *BSD i386 fdisk, cfdisk etc.
242 */
243
244 static char *get_part_type(int type)
245 {
246 int i;
247 struct
248 {
249 int t;
250 char *n;
251 } ptypes[] =
252 {
253 { 0x00, "unused" },
254 { 0x01, "Primary DOS with 12 bit FAT" },
255 { 0x02, "XENIX / filesystem" },
256 { 0x03, "XENIX /usr filesystem" },
257 { 0x04, "Primary DOS with 16 bit FAT (<= 32MB)" },
258 { 0x05, "Extended DOS" },
259 { 0x06, "Primary 'big' DOS (> 32MB)" },
260 { 0x07, "OS/2 HPFS, NTFS, QNX or Advanced UNIX" },
261 { 0x08, "AIX filesystem" },
262 { 0x09, "AIX boot partition or Coherent" },
263 { 0x0A, "OS/2 Boot Manager or OPUS" },
264 { 0x0B, "DOS or Windows 95 with 32 bit FAT" },
265 { 0x0C, "DOS or Windows 95 with 32 bit FAT, LBA" },
266 { 0x0E, "Primary 'big' DOS (> 32MB, LBA)" },
267 { 0x0F, "Extended DOS, LBA" },
268 { 0x10, "OPUS" },
269 { 0x11, "Hidden DOS with 12 bit FAT" },
270 { 0x12, "Compaq Diagnostics" },
271 { 0x14, "Hidden DOS with 16 bit FAT (<= 32MB)" },
272 { 0x16, "Hidden 'big' DOS (> 32MB)" },
273 { 0x17, "OS/2 Boot Manager HPFS" },
274 { 0x18, "AST special Windows swap file" },
275 { 0x24, "NEC MS-DOS 3.x" },
276 { 0x3C, "PowerQuest PartitionMagic recovery partition" },
277 { 0x40, "VENIX 286" },
278 { 0x4D, "QNX4.x" },
279 { 0x4E, "QNX4.x 2nd part" },
280 { 0x4F, "QNX4.x 3rd part" },
281 { 0x50, "DM" },
282 { 0x51, "DM" },
283 { 0x51, "DM" },
284 { 0x52, "CP/M or Microport SysV/AT" },
285 { 0x55, "EZ Drive" },
286 { 0x56, "GB" },
287 { 0x61, "SpeedStor" },
288 { 0x63, "ISC UNIX, other System V/386, GNU HURD or Mach" },
289 { 0x64, "Novell Netware 2.xx" },
290 { 0x65, "Novell Netware 3.xx" },
291 { 0x70, "DiskSecure Multi-Boot" },
292 { 0x75, "PCIX" },
293 { 0x80, "Minix V1" },
294 { 0x81, "Minix V2/Linux" },
295 { 0x82, "Linux swap or Solaris/x86" },
296 { 0x83, "Linux ext2 filesystem" },
297 { 0x85, "Extended Linux" },
298 { 0x86, "FAT16 volume/stripe set" },
299 { 0x8E, "Linux LVM physical volume" },
300 { 0x93, "Amoeba filesystem" },
301 { 0x94, "Amoeba bad block table" },
302 { 0xA5, "FreeBSD/NetBSD/386BSD" },
303 { 0xA6, "OpenBSD" },
304 { 0xA7, "NEXTSTEP" },
305 { 0xB7, "BSDI BSD/386 filesystem" },
306 { 0xB8, "BSDI BSD/386 swap" },
307 { 0xC7, "Syrinx" },
308 { 0xDB, "Concurrent CPM or C.DOS or CTOS" },
309 { 0xE1, "SpeedStor 12-bit FAT extended" },
310 { 0xE3, "Speed" },
311 { 0xE4, "SpeedStor 16-bit FAT" },
312 { 0xEB, "BeOS fs" },
313 { 0xF1, "SpeedStor" },
314 { 0xF2, "DOS 3.3+ Secondary" },
315 { 0xF4, "SpeedStor" },
316 { 0xFD, "Linux raid autodetect" },
317 { 0xFE, "LANstep" },
318 { 0xFF, "BBT (Bad Blocks Table)" }
319 };
320
321 for (i = 0; i < sizeof(ptypes)/sizeof(ptypes[0]); i++)
322 if (type == ptypes[i].t)
323 return (ptypes[i].n);
324 return (0);
325 }
326
327
328
329 static int is_ext_parttype(dos_part_entry *p)
330 {
331 return (p->p_size && ((p->p_typ == 0x05) ||
332 (p->p_typ == 0x0F) || (p->p_typ == 0x85)));
333 }
334
335
336
337 static int is_sane_partentry(disk_desc *d,dos_part_entry *p,int c)
338 {
339 if (p->p_start >= d->d_nsecs)
340 {
341 if (c) pr(WARN,EM_PSTART2BIG,get_part_type(p->p_typ));
342 return (0);
343 }
344 if (p->p_size > d->d_nsecs)
345 {
346 if (c) pr(WARN,EM_PSIZE2BIG,get_part_type(p->p_typ));
347 return (0);
348 }
349 if (p->p_start + p->p_size > d->d_nsecs)
350 {
351 if (c) pr(WARN,EM_PEND2BIG,get_part_type(p->p_typ));
352 return (0);
353 }
354 if (p->p_flag && (p->p_flag != DOSPARTACTIVE))
355 {
356 if (c) pr(WARN,EM_STRANGEPTYPE,get_part_type(p->p_typ));
357 return (0);
358 }
359 return (1);
360 }
361
362
363
364 static int is_real_parttype(dos_part_entry *p)
365 {
366 return (!is_ext_parttype(p) && p->p_typ && get_part_type(p->p_typ));
367 }
368
369
370
371 static int no_of_ext_partitions(dos_part_entry *p)
372 {
373 dos_part_entry *t;
374 int ne = 0;
375
376 for (t = &p[0]; t < &p[NDOSPARTS]; t++)
377 if (is_ext_parttype(t))
378 ne++;
379 return (ne);
380 }
381
382
383
384 static int no_of_real_partitions(dos_part_entry *p)
385 {
386 dos_part_entry *t;
387 int nr = 0;
388
389 for (t = &p[0]; t < &p[NDOSPARTS]; t++)
390 if (is_real_parttype(t))
391 nr++;
392 return (nr);
393 }
394
395
396
397 /*
398 * Test similarity of partition types
399 */
400
401 static int is_same_partition_type(dos_part_entry *p1,dos_part_entry *p2)
402 {
403 int ret = 0;
404
405 switch (p1->p_typ)
406 {
407 case 0x01: case 0x11:
408 ret = (p2->p_typ == 0x06) || (p2->p_typ == 0x0E);
409 break;
410
411 case 0x06: case 0x0E: case 0x16:
412 ret = (p2->p_typ == 0x06) || (p2->p_typ == 0x0E) || (p2->p_typ == 0x16);
413 break;
414
415 case 0x05: case 0x0F:
416 ret = (p2->p_typ == 0x05) || (p2->p_typ == 0x0F);
417 break;
418
419 case 0x0B: case 0x0C:
420 ret = (p2->p_typ == 0x0B) || (p2->p_typ == 0x0C);
421 break;
422
423 case 0x8E: case 0xFE:
424 ret = (p2->p_typ == 0x8E) || (p2->p_typ == 0xFE);
425 break;
426
427 default :
428 ret = p1->p_typ == p2->p_typ;
429 break;
430 }
431 return (ret);
432 }
433
434
435
436 /*
437 * detecting an extended ptbl isn't unambiguous, the boot code
438 * preceding the ptbl should be zeroed but isn't always. The
439 * ptbl should in theory contain one 'normal' entry, zero or
440 * one link to the next extended ptbl and two or three zeroed
441 * entries.
442 */
443
444 static int is_ext_parttable(disk_desc *d,byte_t *buf)
445 {
446 int r, e;
447 byte_t *magic;
448 dos_part_entry *p, *t;
449
450 p = (dos_part_entry *)(buf + DOSPARTOFF);
451 magic = (byte_t *)&p[NDOSPARTS];
452 if (*(unsigned short *)magic != le16(DOSPTMAGIC))
453 return (0);
454
455 /*
456 * ptbl sanity checks.
457 */
458
459 for (t = p; t < &p[NDOSPARTS]; t++)
460 if (! is_sane_partentry(d,t,0))
461 return (0);
462
463 /*
464 * one real, zero or one extended and two or three unused
465 * partition entries.
466 */
467
468 r = no_of_real_partitions(p);
469 e = no_of_ext_partitions(p);
470 return ((r == 1) && ((e == 0) || (e == 1)));
471 }
472
473
474
475 static void fillin_dos_chs(disk_desc *d,dos_part_entry *p,s64_t offset)
476 {
477 unsigned long n;
478
479 n = p->p_start;
480 if (n > 1023 * d->d_dg.d_h * d->d_dg.d_s)
481 {
482 p->p_ssect = d->d_dg.d_s | ((1023 >> 2) & 0xc0);
483 p->p_shd = d->d_dg.d_h - 1;
484 p->p_scyl = 1023 & 0xff;
485 }
486 else
487 {
488 p->p_ssect = (n % d->d_dg.d_s) + 1;
489 n /= d->d_dg.d_s;
490 p->p_shd = n % d->d_dg.d_h;
491 n /= d->d_dg.d_h;
492 p->p_scyl = n & 0xff;
493 p->p_ssect |= (n >> 2) & 0xc0;
494 }
495 n = p->p_size + p->p_start - 1;
496 if (n > 1023 * d->d_dg.d_h * d->d_dg.d_s)
497 {
498 p->p_esect = d->d_dg.d_s | ((1023 >> 2) & 0xc0);
499 p->p_ehd = d->d_dg.d_h - 1;
500 p->p_ecyl = 1023 & 0xff;
501 }
502 else
503 {
504 p->p_esect = (n % d->d_dg.d_s) + 1;
505 n /= d->d_dg.d_s;
506 p->p_ehd = n % d->d_dg.d_h;
507 n /= d->d_dg.d_h;
508 p->p_ecyl = n & 0xff;
509 p->p_esect |= (n >> 2) & 0xc0;
510 }
511 }
512
513
514
515 static void u_to_chs(disk_desc *d,unsigned long u,long *c,long *h,long *s)
516 {
517 struct disk_geom *g = &d->d_dg;
518
519 *c = *h = *s = 0;
520 if (g->d_h && g->d_s && u)
521 {
522 *c = u / (g->d_h * g->d_s);
523 *h = (u / g->d_s) % g->d_h;
524 *s = u % g->d_s + 1;
525 }
526 }
527
528
529
530 static int on_cyl_boundary(disk_desc *d,s64_t sec)
531 {
532 struct disk_geom *g = &d->d_dg;
533
534 if (g->d_h && g->d_s)
535 return ((sec % (g->d_h * g->d_s)) == 0);
536 return (1);
537 }
538
539
540
541 static int on_head_boundary(disk_desc *d,s64_t sec)
542 {
543 struct disk_geom *g = &d->d_dg;
544
545 if (g->d_s)
546 return ((sec % g->d_s) == 0);
547 return (1);
548 }
549
550
551
552 static void print_partition(disk_desc *d,dos_part_entry *p,int inset,s64_t offset)
553 {
554 long i, c = 0, h = 0, s = 0;
555 s64_t size;
556 char *ptyp = get_part_type(p->p_typ);
557
558 #define indent(s) for (i = 0; i < s; i++) pr(MSG," ")
559
560 size = p->p_size; s2mb(d,size);
561 indent(inset);
562 pr(MSG,PM_PT_TYPE,p->p_typ,p->p_typ,ptyp ? ptyp : "UNKNOWN");
563 if (p->p_flag == DOSPARTACTIVE)
564 pr(MSG," (BOOT)");
565 pr(MSG,"\n");
566
567 indent(inset);
568 pr(MSG,PM_PT_SIZE,size,(s64_t)p->p_size);
569 size = p->p_start; size += offset; size += p->p_size;
570 if (size) size -= 1;
571 pr(MSG," s(%qd-%qd)\n",(s64_t)p->p_start + offset,size);
572
573 indent(inset);
574 pr(MSG,PM_PT_CHS,
575 DOSCYL(p->p_scyl,p->p_ssect),p->p_shd,DOSSEC(p->p_ssect),
576 DOSCYL(p->p_ecyl,p->p_esect),p->p_ehd,DOSSEC(p->p_esect));
577 if (size) u_to_chs(d,p->p_start + offset,&c,&h,&s);
578 pr(MSG," (%ld/%ld/%ld)-",c,h,s);
579 if (size) u_to_chs(d,p->p_start + offset + p->p_size - 1,&c,&h,&s);
580 pr(MSG,"(%ld/%ld/%ld)r\n",c,h,s);
581
582 if (f_verbose > 0)
583 {
584 indent(inset);
585 pr(MSG,PM_PT_HEX);
586 for (i = 0; i < sizeof(dos_part_entry); i++)
587 pr(MSG," %02X",((byte_t *)p)[i]);
588 pr(MSG,"\n");
589 }
590 pr(MSG,"\n");
591 }
592
593
594
595 static void print_ext_partitions(disk_desc *d,s64_t offset)
596 {
597 dos_part_table *pt = d->d_pt.t_ext;
598 dos_part_entry *p;
599 s64_t extst = 0;
600
601 for ( ; pt; pt = pt->t_ext)
602 {
603 pr(MSG,PM_EXTPART);
604 for (p = pt->t_parts; p < &pt->t_parts[NDOSPARTS + 1]; p++)
605 if (is_real_parttype(p))
606 print_partition(d,p,1,offset + extst);
607
608 for (p = pt->t_parts; p < &pt->t_parts[NDOSPARTS + 1]; p++)
609 if (is_ext_parttype(p))
610 extst = p->p_start;
611 }
612 }
613
614
615
616 static void print_ptable(disk_desc *d,dos_part_table *pt,int pr_ext)
617 {
618 int n;
619
620 for (n = 0; n < NDOSPARTS; n++)
621 {
622 pr(MSG,PM_PRIMPART,n + 1);
623 print_partition(d,&pt->t_parts[n],0,0);
624 if (pr_ext && is_ext_parttype(&pt->t_parts[n]))
625 print_ext_partitions(d,pt->t_parts[n].p_start);
626 }
627 }
628
629
630
631 static void print_disk_desc(disk_desc *d)
632 {
633 s64_t s;
634
635 pr(MSG,PM_DEVDESC1,d->d_dev,d->d_ssize);
636 if (f_getgeom)
637 {
638 s = d->d_nsecs; s2mb(d,s);
639 pr(MSG,PM_DEVDESC2,
640 d->d_dg.d_c,d->d_dg.d_h,d->d_dg.d_s,
641 d->d_lba ? "(LBA) " : " ",
642 d->d_nsecs,s);
643 }
644 pr(MSG,"\n");
645 if (d->d_pt.t_magic != le16(DOSPTMAGIC))
646 pr(WARN,EM_STRANGEPTBLMAGIC,d->d_pt.t_magic);
647 print_ptable(d,&d->d_pt,1);
648 }
649
650
651
652 static void print_mboot_block(disk_desc *d)
653 {
654 int n, m, cols = 16;
655 byte_t *boot = d->d_pt.t_boot;
656
657 pr(MSG,PM_MBRPRINT,d->d_dev);
658 for (n = 0; n < DOSPARTOFF - cols; n += cols)
659 {
660 pr(MSG," %04X: ",n);
661 for (m = n; m < n + cols; m++)
662 pr(MSG," %02x",boot[m]);
663 pr(MSG,"\n ");
664 for (m = n; m < n + cols; m++)
665 pr(MSG," %c ",isprint(boot[m]) ? boot[m] : '.');
666 pr(MSG,"\n");
667 }
668 }
669
670
671
672 static void read_part_table(disk_desc *d,s64_t sec,byte_t *where)
673 {
674 ssize_t rd;
675 size_t psize;
676 byte_t *ubuf, *buf;
677
678 psize = getpagesize();
679 ubuf = alloc(MAXSSIZE + psize);
680 buf = align(ubuf,psize);
681 sec *= d->d_ssize;
682 if (l64seek(d->d_fd,sec,SEEK_SET) == -1)
683 pr(FATAL,EM_SEEKFAILURE,d->d_dev);
684
685 if (d->d_ssize < 512)
686 rd = bread(d->d_fd,buf,d->d_ssize,512 / d->d_ssize);
687 else
688 rd = bread(d->d_fd,buf,d->d_ssize,1);
689
690 if (rd == -1)
691 pr(FATAL,EM_PTBLREAD);
692 memcpy(where,buf,512);
693 free((void *)ubuf);
694 }
695
696
697
698 static void read_ext_part_table(disk_desc *d,dos_part_table *pt)
699 {
700 dos_part_entry *p, *ep;
701 s64_t epsize, epstart, epoffset;
702 int epcount;
703
704 epsize = epstart = epoffset = epcount = 0;
705 while (1)
706 {
707 ep = 0;
708 for (p = pt->t_parts; p < &pt->t_parts[NDOSPARTS + 1]; p++)
709 if (is_ext_parttype(p))
710 {
711 if (ep == 0)
712 {
713 ep = p;
714 break;
715 }
716 pr(ERROR,EM_TOOMANYEXTP);
717 }
718
719 if (ep == 0)
720 return;
721 if (++epcount > 128) /* arbitrary maximum */
722 {
723 pr(ERROR,EM_TOOMANYLOGP,128);
724 return;
725 }
726 if (epstart == 0)
727 {
728 epstart = ep->p_start;
729 epsize = ep->p_size;
730 epoffset = 0;
731 }
732 else
733 epoffset = ep->p_start;
734 if (epoffset > epsize)
735 {
736 pr(ERROR,EM_EPILLEGALOFS);
737 return;
738 }
739
740 /*
741 * link in new extended ptbl.
742 */
743
744 pt->t_ext = (dos_part_table *)alloc(sizeof(dos_part_table));
745 read_part_table(d,epstart + epoffset,(pt = pt->t_ext)->t_boot);
746 if (! is_ext_parttable(d,pt->t_boot))
747 {
748 pr(ERROR,EM_INVXPTBL,epstart + epoffset);
749 return;
750 }
751 }
752 }
753
754
755
756 static void free_disk_desc(disk_desc *d)
757 {
758 dos_part_table *pt;
759 dos_guessed_pt *pg;
760 void *t;
761
762 for (pt = d->d_pt.t_ext; pt; )
763 {
764 t = pt->t_ext; free((void *)pt); pt = t;
765 }
766 for (pt = d->d_gpt.t_ext; pt; )
767 {
768 t = pt->t_ext; free((void *)pt); pt = t;
769 }
770 for (pg = d->d_gl; pg; )
771 {
772 t = pg->g_next; free((void *)pg); pg = t;
773 }
774 free((void *)d);
775 }
776
777
778
779 static disk_desc *get_disk_desc(char *dev,int sectsize)
780 {
781 byte_t *ubuf, *buf;
782 disk_desc *d;
783 int psize, ssize;
784 struct disk_geom *dg;
785
786 psize = getpagesize();
787 ubuf = alloc(MAXSSIZE + psize);
788 buf = align(ubuf,psize);
789 d = (disk_desc *)alloc(sizeof(disk_desc));
790
791 /*
792 * I don't care if the given name denotes a block or character
793 * special file or just a regular file.
794 */
795
796 if ((d->d_fd = open(dev,O_RDONLY)) == -1)
797 pr(FATAL,EM_OPENFAIL,dev,strerror(errno));
798
799 /*
800 * try to test for sector sizes (doesn't work under many systems).
801 */
802
803 if (sectsize > MAXSSIZE)
804 pr(FATAL,EM_WRONGSECTSIZE,MAXSSIZE);
805
806 if (sectsize)
807 {
808 ssize = bread(d->d_fd,buf,sectsize,1);
809 if (ssize != sectsize)
810 pr(FATAL,EM_FAILSSIZEATTEMPT,sectsize);
811 d->d_ssize = sectsize;
812 }
813 else
814 {
815 for (d->d_ssize = MINSSIZE; d->d_ssize <= MAXSSIZE; d->d_ssize *= 2)
816 {
817 if (l64seek(d->d_fd,0,SEEK_SET) == -1)
818 pr(FATAL,EM_SEEKFAILURE,dev);
819 ssize = bread(d->d_fd,buf,d->d_ssize,1);
820 if (ssize == d->d_ssize)
821 break;
822 }
823 if (ssize == -1)
824 pr(FATAL,EM_CANTGETSSIZE,dev);
825 }
826
827 d->d_dev = dev;
828 read_part_table(d,0,d->d_pt.t_boot);
829 if (f_getgeom)
830 {
831 if ((dg = disk_geometry(d)) == 0)
832 pr(FATAL,EM_CANTGETGEOM);
833 memcpy(&d->d_dg,dg,sizeof(struct disk_geom));
834
835 /*
836 * command line geometry overrides
837 */
838
839 if (gc) d->d_dg.d_c = gc;
840 if (gh) d->d_dg.d_h = gh;
841 if (gs) d->d_dg.d_s = gs;
842 }
843 else
844 {
845 d->d_dg.d_c = gc;
846 d->d_dg.d_h = gh;
847 d->d_dg.d_s = gs;
848 }
849 if (d->d_dg.d_c < 1024) d->d_dosc = 1;
850 if ((d->d_dg.d_h > 16) || (d->d_dg.d_s > 63)) d->d_lba = 1;
851 d->d_nsecs = d->d_dg.d_c;
852 d->d_nsecs *= d->d_dg.d_h;
853 d->d_nsecs *= d->d_dg.d_s;
854 read_ext_part_table(d,&d->d_pt);
855 close(d->d_fd);
856 free((void *)ubuf);
857 return (d);
858 }
859
860
861
862 static void add_guessed_p(disk_desc *d,dos_part_entry *p,int cnt)
863 {
864 dos_guessed_pt *gpt;
865
866 if (d->d_gl == 0)
867 gpt = d->d_gl = (dos_guessed_pt *)alloc(sizeof(dos_guessed_pt));
868 else
869 {
870 for (gpt = d->d_gl; gpt->g_next; gpt = gpt->g_next)
871 ;
872 gpt->g_next = (dos_guessed_pt *)alloc(sizeof(dos_guessed_pt));
873 gpt = gpt->g_next;
874 }
875
876 gpt->g_ext = (cnt > 1);
877 for ( ; cnt > 0; cnt--)
878 memcpy(&gpt->g_p[cnt-1],&p[cnt-1],sizeof(dos_part_entry));
879 gpt->g_sec = d->d_nsb;
880 }
881
882
883
884 static g_module *get_best_guess(g_module **g,int count)
885 {
886 int mx, i;
887 float bestg = 0.0;
888
889 /*
890 * up to now the best guess is simple that one which
891 * reported the largest probability (if there are more
892 * than one, the last one of them).
893 */
894
895 for (mx = i = 0; i < count; i++)
896 if (g[i]->m_guess * g[i]->m_weight > bestg)
897 bestg = g[mx = i]->m_guess * g[i]->m_weight;
898
899 return ((bestg > 0.0) ? g[mx] : 0);
900 }
901
902
903
904 static int mod_is_aligned(disk_desc *d,g_module *m)
905 {
906 s64_t al;
907
908 switch (m->m_align)
909 {
910 case 'h' :
911 return (on_head_boundary(d,d->d_nsb));
912
913 case 'c' :
914 return (on_cyl_boundary(d,d->d_nsb));
915
916 case 1 :
917 case 's' :
918 return (1);
919 default :
920 if (m->m_align > 0)
921 {
922 al = d->d_nsb; al %= m->m_align;
923 return (al == 0);
924 }
925 break;
926 }
927 return (1);
928 }
929
930
931
932 /*
933 * the main guessing loop.
934 */
935
936 static void do_guess_loop(disk_desc *d)
937 {
938 g_module *m, **guesses;
939 unsigned long incr = 0;
940 int nsecs, in_ext = 0, end_of_ext = 0, psize;
941 ssize_t rd, bsize = d->d_ssize;
942 s64_t bincr, noffset, start;
943 byte_t *ubuf;
944
945 if ((d->d_fd = open(d->d_dev,O_RDONLY)) == -1)
946 pr(FATAL,EM_OPENFAIL,d->d_dev,strerror(errno));
947
948 /*
949 * initialize modules. Each should return the minimum
950 * size in bytes it wants to receive for a test.
951 */
952
953 for (m = g_mod_head(); m; m = m->m_next)
954 if (m->m_init)
955 {
956 int sz;
957
958 if ((sz = (*m->m_init)(d,m)) <= 0)
959 pr(ERROR,EM_MINITFAILURE,m->m_name);
960 bsize = max(sz,bsize);
961 }
962
963 if (bsize % d->d_ssize)
964 bsize += d->d_ssize - bsize % d->d_ssize;
965 nsecs = bsize / d->d_ssize;
966 switch (increment)
967 {
968 case 's' : incr = 1; break;
969 case 'h' : incr = d->d_dg.d_s; break;
970 case 'c' : incr = d->d_dg.d_s * d->d_dg.d_h; break;
971 default : incr = increment; break;
972 }
973 if (incr == 0)
974 incr = 1;
975
976 boundary_fun = (incr == 1) ? on_head_boundary : on_cyl_boundary;
977 psize = getpagesize();
978 ubuf = alloc(bsize + psize);
979 d->d_sbuf = align(ubuf,psize);
980 d->d_nsb = 0;
981 bincr = incr * d->d_ssize;
982
983 start = skipsec ? skipsec : d->d_dg.d_s;
984 d->d_nsb = start - incr;
985 start *= d->d_ssize;
986 if (l64seek(d->d_fd,start,SEEK_SET) == -1)
987 pr(FATAL,EM_SEEKFAILURE,d->d_dev);
988
989 /*
990 * do the work: read blocks, distribute to modules, check
991 * for probable hits.
992 */
993
994 guesses = (g_module **)alloc(g_mod_count() * sizeof(g_module *));
995 pr(MSG,DM_STARTSCAN);
996
997 scanloop:
998 while ((rd = bread(d->d_fd,d->d_sbuf,d->d_ssize,nsecs)) == bsize)
999 {
1000 int mod, have_ext = 0;
1001 g_module *bg;
1002 s64_t sz, ofs;
1003
1004 d->d_nsb += incr; noffset = 0;
1005 ofs = d->d_nsb; s2mb(d,ofs);
1006 if (maxsec && (d->d_nsb > maxsec)) break;
1007
1008 /*
1009 * reset modules
1010 */
1011
1012 for (m = g_mod_head(); m; m = m->m_next)
1013 m->m_skip = 0;
1014
1015 guessit:
1016 bg = 0; mod = 0;
1017 for (m = g_mod_head(); m; m = m->m_next)
1018 {
1019 if (m->m_skip || (in_ext && m->m_notinext) || !mod_is_aligned(d,m))
1020 continue;
1021
1022 /*
1023 * because a gmodule is allowed to seek on
1024 * d->d_fd the current file position must be
1025 * saved.
1026 */
1027
1028 memset(&m->m_part,0,sizeof(dos_part_entry));
1029 m->m_guess = GM_NO; l64opush(d->d_fd);
1030 if ((*m->m_gfun)(d,m) && (m->m_guess * m->m_weight >= GM_PERHAPS))
1031 guesses[mod++] = m;
1032 if ((sz = l64opop(d->d_fd)) != l64tell(d->d_fd))
1033 l64seek(d->d_fd,sz,SEEK_SET);
1034 }
1035
1036 /*
1037 * now fetch the best guess.
1038 */
1039
1040 if (mod && (bg = get_best_guess(guesses,mod)))
1041 {
1042 noffset = bg->m_part.p_size;
1043 fillin_dos_chs(d,&bg->m_part,0);
1044 }
1045
1046 /*
1047 * extended partition begin?
1048 */
1049
1050 if (f_testext && boundary_fun(d,d->d_nsb) &&
1051 (!bg || !bg->m_hasptbl) && is_ext_parttable(d,d->d_sbuf))
1052 {
1053 dos_part_entry *p;
1054 int no_ext;
1055
1056 p = (dos_part_entry *)(d->d_sbuf + DOSPARTOFF);
1057 no_ext = no_of_ext_partitions(p);
1058 if (! in_ext)
1059 {
1060 pr(MSG,PM_POSSIBLEEXTPART,ofs);
1061 in_ext = 1; end_of_ext = 0; noffset = 0;
1062 }
1063 else if (no_ext == 0)
1064 end_of_ext = 1;
1065
1066 if (in_ext)
1067 {
1068 if (f_interactive)
1069 {
1070 if (yesno(DM_ACCEPTGUESS))
1071 add_guessed_p(d,p,have_ext = NDOSPARTS);
1072 else
1073 if (mod && bg)
1074 {
1075 bg->m_skip = 1;
1076 goto guessit;
1077 }
1078 }
1079 else
1080 add_guessed_p(d,p,have_ext = NDOSPARTS);
1081 }
1082 }
1083
1084 if (! have_ext && noffset)
1085 {
1086 sz = noffset; s2mb(d,sz);
1087 if (in_ext) pr(MSG," ");
1088 pr(MSG,PM_POSSIBLEPART,bg->m_desc ? bg->m_desc : bg->m_name,sz,ofs);
1089 if (f_verbose)
1090 print_partition(d,&bg->m_part,in_ext ? 1 : 0,0);
1091 if (f_interactive)
1092 if (! yesno(DM_ACCEPTGUESS))
1093 {
1094 noffset = 0;
1095 if (mod && bg)
1096 {
1097 bg->m_skip = 1;
1098 goto guessit;
1099 }
1100 }
1101
1102 if (noffset)
1103 {
1104 add_guessed_p(d,&bg->m_part,1);
1105 if (end_of_ext) in_ext = 0;
1106 }
1107 }
1108
1109 /*
1110 * seek to next sectors to investigate (may seek
1111 * backwards).
1112 */
1113
1114 if (noffset && f_fast)
1115 {
1116 if (noffset % incr)
1117 noffset += incr - noffset % incr;
1118 d->d_nsb += noffset - incr;
1119 noffset -= nsecs; noffset *= d->d_ssize;
1120 if (l64seek(d->d_fd,noffset,SEEK_CUR) == -1)
1121 pr(FATAL,EM_SEEKFAILURE,d->d_dev);
1122 }
1123 else if (bincr)
1124 if (l64seek(d->d_fd,bincr - bsize,SEEK_CUR) == -1)
1125 pr(FATAL,EM_SEEKFAILURE,d->d_dev);
1126 }
1127
1128 /*
1129 * short read?
1130 */
1131
1132 if ((rd > 0) && (rd < bsize))
1133 if (d->d_nsb + nsecs + 1 < d->d_nsecs)
1134 {
1135 /*
1136 * short read not at end of disk
1137 */
1138
1139 pr(f_skiperrors ? WARN : FATAL,EM_SHORTBREAD,d->d_nsb,rd,bsize);
1140 noffset = l64tell(d->d_fd); noffset /= d->d_ssize;
1141 noffset *= d->d_ssize;
1142 if (l64seek(d->d_fd,noffset,SEEK_SET) == -1)
1143 pr(FATAL,EM_SEEKFAILURE,d->d_dev);
1144 d->d_nsb = l64tell(d->d_fd) / d->d_ssize - incr;
1145 goto scanloop;
1146 }
1147
1148 if (rd == -1)
1149 {
1150 /*
1151 * EIO is ignored (skipping current sector(s))
1152 */
1153
1154 if (f_skiperrors && (berrno == EIO))
1155 {
1156 pr(WARN,EM_BADREADIO,d->d_nsb);
1157 noffset = l64tell(d->d_fd); noffset /= d->d_ssize;
1158 noffset += incr; noffset *= d->d_ssize;
1159 if (l64seek(d->d_fd,noffset,SEEK_SET) == -1)
1160 pr(FATAL,EM_SEEKFAILURE,d->d_dev);
1161 d->d_nsb = l64tell(d->d_fd) / d->d_ssize - incr;
1162 goto scanloop;
1163 }
1164 pr(FATAL,EM_READERROR,d->d_dev,d->d_nsb,strerror(berrno));
1165 }
1166
1167 pr(MSG,DM_ENDSCAN);
1168 if (guesses) free((void *)guesses);
1169
1170 for (m = g_mod_head(); m; m = m->m_next)
1171 if (m->m_term)
1172 (*m->m_term)(d);
1173 free((void *)ubuf);
1174 close(d->d_fd);
1175 }
1176
1177
1178
1179 static void edit_partition(disk_desc *d,dos_part_entry *p)
1180 {
1181 char ans[32];
1182 int n;
1183 unsigned long val;
1184
1185 while (1)
1186 {
1187 pr(MSG,DM_NOCHECKWARNING);
1188 pr(MSG,PM_EDITITEM1,p->p_start);
1189 pr(MSG,PM_EDITITEM2,p->p_size);
1190 pr(MSG,PM_EDITITEM3,p->p_typ,get_part_type(p->p_typ));
1191 if ((n = number_or_quit(DM_EDITWHICHITEM,1,3)) < 0)
1192 break;
1193 if ((n < 1) || (n > 3))
1194 continue;
1195 pr(MSG,"Enter value for %d : ",n);
1196 if (fgets(ans,32,stdin))
1197 {
1198 val = strtoul(ans,0,0);
1199 switch (n)
1200 {
1201 case 1:
1202 p->p_start = val;
1203 fillin_dos_chs(d,p,0);
1204 break;
1205 case 2:
1206 p->p_size = val;
1207 fillin_dos_chs(d,p,0);
1208 break;
1209 case 3:
1210 p->p_typ = val & 0xFF;
1211 break;
1212 }
1213 }
1214 }
1215 }
1216
1217
1218
1219 static int make_mbr_backup(disk_desc *d,char *bfile)
1220 {
1221 int fd, ret = 0;
1222
1223 if ((fd = open(bfile,O_WRONLY|O_CREAT)) < 0)
1224 return (ret);
1225
1226 if (write(fd,d->d_pt.t_boot,512) == 512)
1227 ret = 1;
1228 close(fd);
1229 return (ret);
1230 }
1231
1232
1233
1234 static void write_primary_ptbl(disk_desc *d,char *dev)
1235 {
1236 struct stat sbuf;
1237 byte_t *ptbl, *uptbl;
1238 int fd, doesntexist = 0, n;
1239
1240 uptbl = alloc(d->d_ssize + getpagesize());
1241 ptbl = align(uptbl,getpagesize());
1242
1243 if (stat(dev,&sbuf) == -1)
1244 {
1245 if (errno != ENOENT)
1246 pr(FATAL,EM_STATFAILURE,dev,strerror(errno));
1247 else
1248 doesntexist = 1;
1249 }
1250 fd = open(dev,O_WRONLY | (doesntexist ? O_CREAT | O_EXCL : 0),0660);
1251 if (fd == -1)
1252 pr(FATAL,EM_OPENFAIL,dev,strerror(errno));
1253 if (l64seek(fd,0,SEEK_SET) == -1)
1254 pr(FATAL,EM_SEEKFAILURE,dev);
1255
1256 /*
1257 * is there a guessed partition table?
1258 */
1259
1260 if (d->d_gpt.t_magic == le16(DOSPTMAGIC))
1261 {
1262 /*
1263 * ask if table should be hand-edited
1264 */
1265
1266 if (yesno(DM_EDITPTBL))
1267 while (1)
1268 {
1269 if ((n = number_or_quit(DM_EDITWHICHPART,1,NDOSPARTS)) < 0)
1270 break;
1271 if ((n >= 1) && (n <= NDOSPARTS))
1272 edit_partition(d,&d->d_gpt.t_parts[n - 1]);
1273 else
1274 break;
1275 print_ptable(d,&d->d_gpt,0);
1276 }
1277
1278
1279 /*
1280 * ask for the active partition.
1281 */
1282
1283 while (1)
1284 {
1285 if ((n = number_or_quit(DM_ACTWHICHPART,1,NDOSPARTS)) < 0)
1286 break;
1287 if ((n >= 1) && (n <= NDOSPARTS) &&
1288 get_part_type(d->d_gpt.t_parts[n].p_typ))
1289 {
1290 d->d_gpt.t_parts[n - 1].p_flag = DOSPARTACTIVE;
1291 break;
1292 }
1293 }
1294
1295 if (yesno(DM_WRITEIT))
1296 {
1297 memcpy(ptbl,d->d_pt.t_boot,DOSPARTOFF);
1298 memcpy(ptbl + DOSPARTOFF,d->d_gpt.t_parts,NDOSPARTS * sizeof(dos_part_entry) + 2);
1299 if (write(fd,ptbl,d->d_ssize) != d->d_ssize)
1300 pr(FATAL,EM_PTBLWRITE);
1301
1302 if (S_ISBLK(sbuf.st_mode) || S_ISCHR(sbuf.st_mode))
1303 {
1304 sync(); sleep(1); sync();
1305 reread_partition_table(fd);
1306 pr(WARN,DM_ASKTOREBOOT);
1307 }
1308 }
1309 else
1310 pr(MSG,DM_NOTWRITTEN);
1311 }
1312 close(fd);
1313 free((void *)uptbl);
1314 }
1315
1316
1317
1318 static void warn_invalid(disk_desc *d,dos_part_entry *p,char *w)
1319 {
1320 if (f_verbose > 1)
1321 {
1322 pr(MSG,EM_PINVALID,w);
1323 print_partition(d,p,0,0);
1324 }
1325 }
1326
1327
1328
1329 /*
1330 * after having gathered a list of possible partitions they
1331 * have to be checked for consistency. This routine must be
1332 * improved, it's too weird and is mistaken too often.
1333 */
1334
1335 static int check_partition_list(disk_desc *d)
1336 {
1337 dos_guessed_pt *gp, *prev;
1338 dos_part_entry *p, *rp, *ep, *lep;
1339 int n, npp, epp, maxp, in_ext;
1340 s64_t size, ofs;
1341
1342 p = rp = ep = lep = 0;
1343
1344 pr(MSG,DM_STARTCHECK);
1345
1346 /*
1347 * 1. pass: discard overlapping entries. This means
1348 * that the first entry is assumed to be ok.
1349 */
1350
1351 ofs = 0; prev = 0; npp = 0;
1352 for (gp = d->d_gl; gp; gp = gp->g_next)
1353 {
1354 if (gp->g_ext || gp->g_inv) continue;
1355 p = &gp->g_p[0];
1356 if (gp == d->d_gl)
1357 ofs = p->p_start + p->p_size;
1358 else
1359 {
1360 if (p->p_start < ofs)
1361 {
1362 /*
1363 * overlap. unlink and discard.
1364 */
1365
1366 prev->g_next = gp->g_next;
1367 free((void *)gp);
1368 gp = prev; npp++;
1369 }
1370 else
1371 ofs += p->p_size;
1372 }
1373 prev = gp;
1374 }
1375
1376 if (npp)
1377 pr(WARN,EM_DISCARDOVLP,npp);
1378
1379 /*
1380 * 2. pass: decide type of every partition,
1381 * marking inconsistent ones as invalid.
1382 */
1383
1384 size = 0;
1385 in_ext = npp = epp = 0; maxp = NDOSPARTS;
1386 for (n = 1, gp = d->d_gl; gp; gp = gp->g_next, n++)
1387 {
1388 if (gp->g_inv) continue;
1389 if (gp->g_ext)
1390 {
1391 if (gp->g_next == 0)
1392 {
1393 /*
1394 * ext ptbl without logical p.
1395 */
1396
1397 gp->g_inv = 1;
1398 warn_invalid(d,p,EM_P_EATEND);
1399 break;
1400 }
1401 if (! in_ext)
1402 {
1403 /*
1404 * new extended p. chain.
1405 */
1406
1407 if (no_of_ext_partitions(gp->g_p) == 0)
1408 {
1409 gp->g_inv = 1;
1410 warn_invalid(d,p,EM_P_EWLP);
1411 continue;
1412 }
1413
1414 in_ext = 1; epp++;
1415 if (maxp >= NDOSPARTS) maxp--;
1416
1417 /*
1418 * already had one?
1419 */
1420
1421 if (epp > 1)
1422 {
1423 gp->g_inv = 1;
1424 warn_invalid(d,p,EM_P_MTOE);
1425 continue;
1426 }
1427
1428 }
1429 if (no_of_ext_partitions(gp->g_p) == 0)
1430 in_ext = 0;
1431 rp = 0;
1432 for (p = &gp->g_p[0]; p < &gp->g_p[NDOSPARTS]; p++)
1433 {
1434 if (is_real_parttype(p))
1435 rp = p;
1436 else if (is_ext_parttype(p) && (n == 1))
1437 size = p->p_start;
1438 }
1439 gp = gp->g_next;
1440 if (gp->g_ext)
1441 {
1442 /*
1443 * should not happen: a supposedly logical
1444 * partition which is an extended p itself.
1445 */
1446
1447 gp->g_inv = 1;
1448 warn_invalid(d,p,EM_P_LISAE);
1449 continue;
1450 }
1451 else
1452 gp->g_log = 1;
1453
1454 /*
1455 * the p. type in the extended ptbl and the following
1456 * logical p. type must be identical. Also check size.
1457 */
1458
1459 p = &gp->g_p[0];
1460 if (is_real_parttype(p) && is_same_partition_type(rp,p) &&
1461 (rp->p_size >= p->p_size))
1462 {
1463 if (! is_sane_partentry(d,p,1))
1464 gp->g_inv = 1;
1465 else
1466 size += gp->g_p[0].p_size + 1;
1467 }
1468 else
1469 {
1470 gp->g_inv = 1;
1471 warn_invalid(d,p,EM_P_UTS);
1472 }
1473 }
1474 else if (! in_ext)
1475 {
1476 /*
1477 * primary entry.
1478 */
1479
1480 gp->g_prim = 1; p = &gp->g_p[0];
1481 if (n == 1) size = p->p_start;
1482 if (npp++ >= maxp)
1483 {
1484 gp->g_inv = 1;
1485 warn_invalid(d,p,EM_P_2MANYPP);
1486 }
1487 else
1488 {
1489 if (! is_sane_partentry(d,p,1))
1490 {
1491 gp->g_inv = 1;
1492 warn_invalid(d,p,EM_P_NOTSANE);
1493 }
1494 else
1495 size += p->p_size;
1496 }
1497 }
1498 else
1499 {
1500 /*
1501 * in_ext && !gp->g_ext. This means the end
1502 * of the logical partition chain hasn't been
1503 * found. Reset it.
1504 */
1505
1506 in_ext = 0; gp->g_inv = 1;
1507 warn_invalid(d,p,EM_P_ENDNOTF);
1508 }
1509 }
1510
1511 if (epp > 1)
1512 pr(WARN,EM_TOOMANYXPTS,epp);
1513 if (npp > maxp)
1514 pr(WARN,EM_TOOMANYPPTS,maxp,npp);
1515
1516 /*
1517 * 3. pass: check logical partition chain. Logical
1518 * partitions which seem ok but are not found in the
1519 * link chain are marked orphaned.
1520 */
1521
1522 in_ext = size = ofs = 0; lep = 0;
1523 for (gp = d->d_gl; gp; gp = gp->g_next)
1524 {
1525 if (gp->g_inv) continue;
1526 if (gp->g_ext)
1527 {
1528 if (! in_ext)
1529 {
1530 in_ext = 1; ofs = gp->g_sec;
1531 }
1532 rp = ep = 0;
1533 for (p = &gp->g_p[0]; p < &gp->g_p[NDOSPARTS]; p++)
1534 {
1535 if (is_real_parttype(p))
1536 rp = p;
1537 else if (is_ext_parttype(p))
1538 ep = p;
1539 }
1540
1541 if (lep && rp)
1542 if (gp->g_sec != ofs + lep->p_start)
1543 gp->g_next->g_orph = 1;
1544 if (ep) lep = ep;
1545 gp = gp->g_next;
1546 }
1547 }
1548
1549 /*
1550 * if the list was consistent the size of the whole
1551 * extended ptbl is equal to the end of the last eptbl
1552 * link.
1553 */
1554
1555 if (rp && lep)
1556 size = lep->p_start + lep->p_size;
1557 else
1558 size = ofs = 0;
1559
1560 for (gp = d->d_gl; gp; gp = gp->g_next)
1561 {
1562 if (gp->g_ext) continue;
1563 p = &gp->g_p[0];
1564 if (gp->g_log) pr(MSG," ");
1565 pr(MSG,"Partition(%s): ",get_part_type(p->p_typ));
1566 if (gp->g_inv) pr(MSG,PM_G_INVALID);
1567 if (gp->g_orph) pr(MSG,PM_G_ORPHANED);
1568 if (gp->g_prim) pr(MSG,PM_G_PRIMARY);
1569 if (gp->g_log) pr(MSG,PM_G_LOGICAL);
1570 pr(MSG,"\n");
1571 if (f_verbose > 1)
1572 print_partition(d,p,gp->g_log ? 1 : 0,0);
1573 }
1574
1575 /*
1576 * now fill in the guessed primary partition table.
1577 */
1578
1579 in_ext = n = 0;
1580 memset(&d->d_gpt,0,sizeof(dos_part_table));
1581 for (gp = d->d_gl; gp; gp = gp->g_next)
1582 {
1583 if (n >= NDOSPARTS) break;
1584 if (gp->g_inv) continue;
1585 if (gp->g_ext)
1586 {
1587 if (! in_ext)
1588 {
1589 in_ext = 1;
1590 if (size && ofs)
1591 {
1592 p = &d->d_gpt.t_parts[n++];
1593 p->p_start = ofs;
1594 p->p_typ = 0x05;
1595 p->p_typ = d->d_lba ? 0x0F : 0x05;
1596 p->p_size = size;
1597 fillin_dos_chs(d,p,0);
1598 }
1599 }
1600 gp = gp->g_next;
1601 continue;
1602 }
1603 if (gp->g_prim)
1604 memcpy(&d->d_gpt.t_parts[n++],&gp->g_p[0],sizeof(dos_part_entry));
1605 }
1606
1607 /*
1608 * final step: re-check this table. If ok, set the
1609 * ptbl magic number which is the indicator for
1610 * write_primary_ptbl that it seems to be ok.
1611 */
1612
1613 ep = 0; npp = 0;
1614 for (n = 0; n < NDOSPARTS; n++)
1615 {
1616 p = &d->d_gpt.t_parts[n];
1617 if (ep && p->p_typ)
1618 {
1619 if ((ep->p_start + ep->p_size > p->p_start) ||
1620 ! is_sane_partentry(d,p,1))
1621 {
1622 /*
1623 * zis is not funny. Perhaps the p. list
1624 * can be re-checked but for now only
1625 * inconsistencies are counted.
1626 */
1627
1628 npp++;
1629 if (f_verbose > 2)
1630 {
1631 pr(WARN,EM_PINCONS);
1632 print_partition(d,p,0,0);
1633 }
1634 }
1635 }
1636 ep = p;
1637 }
1638 if (npp == 0)
1639 {
1640 d->d_gpt.t_magic = le16(DOSPTMAGIC);
1641 pr(MSG,"Ok.\n");
1642 }
1643 else
1644 pr(MSG,DM_NOOFINCONS,npp);
1645 return (npp);
1646 }
1647
1648
1649
1650 /*
1651 * compare both existing and guessed partition tables.
1652 * The order of the ptbl entries is not important (the
1653 * physically first partition on disk can be in the last
1654 * ptbl slot).
1655 */
1656
1657 static int compare_parttables(disk_desc *d)
1658 {
1659 int ret, i, j, diff;
1660 byte_t *pr, *pg;
1661
1662 ret = 0;
1663 for (i = 0; i < NDOSPARTS; i++)
1664 {
1665 pr = (byte_t *)&d->d_pt.t_parts[i];
1666 for (j = 0; j < NDOSPARTS; j++)
1667 {
1668 pg = (byte_t *)&d->d_gpt.t_parts[j];
1669
1670 /*
1671 * the p_flag entry cannot be included
1672 * in the comparison.
1673 */
1674
1675 diff = memcmp(pr + 1,pg + 1,sizeof(dos_part_entry) - 1);
1676 if (diff == 0) break;
1677 }
1678 if (diff) ret++;
1679 }
1680 return (ret);
1681 }
1682
1683
1684
1685 /*
1686 * main
1687 */
1688
1689 int main(int ac,char **av)
1690 {
1691 char *optstr = "b:C:cdEefghiK:k:Ll:n:qs:t:VvW:w:";
1692 char *p1, *p2, *p3, *odev = 0, *backup = 0;
1693 int opt, sectsize = 0, no_of_incons = 0;
1694 disk_desc *d;
1695
1696
1697 g_mod_addinternals();
1698 while ((opt = getopt(ac,av,optstr)) != -1)
1699 switch (opt)
1700 {
1701 case 'b' :
1702 backup = optarg; break;
1703 case 'C' :
1704 if (! get_csep_arg(optarg,&p1,&p2,&p3))
1705 {
1706 usage();
1707 return (EXIT_FAILURE);
1708 }
1709 gc = strtoul(p1,0,0);
1710 if (errno == ERANGE) pr(FATAL,EM_INVVALUE);
1711 gh = strtoul(p2,0,0);
1712 if (errno == ERANGE) pr(FATAL,EM_INVVALUE);
1713 gs = strtoul(p3,0,0);
1714 if (errno == ERANGE) pr(FATAL,EM_INVVALUE);
1715 break;
1716 case 'c' :
1717 f_check = 1; break;
1718 case 'd' :
1719 f_dontguess = 1; break;
1720 case 'E' :
1721 f_testext = 0; break;
1722 case 'e' :
1723 f_skiperrors = 0; break;
1724 case 'f' :
1725 f_fast = 0; break;
1726 case 'g' :
1727 f_getgeom = 0; break;
1728 case 'i' :
1729 f_interactive = 1; break;
1730 case 'K' :
1731 maxsec = strtoul(optarg,0,0);
1732 if ((maxsec <= 0) || (errno == ERANGE))
1733 pr(FATAL,EM_INVVALUE);
1734 break;
1735 case 'k' :
1736 /* strtos64? */
1737 skipsec = strtoul(optarg,0,0);
1738 if (errno == ERANGE) pr(FATAL,EM_INVVALUE);
1739 break;
1740 case 'n' :
1741 if ((*optarg == 's') || (*optarg == 'h') ||
1742 (*optarg == 'c'))
1743 increment = *optarg;
1744 else
1745 {
1746 increment = strtoul(optarg,0,0);
1747 if (errno == ERANGE)
1748 pr(FATAL,EM_INVVALUE);
1749 }
1750 break;
1751 case 'l' :
1752 if (log) fclose(log);
1753 if ((log = fopen(optarg,"w")) == 0)
1754 pr(FATAL,EM_OPENLOG,optarg);
1755 break;
1756 case 'L' :
1757 g_mod_list();
1758 return (EXIT_SUCCESS);
1759 case 'q' :
1760 f_quiet = 1; break;
1761 case 's' :
1762 if ((sectsize = atoi(optarg)) <= 0)
1763 pr(FATAL,"sector size must be >= 0");
1764 break;
1765 case 't' :
1766 if (! g_mod_addexternal(optarg))
1767 return (EXIT_FAILURE);
1768 break;
1769 case 'v' :
1770 f_verbose++; break;
1771 case 'V' :
1772 fprintf(stderr,"%s\n",gpart_version);
1773 return (EXIT_SUCCESS);
1774 case 'w' :
1775 if (! get_csep_arg(optarg,&p1,&p2,0))
1776 {
1777 usage();
1778 return (EXIT_FAILURE);
1779 }
1780 if (! g_mod_setweight(p1,atof(p2)))
1781 pr(FATAL,EM_NOSUCHMOD,p1);
1782 break;
1783 case 'W' :
1784 odev = optarg;
1785 break;
1786 case '?' :
1787 case 'h' :
1788 default :
1789 usage(); return (EXIT_FAILURE);
1790 }
1791
1792 if ((optind + 1) != ac)
1793 {
1794 usage();
1795 return (EXIT_FAILURE);
1796 }
1797
1798 if (f_dontguess) f_check = 0;
1799 if (f_check)
1800 {
1801 f_quiet = 1;
1802 f_dontguess = 0;
1803 odev = 0;
1804 }
1805 if (f_quiet)
1806 f_interactive = 0;
1807
1808 sync(); d = get_disk_desc(av[optind],sectsize);
1809 if (f_verbose > 0)
1810 print_disk_desc(d);
1811 if (f_verbose > 2)
1812 print_mboot_block(d);
1813
1814 if (! f_dontguess)
1815 {
1816 sleep(1); sync();
1817 do_guess_loop(d);
1818 no_of_incons = check_partition_list(d);
1819 pr(MSG,DM_GUESSEDPTBL);
1820 print_ptable(d,&d->d_gpt,0);
1821
1822 if ((no_of_incons == 0) && f_check)
1823 no_of_incons = compare_parttables(d);
1824
1825 if ((no_of_incons == 0) && odev)
1826 {
1827 if (backup)
1828 make_mbr_backup(d,backup);
1829 write_primary_ptbl(d,odev);
1830 }
1831 }
1832 free_disk_desc(d);
1833 if (log) fclose(log);
1834
1835 return (f_check ? no_of_incons : 0);
1836 }
0 /*
1 * gpart.h -- gpart main header file
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _GPART_H
17 #define _GPART_H
18
19 #include "errmsgs.h"
20 #include "l64seek.h"
21
22 #define PROGRAM "gpart"
23
24
25 typedef unsigned char byte_t;
26
27
28
29 /*
30 * endianness (incomplete, later)
31 */
32
33 #if defined(__i386__) || defined(__alpha__)
34 # define le16(x) (x) /* x as little endian */
35 # define be16(x) ((((x)&0xff00)>>8) | \
36 (((x)&0x00ff)<<8))
37 # define le32(x) (x)
38 # define be32(x) ((((x)&0xff000000L)>>24) | \
39 (((x)&0x00ff0000L)>>8) | \
40 (((x)&0x0000ff00L)<<8) | \
41 (((x)&0x000000ffL)<<24))
42 # define le64(x) (x)
43 # define be64(x) ((((x)&0xff00000000000000LL)>>56) | \
44 (((x)&0x00ff000000000000LL)>>40) | \
45 (((x)&0x0000ff0000000000LL)>>24) | \
46 (((x)&0x000000ff00000000LL)>>8) | \
47 (((x)&0x00000000ff000000LL)<<8) | \
48 (((x)&0x0000000000ff0000LL)<<24) | \
49 (((x)&0x000000000000ff00LL)<<40) | \
50 (((x)&0x00000000000000ffLL)<<56))
51 #else /* bigendian */
52 # define le16(x) ((((x)&0xff00)>>8) | \
53 (((x)&0x00ff)<<8))
54 # define be16(x) (x)
55 # define le32(x) ((((x)&0xff000000L)>>24) | \
56 (((x)&0x00ff0000L)>>8) | \
57 (((x)&0x0000ff00L)<<8) | \
58 (((x)&0x000000ffL)<<24))
59 # define be32(x) (x)
60 # define le64(x) ((((x)&0xff00000000000000LL)>>56) | \
61 (((x)&0x00ff000000000000LL)>>40) | \
62 (((x)&0x0000ff0000000000LL)>>24) | \
63 (((x)&0x000000ff00000000LL)>>8) | \
64 (((x)&0x00000000ff000000LL)<<8) | \
65 (((x)&0x0000000000ff0000LL)<<24) | \
66 (((x)&0x000000000000ff00LL)<<40) | \
67 (((x)&0x00000000000000ffLL)<<56))
68 # define be64(x) (x)
69 #endif
70
71
72 #ifndef max
73 # define max(a,b) ((a)>(b)?(a):(b))
74 # define min(a,b) ((a)<(b)?(a):(b))
75 #endif
76
77 #define MINSSIZE (512) /* min. sector size */
78 #define MAXSSIZE (16384)
79
80 #define FATAL 1 /* fatal error, exit */
81 #define ERROR 2 /* non-fatal error */
82 #define WARN 3
83 #define MSG 4 /* normal message */
84
85 void pr(int,char *,...);
86 ssize_t bread(int,byte_t *,size_t,size_t);
87 byte_t *alloc(ssize_t);
88
89
90
91 /*
92 * dos partition table stuff
93 */
94
95 #define DOSMBSECTOR 0 /* absolute sector # of mbr */
96 #define NDOSPARTS 4 /* # of primary partitions */
97 #define DOSPARTOFF 446 /* offset of part-table in mbr */
98 #define DOSPARTACTIVE 0x80 /* active (boot) flag */
99 #define DOSPTMAGIC 0xaa55 /* signature */
100 #define DOSCYL(cyl,s) ((cyl)+(((s)&0xc0)<<2))
101 #define DOSSEC(s) ((s)&0x3f)
102
103
104 typedef struct
105 {
106 byte_t p_flag; /* bootstrap flags */
107 byte_t p_shd; /* starting head */
108 byte_t p_ssect; /* starting sector */
109 byte_t p_scyl; /* starting cylinder */
110 byte_t p_typ; /* partition type */
111 byte_t p_ehd; /* end head */
112 byte_t p_esect; /* end sector */
113 byte_t p_ecyl; /* end cylinder */
114 unsigned long p_start; /* start sector (absolute) */
115 unsigned long p_size; /* # of sectors */
116 } dos_part_entry;
117
118
119 typedef struct dos_pt
120 {
121 struct dos_pt *t_ext; /* -> extended parttable */
122 byte_t _align[2];
123 byte_t t_boot[DOSPARTOFF];
124 dos_part_entry t_parts[NDOSPARTS];
125 unsigned short t_magic; /* DOSPTMAGIC */
126 } dos_part_table;
127
128
129 typedef struct dos_gp
130 {
131 dos_part_entry g_p[NDOSPARTS];
132 struct dos_gp *g_next;
133 s64_t g_sec; /* found there */
134 unsigned int g_ext : 1; /* extended ptbl */
135 unsigned int g_prim : 1; /* primary partition */
136 unsigned int g_log : 1; /* logical partition */
137 unsigned int g_inv : 1; /* invalid entry */
138 unsigned int g_orph : 1; /* orphaned partition */
139 } dos_guessed_pt;
140
141 /*
142 * disk description used
143 */
144
145 typedef struct
146 {
147 char *d_dev; /* device name */
148 int d_fd; /* file descriptor when open */
149 ssize_t d_ssize; /* sector size */
150 byte_t *d_sbuf; /* sector buffer */
151 s64_t d_nsecs; /* total no of sectors */
152 s64_t d_nsb; /* # of first sector in sbuf on disk */
153 struct disk_geom /* disk geometry */
154 {
155 long d_c; /* cylinder count */
156 long d_h; /* heads/cyl */
157 long d_s; /* sectors/head */
158 long d_rc; /* real values if the above are */
159 long d_rh; /* translated */
160 long d_rs;
161 } d_dg;
162 unsigned int d_lba : 1;
163 unsigned int d_dosc : 1; /* dos compatible? (g_c < 1024) */
164 dos_part_table d_pt; /* table of primary partitions */
165 dos_part_table d_gpt; /* guessed ptbl */
166 dos_guessed_pt *d_gl; /* list of gathered guesses */
167 } disk_desc;
168
169
170 struct disk_geom *disk_geometry(disk_desc *);
171 int reread_partition_table(int);
172
173 #define s2mb(d,s) { (s)*=(d)->d_ssize; (s)/=1024; (s)/=1024; }
174 #define align(b,s) (byte_t *)(((size_t)(b)+(s)-1)&~((s)-1))
175
176 #include "gmodules.h"
177
178
179 #endif /* _GPART_H */
0 /*
1 * l64seek.c -- gpart signed 64bit seek
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #include "l64seek.h"
17
18
19 #define OSTACKLEN 16
20 static struct
21 {
22 s64_t fpos;
23 int fd;
24 } ostck[OSTACKLEN];
25 static int osptr = -1;
26
27 #if defined(__linux__) && defined(__i386__)
28 _syscall5(int,_llseek,uint,fd,ulong,hi,ulong,lo,loff_t *,res,uint,wh)
29 #endif
30
31
32
33 off64_t l64seek(int fd,off64_t offset,int whence)
34 {
35 off64_t ret = (off64_t)-1;
36
37 #if defined(__linux__) && defined(__i386__)
38 int iret;
39 unsigned long ohi, olo;
40
41 ohi = (unsigned long)((offset >> 32) & 0xFFFFFFFF);
42 olo = (unsigned long)(offset & 0xFFFFFFFF);
43 iret = _llseek(fd,ohi,olo,&ret,whence);
44 if (iret == -1)
45 ret = (off64_t)-1;
46 #endif
47
48 #if defined(__FreeBSD__) || (defined(__linux__) && defined(__alpha__))
49 ret = lseek(fd,offset,whence);
50 #endif
51
52 return (ret);
53 }
54
55
56
57 int l64opush(int fd)
58 {
59 s64_t fpos;
60
61 if (osptr < OSTACKLEN - 1)
62 {
63 if ((fpos = l64tell(fd)) >= 0)
64 {
65 ostck[++osptr].fd = fd;
66 ostck[osptr].fpos = fpos;
67 return (1);
68 }
69 }
70 return (0);
71 }
72
73
74 s64_t l64opop(int fd)
75 {
76 if ((osptr >= 0) && (ostck[osptr].fd == fd))
77 return (ostck[osptr--].fpos);
78 return (-1);
79 }
0 /*
1 * l64seek.h -- gpart signed 64bit seek header file
2 *
3 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
4 * Guess PC-type hard disk partitions.
5 *
6 * gpart is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * Created: 04.01.1999 <mb@ichabod.han.de>
12 * Modified:
13 *
14 */
15
16 #ifndef _L64SEEK_H
17 #define _L64SEEK_H
18
19 #include <unistd.h>
20
21 /*
22 * define a type 'off64_t' which is at least 64bit, and a
23 * lseek function capable of seeking with at least 64bit
24 * offsets.
25 */
26
27
28 #if defined(__linux__)
29 # include <linux/unistd.h>
30 # include <sys/types.h>
31 typedef int64_t off64_t;
32 #endif
33
34
35 #if defined(__FreeBSD__)
36 typedef off_t off64_t;
37 #endif
38
39
40 typedef off64_t s64_t;
41
42 off64_t l64seek(int fd, off64_t offset, int whence);
43 #define l64tell(fd) l64seek(fd,0,SEEK_CUR)
44 int l64opush(int);
45 s64_t l64opop(int);
46
47
48 #endif