Adding upstream version 0.1h.
Daniel Baumann
15 years ago
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. |
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 |