1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libe2access/Control Wed Aug 25 01:28:08 2021 +0200
1.3 @@ -0,0 +1,3 @@
1.4 +requires: libc libext2fs libsystypes
1.5 +provides: libe2access
1.6 +maintainer: paul@boddie.org.uk
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/libe2access/Makefile Wed Aug 25 01:28:08 2021 +0200
2.3 @@ -0,0 +1,4 @@
2.4 +PKGDIR ?= .
2.5 +L4DIR ?= $(PKGDIR)/../../..
2.6 +
2.7 +include $(L4DIR)/mk/subdir.mk
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/libe2access/docs/COPYING-GPL-2 Wed Aug 25 01:28:08 2021 +0200
3.3 @@ -0,0 +1,1 @@
3.4 +LICENCE.txt
3.5 \ No newline at end of file
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/libe2access/docs/COPYING.txt Wed Aug 25 01:28:08 2021 +0200
4.3 @@ -0,0 +1,22 @@
4.4 +Licence Agreement
4.5 +-----------------
4.6 +
4.7 +All original work in this distribution is covered by the following copyright
4.8 +and licensing information:
4.9 +
4.10 +Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
4.11 +
4.12 +This software is free software; you can redistribute it and/or
4.13 +modify it under the terms of the GNU General Public License as
4.14 +published by the Free Software Foundation; either version 2 of
4.15 +the License, or (at your option) any later version.
4.16 +
4.17 +This software is distributed in the hope that it will be useful,
4.18 +but WITHOUT ANY WARRANTY; without even the implied warranty of
4.19 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.20 +GNU General Public License for more details.
4.21 +
4.22 +You should have received a copy of the GNU General Public
4.23 +License along with this library; see the file LICENCE.txt
4.24 +If not, write to the Free Software Foundation, Inc.,
4.25 +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/libe2access/docs/LICENCE.txt Wed Aug 25 01:28:08 2021 +0200
5.3 @@ -0,0 +1,339 @@
5.4 + GNU GENERAL PUBLIC LICENSE
5.5 + Version 2, June 1991
5.6 +
5.7 + Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5.8 + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
5.9 + Everyone is permitted to copy and distribute verbatim copies
5.10 + of this license document, but changing it is not allowed.
5.11 +
5.12 + Preamble
5.13 +
5.14 + The licenses for most software are designed to take away your
5.15 +freedom to share and change it. By contrast, the GNU General Public
5.16 +License is intended to guarantee your freedom to share and change free
5.17 +software--to make sure the software is free for all its users. This
5.18 +General Public License applies to most of the Free Software
5.19 +Foundation's software and to any other program whose authors commit to
5.20 +using it. (Some other Free Software Foundation software is covered by
5.21 +the GNU Lesser General Public License instead.) You can apply it to
5.22 +your programs, too.
5.23 +
5.24 + When we speak of free software, we are referring to freedom, not
5.25 +price. Our General Public Licenses are designed to make sure that you
5.26 +have the freedom to distribute copies of free software (and charge for
5.27 +this service if you wish), that you receive source code or can get it
5.28 +if you want it, that you can change the software or use pieces of it
5.29 +in new free programs; and that you know you can do these things.
5.30 +
5.31 + To protect your rights, we need to make restrictions that forbid
5.32 +anyone to deny you these rights or to ask you to surrender the rights.
5.33 +These restrictions translate to certain responsibilities for you if you
5.34 +distribute copies of the software, or if you modify it.
5.35 +
5.36 + For example, if you distribute copies of such a program, whether
5.37 +gratis or for a fee, you must give the recipients all the rights that
5.38 +you have. You must make sure that they, too, receive or can get the
5.39 +source code. And you must show them these terms so they know their
5.40 +rights.
5.41 +
5.42 + We protect your rights with two steps: (1) copyright the software, and
5.43 +(2) offer you this license which gives you legal permission to copy,
5.44 +distribute and/or modify the software.
5.45 +
5.46 + Also, for each author's protection and ours, we want to make certain
5.47 +that everyone understands that there is no warranty for this free
5.48 +software. If the software is modified by someone else and passed on, we
5.49 +want its recipients to know that what they have is not the original, so
5.50 +that any problems introduced by others will not reflect on the original
5.51 +authors' reputations.
5.52 +
5.53 + Finally, any free program is threatened constantly by software
5.54 +patents. We wish to avoid the danger that redistributors of a free
5.55 +program will individually obtain patent licenses, in effect making the
5.56 +program proprietary. To prevent this, we have made it clear that any
5.57 +patent must be licensed for everyone's free use or not licensed at all.
5.58 +
5.59 + The precise terms and conditions for copying, distribution and
5.60 +modification follow.
5.61 +
5.62 + GNU GENERAL PUBLIC LICENSE
5.63 + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
5.64 +
5.65 + 0. This License applies to any program or other work which contains
5.66 +a notice placed by the copyright holder saying it may be distributed
5.67 +under the terms of this General Public License. The "Program", below,
5.68 +refers to any such program or work, and a "work based on the Program"
5.69 +means either the Program or any derivative work under copyright law:
5.70 +that is to say, a work containing the Program or a portion of it,
5.71 +either verbatim or with modifications and/or translated into another
5.72 +language. (Hereinafter, translation is included without limitation in
5.73 +the term "modification".) Each licensee is addressed as "you".
5.74 +
5.75 +Activities other than copying, distribution and modification are not
5.76 +covered by this License; they are outside its scope. The act of
5.77 +running the Program is not restricted, and the output from the Program
5.78 +is covered only if its contents constitute a work based on the
5.79 +Program (independent of having been made by running the Program).
5.80 +Whether that is true depends on what the Program does.
5.81 +
5.82 + 1. You may copy and distribute verbatim copies of the Program's
5.83 +source code as you receive it, in any medium, provided that you
5.84 +conspicuously and appropriately publish on each copy an appropriate
5.85 +copyright notice and disclaimer of warranty; keep intact all the
5.86 +notices that refer to this License and to the absence of any warranty;
5.87 +and give any other recipients of the Program a copy of this License
5.88 +along with the Program.
5.89 +
5.90 +You may charge a fee for the physical act of transferring a copy, and
5.91 +you may at your option offer warranty protection in exchange for a fee.
5.92 +
5.93 + 2. You may modify your copy or copies of the Program or any portion
5.94 +of it, thus forming a work based on the Program, and copy and
5.95 +distribute such modifications or work under the terms of Section 1
5.96 +above, provided that you also meet all of these conditions:
5.97 +
5.98 + a) You must cause the modified files to carry prominent notices
5.99 + stating that you changed the files and the date of any change.
5.100 +
5.101 + b) You must cause any work that you distribute or publish, that in
5.102 + whole or in part contains or is derived from the Program or any
5.103 + part thereof, to be licensed as a whole at no charge to all third
5.104 + parties under the terms of this License.
5.105 +
5.106 + c) If the modified program normally reads commands interactively
5.107 + when run, you must cause it, when started running for such
5.108 + interactive use in the most ordinary way, to print or display an
5.109 + announcement including an appropriate copyright notice and a
5.110 + notice that there is no warranty (or else, saying that you provide
5.111 + a warranty) and that users may redistribute the program under
5.112 + these conditions, and telling the user how to view a copy of this
5.113 + License. (Exception: if the Program itself is interactive but
5.114 + does not normally print such an announcement, your work based on
5.115 + the Program is not required to print an announcement.)
5.116 +
5.117 +These requirements apply to the modified work as a whole. If
5.118 +identifiable sections of that work are not derived from the Program,
5.119 +and can be reasonably considered independent and separate works in
5.120 +themselves, then this License, and its terms, do not apply to those
5.121 +sections when you distribute them as separate works. But when you
5.122 +distribute the same sections as part of a whole which is a work based
5.123 +on the Program, the distribution of the whole must be on the terms of
5.124 +this License, whose permissions for other licensees extend to the
5.125 +entire whole, and thus to each and every part regardless of who wrote it.
5.126 +
5.127 +Thus, it is not the intent of this section to claim rights or contest
5.128 +your rights to work written entirely by you; rather, the intent is to
5.129 +exercise the right to control the distribution of derivative or
5.130 +collective works based on the Program.
5.131 +
5.132 +In addition, mere aggregation of another work not based on the Program
5.133 +with the Program (or with a work based on the Program) on a volume of
5.134 +a storage or distribution medium does not bring the other work under
5.135 +the scope of this License.
5.136 +
5.137 + 3. You may copy and distribute the Program (or a work based on it,
5.138 +under Section 2) in object code or executable form under the terms of
5.139 +Sections 1 and 2 above provided that you also do one of the following:
5.140 +
5.141 + a) Accompany it with the complete corresponding machine-readable
5.142 + source code, which must be distributed under the terms of Sections
5.143 + 1 and 2 above on a medium customarily used for software interchange; or,
5.144 +
5.145 + b) Accompany it with a written offer, valid for at least three
5.146 + years, to give any third party, for a charge no more than your
5.147 + cost of physically performing source distribution, a complete
5.148 + machine-readable copy of the corresponding source code, to be
5.149 + distributed under the terms of Sections 1 and 2 above on a medium
5.150 + customarily used for software interchange; or,
5.151 +
5.152 + c) Accompany it with the information you received as to the offer
5.153 + to distribute corresponding source code. (This alternative is
5.154 + allowed only for noncommercial distribution and only if you
5.155 + received the program in object code or executable form with such
5.156 + an offer, in accord with Subsection b above.)
5.157 +
5.158 +The source code for a work means the preferred form of the work for
5.159 +making modifications to it. For an executable work, complete source
5.160 +code means all the source code for all modules it contains, plus any
5.161 +associated interface definition files, plus the scripts used to
5.162 +control compilation and installation of the executable. However, as a
5.163 +special exception, the source code distributed need not include
5.164 +anything that is normally distributed (in either source or binary
5.165 +form) with the major components (compiler, kernel, and so on) of the
5.166 +operating system on which the executable runs, unless that component
5.167 +itself accompanies the executable.
5.168 +
5.169 +If distribution of executable or object code is made by offering
5.170 +access to copy from a designated place, then offering equivalent
5.171 +access to copy the source code from the same place counts as
5.172 +distribution of the source code, even though third parties are not
5.173 +compelled to copy the source along with the object code.
5.174 +
5.175 + 4. You may not copy, modify, sublicense, or distribute the Program
5.176 +except as expressly provided under this License. Any attempt
5.177 +otherwise to copy, modify, sublicense or distribute the Program is
5.178 +void, and will automatically terminate your rights under this License.
5.179 +However, parties who have received copies, or rights, from you under
5.180 +this License will not have their licenses terminated so long as such
5.181 +parties remain in full compliance.
5.182 +
5.183 + 5. You are not required to accept this License, since you have not
5.184 +signed it. However, nothing else grants you permission to modify or
5.185 +distribute the Program or its derivative works. These actions are
5.186 +prohibited by law if you do not accept this License. Therefore, by
5.187 +modifying or distributing the Program (or any work based on the
5.188 +Program), you indicate your acceptance of this License to do so, and
5.189 +all its terms and conditions for copying, distributing or modifying
5.190 +the Program or works based on it.
5.191 +
5.192 + 6. Each time you redistribute the Program (or any work based on the
5.193 +Program), the recipient automatically receives a license from the
5.194 +original licensor to copy, distribute or modify the Program subject to
5.195 +these terms and conditions. You may not impose any further
5.196 +restrictions on the recipients' exercise of the rights granted herein.
5.197 +You are not responsible for enforcing compliance by third parties to
5.198 +this License.
5.199 +
5.200 + 7. If, as a consequence of a court judgment or allegation of patent
5.201 +infringement or for any other reason (not limited to patent issues),
5.202 +conditions are imposed on you (whether by court order, agreement or
5.203 +otherwise) that contradict the conditions of this License, they do not
5.204 +excuse you from the conditions of this License. If you cannot
5.205 +distribute so as to satisfy simultaneously your obligations under this
5.206 +License and any other pertinent obligations, then as a consequence you
5.207 +may not distribute the Program at all. For example, if a patent
5.208 +license would not permit royalty-free redistribution of the Program by
5.209 +all those who receive copies directly or indirectly through you, then
5.210 +the only way you could satisfy both it and this License would be to
5.211 +refrain entirely from distribution of the Program.
5.212 +
5.213 +If any portion of this section is held invalid or unenforceable under
5.214 +any particular circumstance, the balance of the section is intended to
5.215 +apply and the section as a whole is intended to apply in other
5.216 +circumstances.
5.217 +
5.218 +It is not the purpose of this section to induce you to infringe any
5.219 +patents or other property right claims or to contest validity of any
5.220 +such claims; this section has the sole purpose of protecting the
5.221 +integrity of the free software distribution system, which is
5.222 +implemented by public license practices. Many people have made
5.223 +generous contributions to the wide range of software distributed
5.224 +through that system in reliance on consistent application of that
5.225 +system; it is up to the author/donor to decide if he or she is willing
5.226 +to distribute software through any other system and a licensee cannot
5.227 +impose that choice.
5.228 +
5.229 +This section is intended to make thoroughly clear what is believed to
5.230 +be a consequence of the rest of this License.
5.231 +
5.232 + 8. If the distribution and/or use of the Program is restricted in
5.233 +certain countries either by patents or by copyrighted interfaces, the
5.234 +original copyright holder who places the Program under this License
5.235 +may add an explicit geographical distribution limitation excluding
5.236 +those countries, so that distribution is permitted only in or among
5.237 +countries not thus excluded. In such case, this License incorporates
5.238 +the limitation as if written in the body of this License.
5.239 +
5.240 + 9. The Free Software Foundation may publish revised and/or new versions
5.241 +of the General Public License from time to time. Such new versions will
5.242 +be similar in spirit to the present version, but may differ in detail to
5.243 +address new problems or concerns.
5.244 +
5.245 +Each version is given a distinguishing version number. If the Program
5.246 +specifies a version number of this License which applies to it and "any
5.247 +later version", you have the option of following the terms and conditions
5.248 +either of that version or of any later version published by the Free
5.249 +Software Foundation. If the Program does not specify a version number of
5.250 +this License, you may choose any version ever published by the Free Software
5.251 +Foundation.
5.252 +
5.253 + 10. If you wish to incorporate parts of the Program into other free
5.254 +programs whose distribution conditions are different, write to the author
5.255 +to ask for permission. For software which is copyrighted by the Free
5.256 +Software Foundation, write to the Free Software Foundation; we sometimes
5.257 +make exceptions for this. Our decision will be guided by the two goals
5.258 +of preserving the free status of all derivatives of our free software and
5.259 +of promoting the sharing and reuse of software generally.
5.260 +
5.261 + NO WARRANTY
5.262 +
5.263 + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
5.264 +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
5.265 +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
5.266 +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
5.267 +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5.268 +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
5.269 +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
5.270 +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
5.271 +REPAIR OR CORRECTION.
5.272 +
5.273 + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
5.274 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
5.275 +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
5.276 +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
5.277 +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
5.278 +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
5.279 +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
5.280 +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
5.281 +POSSIBILITY OF SUCH DAMAGES.
5.282 +
5.283 + END OF TERMS AND CONDITIONS
5.284 +
5.285 + How to Apply These Terms to Your New Programs
5.286 +
5.287 + If you develop a new program, and you want it to be of the greatest
5.288 +possible use to the public, the best way to achieve this is to make it
5.289 +free software which everyone can redistribute and change under these terms.
5.290 +
5.291 + To do so, attach the following notices to the program. It is safest
5.292 +to attach them to the start of each source file to most effectively
5.293 +convey the exclusion of warranty; and each file should have at least
5.294 +the "copyright" line and a pointer to where the full notice is found.
5.295 +
5.296 + <one line to give the program's name and a brief idea of what it does.>
5.297 + Copyright (C) <year> <name of author>
5.298 +
5.299 + This program is free software; you can redistribute it and/or modify
5.300 + it under the terms of the GNU General Public License as published by
5.301 + the Free Software Foundation; either version 2 of the License, or
5.302 + (at your option) any later version.
5.303 +
5.304 + This program is distributed in the hope that it will be useful,
5.305 + but WITHOUT ANY WARRANTY; without even the implied warranty of
5.306 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.307 + GNU General Public License for more details.
5.308 +
5.309 + You should have received a copy of the GNU General Public License along
5.310 + with this program; if not, write to the Free Software Foundation, Inc.,
5.311 + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
5.312 +
5.313 +Also add information on how to contact you by electronic and paper mail.
5.314 +
5.315 +If the program is interactive, make it output a short notice like this
5.316 +when it starts in an interactive mode:
5.317 +
5.318 + Gnomovision version 69, Copyright (C) year name of author
5.319 + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
5.320 + This is free software, and you are welcome to redistribute it
5.321 + under certain conditions; type `show c' for details.
5.322 +
5.323 +The hypothetical commands `show w' and `show c' should show the appropriate
5.324 +parts of the General Public License. Of course, the commands you use may
5.325 +be called something other than `show w' and `show c'; they could even be
5.326 +mouse-clicks or menu items--whatever suits your program.
5.327 +
5.328 +You should also get your employer (if you work as a programmer) or your
5.329 +school, if any, to sign a "copyright disclaimer" for the program, if
5.330 +necessary. Here is a sample; alter the names:
5.331 +
5.332 + Yoyodyne, Inc., hereby disclaims all copyright interest in the program
5.333 + `Gnomovision' (which makes passes at compilers) written by James Hacker.
5.334 +
5.335 + <signature of Ty Coon>, 1 April 1989
5.336 + Ty Coon, President of Vice
5.337 +
5.338 +This General Public License does not permit incorporating your program into
5.339 +proprietary programs. If your program is a subroutine library, you may
5.340 +consider it more useful to permit linking proprietary applications with the
5.341 +library. If this is what you want to do, use the GNU Lesser General
5.342 +Public License instead of this License.
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/libe2access/include/Makefile Wed Aug 25 01:28:08 2021 +0200
6.3 @@ -0,0 +1,7 @@
6.4 +PKGDIR ?= ..
6.5 +L4DIR ?= $(PKGDIR)/../../..
6.6 +
6.7 +PKGNAME = libe2access
6.8 +CONTRIB_HEADERS = 1
6.9 +
6.10 +include $(L4DIR)/mk/include.mk
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/libe2access/include/e2access/access.h Wed Aug 25 01:28:08 2021 +0200
7.3 @@ -0,0 +1,32 @@
7.4 +/*
7.5 + * Access control functions.
7.6 + *
7.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
7.8 + *
7.9 + * This program is free software; you can redistribute it and/or
7.10 + * modify it under the terms of the GNU General Public License as
7.11 + * published by the Free Software Foundation; either version 2 of
7.12 + * the License, or (at your option) any later version.
7.13 + *
7.14 + * This program is distributed in the hope that it will be useful,
7.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.17 + * GNU General Public License for more details.
7.18 + *
7.19 + * You should have received a copy of the GNU General Public License
7.20 + * along with this program; if not, write to the Free Software
7.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
7.22 + * Boston, MA 02110-1301, USA
7.23 + */
7.24 +
7.25 +#pragma once
7.26 +
7.27 +#include <ext2fs/ext2fs.h>
7.28 +#include <systypes/user.h>
7.29 +
7.30 +EXTERN_C_BEGIN
7.31 +
7.32 +int access_can_read(user_t user, struct ext2_inode *inode);
7.33 +int access_can_write(user_t user, struct ext2_inode *inode);
7.34 +
7.35 +EXTERN_C_END
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/libe2access/include/e2access/format.h Wed Aug 25 01:28:08 2021 +0200
8.3 @@ -0,0 +1,37 @@
8.4 +/*
8.5 + * File metadata formatting.
8.6 + *
8.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
8.8 + *
8.9 + * This program is free software; you can redistribute it and/or
8.10 + * modify it under the terms of the GNU General Public License as
8.11 + * published by the Free Software Foundation; either version 2 of
8.12 + * the License, or (at your option) any later version.
8.13 + *
8.14 + * This program is distributed in the hope that it will be useful,
8.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.17 + * GNU General Public License for more details.
8.18 + *
8.19 + * You should have received a copy of the GNU General Public License
8.20 + * along with this program; if not, write to the Free Software
8.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
8.22 + * Boston, MA 02110-1301, USA
8.23 + */
8.24 +
8.25 +#ifndef __FORMAT_H__
8.26 +#define __FORMAT_H__
8.27 +
8.28 +#include <stdint.h>
8.29 +
8.30 +#ifdef __cplusplus
8.31 +extern "C" {
8.32 +#endif
8.33 +
8.34 +char *get_permission_string(uint16_t permissions);
8.35 +
8.36 +#ifdef __cplusplus
8.37 +}
8.38 +#endif
8.39 +
8.40 +#endif /* __FORMAT_H__ */
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/libe2access/include/e2access/image.h Wed Aug 25 01:28:08 2021 +0200
9.3 @@ -0,0 +1,79 @@
9.4 +/*
9.5 + * Filesystem image access functions.
9.6 + *
9.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
9.8 + *
9.9 + * This program is free software; you can redistribute it and/or
9.10 + * modify it under the terms of the GNU General Public License as
9.11 + * published by the Free Software Foundation; either version 2 of
9.12 + * the License, or (at your option) any later version.
9.13 + *
9.14 + * This program is distributed in the hope that it will be useful,
9.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9.17 + * GNU General Public License for more details.
9.18 + *
9.19 + * You should have received a copy of the GNU General Public License
9.20 + * along with this program; if not, write to the Free Software
9.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
9.22 + * Boston, MA 02110-1301, USA
9.23 + */
9.24 +
9.25 +#ifndef __IMAGE_H__
9.26 +#define __IMAGE_H__
9.27 +
9.28 +#include <ext2fs/ext2fs.h>
9.29 +
9.30 +
9.31 +
9.32 +#ifdef __cplusplus
9.33 +extern "C" {
9.34 +#endif
9.35 +
9.36 +errcode_t image_create_file(ext2_filsys fs, ext2_ino_t ino_target,
9.37 + const char *basename, __u16 mode,
9.38 + __u16 uid, __u16 gid, ext2_ino_t *ino_file);
9.39 +
9.40 +errcode_t image_find_next(ext2_filsys fs, ext2_ino_t ino_dir,
9.41 + const char **basename, char *buf, ext2_ino_t *ino);
9.42 +
9.43 +errcode_t image_find_path(ext2_filsys fs, const char **pathname,
9.44 + ext2_ino_t *ino);
9.45 +
9.46 +errcode_t image_find_file(ext2_filsys fs, const char *dirname,
9.47 + const char *basename, ext2_ino_t *ino);
9.48 +
9.49 +errcode_t image_inode(ext2_filsys fs, const char *pathname,
9.50 + struct ext2_inode *inode);
9.51 +
9.52 +errcode_t image_make_dir(ext2_filsys fs, ext2_ino_t ino_dir,
9.53 + const char *basename, __u16 mode,
9.54 + __u16 uid, __u16 gid, ext2_ino_t *ino);
9.55 +
9.56 +errcode_t image_make_next_dir(ext2_filsys fs, ext2_ino_t ino_dir,
9.57 + const char **basename, __u16 mode, __u16 uid,
9.58 + __u16 gid, ext2_ino_t *ino);
9.59 +
9.60 +errcode_t image_make_dirs(ext2_filsys fs, const char **pathname,
9.61 + ext2_ino_t ino_dir, __u16 mode, __u16 uid,
9.62 + __u16 gid);
9.63 +
9.64 +void image_set_metadata(struct ext2_inode *inode, int clean, __u16 mode,
9.65 + __u16 uid, __u16 gid);
9.66 +
9.67 +errcode_t image_stat_inode(ext2_filsys fs, ext2_ino_t ino, struct stat *st);
9.68 +
9.69 +int _image_isdir(ext2_filsys fs, ext2_ino_t ino);
9.70 +
9.71 +int image_isdir(ext2_filsys fs, const char *name);
9.72 +
9.73 +int _image_isfile(ext2_filsys fs, ext2_ino_t ino);
9.74 +
9.75 +int image_isfile(ext2_filsys fs, const char *name);
9.76 +
9.77 +#ifdef __cplusplus
9.78 +}
9.79 +#endif
9.80 +
9.81 +
9.82 +#endif /* __IMAGE_H__ */
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/libe2access/include/e2access/path.h Wed Aug 25 01:28:08 2021 +0200
10.3 @@ -0,0 +1,38 @@
10.4 +/*
10.5 + * Path functions.
10.6 + *
10.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
10.8 + *
10.9 + * This program is free software; you can redistribute it and/or
10.10 + * modify it under the terms of the GNU General Public License as
10.11 + * published by the Free Software Foundation; either version 2 of
10.12 + * the License, or (at your option) any later version.
10.13 + *
10.14 + * This program is distributed in the hope that it will be useful,
10.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10.17 + * GNU General Public License for more details.
10.18 + *
10.19 + * You should have received a copy of the GNU General Public License
10.20 + * along with this program; if not, write to the Free Software
10.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
10.22 + * Boston, MA 02110-1301, USA
10.23 + */
10.24 +
10.25 +#ifndef __PATH_H__
10.26 +#define __PATH_H__
10.27 +
10.28 +#ifdef __cplusplus
10.29 +extern "C" {
10.30 +#endif
10.31 +
10.32 +const char *path_basename(const char *path);
10.33 +const char *path_component_end(const char *path);
10.34 +const char *path_component_next(const char *end);
10.35 +int path_is_leafname(const char *path);
10.36 +
10.37 +#ifdef __cplusplus
10.38 +}
10.39 +#endif
10.40 +
10.41 +#endif /* __PATH_H__ */
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/libe2access/lib/Makefile Wed Aug 25 01:28:08 2021 +0200
11.3 @@ -0,0 +1,4 @@
11.4 +PKGDIR ?= ..
11.5 +L4DIR ?= $(PKGDIR)/../../..
11.6 +
11.7 +include $(L4DIR)/mk/subdir.mk
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/libe2access/lib/src/Makefile Wed Aug 25 01:28:08 2021 +0200
12.3 @@ -0,0 +1,13 @@
12.4 +PKGDIR ?= ../..
12.5 +L4DIR ?= $(PKGDIR)/../../..
12.6 +
12.7 +TARGET = libe2access.a libe2access.so
12.8 +PC_FILENAME = libe2access
12.9 +SRC_C = access.c format.c image.c path.c
12.10 +
12.11 +REQUIRES_LIBS = libext2fs libsystypes
12.12 +
12.13 +PRIVATE_INCDIR = $(PKGDIR)/include/e2access
12.14 +CONTRIB_INCDIR = libe2access
12.15 +
12.16 +include $(L4DIR)/mk/lib.mk
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/libe2access/lib/src/access.c Wed Aug 25 01:28:08 2021 +0200
13.3 @@ -0,0 +1,42 @@
13.4 +/*
13.5 + * Access control functions.
13.6 + *
13.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
13.8 + *
13.9 + * This program is free software; you can redistribute it and/or
13.10 + * modify it under the terms of the GNU General Public License as
13.11 + * published by the Free Software Foundation; either version 2 of
13.12 + * the License, or (at your option) any later version.
13.13 + *
13.14 + * This program is distributed in the hope that it will be useful,
13.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13.17 + * GNU General Public License for more details.
13.18 + *
13.19 + * You should have received a copy of the GNU General Public License
13.20 + * along with this program; if not, write to the Free Software
13.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
13.22 + * Boston, MA 02110-1301, USA
13.23 + */
13.24 +
13.25 +#include "access.h"
13.26 +
13.27 +int access_can_read(user_t user, struct ext2_inode *inode)
13.28 +{
13.29 + /* NOTE: Could use a generic function for properly testing access.
13.30 + NOTE: For example, this does not permit multiple groups. */
13.31 +
13.32 + return ((inode->i_uid == user.uid) && (inode->i_mode & LINUX_S_IRUSR)) ||
13.33 + ((inode->i_gid == user.gid) && (inode->i_mode & LINUX_S_IRGRP)) ||
13.34 + (inode->i_mode & LINUX_S_IROTH);
13.35 +}
13.36 +
13.37 +int access_can_write(user_t user, struct ext2_inode *inode)
13.38 +{
13.39 + /* NOTE: Could use a generic function for properly testing access.
13.40 + NOTE: For example, this does not permit multiple groups. */
13.41 +
13.42 + return ((inode->i_uid == user.uid) && (inode->i_mode & LINUX_S_IWUSR)) ||
13.43 + ((inode->i_gid == user.gid) && (inode->i_mode & LINUX_S_IWGRP)) ||
13.44 + (inode->i_mode & LINUX_S_IWOTH);
13.45 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/libe2access/lib/src/format.c Wed Aug 25 01:28:08 2021 +0200
14.3 @@ -0,0 +1,39 @@
14.4 +/*
14.5 + * File metadata formatting.
14.6 + *
14.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
14.8 + *
14.9 + * This program is free software; you can redistribute it and/or
14.10 + * modify it under the terms of the GNU General Public License as
14.11 + * published by the Free Software Foundation; either version 2 of
14.12 + * the License, or (at your option) any later version.
14.13 + *
14.14 + * This program is distributed in the hope that it will be useful,
14.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14.17 + * GNU General Public License for more details.
14.18 + *
14.19 + * You should have received a copy of the GNU General Public License
14.20 + * along with this program; if not, write to the Free Software
14.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
14.22 + * Boston, MA 02110-1301, USA
14.23 + */
14.24 +
14.25 +#include "format.h"
14.26 +
14.27 +
14.28 +
14.29 +/* Return the permissions of an object as a string. */
14.30 +
14.31 +char *get_permission_string(uint16_t permissions)
14.32 +{
14.33 + static char s[9] = "--------\0";
14.34 + static char letters[] = "rwx";
14.35 + int i, letter;
14.36 + uint16_t selector = 0400;
14.37 +
14.38 + for (i = 0, letter = 0; i < 9; i++, letter = (letter + 1) % 3, selector >>= 1)
14.39 + s[i] = permissions & selector ? letters[letter] : '-';
14.40 +
14.41 + return s;
14.42 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/libe2access/lib/src/image.c Wed Aug 25 01:28:08 2021 +0200
15.3 @@ -0,0 +1,343 @@
15.4 +/*
15.5 + * Filesystem access functions.
15.6 + *
15.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
15.8 + *
15.9 + * This program is free software; you can redistribute it and/or
15.10 + * modify it under the terms of the GNU General Public License as
15.11 + * published by the Free Software Foundation; either version 2 of
15.12 + * the License, or (at your option) any later version.
15.13 + *
15.14 + * This program is distributed in the hope that it will be useful,
15.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
15.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15.17 + * GNU General Public License for more details.
15.18 + *
15.19 + * You should have received a copy of the GNU General Public License
15.20 + * along with this program; if not, write to the Free Software
15.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
15.22 + * Boston, MA 02110-1301, USA
15.23 + */
15.24 +
15.25 +#include <string.h>
15.26 +#include <sys/stat.h>
15.27 +
15.28 +#include <ext2fs/ext2fs.h>
15.29 +
15.30 +#include "image.h"
15.31 +#include "path.h"
15.32 +
15.33 +
15.34 +
15.35 +/* Create an inode for a file. */
15.36 +
15.37 +errcode_t image_create_file(ext2_filsys fs, ext2_ino_t ino_target,
15.38 + const char *basename, __u16 mode,
15.39 + __u16 uid, __u16 gid, ext2_ino_t *ino_file)
15.40 +{
15.41 + struct ext2_inode inode_file;
15.42 + errcode_t retval;
15.43 +
15.44 + /* Without an inode, create a new one. */
15.45 +
15.46 + retval = ext2fs_new_inode(fs, ino_target, LINUX_S_IFREG | mode, 0, ino_file);
15.47 + if (retval)
15.48 + return retval;
15.49 +
15.50 + /* Connect the inode to its parent. */
15.51 +
15.52 + while (1)
15.53 + {
15.54 + retval = ext2fs_link(fs, ino_target, basename, *ino_file,
15.55 + EXT2_FT_REG_FILE);
15.56 +
15.57 + if (!retval)
15.58 + break;
15.59 +
15.60 + /* Expand the directory if necessary. */
15.61 +
15.62 + if (retval == EXT2_ET_DIR_NO_SPACE)
15.63 + retval = ext2fs_expand_dir(fs, ino_target);
15.64 +
15.65 + if (retval)
15.66 + return retval;
15.67 + }
15.68 +
15.69 + /* Make sure that subsequent files employ different inodes. */
15.70 +
15.71 + ext2fs_inode_alloc_stats2(fs, *ino_file, 1, 0);
15.72 +
15.73 + /* Populate the inode details. */
15.74 +
15.75 + image_set_metadata(&inode_file, 1, LINUX_S_IFREG | mode, uid, gid);
15.76 +
15.77 + return ext2fs_write_new_inode(fs, *ino_file, &inode_file);
15.78 +}
15.79 +
15.80 +/* Set the mode, user and group metadata for a file. */
15.81 +
15.82 +void image_set_metadata(struct ext2_inode *inode, int clean, __u16 mode,
15.83 + __u16 uid, __u16 gid)
15.84 +{
15.85 + if (clean)
15.86 + memset(inode, 0, sizeof(*inode));
15.87 +
15.88 + inode->i_mode = mode;
15.89 + inode->i_uid = uid;
15.90 + inode->i_gid = gid;
15.91 +}
15.92 +
15.93 +/* Find an object in the given directory with the given name in the filesystem
15.94 + image, updating the name reference to refer to the next component. */
15.95 +
15.96 +errcode_t image_find_next(ext2_filsys fs, ext2_ino_t ino_dir,
15.97 + const char **basename, char *buf, ext2_ino_t *ino)
15.98 +{
15.99 + const char *end = path_component_end(*basename);
15.100 + errcode_t retval;
15.101 +
15.102 + /* Find the basename in the directory. */
15.103 +
15.104 + retval = ext2fs_lookup(fs, ino_dir, *basename, end - *basename, buf, ino);
15.105 +
15.106 + /* Update the current component. */
15.107 +
15.108 + if (!retval)
15.109 + *basename = path_component_next(end);
15.110 +
15.111 + return retval;
15.112 +}
15.113 +
15.114 +/* Find an object with the given pathname in the filesystem image. */
15.115 +
15.116 +errcode_t image_find_path(ext2_filsys fs, const char **pathname, ext2_ino_t *ino)
15.117 +{
15.118 + char *buf;
15.119 + ext2_ino_t ino_dir;
15.120 + errcode_t retval;
15.121 +
15.122 + retval = ext2fs_get_mem(fs->blocksize, &buf);
15.123 + if (retval)
15.124 + return retval;
15.125 +
15.126 + /* Skip any leading root marker. */
15.127 +
15.128 + if (**pathname == '/')
15.129 + (*pathname)++;
15.130 +
15.131 + if (!**pathname)
15.132 + *ino = EXT2_ROOT_INO;
15.133 +
15.134 + /* Start at the root. */
15.135 +
15.136 + ino_dir = EXT2_ROOT_INO;
15.137 +
15.138 + /* With any remaining path, find the next component. */
15.139 +
15.140 + while (**pathname)
15.141 + {
15.142 + retval = image_find_next(fs, ino_dir, pathname, buf, ino);
15.143 + if (retval)
15.144 + {
15.145 + *ino = ino_dir;
15.146 + break;
15.147 + }
15.148 +
15.149 + /* Move into the found object for searching the next component. */
15.150 +
15.151 + ino_dir = *ino;
15.152 + }
15.153 +
15.154 + ext2fs_free_mem(&buf);
15.155 +
15.156 + return retval;
15.157 +}
15.158 +
15.159 +/* Find an object in the given directory with the given name in the filesystem
15.160 + image. */
15.161 +
15.162 +errcode_t image_find_file(ext2_filsys fs, const char *dirname,
15.163 + const char *basename, ext2_ino_t *ino)
15.164 +{
15.165 + char pathname[strlen(dirname) + strlen(basename) + 2];
15.166 + const char *s = pathname;
15.167 +
15.168 + strcpy(pathname, dirname);
15.169 + strcat(pathname, "/");
15.170 + strcat(pathname, basename);
15.171 +
15.172 + return image_find_path(fs, &s, ino);
15.173 +}
15.174 +
15.175 +/* Obtain the inode for the object with the given pathname in the filesystem
15.176 + image. */
15.177 +
15.178 +errcode_t image_inode(ext2_filsys fs, const char *pathname,
15.179 + struct ext2_inode *inode)
15.180 +{
15.181 + ext2_ino_t ino;
15.182 + errcode_t retval;
15.183 +
15.184 + retval = image_find_path(fs, &pathname, &ino);
15.185 + if (retval)
15.186 + return retval;
15.187 +
15.188 + return ext2fs_read_inode(fs, ino, inode);
15.189 +}
15.190 +
15.191 +/* Make a directory in the given directory in the filesystem image having the
15.192 + given name and metadata. */
15.193 +
15.194 +errcode_t image_make_dir(ext2_filsys fs, ext2_ino_t ino_dir,
15.195 + const char *basename, __u16 mode,
15.196 + __u16 uid, __u16 gid, ext2_ino_t *ino)
15.197 +{
15.198 + struct ext2_inode inode_dir;
15.199 + errcode_t retval = 0;
15.200 +
15.201 + /* Create an inode in the directory. */
15.202 +
15.203 + retval = ext2fs_new_inode(fs, ino_dir, LINUX_S_IFDIR | mode, 0, ino);
15.204 + if (retval)
15.205 + return retval;
15.206 +
15.207 + /* Make the directory and update the metadata (due to ext2fs_mkdir
15.208 + limitation). */
15.209 +
15.210 + retval = ext2fs_mkdir(fs, ino_dir, *ino, basename);
15.211 + if (retval)
15.212 + return retval;
15.213 +
15.214 + retval = ext2fs_read_inode(fs, *ino, &inode_dir);
15.215 + if (retval)
15.216 + return retval;
15.217 +
15.218 + image_set_metadata(&inode_dir, 0, LINUX_S_IFDIR | mode, uid, gid);
15.219 + return ext2fs_write_inode(fs, *ino, &inode_dir);
15.220 +}
15.221 +
15.222 +/* Make a directory in the given directory in the filesystem image, updating
15.223 + the name reference to refer to the next component. */
15.224 +
15.225 +errcode_t image_make_next_dir(ext2_filsys fs, ext2_ino_t ino_dir,
15.226 + const char **basename, __u16 mode, __u16 uid,
15.227 + __u16 gid, ext2_ino_t *ino)
15.228 +{
15.229 + char *end = (char *) path_component_end(*basename);
15.230 + char endchar = *end;
15.231 + errcode_t retval = 0;
15.232 +
15.233 + /* Delimit the basename and make a directory using the inode. */
15.234 +
15.235 + if (endchar)
15.236 + *end = '\0';
15.237 +
15.238 + /* Do not create directories for empty components. */
15.239 +
15.240 + if (**basename)
15.241 + retval = image_make_dir(fs, ino_dir, *basename, mode, uid, gid, ino);
15.242 +
15.243 + /* Restore the path separator and update the current component. */
15.244 +
15.245 + if (endchar)
15.246 + *end = '/';
15.247 +
15.248 + if (!retval)
15.249 + *basename = path_component_next(end);
15.250 +
15.251 + return retval;
15.252 +}
15.253 +
15.254 +/* Make directories descending to the given path in the filesystem image. */
15.255 +
15.256 +errcode_t image_make_dirs(ext2_filsys fs, const char **pathname,
15.257 + ext2_ino_t ino_dir, __u16 mode, __u16 uid, __u16 gid)
15.258 +{
15.259 + ext2_ino_t ino;
15.260 + errcode_t retval;
15.261 +
15.262 + while (**pathname)
15.263 + {
15.264 + retval = image_make_next_dir(fs, ino_dir, pathname, mode, uid, gid, &ino);
15.265 + if (retval)
15.266 + return retval;
15.267 +
15.268 + /* Move into the created object for handling the next component. */
15.269 +
15.270 + ino_dir = ino;
15.271 + }
15.272 +
15.273 + return 0;
15.274 +}
15.275 +
15.276 +/* Copy file metadata into a stat structure. */
15.277 +
15.278 +errcode_t image_stat_inode(ext2_filsys fs, ext2_ino_t ino, struct stat *st)
15.279 +{
15.280 + struct ext2_inode inode;
15.281 + errcode_t retval = ext2fs_read_inode(fs, ino, &inode);
15.282 +
15.283 + if (retval)
15.284 + return retval;
15.285 +
15.286 + st->st_dev = 0; /* device identifier */
15.287 + st->st_ino = ino;
15.288 + st->st_mode = inode.i_mode;
15.289 + st->st_nlink = inode.i_links_count;
15.290 + st->st_uid = inode_uid(inode);
15.291 + st->st_gid = inode_gid(inode);
15.292 + st->st_rdev = 0; /* special file device identifier */
15.293 + st->st_size = EXT2_I_SIZE(&inode);
15.294 + st->st_blksize = fs->blocksize;
15.295 + st->st_blocks = 0; /* number of 512 byte blocks allocated */
15.296 + st->st_atim.tv_sec = inode.i_atime;
15.297 + st->st_atim.tv_nsec = 0; /* nanosecond resolution */
15.298 + st->st_mtim.tv_sec = inode.i_mtime;
15.299 + st->st_mtim.tv_nsec = 0;
15.300 + st->st_ctim.tv_sec = inode.i_ctime;
15.301 + st->st_ctim.tv_nsec = 0;
15.302 +
15.303 + return 0;
15.304 +}
15.305 +
15.306 +/* Test object types in the filesystem image. */
15.307 +
15.308 +int _image_isdir(ext2_filsys fs, ext2_ino_t ino)
15.309 +{
15.310 + struct ext2_inode inode;
15.311 +
15.312 + if (ext2fs_read_inode(fs, ino, &inode))
15.313 + return 0;
15.314 +
15.315 + return LINUX_S_ISDIR(inode.i_mode);
15.316 +}
15.317 +
15.318 +int image_isdir(ext2_filsys fs, const char *name)
15.319 +{
15.320 + ext2_ino_t ino;
15.321 +
15.322 + if (image_find_path(fs, &name, &ino))
15.323 + return 0;
15.324 +
15.325 + return _image_isdir(fs, ino);
15.326 +}
15.327 +
15.328 +int _image_isfile(ext2_filsys fs, ext2_ino_t ino)
15.329 +{
15.330 + struct ext2_inode inode;
15.331 +
15.332 + if (ext2fs_read_inode(fs, ino, &inode))
15.333 + return 0;
15.334 +
15.335 + return LINUX_S_ISREG(inode.i_mode);
15.336 +}
15.337 +
15.338 +int image_isfile(ext2_filsys fs, const char *name)
15.339 +{
15.340 + ext2_ino_t ino;
15.341 +
15.342 + if (image_find_path(fs, &name, &ino))
15.343 + return 0;
15.344 +
15.345 + return _image_isfile(fs, ino);
15.346 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/libe2access/lib/src/path.c Wed Aug 25 01:28:08 2021 +0200
16.3 @@ -0,0 +1,66 @@
16.4 +/*
16.5 + * Path functions.
16.6 + *
16.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
16.8 + *
16.9 + * This program is free software; you can redistribute it and/or
16.10 + * modify it under the terms of the GNU General Public License as
16.11 + * published by the Free Software Foundation; either version 2 of
16.12 + * the License, or (at your option) any later version.
16.13 + *
16.14 + * This program is distributed in the hope that it will be useful,
16.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16.17 + * GNU General Public License for more details.
16.18 + *
16.19 + * You should have received a copy of the GNU General Public License
16.20 + * along with this program; if not, write to the Free Software
16.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
16.22 + * Boston, MA 02110-1301, USA
16.23 + */
16.24 +
16.25 +#include <string.h>
16.26 +
16.27 +#include "path.h"
16.28 +
16.29 +/* Return the basename from a path. */
16.30 +
16.31 +const char *path_basename(const char *path)
16.32 +{
16.33 + char *s = strrchr(path, (int) '/');
16.34 +
16.35 + if (s == NULL)
16.36 + return path;
16.37 + else
16.38 + return s + 1;
16.39 +}
16.40 +
16.41 +/* Return the end of the first component in the given path. */
16.42 +
16.43 +const char *path_component_end(const char *path)
16.44 +{
16.45 + char *end = strchr(path, (int) '/');
16.46 +
16.47 + if (end == NULL)
16.48 + return path + strlen(path);
16.49 + else
16.50 + return end;
16.51 +}
16.52 +
16.53 +/* Return the start of the next component in a path given the end of the
16.54 + previous one. */
16.55 +
16.56 +const char *path_component_next(const char *end)
16.57 +{
16.58 + if (*end)
16.59 + return end + 1;
16.60 + else
16.61 + return end;
16.62 +}
16.63 +
16.64 +/* Return whether the path lacks a path separator. */
16.65 +
16.66 +int path_is_leafname(const char *path)
16.67 +{
16.68 + return strchr(path, (int) '/') == NULL;
16.69 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/libext2fs/Control Wed Aug 25 01:28:08 2021 +0200
17.3 @@ -0,0 +1,3 @@
17.4 +requires: libc libc_support_misc
17.5 +provides: libblkid libe2p libet libext2fs libsupport libuuid
17.6 +maintainer: paul@boddie.org.uk
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/libext2fs/Makefile Wed Aug 25 01:28:08 2021 +0200
18.3 @@ -0,0 +1,4 @@
18.4 +PKGDIR ?= .
18.5 +L4DIR ?= $(PKGDIR)/../../..
18.6 +
18.7 +include $(L4DIR)/mk/subdir.mk
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/libext2fs/NOTICE Wed Aug 25 01:28:08 2021 +0200
19.3 @@ -0,0 +1,849 @@
19.4 +This package, the EXT2 filesystem utilities, are made available under
19.5 +the GNU Public License version 2, with the exception of the lib/ext2fs
19.6 +and lib/e2p libraries, which are made available under the GNU Library
19.7 +General Public License Version 2, the lib/uuid library which is made
19.8 +available under a BSD-style license and the lib/et and lib/ss
19.9 +libraries which are made available under an MIT-style license. Please
19.10 +see lib/uuid/COPYING for more details for the license for the files
19.11 +comprising the libuuid library, and the source file headers of the
19.12 +libet and libss libraries for more information.
19.13 +
19.14 +The most recent officially distributed version can be found at
19.15 +http://e2fsprogs.sourceforge.net. If you need to make a distribution,
19.16 +that's the one you should use. If there is some reason why you'd like
19.17 +a more recent version that is still in ALPHA testing (i.e., either
19.18 +using the "WIP" test distributions or one from the hg or git
19.19 +repository from the development branch, please contact me
19.20 +(tytso@mit.edu) before you ship. The release schedules for this
19.21 +package are flexible, if you give me enough lead time.
19.22 +
19.23 +
19.24 + Theodore Ts'o
19.25 + 23-June-2007
19.26 +
19.27 +----------------------------------------------------------------------
19.28 +
19.29 + GNU GENERAL PUBLIC LICENSE
19.30 + Version 2, June 1991
19.31 +
19.32 + Copyright (C) 1989, 1991 Free Software Foundation, Inc.
19.33 + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19.34 + Everyone is permitted to copy and distribute verbatim copies
19.35 + of this license document, but changing it is not allowed.
19.36 +
19.37 + Preamble
19.38 +
19.39 + The licenses for most software are designed to take away your
19.40 +freedom to share and change it. By contrast, the GNU General Public
19.41 +License is intended to guarantee your freedom to share and change free
19.42 +software--to make sure the software is free for all its users. This
19.43 +General Public License applies to most of the Free Software
19.44 +Foundation's software and to any other program whose authors commit to
19.45 +using it. (Some other Free Software Foundation software is covered by
19.46 +the GNU Library General Public License instead.) You can apply it to
19.47 +your programs, too.
19.48 +
19.49 + When we speak of free software, we are referring to freedom, not
19.50 +price. Our General Public Licenses are designed to make sure that you
19.51 +have the freedom to distribute copies of free software (and charge for
19.52 +this service if you wish), that you receive source code or can get it
19.53 +if you want it, that you can change the software or use pieces of it
19.54 +in new free programs; and that you know you can do these things.
19.55 +
19.56 + To protect your rights, we need to make restrictions that forbid
19.57 +anyone to deny you these rights or to ask you to surrender the rights.
19.58 +These restrictions translate to certain responsibilities for you if you
19.59 +distribute copies of the software, or if you modify it.
19.60 +
19.61 + For example, if you distribute copies of such a program, whether
19.62 +gratis or for a fee, you must give the recipients all the rights that
19.63 +you have. You must make sure that they, too, receive or can get the
19.64 +source code. And you must show them these terms so they know their
19.65 +rights.
19.66 +
19.67 + We protect your rights with two steps: (1) copyright the software, and
19.68 +(2) offer you this license which gives you legal permission to copy,
19.69 +distribute and/or modify the software.
19.70 +
19.71 + Also, for each author's protection and ours, we want to make certain
19.72 +that everyone understands that there is no warranty for this free
19.73 +software. If the software is modified by someone else and passed on, we
19.74 +want its recipients to know that what they have is not the original, so
19.75 +that any problems introduced by others will not reflect on the original
19.76 +authors' reputations.
19.77 +
19.78 + Finally, any free program is threatened constantly by software
19.79 +patents. We wish to avoid the danger that redistributors of a free
19.80 +program will individually obtain patent licenses, in effect making the
19.81 +program proprietary. To prevent this, we have made it clear that any
19.82 +patent must be licensed for everyone's free use or not licensed at all.
19.83 +
19.84 + The precise terms and conditions for copying, distribution and
19.85 +modification follow.
19.86 +
19.87 + GNU GENERAL PUBLIC LICENSE
19.88 + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
19.89 +
19.90 + 0. This License applies to any program or other work which contains
19.91 +a notice placed by the copyright holder saying it may be distributed
19.92 +under the terms of this General Public License. The "Program", below,
19.93 +refers to any such program or work, and a "work based on the Program"
19.94 +means either the Program or any derivative work under copyright law:
19.95 +that is to say, a work containing the Program or a portion of it,
19.96 +either verbatim or with modifications and/or translated into another
19.97 +language. (Hereinafter, translation is included without limitation in
19.98 +the term "modification".) Each licensee is addressed as "you".
19.99 +
19.100 +Activities other than copying, distribution and modification are not
19.101 +covered by this License; they are outside its scope. The act of
19.102 +running the Program is not restricted, and the output from the Program
19.103 +is covered only if its contents constitute a work based on the
19.104 +Program (independent of having been made by running the Program).
19.105 +Whether that is true depends on what the Program does.
19.106 +
19.107 + 1. You may copy and distribute verbatim copies of the Program's
19.108 +source code as you receive it, in any medium, provided that you
19.109 +conspicuously and appropriately publish on each copy an appropriate
19.110 +copyright notice and disclaimer of warranty; keep intact all the
19.111 +notices that refer to this License and to the absence of any warranty;
19.112 +and give any other recipients of the Program a copy of this License
19.113 +along with the Program.
19.114 +
19.115 +You may charge a fee for the physical act of transferring a copy, and
19.116 +you may at your option offer warranty protection in exchange for a fee.
19.117 +
19.118 + 2. You may modify your copy or copies of the Program or any portion
19.119 +of it, thus forming a work based on the Program, and copy and
19.120 +distribute such modifications or work under the terms of Section 1
19.121 +above, provided that you also meet all of these conditions:
19.122 +
19.123 + a) You must cause the modified files to carry prominent notices
19.124 + stating that you changed the files and the date of any change.
19.125 +
19.126 + b) You must cause any work that you distribute or publish, that in
19.127 + whole or in part contains or is derived from the Program or any
19.128 + part thereof, to be licensed as a whole at no charge to all third
19.129 + parties under the terms of this License.
19.130 +
19.131 + c) If the modified program normally reads commands interactively
19.132 + when run, you must cause it, when started running for such
19.133 + interactive use in the most ordinary way, to print or display an
19.134 + announcement including an appropriate copyright notice and a
19.135 + notice that there is no warranty (or else, saying that you provide
19.136 + a warranty) and that users may redistribute the program under
19.137 + these conditions, and telling the user how to view a copy of this
19.138 + License. (Exception: if the Program itself is interactive but
19.139 + does not normally print such an announcement, your work based on
19.140 + the Program is not required to print an announcement.)
19.141 +
19.142 +These requirements apply to the modified work as a whole. If
19.143 +identifiable sections of that work are not derived from the Program,
19.144 +and can be reasonably considered independent and separate works in
19.145 +themselves, then this License, and its terms, do not apply to those
19.146 +sections when you distribute them as separate works. But when you
19.147 +distribute the same sections as part of a whole which is a work based
19.148 +on the Program, the distribution of the whole must be on the terms of
19.149 +this License, whose permissions for other licensees extend to the
19.150 +entire whole, and thus to each and every part regardless of who wrote it.
19.151 +
19.152 +Thus, it is not the intent of this section to claim rights or contest
19.153 +your rights to work written entirely by you; rather, the intent is to
19.154 +exercise the right to control the distribution of derivative or
19.155 +collective works based on the Program.
19.156 +
19.157 +In addition, mere aggregation of another work not based on the Program
19.158 +with the Program (or with a work based on the Program) on a volume of
19.159 +a storage or distribution medium does not bring the other work under
19.160 +the scope of this License.
19.161 +
19.162 + 3. You may copy and distribute the Program (or a work based on it,
19.163 +under Section 2) in object code or executable form under the terms of
19.164 +Sections 1 and 2 above provided that you also do one of the following:
19.165 +
19.166 + a) Accompany it with the complete corresponding machine-readable
19.167 + source code, which must be distributed under the terms of Sections
19.168 + 1 and 2 above on a medium customarily used for software interchange; or,
19.169 +
19.170 + b) Accompany it with a written offer, valid for at least three
19.171 + years, to give any third party, for a charge no more than your
19.172 + cost of physically performing source distribution, a complete
19.173 + machine-readable copy of the corresponding source code, to be
19.174 + distributed under the terms of Sections 1 and 2 above on a medium
19.175 + customarily used for software interchange; or,
19.176 +
19.177 + c) Accompany it with the information you received as to the offer
19.178 + to distribute corresponding source code. (This alternative is
19.179 + allowed only for noncommercial distribution and only if you
19.180 + received the program in object code or executable form with such
19.181 + an offer, in accord with Subsection b above.)
19.182 +
19.183 +The source code for a work means the preferred form of the work for
19.184 +making modifications to it. For an executable work, complete source
19.185 +code means all the source code for all modules it contains, plus any
19.186 +associated interface definition files, plus the scripts used to
19.187 +control compilation and installation of the executable. However, as a
19.188 +special exception, the source code distributed need not include
19.189 +anything that is normally distributed (in either source or binary
19.190 +form) with the major components (compiler, kernel, and so on) of the
19.191 +operating system on which the executable runs, unless that component
19.192 +itself accompanies the executable.
19.193 +
19.194 +If distribution of executable or object code is made by offering
19.195 +access to copy from a designated place, then offering equivalent
19.196 +access to copy the source code from the same place counts as
19.197 +distribution of the source code, even though third parties are not
19.198 +compelled to copy the source along with the object code.
19.199 +
19.200 + 4. You may not copy, modify, sublicense, or distribute the Program
19.201 +except as expressly provided under this License. Any attempt
19.202 +otherwise to copy, modify, sublicense or distribute the Program is
19.203 +void, and will automatically terminate your rights under this License.
19.204 +However, parties who have received copies, or rights, from you under
19.205 +this License will not have their licenses terminated so long as such
19.206 +parties remain in full compliance.
19.207 +
19.208 + 5. You are not required to accept this License, since you have not
19.209 +signed it. However, nothing else grants you permission to modify or
19.210 +distribute the Program or its derivative works. These actions are
19.211 +prohibited by law if you do not accept this License. Therefore, by
19.212 +modifying or distributing the Program (or any work based on the
19.213 +Program), you indicate your acceptance of this License to do so, and
19.214 +all its terms and conditions for copying, distributing or modifying
19.215 +the Program or works based on it.
19.216 +
19.217 + 6. Each time you redistribute the Program (or any work based on the
19.218 +Program), the recipient automatically receives a license from the
19.219 +original licensor to copy, distribute or modify the Program subject to
19.220 +these terms and conditions. You may not impose any further
19.221 +restrictions on the recipients' exercise of the rights granted herein.
19.222 +You are not responsible for enforcing compliance by third parties to
19.223 +this License.
19.224 +
19.225 + 7. If, as a consequence of a court judgment or allegation of patent
19.226 +infringement or for any other reason (not limited to patent issues),
19.227 +conditions are imposed on you (whether by court order, agreement or
19.228 +otherwise) that contradict the conditions of this License, they do not
19.229 +excuse you from the conditions of this License. If you cannot
19.230 +distribute so as to satisfy simultaneously your obligations under this
19.231 +License and any other pertinent obligations, then as a consequence you
19.232 +may not distribute the Program at all. For example, if a patent
19.233 +license would not permit royalty-free redistribution of the Program by
19.234 +all those who receive copies directly or indirectly through you, then
19.235 +the only way you could satisfy both it and this License would be to
19.236 +refrain entirely from distribution of the Program.
19.237 +
19.238 +If any portion of this section is held invalid or unenforceable under
19.239 +any particular circumstance, the balance of the section is intended to
19.240 +apply and the section as a whole is intended to apply in other
19.241 +circumstances.
19.242 +
19.243 +It is not the purpose of this section to induce you to infringe any
19.244 +patents or other property right claims or to contest validity of any
19.245 +such claims; this section has the sole purpose of protecting the
19.246 +integrity of the free software distribution system, which is
19.247 +implemented by public license practices. Many people have made
19.248 +generous contributions to the wide range of software distributed
19.249 +through that system in reliance on consistent application of that
19.250 +system; it is up to the author/donor to decide if he or she is willing
19.251 +to distribute software through any other system and a licensee cannot
19.252 +impose that choice.
19.253 +
19.254 +This section is intended to make thoroughly clear what is believed to
19.255 +be a consequence of the rest of this License.
19.256 +
19.257 + 8. If the distribution and/or use of the Program is restricted in
19.258 +certain countries either by patents or by copyrighted interfaces, the
19.259 +original copyright holder who places the Program under this License
19.260 +may add an explicit geographical distribution limitation excluding
19.261 +those countries, so that distribution is permitted only in or among
19.262 +countries not thus excluded. In such case, this License incorporates
19.263 +the limitation as if written in the body of this License.
19.264 +
19.265 + 9. The Free Software Foundation may publish revised and/or new versions
19.266 +of the General Public License from time to time. Such new versions will
19.267 +be similar in spirit to the present version, but may differ in detail to
19.268 +address new problems or concerns.
19.269 +
19.270 +Each version is given a distinguishing version number. If the Program
19.271 +specifies a version number of this License which applies to it and "any
19.272 +later version", you have the option of following the terms and conditions
19.273 +either of that version or of any later version published by the Free
19.274 +Software Foundation. If the Program does not specify a version number of
19.275 +this License, you may choose any version ever published by the Free Software
19.276 +Foundation.
19.277 +
19.278 + 10. If you wish to incorporate parts of the Program into other free
19.279 +programs whose distribution conditions are different, write to the author
19.280 +to ask for permission. For software which is copyrighted by the Free
19.281 +Software Foundation, write to the Free Software Foundation; we sometimes
19.282 +make exceptions for this. Our decision will be guided by the two goals
19.283 +of preserving the free status of all derivatives of our free software and
19.284 +of promoting the sharing and reuse of software generally.
19.285 +
19.286 + NO WARRANTY
19.287 +
19.288 + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
19.289 +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
19.290 +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
19.291 +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
19.292 +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19.293 +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
19.294 +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
19.295 +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
19.296 +REPAIR OR CORRECTION.
19.297 +
19.298 + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
19.299 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
19.300 +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
19.301 +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
19.302 +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
19.303 +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
19.304 +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
19.305 +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
19.306 +POSSIBILITY OF SUCH DAMAGES.
19.307 +
19.308 + END OF TERMS AND CONDITIONS
19.309 +
19.310 + How to Apply These Terms to Your New Programs
19.311 +
19.312 + If you develop a new program, and you want it to be of the greatest
19.313 +possible use to the public, the best way to achieve this is to make it
19.314 +free software which everyone can redistribute and change under these terms.
19.315 +
19.316 + To do so, attach the following notices to the program. It is safest
19.317 +to attach them to the start of each source file to most effectively
19.318 +convey the exclusion of warranty; and each file should have at least
19.319 +the "copyright" line and a pointer to where the full notice is found.
19.320 +
19.321 + <one line to give the program's name and a brief idea of what it does.>
19.322 + Copyright (C) <year> <name of author>
19.323 +
19.324 + This program is free software; you can redistribute it and/or modify
19.325 + it under the terms of the GNU General Public License as published by
19.326 + the Free Software Foundation; either version 2 of the License, or
19.327 + (at your option) any later version.
19.328 +
19.329 + This program is distributed in the hope that it will be useful,
19.330 + but WITHOUT ANY WARRANTY; without even the implied warranty of
19.331 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19.332 + GNU General Public License for more details.
19.333 +
19.334 + You should have received a copy of the GNU General Public License
19.335 + along with this program; if not, write to the Free Software
19.336 + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19.337 +
19.338 +
19.339 +Also add information on how to contact you by electronic and paper mail.
19.340 +
19.341 +If the program is interactive, make it output a short notice like this
19.342 +when it starts in an interactive mode:
19.343 +
19.344 + Gnomovision version 69, Copyright (C) year name of author
19.345 + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
19.346 + This is free software, and you are welcome to redistribute it
19.347 + under certain conditions; type `show c' for details.
19.348 +
19.349 +The hypothetical commands `show w' and `show c' should show the appropriate
19.350 +parts of the General Public License. Of course, the commands you use may
19.351 +be called something other than `show w' and `show c'; they could even be
19.352 +mouse-clicks or menu items--whatever suits your program.
19.353 +
19.354 +You should also get your employer (if you work as a programmer) or your
19.355 +school, if any, to sign a "copyright disclaimer" for the program, if
19.356 +necessary. Here is a sample; alter the names:
19.357 +
19.358 + Yoyodyne, Inc., hereby disclaims all copyright interest in the program
19.359 + `Gnomovision' (which makes passes at compilers) written by James Hacker.
19.360 +
19.361 + <signature of Ty Coon>, 1 April 1989
19.362 + Ty Coon, President of Vice
19.363 +
19.364 +This General Public License does not permit incorporating your program into
19.365 +proprietary programs. If your program is a subroutine library, you may
19.366 +consider it more useful to permit linking proprietary applications with the
19.367 +library. If this is what you want to do, use the GNU Library General
19.368 +Public License instead of this License.
19.369 +
19.370 +----------------------------------------------------------------------
19.371 +
19.372 + GNU LIBRARY GENERAL PUBLIC LICENSE
19.373 + Version 2, June 1991
19.374 +
19.375 + Copyright (C) 1991 Free Software Foundation, Inc.
19.376 + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19.377 + Everyone is permitted to copy and distribute verbatim copies
19.378 + of this license document, but changing it is not allowed.
19.379 +
19.380 +[This is the first released version of the library GPL. It is
19.381 + numbered 2 because it goes with version 2 of the ordinary GPL.]
19.382 +
19.383 + Preamble
19.384 +
19.385 + The licenses for most software are designed to take away your
19.386 +freedom to share and change it. By contrast, the GNU General Public
19.387 +Licenses are intended to guarantee your freedom to share and change
19.388 +free software--to make sure the software is free for all its users.
19.389 +
19.390 + This license, the Library General Public License, applies to some
19.391 +specially designated Free Software Foundation software, and to any
19.392 +other libraries whose authors decide to use it. You can use it for
19.393 +your libraries, too.
19.394 +
19.395 + When we speak of free software, we are referring to freedom, not
19.396 +price. Our General Public Licenses are designed to make sure that you
19.397 +have the freedom to distribute copies of free software (and charge for
19.398 +this service if you wish), that you receive source code or can get it
19.399 +if you want it, that you can change the software or use pieces of it
19.400 +in new free programs; and that you know you can do these things.
19.401 +
19.402 + To protect your rights, we need to make restrictions that forbid
19.403 +anyone to deny you these rights or to ask you to surrender the rights.
19.404 +These restrictions translate to certain responsibilities for you if
19.405 +you distribute copies of the library, or if you modify it.
19.406 +
19.407 + For example, if you distribute copies of the library, whether gratis
19.408 +or for a fee, you must give the recipients all the rights that we gave
19.409 +you. You must make sure that they, too, receive or can get the source
19.410 +code. If you link a program with the library, you must provide
19.411 +complete object files to the recipients so that they can relink them
19.412 +with the library, after making changes to the library and recompiling
19.413 +it. And you must show them these terms so they know their rights.
19.414 +
19.415 + Our method of protecting your rights has two steps: (1) copyright
19.416 +the library, and (2) offer you this license which gives you legal
19.417 +permission to copy, distribute and/or modify the library.
19.418 +
19.419 + Also, for each distributor's protection, we want to make certain
19.420 +that everyone understands that there is no warranty for this free
19.421 +library. If the library is modified by someone else and passed on, we
19.422 +want its recipients to know that what they have is not the original
19.423 +version, so that any problems introduced by others will not reflect on
19.424 +the original authors' reputations.
19.425 +
19.426 + Finally, any free program is threatened constantly by software
19.427 +patents. We wish to avoid the danger that companies distributing free
19.428 +software will individually obtain patent licenses, thus in effect
19.429 +transforming the program into proprietary software. To prevent this,
19.430 +we have made it clear that any patent must be licensed for everyone's
19.431 +free use or not licensed at all.
19.432 +
19.433 + Most GNU software, including some libraries, is covered by the ordinary
19.434 +GNU General Public License, which was designed for utility programs. This
19.435 +license, the GNU Library General Public License, applies to certain
19.436 +designated libraries. This license is quite different from the ordinary
19.437 +one; be sure to read it in full, and don't assume that anything in it is
19.438 +the same as in the ordinary license.
19.439 +
19.440 + The reason we have a separate public license for some libraries is that
19.441 +they blur the distinction we usually make between modifying or adding to a
19.442 +program and simply using it. Linking a program with a library, without
19.443 +changing the library, is in some sense simply using the library, and is
19.444 +analogous to running a utility program or application program. However, in
19.445 +a textual and legal sense, the linked executable is a combined work, a
19.446 +derivative of the original library, and the ordinary General Public License
19.447 +treats it as such.
19.448 +
19.449 + Because of this blurred distinction, using the ordinary General
19.450 +Public License for libraries did not effectively promote software
19.451 +sharing, because most developers did not use the libraries. We
19.452 +concluded that weaker conditions might promote sharing better.
19.453 +
19.454 + However, unrestricted linking of non-free programs would deprive the
19.455 +users of those programs of all benefit from the free status of the
19.456 +libraries themselves. This Library General Public License is intended to
19.457 +permit developers of non-free programs to use free libraries, while
19.458 +preserving your freedom as a user of such programs to change the free
19.459 +libraries that are incorporated in them. (We have not seen how to achieve
19.460 +this as regards changes in header files, but we have achieved it as regards
19.461 +changes in the actual functions of the Library.) The hope is that this
19.462 +will lead to faster development of free libraries.
19.463 +
19.464 + The precise terms and conditions for copying, distribution and
19.465 +modification follow. Pay close attention to the difference between a
19.466 +"work based on the library" and a "work that uses the library". The
19.467 +former contains code derived from the library, while the latter only
19.468 +works together with the library.
19.469 +
19.470 + Note that it is possible for a library to be covered by the ordinary
19.471 +General Public License rather than by this special one.
19.472 +
19.473 + GNU LIBRARY GENERAL PUBLIC LICENSE
19.474 + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
19.475 +
19.476 + 0. This License Agreement applies to any software library which
19.477 +contains a notice placed by the copyright holder or other authorized
19.478 +party saying it may be distributed under the terms of this Library
19.479 +General Public License (also called "this License"). Each licensee is
19.480 +addressed as "you".
19.481 +
19.482 + A "library" means a collection of software functions and/or data
19.483 +prepared so as to be conveniently linked with application programs
19.484 +(which use some of those functions and data) to form executables.
19.485 +
19.486 + The "Library", below, refers to any such software library or work
19.487 +which has been distributed under these terms. A "work based on the
19.488 +Library" means either the Library or any derivative work under
19.489 +copyright law: that is to say, a work containing the Library or a
19.490 +portion of it, either verbatim or with modifications and/or translated
19.491 +straightforwardly into another language. (Hereinafter, translation is
19.492 +included without limitation in the term "modification".)
19.493 +
19.494 + "Source code" for a work means the preferred form of the work for
19.495 +making modifications to it. For a library, complete source code means
19.496 +all the source code for all modules it contains, plus any associated
19.497 +interface definition files, plus the scripts used to control compilation
19.498 +and installation of the library.
19.499 +
19.500 + Activities other than copying, distribution and modification are not
19.501 +covered by this License; they are outside its scope. The act of
19.502 +running a program using the Library is not restricted, and output from
19.503 +such a program is covered only if its contents constitute a work based
19.504 +on the Library (independent of the use of the Library in a tool for
19.505 +writing it). Whether that is true depends on what the Library does
19.506 +and what the program that uses the Library does.
19.507 +
19.508 + 1. You may copy and distribute verbatim copies of the Library's
19.509 +complete source code as you receive it, in any medium, provided that
19.510 +you conspicuously and appropriately publish on each copy an
19.511 +appropriate copyright notice and disclaimer of warranty; keep intact
19.512 +all the notices that refer to this License and to the absence of any
19.513 +warranty; and distribute a copy of this License along with the
19.514 +Library.
19.515 +
19.516 + You may charge a fee for the physical act of transferring a copy,
19.517 +and you may at your option offer warranty protection in exchange for a
19.518 +fee.
19.519 +
19.520 + 2. You may modify your copy or copies of the Library or any portion
19.521 +of it, thus forming a work based on the Library, and copy and
19.522 +distribute such modifications or work under the terms of Section 1
19.523 +above, provided that you also meet all of these conditions:
19.524 +
19.525 + a) The modified work must itself be a software library.
19.526 +
19.527 + b) You must cause the files modified to carry prominent notices
19.528 + stating that you changed the files and the date of any change.
19.529 +
19.530 + c) You must cause the whole of the work to be licensed at no
19.531 + charge to all third parties under the terms of this License.
19.532 +
19.533 + d) If a facility in the modified Library refers to a function or a
19.534 + table of data to be supplied by an application program that uses
19.535 + the facility, other than as an argument passed when the facility
19.536 + is invoked, then you must make a good faith effort to ensure that,
19.537 + in the event an application does not supply such function or
19.538 + table, the facility still operates, and performs whatever part of
19.539 + its purpose remains meaningful.
19.540 +
19.541 + (For example, a function in a library to compute square roots has
19.542 + a purpose that is entirely well-defined independent of the
19.543 + application. Therefore, Subsection 2d requires that any
19.544 + application-supplied function or table used by this function must
19.545 + be optional: if the application does not supply it, the square
19.546 + root function must still compute square roots.)
19.547 +
19.548 +These requirements apply to the modified work as a whole. If
19.549 +identifiable sections of that work are not derived from the Library,
19.550 +and can be reasonably considered independent and separate works in
19.551 +themselves, then this License, and its terms, do not apply to those
19.552 +sections when you distribute them as separate works. But when you
19.553 +distribute the same sections as part of a whole which is a work based
19.554 +on the Library, the distribution of the whole must be on the terms of
19.555 +this License, whose permissions for other licensees extend to the
19.556 +entire whole, and thus to each and every part regardless of who wrote
19.557 +it.
19.558 +
19.559 +Thus, it is not the intent of this section to claim rights or contest
19.560 +your rights to work written entirely by you; rather, the intent is to
19.561 +exercise the right to control the distribution of derivative or
19.562 +collective works based on the Library.
19.563 +
19.564 +In addition, mere aggregation of another work not based on the Library
19.565 +with the Library (or with a work based on the Library) on a volume of
19.566 +a storage or distribution medium does not bring the other work under
19.567 +the scope of this License.
19.568 +
19.569 + 3. You may opt to apply the terms of the ordinary GNU General Public
19.570 +License instead of this License to a given copy of the Library. To do
19.571 +this, you must alter all the notices that refer to this License, so
19.572 +that they refer to the ordinary GNU General Public License, version 2,
19.573 +instead of to this License. (If a newer version than version 2 of the
19.574 +ordinary GNU General Public License has appeared, then you can specify
19.575 +that version instead if you wish.) Do not make any other change in
19.576 +these notices.
19.577 +
19.578 + Once this change is made in a given copy, it is irreversible for
19.579 +that copy, so the ordinary GNU General Public License applies to all
19.580 +subsequent copies and derivative works made from that copy.
19.581 +
19.582 + This option is useful when you wish to copy part of the code of
19.583 +the Library into a program that is not a library.
19.584 +
19.585 + 4. You may copy and distribute the Library (or a portion or
19.586 +derivative of it, under Section 2) in object code or executable form
19.587 +under the terms of Sections 1 and 2 above provided that you accompany
19.588 +it with the complete corresponding machine-readable source code, which
19.589 +must be distributed under the terms of Sections 1 and 2 above on a
19.590 +medium customarily used for software interchange.
19.591 +
19.592 + If distribution of object code is made by offering access to copy
19.593 +from a designated place, then offering equivalent access to copy the
19.594 +source code from the same place satisfies the requirement to
19.595 +distribute the source code, even though third parties are not
19.596 +compelled to copy the source along with the object code.
19.597 +
19.598 + 5. A program that contains no derivative of any portion of the
19.599 +Library, but is designed to work with the Library by being compiled or
19.600 +linked with it, is called a "work that uses the Library". Such a
19.601 +work, in isolation, is not a derivative work of the Library, and
19.602 +therefore falls outside the scope of this License.
19.603 +
19.604 + However, linking a "work that uses the Library" with the Library
19.605 +creates an executable that is a derivative of the Library (because it
19.606 +contains portions of the Library), rather than a "work that uses the
19.607 +library". The executable is therefore covered by this License.
19.608 +Section 6 states terms for distribution of such executables.
19.609 +
19.610 + When a "work that uses the Library" uses material from a header file
19.611 +that is part of the Library, the object code for the work may be a
19.612 +derivative work of the Library even though the source code is not.
19.613 +Whether this is true is especially significant if the work can be
19.614 +linked without the Library, or if the work is itself a library. The
19.615 +threshold for this to be true is not precisely defined by law.
19.616 +
19.617 + If such an object file uses only numerical parameters, data
19.618 +structure layouts and accessors, and small macros and small inline
19.619 +functions (ten lines or less in length), then the use of the object
19.620 +file is unrestricted, regardless of whether it is legally a derivative
19.621 +work. (Executables containing this object code plus portions of the
19.622 +Library will still fall under Section 6.)
19.623 +
19.624 + Otherwise, if the work is a derivative of the Library, you may
19.625 +distribute the object code for the work under the terms of Section 6.
19.626 +Any executables containing that work also fall under Section 6,
19.627 +whether or not they are linked directly with the Library itself.
19.628 +
19.629 + 6. As an exception to the Sections above, you may also compile or
19.630 +link a "work that uses the Library" with the Library to produce a
19.631 +work containing portions of the Library, and distribute that work
19.632 +under terms of your choice, provided that the terms permit
19.633 +modification of the work for the customer's own use and reverse
19.634 +engineering for debugging such modifications.
19.635 +
19.636 + You must give prominent notice with each copy of the work that the
19.637 +Library is used in it and that the Library and its use are covered by
19.638 +this License. You must supply a copy of this License. If the work
19.639 +during execution displays copyright notices, you must include the
19.640 +copyright notice for the Library among them, as well as a reference
19.641 +directing the user to the copy of this License. Also, you must do one
19.642 +of these things:
19.643 +
19.644 + a) Accompany the work with the complete corresponding
19.645 + machine-readable source code for the Library including whatever
19.646 + changes were used in the work (which must be distributed under
19.647 + Sections 1 and 2 above); and, if the work is an executable linked
19.648 + with the Library, with the complete machine-readable "work that
19.649 + uses the Library", as object code and/or source code, so that the
19.650 + user can modify the Library and then relink to produce a modified
19.651 + executable containing the modified Library. (It is understood
19.652 + that the user who changes the contents of definitions files in the
19.653 + Library will not necessarily be able to recompile the application
19.654 + to use the modified definitions.)
19.655 +
19.656 + b) Accompany the work with a written offer, valid for at
19.657 + least three years, to give the same user the materials
19.658 + specified in Subsection 6a, above, for a charge no more
19.659 + than the cost of performing this distribution.
19.660 +
19.661 + c) If distribution of the work is made by offering access to copy
19.662 + from a designated place, offer equivalent access to copy the above
19.663 + specified materials from the same place.
19.664 +
19.665 + d) Verify that the user has already received a copy of these
19.666 + materials or that you have already sent this user a copy.
19.667 +
19.668 + For an executable, the required form of the "work that uses the
19.669 +Library" must include any data and utility programs needed for
19.670 +reproducing the executable from it. However, as a special exception,
19.671 +the source code distributed need not include anything that is normally
19.672 +distributed (in either source or binary form) with the major
19.673 +components (compiler, kernel, and so on) of the operating system on
19.674 +which the executable runs, unless that component itself accompanies
19.675 +the executable.
19.676 +
19.677 + It may happen that this requirement contradicts the license
19.678 +restrictions of other proprietary libraries that do not normally
19.679 +accompany the operating system. Such a contradiction means you cannot
19.680 +use both them and the Library together in an executable that you
19.681 +distribute.
19.682 +
19.683 + 7. You may place library facilities that are a work based on the
19.684 +Library side-by-side in a single library together with other library
19.685 +facilities not covered by this License, and distribute such a combined
19.686 +library, provided that the separate distribution of the work based on
19.687 +the Library and of the other library facilities is otherwise
19.688 +permitted, and provided that you do these two things:
19.689 +
19.690 + a) Accompany the combined library with a copy of the same work
19.691 + based on the Library, uncombined with any other library
19.692 + facilities. This must be distributed under the terms of the
19.693 + Sections above.
19.694 +
19.695 + b) Give prominent notice with the combined library of the fact
19.696 + that part of it is a work based on the Library, and explaining
19.697 + where to find the accompanying uncombined form of the same work.
19.698 +
19.699 + 8. You may not copy, modify, sublicense, link with, or distribute
19.700 +the Library except as expressly provided under this License. Any
19.701 +attempt otherwise to copy, modify, sublicense, link with, or
19.702 +distribute the Library is void, and will automatically terminate your
19.703 +rights under this License. However, parties who have received copies,
19.704 +or rights, from you under this License will not have their licenses
19.705 +terminated so long as such parties remain in full compliance.
19.706 +
19.707 + 9. You are not required to accept this License, since you have not
19.708 +signed it. However, nothing else grants you permission to modify or
19.709 +distribute the Library or its derivative works. These actions are
19.710 +prohibited by law if you do not accept this License. Therefore, by
19.711 +modifying or distributing the Library (or any work based on the
19.712 +Library), you indicate your acceptance of this License to do so, and
19.713 +all its terms and conditions for copying, distributing or modifying
19.714 +the Library or works based on it.
19.715 +
19.716 + 10. Each time you redistribute the Library (or any work based on the
19.717 +Library), the recipient automatically receives a license from the
19.718 +original licensor to copy, distribute, link with or modify the Library
19.719 +subject to these terms and conditions. You may not impose any further
19.720 +restrictions on the recipients' exercise of the rights granted herein.
19.721 +You are not responsible for enforcing compliance by third parties to
19.722 +this License.
19.723 +
19.724 + 11. If, as a consequence of a court judgment or allegation of patent
19.725 +infringement or for any other reason (not limited to patent issues),
19.726 +conditions are imposed on you (whether by court order, agreement or
19.727 +otherwise) that contradict the conditions of this License, they do not
19.728 +excuse you from the conditions of this License. If you cannot
19.729 +distribute so as to satisfy simultaneously your obligations under this
19.730 +License and any other pertinent obligations, then as a consequence you
19.731 +may not distribute the Library at all. For example, if a patent
19.732 +license would not permit royalty-free redistribution of the Library by
19.733 +all those who receive copies directly or indirectly through you, then
19.734 +the only way you could satisfy both it and this License would be to
19.735 +refrain entirely from distribution of the Library.
19.736 +
19.737 +If any portion of this section is held invalid or unenforceable under any
19.738 +particular circumstance, the balance of the section is intended to apply,
19.739 +and the section as a whole is intended to apply in other circumstances.
19.740 +
19.741 +It is not the purpose of this section to induce you to infringe any
19.742 +patents or other property right claims or to contest validity of any
19.743 +such claims; this section has the sole purpose of protecting the
19.744 +integrity of the free software distribution system which is
19.745 +implemented by public license practices. Many people have made
19.746 +generous contributions to the wide range of software distributed
19.747 +through that system in reliance on consistent application of that
19.748 +system; it is up to the author/donor to decide if he or she is willing
19.749 +to distribute software through any other system and a licensee cannot
19.750 +impose that choice.
19.751 +
19.752 +This section is intended to make thoroughly clear what is believed to
19.753 +be a consequence of the rest of this License.
19.754 +
19.755 + 12. If the distribution and/or use of the Library is restricted in
19.756 +certain countries either by patents or by copyrighted interfaces, the
19.757 +original copyright holder who places the Library under this License may add
19.758 +an explicit geographical distribution limitation excluding those countries,
19.759 +so that distribution is permitted only in or among countries not thus
19.760 +excluded. In such case, this License incorporates the limitation as if
19.761 +written in the body of this License.
19.762 +
19.763 + 13. The Free Software Foundation may publish revised and/or new
19.764 +versions of the Library General Public License from time to time.
19.765 +Such new versions will be similar in spirit to the present version,
19.766 +but may differ in detail to address new problems or concerns.
19.767 +
19.768 +Each version is given a distinguishing version number. If the Library
19.769 +specifies a version number of this License which applies to it and
19.770 +"any later version", you have the option of following the terms and
19.771 +conditions either of that version or of any later version published by
19.772 +the Free Software Foundation. If the Library does not specify a
19.773 +license version number, you may choose any version ever published by
19.774 +the Free Software Foundation.
19.775 +
19.776 + 14. If you wish to incorporate parts of the Library into other free
19.777 +programs whose distribution conditions are incompatible with these,
19.778 +write to the author to ask for permission. For software which is
19.779 +copyrighted by the Free Software Foundation, write to the Free
19.780 +Software Foundation; we sometimes make exceptions for this. Our
19.781 +decision will be guided by the two goals of preserving the free status
19.782 +of all derivatives of our free software and of promoting the sharing
19.783 +and reuse of software generally.
19.784 +
19.785 + NO WARRANTY
19.786 +
19.787 + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
19.788 +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
19.789 +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
19.790 +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
19.791 +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
19.792 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19.793 +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
19.794 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
19.795 +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
19.796 +
19.797 + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
19.798 +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
19.799 +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
19.800 +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
19.801 +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
19.802 +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
19.803 +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
19.804 +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
19.805 +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
19.806 +DAMAGES.
19.807 +
19.808 + END OF TERMS AND CONDITIONS
19.809 +
19.810 + How to Apply These Terms to Your New Libraries
19.811 +
19.812 + If you develop a new library, and you want it to be of the greatest
19.813 +possible use to the public, we recommend making it free software that
19.814 +everyone can redistribute and change. You can do so by permitting
19.815 +redistribution under these terms (or, alternatively, under the terms of the
19.816 +ordinary General Public License).
19.817 +
19.818 + To apply these terms, attach the following notices to the library. It is
19.819 +safest to attach them to the start of each source file to most effectively
19.820 +convey the exclusion of warranty; and each file should have at least the
19.821 +"copyright" line and a pointer to where the full notice is found.
19.822 +
19.823 + <one line to give the library's name and a brief idea of what it does.>
19.824 + Copyright (C) <year> <name of author>
19.825 +
19.826 + This library is free software; you can redistribute it and/or
19.827 + modify it under the terms of the GNU Library General Public
19.828 + License as published by the Free Software Foundation; either
19.829 + version 2 of the License, or (at your option) any later version.
19.830 +
19.831 + This library is distributed in the hope that it will be useful,
19.832 + but WITHOUT ANY WARRANTY; without even the implied warranty of
19.833 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19.834 + Library General Public License for more details.
19.835 +
19.836 + You should have received a copy of the GNU Library General Public
19.837 + License along with this library; if not, write to the Free Software
19.838 + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19.839 +
19.840 +Also add information on how to contact you by electronic and paper mail.
19.841 +
19.842 +You should also get your employer (if you work as a programmer) or your
19.843 +school, if any, to sign a "copyright disclaimer" for the library, if
19.844 +necessary. Here is a sample; alter the names:
19.845 +
19.846 + Yoyodyne, Inc., hereby disclaims all copyright interest in the
19.847 + library `Frob' (a library for tweaking knobs) written by James Random Hacker.
19.848 +
19.849 + <signature of Ty Coon>, 1 April 1990
19.850 + Ty Coon, President of Vice
19.851 +
19.852 +That's all there is to it!
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/libext2fs/docs/README Wed Aug 25 01:28:08 2021 +0200
20.3 @@ -0,0 +1,19 @@
20.4 + This is the new version (1.44.5) of the second extended file
20.5 +system management programs.
20.6 +
20.7 + From time to time, I release new versions of e2fsprogs, to fix
20.8 +bugs and to make the utilities more robust. You can always find
20.9 +information about the latest version at the the e2fsprogs web page,
20.10 +which is:
20.11 +
20.12 + http://e2fsprogs.sourceforge.net
20.13 +
20.14 + The INSTALL file has instructions on building and installing
20.15 +e2fsprogs. Provisions for building Red Hat RPMs and Debian dpkg files
20.16 +are supplied as well.
20.17 +
20.18 + In case of bugs in these programs, please contact Ted Ts'o at
20.19 +tytso@mit.edu or tytso@alum.mit.edu. See the e2fsck man page for
20.20 +suggestions of what sort of information to include when submitting bug
20.21 +reports for these programs.
20.22 +
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/libext2fs/docs/RELEASE-NOTES Wed Aug 25 01:28:08 2021 +0200
21.3 @@ -0,0 +1,77 @@
21.4 +E2fsprogs 1.44.5 (December 15, 2018)
21.5 +====================================
21.6 +
21.7 +Updates/Fixes since v1.44.4:
21.8 +
21.9 +UI and Features
21.10 +---------------
21.11 +
21.12 +When e2fsck notices it could optimize an extent tree, it will now ask
21.13 +"Optimize?" instead of "Fix?", which was confusing some users since it
21.14 +implied that something was broken.
21.15 +
21.16 +
21.17 +Fixes
21.18 +-----
21.19 +
21.20 +Use 64-bit counters to track the number of files that are defragmented
21.21 +using in e4defrag, to avoid overflows when more than 2**32 files are
21.22 +defragmented. (Addresses Debian Bug: #888899)
21.23 +
21.24 +Correctly translate Posix ACL's. This was a regression introduced in
21.25 +v1.44.4. (Addresses Launchpad Bug: #1807288)
21.26 +
21.27 +Use the online free block counts so e2freefrag's percentages are
21.28 +correct.
21.29 +
21.30 +Fix a false warning that tune2fs will take long time to change a UUID if
21.31 +the metadata_csum feature is not enabled.
21.32 +
21.33 +E2fsck will only offer to set the inline_data feature flag when the
21.34 +inline flag is set on the inode, *and* the system.data xattr is present.
21.35 +
21.36 +E4defrag will handle the case where it is running as root and it can't
21.37 +find the file system to open more gracefully. (Addresses Debian Bug:
21.38 +#907634)
21.39 +
21.40 +Fix a bug where resize2fs was failing to update the extent tree
21.41 +checksums in an corner case. (Addresses Launchpad Bug: #1798562)
21.42 +
21.43 +Fix fuse2fs's command line parsing when options are specified after the
21.44 +target device/image.
21.45 +
21.46 +Fix a bug which could cause e2fsprogs tools to segfault on a corrupted
21.47 +file system where the journal's s_nr_users is impossibly large.
21.48 +
21.49 +E2image now includes the mmp block (if needed) when creating a
21.50 +metadata-only image.
21.51 +
21.52 +If various Verity handling bugs which made it completely unusable in
21.53 +e2fsprogs 1.44.4.
21.54 +
21.55 +Fox a bug in tune2fs where it would dereference of freed memory after
21.56 +replaying the journal.
21.57 +
21.58 +
21.59 +Performance, Internal Implementation, Development Support etc.
21.60 +--------------------------------------------------------------
21.61 +
21.62 +Synchronized changes from Android's AOSP e2fsprogs tree.
21.63 +
21.64 +Fix groff formatting nits in various man pages. (Addresses Debian Bug:
21.65 +#916188)
21.66 +
21.67 +Fixed various debian packaging issues (Addresses Debian Bug: #915942)
21.68 +
21.69 +Adjusted the copyright license for lib/blkid/version.c to be LGPL (and
21.70 +consistent with the rest of files in that directory).
21.71 +
21.72 +Fix various clang warnings.
21.73 +
21.74 +Fix "make install" when configure was run with --enable-subset.
21.75 +
21.76 +Make sure the regression tests clean up their tmpfile if the test script
21.77 +exits.
21.78 +
21.79 +Fix build failures on non-glibc systems.
21.80 +
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/libext2fs/include/Makefile Wed Aug 25 01:28:08 2021 +0200
22.3 @@ -0,0 +1,6 @@
22.4 +PKGDIR ?= ..
22.5 +L4DIR ?= $(PKGDIR)/../../..
22.6 +
22.7 +TARGET := libuuid libblkid libsupport libe2p libet libext2fs
22.8 +
22.9 +include $(L4DIR)/mk/subdir.mk
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/libext2fs/include/libblkid/blkid/blkid.h Wed Aug 25 01:28:08 2021 +0200
23.3 @@ -0,0 +1,110 @@
23.4 +/*
23.5 + * blkid.h - Interface for libblkid, a library to identify block devices
23.6 + *
23.7 + * Copyright (C) 2001 Andreas Dilger
23.8 + * Copyright (C) 2003 Theodore Ts'o
23.9 + *
23.10 + * %Begin-Header%
23.11 + * This file may be redistributed under the terms of the
23.12 + * GNU Lesser General Public License.
23.13 + * %End-Header%
23.14 + */
23.15 +
23.16 +#ifndef _BLKID_BLKID_H
23.17 +#define _BLKID_BLKID_H
23.18 +
23.19 +#include <sys/types.h>
23.20 +#include <blkid/blkid_types.h>
23.21 +
23.22 +#ifdef __cplusplus
23.23 +extern "C" {
23.24 +#endif
23.25 +
23.26 +#define BLKID_VERSION "1.0.0"
23.27 +#define BLKID_DATE "12-Feb-2003"
23.28 +
23.29 +typedef struct blkid_struct_dev *blkid_dev;
23.30 +typedef struct blkid_struct_cache *blkid_cache;
23.31 +typedef __s64 blkid_loff_t;
23.32 +
23.33 +typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
23.34 +typedef struct blkid_struct_dev_iterate *blkid_dev_iterate;
23.35 +
23.36 +/*
23.37 + * Flags for blkid_get_dev
23.38 + *
23.39 + * BLKID_DEV_CREATE Create an empty device structure if not found
23.40 + * in the cache.
23.41 + * BLKID_DEV_VERIFY Make sure the device structure corresponds
23.42 + * with reality.
23.43 + * BLKID_DEV_FIND Just look up a device entry, and return NULL
23.44 + * if it is not found.
23.45 + * BLKID_DEV_NORMAL Get a valid device structure, either from the
23.46 + * cache or by probing the device.
23.47 + */
23.48 +#define BLKID_DEV_FIND 0x0000
23.49 +#define BLKID_DEV_CREATE 0x0001
23.50 +#define BLKID_DEV_VERIFY 0x0002
23.51 +#define BLKID_DEV_NORMAL (BLKID_DEV_CREATE | BLKID_DEV_VERIFY)
23.52 +
23.53 +/* cache.c */
23.54 +extern void blkid_put_cache(blkid_cache cache);
23.55 +extern int blkid_get_cache(blkid_cache *cache, const char *filename);
23.56 +extern void blkid_gc_cache(blkid_cache cache);
23.57 +
23.58 +/* dev.c */
23.59 +extern const char *blkid_dev_devname(blkid_dev dev);
23.60 +
23.61 +extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache);
23.62 +extern int blkid_dev_set_search(blkid_dev_iterate iter,
23.63 + char *search_type, char *search_value);
23.64 +extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev);
23.65 +extern void blkid_dev_iterate_end(blkid_dev_iterate iterate);
23.66 +
23.67 +/* devno.c */
23.68 +extern char *blkid_devno_to_devname(dev_t devno);
23.69 +
23.70 +/* devname.c */
23.71 +extern int blkid_probe_all(blkid_cache cache);
23.72 +extern int blkid_probe_all_new(blkid_cache cache);
23.73 +extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname,
23.74 + int flags);
23.75 +
23.76 +/* getsize.c */
23.77 +extern blkid_loff_t blkid_get_dev_size(int fd);
23.78 +
23.79 +/* probe.c */
23.80 +int blkid_known_fstype(const char *fstype);
23.81 +extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev);
23.82 +
23.83 +/* read.c */
23.84 +
23.85 +/* resolve.c */
23.86 +extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
23.87 + const char *devname);
23.88 +extern char *blkid_get_devname(blkid_cache cache, const char *token,
23.89 + const char *value);
23.90 +
23.91 +/* tag.c */
23.92 +extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev);
23.93 +extern int blkid_tag_next(blkid_tag_iterate iterate,
23.94 + const char **type, const char **value);
23.95 +extern void blkid_tag_iterate_end(blkid_tag_iterate iterate);
23.96 +extern int blkid_dev_has_tag(blkid_dev dev, const char *type,
23.97 + const char *value);
23.98 +extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
23.99 + const char *type,
23.100 + const char *value);
23.101 +extern int blkid_parse_tag_string(const char *token, char **ret_type,
23.102 + char **ret_val);
23.103 +
23.104 +/* version.c */
23.105 +extern int blkid_parse_version_string(const char *ver_string);
23.106 +extern int blkid_get_library_version(const char **ver_string,
23.107 + const char **date_string);
23.108 +
23.109 +#ifdef __cplusplus
23.110 +}
23.111 +#endif
23.112 +
23.113 +#endif /* _BLKID_BLKID_H */
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/libext2fs/include/libblkid/blkid/blkid_types.h Wed Aug 25 01:28:08 2021 +0200
24.3 @@ -0,0 +1,174 @@
24.4 +/*
24.5 + * If linux/types.h is already been included, assume it has defined
24.6 + * everything we need. (cross fingers) Other header files may have
24.7 + * also defined the types that we need.
24.8 + */
24.9 +#if (!defined(_LINUX_TYPES_H) && !defined(_BLKID_TYPES_H) && \
24.10 + !defined(_EXT2_TYPES_H))
24.11 +#define _BLKID_TYPES_H
24.12 +
24.13 +#define __S8_TYPEDEF __signed__ char
24.14 +#define __U8_TYPEDEF unsigned char
24.15 +#define __S16_TYPEDEF __signed__ short
24.16 +#define __U16_TYPEDEF unsigned short
24.17 +#define __S32_TYPEDEF __signed__ int
24.18 +#define __U32_TYPEDEF unsigned int
24.19 +#define __S64_TYPEDEF __signed__ long long
24.20 +#define __U64_TYPEDEF unsigned long long
24.21 +
24.22 +#ifndef HAVE___U8
24.23 +#define HAVE___U8
24.24 +#ifdef __U8_TYPEDEF
24.25 +typedef __U8_TYPEDEF __u8;
24.26 +#else
24.27 +typedef unsigned char __u8;
24.28 +#endif
24.29 +#endif /* HAVE___U8 */
24.30 +
24.31 +#ifndef HAVE___S8
24.32 +#define HAVE___S8
24.33 +#ifdef __S8_TYPEDEF
24.34 +typedef __S8_TYPEDEF __s8;
24.35 +#else
24.36 +typedef signed char __s8;
24.37 +#endif
24.38 +#endif /* HAVE___S8 */
24.39 +
24.40 +#ifndef HAVE___U16
24.41 +#define HAVE___U16
24.42 +#ifdef __U16_TYPEDEF
24.43 +typedef __U16_TYPEDEF __u16;
24.44 +#else
24.45 +#if (4 == 2)
24.46 +typedef unsigned int __u16;
24.47 +#else
24.48 +#if (2 == 2)
24.49 +typedef unsigned short __u16;
24.50 +#else
24.51 +#undef HAVE___U16
24.52 + ?==error: undefined 16 bit type
24.53 +#endif /* SIZEOF_SHORT == 2 */
24.54 +#endif /* SIZEOF_INT == 2 */
24.55 +#endif /* __U16_TYPEDEF */
24.56 +#endif /* HAVE___U16 */
24.57 +
24.58 +#ifndef HAVE___S16
24.59 +#define HAVE___S16
24.60 +#ifdef __S16_TYPEDEF
24.61 +typedef __S16_TYPEDEF __s16;
24.62 +#else
24.63 +#if (4 == 2)
24.64 +typedef int __s16;
24.65 +#else
24.66 +#if (2 == 2)
24.67 +typedef short __s16;
24.68 +#else
24.69 +#undef HAVE___S16
24.70 + ?==error: undefined 16 bit type
24.71 +#endif /* SIZEOF_SHORT == 2 */
24.72 +#endif /* SIZEOF_INT == 2 */
24.73 +#endif /* __S16_TYPEDEF */
24.74 +#endif /* HAVE___S16 */
24.75 +
24.76 +#ifndef HAVE___U32
24.77 +#define HAVE___U32
24.78 +#ifdef __U32_TYPEDEF
24.79 +typedef __U32_TYPEDEF __u32;
24.80 +#else
24.81 +#if (4 == 4)
24.82 +typedef unsigned int __u32;
24.83 +#else
24.84 +#if (4 == 4)
24.85 +typedef unsigned long __u32;
24.86 +#else
24.87 +#if (2 == 4)
24.88 +typedef unsigned short __u32;
24.89 +#else
24.90 +#undef HAVE___U32
24.91 + ?== error: undefined 32 bit type
24.92 +#endif /* SIZEOF_SHORT == 4 */
24.93 +#endif /* SIZEOF_LONG == 4 */
24.94 +#endif /* SIZEOF_INT == 4 */
24.95 +#endif /* __U32_TYPEDEF */
24.96 +#endif /* HAVE___U32 */
24.97 +
24.98 +#ifndef HAVE___S32
24.99 +#define HAVE___S32
24.100 +#ifdef __S32_TYPEDEF
24.101 +typedef __S32_TYPEDEF __s32;
24.102 +#else
24.103 +#if (4 == 4)
24.104 +typedef int __s32;
24.105 +#else
24.106 +#if (4 == 4)
24.107 +typedef long __s32;
24.108 +#else
24.109 +#if (2 == 4)
24.110 +typedef short __s32;
24.111 +#else
24.112 +#undef HAVE___S32
24.113 + ?== error: undefined 32 bit type
24.114 +#endif /* SIZEOF_SHORT == 4 */
24.115 +#endif /* SIZEOF_LONG == 4 */
24.116 +#endif /* SIZEOF_INT == 4 */
24.117 +#endif /* __S32_TYPEDEF */
24.118 +#endif /* HAVE___S32 */
24.119 +
24.120 +#ifndef HAVE___U64
24.121 +#define HAVE___U64
24.122 +#ifdef __U64_TYPEDEF
24.123 +typedef __U64_TYPEDEF __u64;
24.124 +#else
24.125 +#if (4 == 8)
24.126 +typedef unsigned int __u64;
24.127 +#else
24.128 +#if (8 == 8)
24.129 +typedef unsigned long long __u64;
24.130 +#else
24.131 +#if (4 == 8)
24.132 +typedef unsigned long __u64;
24.133 +#else
24.134 +#undef HAVE___U64
24.135 + ?== error: undefined 64 bit type
24.136 +#endif /* SIZEOF_LONG == 8 */
24.137 +#endif /* SIZEOF_LONG_LONG == 8 */
24.138 +#endif /* SIZEOF_INT == 8 */
24.139 +#endif /* __U64_TYPEDEF */
24.140 +#endif /* HAVE___U64 */
24.141 +
24.142 +#ifndef HAVE___S64
24.143 +#define HAVE___S64
24.144 +#ifdef __S64_TYPEDEF
24.145 +typedef __S64_TYPEDEF __s64;
24.146 +#else
24.147 +#if (4 == 8)
24.148 +typedef int __s64;
24.149 +#else
24.150 +#if (8 == 8)
24.151 +#if defined(__GNUC__)
24.152 +typedef __signed__ long long __s64;
24.153 +#else
24.154 +typedef signed long long __s64;
24.155 +#endif /* __GNUC__ */
24.156 +#else
24.157 +#if (4 == 8)
24.158 +typedef long __s64;
24.159 +#else
24.160 +#undef HAVE___S64
24.161 + ?== error: undefined 64 bit type
24.162 +#endif /* SIZEOF_LONG == 8 */
24.163 +#endif /* SIZEOF_LONG_LONG == 8 */
24.164 +#endif /* SIZEOF_INT == 8 */
24.165 +#endif /* __S64_TYPEDEF */
24.166 +#endif /* HAVE___S64 */
24.167 +
24.168 +#undef __S8_TYPEDEF
24.169 +#undef __U8_TYPEDEF
24.170 +#undef __S16_TYPEDEF
24.171 +#undef __U16_TYPEDEF
24.172 +#undef __S32_TYPEDEF
24.173 +#undef __U32_TYPEDEF
24.174 +#undef __S64_TYPEDEF
24.175 +#undef __U64_TYPEDEF
24.176 +
24.177 +#endif /* _*_TYPES_H */
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/libext2fs/include/libblkid/blkid/list.h Wed Aug 25 01:28:08 2021 +0200
25.3 @@ -0,0 +1,184 @@
25.4 +#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD_INIT)
25.5 +#define _BLKID_LIST_H
25.6 +
25.7 +#ifdef __cplusplus
25.8 +extern "C" {
25.9 +#endif
25.10 +
25.11 +#ifdef HAVE_INTTYPES_H
25.12 +#include <inttypes.h>
25.13 +#else
25.14 +#ifdef HAVE_STDINT_H
25.15 +#include <stdint.h>
25.16 +#endif
25.17 +#endif
25.18 +
25.19 +#ifdef __GNUC__
25.20 +#define _INLINE_ static __inline__
25.21 +#else /* For Watcom C */
25.22 +#define _INLINE_ static inline
25.23 +#endif
25.24 +
25.25 +/*
25.26 + * Simple doubly linked list implementation.
25.27 + *
25.28 + * Some of the internal functions ("__xxx") are useful when
25.29 + * manipulating whole lists rather than single entries, as
25.30 + * sometimes we already know the next/prev entries and we can
25.31 + * generate better code by using them directly rather than
25.32 + * using the generic single-entry routines.
25.33 + */
25.34 +
25.35 +struct list_head {
25.36 + struct list_head *next, *prev;
25.37 +};
25.38 +
25.39 +#define LIST_HEAD_INIT(name) { &(name), &(name) }
25.40 +
25.41 +#define INIT_LIST_HEAD(ptr) do { \
25.42 + (ptr)->next = (ptr); (ptr)->prev = (ptr); \
25.43 +} while (0)
25.44 +
25.45 +/*
25.46 + * Insert a new entry between two known consecutive entries.
25.47 + *
25.48 + * This is only for internal list manipulation where we know
25.49 + * the prev/next entries already!
25.50 + */
25.51 +_INLINE_ void __list_add(struct list_head * add,
25.52 + struct list_head * prev,
25.53 + struct list_head * next)
25.54 +{
25.55 + next->prev = add;
25.56 + add->next = next;
25.57 + add->prev = prev;
25.58 + prev->next = add;
25.59 +}
25.60 +
25.61 +/**
25.62 + * list_add - add a new entry
25.63 + * @add: new entry to be added
25.64 + * @head: list head to add it after
25.65 + *
25.66 + * Insert a new entry after the specified head.
25.67 + * This is good for implementing stacks.
25.68 + */
25.69 +_INLINE_ void list_add(struct list_head *add, struct list_head *head)
25.70 +{
25.71 + __list_add(add, head, head->next);
25.72 +}
25.73 +
25.74 +/**
25.75 + * list_add_tail - add a new entry
25.76 + * @add: new entry to be added
25.77 + * @head: list head to add it before
25.78 + *
25.79 + * Insert a new entry before the specified head.
25.80 + * This is useful for implementing queues.
25.81 + */
25.82 +_INLINE_ void list_add_tail(struct list_head *add, struct list_head *head)
25.83 +{
25.84 + __list_add(add, head->prev, head);
25.85 +}
25.86 +
25.87 +/*
25.88 + * Delete a list entry by making the prev/next entries
25.89 + * point to each other.
25.90 + *
25.91 + * This is only for internal list manipulation where we know
25.92 + * the prev/next entries already!
25.93 + */
25.94 +_INLINE_ void __list_del(struct list_head * prev,
25.95 + struct list_head * next)
25.96 +{
25.97 + next->prev = prev;
25.98 + prev->next = next;
25.99 +}
25.100 +
25.101 +/**
25.102 + * list_del - deletes entry from list.
25.103 + * @entry: the element to delete from the list.
25.104 + *
25.105 + * list_empty() on @entry does not return true after this, @entry is
25.106 + * in an undefined state.
25.107 + */
25.108 +_INLINE_ void list_del(struct list_head *entry)
25.109 +{
25.110 + __list_del(entry->prev, entry->next);
25.111 +}
25.112 +
25.113 +/**
25.114 + * list_del_init - deletes entry from list and reinitialize it.
25.115 + * @entry: the element to delete from the list.
25.116 + */
25.117 +_INLINE_ void list_del_init(struct list_head *entry)
25.118 +{
25.119 + __list_del(entry->prev, entry->next);
25.120 + INIT_LIST_HEAD(entry);
25.121 +}
25.122 +
25.123 +/**
25.124 + * list_empty - tests whether a list is empty
25.125 + * @head: the list to test.
25.126 + */
25.127 +_INLINE_ int list_empty(struct list_head *head)
25.128 +{
25.129 + return head->next == head;
25.130 +}
25.131 +
25.132 +/**
25.133 + * list_splice - join two lists
25.134 + * @list: the new list to add.
25.135 + * @head: the place to add it in the first list.
25.136 + */
25.137 +_INLINE_ void list_splice(struct list_head *list, struct list_head *head)
25.138 +{
25.139 + struct list_head *first = list->next;
25.140 +
25.141 + if (first != list) {
25.142 + struct list_head *last = list->prev;
25.143 + struct list_head *at = head->next;
25.144 +
25.145 + first->prev = head;
25.146 + head->next = first;
25.147 +
25.148 + last->next = at;
25.149 + at->prev = last;
25.150 + }
25.151 +}
25.152 +
25.153 +/**
25.154 + * list_entry - get the struct for this entry
25.155 + * @ptr: the &struct list_head pointer.
25.156 + * @type: the type of the struct this is embedded in.
25.157 + * @member: the name of the list_struct within the struct.
25.158 + */
25.159 +#define list_entry(ptr, type, member) \
25.160 + ((type *)((char *)(ptr)-(unsigned long)(intptr_t)(&((type *)0)->member)))
25.161 +
25.162 +/**
25.163 + * list_for_each - iterate over elements in a list
25.164 + * @pos: the &struct list_head to use as a loop counter.
25.165 + * @head: the head for your list.
25.166 + */
25.167 +#define list_for_each(pos, head) \
25.168 + for (pos = (head)->next; pos != (head); pos = pos->next)
25.169 +
25.170 +/**
25.171 + * list_for_each_safe - iterate over elements in a list, but don't dereference
25.172 + * pos after the body is done (in case it is freed)
25.173 + * @pos: the &struct list_head to use as a loop counter.
25.174 + * @pnext: the &struct list_head to use as a pointer to the next item.
25.175 + * @head: the head for your list (not included in iteration).
25.176 + */
25.177 +#define list_for_each_safe(pos, pnext, head) \
25.178 + for (pos = (head)->next, pnext = pos->next; pos != (head); \
25.179 + pos = pnext, pnext = pos->next)
25.180 +
25.181 +#undef _INLINE_
25.182 +
25.183 +#ifdef __cplusplus
25.184 +}
25.185 +#endif
25.186 +
25.187 +#endif /* _BLKID_LIST_H */
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/libext2fs/include/libe2p/Makefile Wed Aug 25 01:28:08 2021 +0200
26.3 @@ -0,0 +1,7 @@
26.4 +PKGDIR ?= ../..
26.5 +L4DIR ?= $(PKGDIR)/../../..
26.6 +
26.7 +PKGNAME = libe2p
26.8 +CONTRIB_HEADERS = 1
26.9 +
26.10 +include $(L4DIR)/mk/include.mk
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/libext2fs/include/libe2p/e2p/e2p.h Wed Aug 25 01:28:08 2021 +0200
27.3 @@ -0,0 +1,82 @@
27.4 +/*
27.5 + * e2p.h --- header file for the e2p library
27.6 + *
27.7 + * %Begin-Header%
27.8 + * This file may be redistributed under the terms of the GNU Library
27.9 + * General Public License, version 2.
27.10 + * %End-Header%
27.11 + */
27.12 +
27.13 +#include <sys/types.h> /* Needed by dirent.h on netbsd */
27.14 +#include <stdio.h>
27.15 +#include <dirent.h>
27.16 +
27.17 +#include <ext2fs/ext2_fs.h>
27.18 +
27.19 +#define E2P_FEATURE_COMPAT 0
27.20 +#define E2P_FEATURE_INCOMPAT 1
27.21 +#define E2P_FEATURE_RO_INCOMPAT 2
27.22 +#define E2P_FEATURE_TYPE_MASK 0x03
27.23 +
27.24 +#define E2P_FEATURE_NEGATE_FLAG 0x80
27.25 +
27.26 +#define E2P_FS_FEATURE 0
27.27 +#define E2P_JOURNAL_FEATURE 1
27.28 +
27.29 +/* `options' for print_flags() */
27.30 +
27.31 +#define PFOPT_LONG 1 /* Must be 1 for compatibility with `int long_format'. */
27.32 +
27.33 +
27.34 +int fgetflags (const char * name, unsigned long * flags);
27.35 +int fgetversion (const char * name, unsigned long * version);
27.36 +int fsetflags (const char * name, unsigned long flags);
27.37 +int fsetversion (const char * name, unsigned long version);
27.38 +int fgetproject(const char *name, unsigned long *project);
27.39 +int fsetproject(const char *name, unsigned long project);
27.40 +int getflags (int fd, unsigned long * flags);
27.41 +int getversion (int fd, unsigned long * version);
27.42 +int iterate_on_dir (const char * dir_name,
27.43 + int (*func) (const char *, struct dirent *, void *),
27.44 + void * private_arg);
27.45 +void list_super(struct ext2_super_block * s);
27.46 +void list_super2(struct ext2_super_block * s, FILE *f);
27.47 +void print_fs_errors (FILE * f, unsigned short errors);
27.48 +void print_flags (FILE * f, unsigned long flags, unsigned options);
27.49 +void print_fs_state (FILE * f, unsigned short state);
27.50 +int setflags (int fd, unsigned long flags);
27.51 +int setversion (int fd, unsigned long version);
27.52 +
27.53 +void e2p_list_journal_super(FILE *f, char *journal_sb_buf,
27.54 + int exp_block_size, int flags);
27.55 +
27.56 +const char *e2p_feature2string(int compat, unsigned int mask);
27.57 +const char *e2p_jrnl_feature2string(int compat, unsigned int mask);
27.58 +int e2p_string2feature(char *string, int *compat, unsigned int *mask);
27.59 +int e2p_jrnl_string2feature(char *string, int *compat_type, unsigned int *mask);
27.60 +int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array);
27.61 +int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array,
27.62 + __u32 *clear_ok_array, int *type_err,
27.63 + unsigned int *mask_err);
27.64 +
27.65 +int e2p_is_null_uuid(void *uu);
27.66 +void e2p_uuid_to_str(void *uu, char *out);
27.67 +const char *e2p_uuid2str(void *uu);
27.68 +
27.69 +const char *e2p_hash2string(int num);
27.70 +int e2p_string2hash(char *string);
27.71 +
27.72 +const char *e2p_mntopt2string(unsigned int mask);
27.73 +int e2p_string2mntopt(char *string, unsigned int *mask);
27.74 +int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok);
27.75 +
27.76 +unsigned long parse_num_blocks(const char *arg, int log_block_size);
27.77 +unsigned long long parse_num_blocks2(const char *arg, int log_block_size);
27.78 +
27.79 +char *e2p_os2string(int os_type);
27.80 +int e2p_string2os(char *str);
27.81 +
27.82 +unsigned int e2p_percent(int percent, unsigned int base);
27.83 +
27.84 +const char *e2p_encmode2string(int num);
27.85 +int e2p_string2encmode(char *string);
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/libext2fs/include/libet/Makefile Wed Aug 25 01:28:08 2021 +0200
28.3 @@ -0,0 +1,7 @@
28.4 +PKGDIR ?= ../..
28.5 +L4DIR ?= $(PKGDIR)/../../..
28.6 +
28.7 +PKGNAME = libet
28.8 +CONTRIB_HEADERS = 1
28.9 +
28.10 +include $(L4DIR)/mk/include.mk
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/libext2fs/include/libet/et/com_err.h Wed Aug 25 01:28:08 2021 +0200
29.3 @@ -0,0 +1,68 @@
29.4 +/*
29.5 + * Header file for common error description library.
29.6 + *
29.7 + * Copyright 1988, Student Information Processing Board of the
29.8 + * Massachusetts Institute of Technology.
29.9 + *
29.10 + * For copyright and distribution info, see the documentation supplied
29.11 + * with this package.
29.12 + */
29.13 +
29.14 +#if !defined(__COM_ERR_H) && !defined(__COM_ERR_H__)
29.15 +
29.16 +#ifdef __GNUC__
29.17 +#define COM_ERR_ATTR(x) __attribute__(x)
29.18 +#else
29.19 +#define COM_ERR_ATTR(x)
29.20 +#endif
29.21 +
29.22 +#include <stddef.h>
29.23 +#include <stdarg.h>
29.24 +
29.25 +typedef long errcode_t;
29.26 +
29.27 +struct error_table {
29.28 + char const * const * msgs;
29.29 + long base;
29.30 + int n_msgs;
29.31 +};
29.32 +struct et_list;
29.33 +
29.34 +extern void com_err (const char *, long, const char *, ...)
29.35 + COM_ERR_ATTR((format(printf, 3, 4)));
29.36 +
29.37 +extern void com_err_va (const char *whoami, errcode_t code, const char *fmt,
29.38 + va_list args)
29.39 + COM_ERR_ATTR((format(printf, 3, 0)));
29.40 +
29.41 +extern char const *error_message (long);
29.42 +extern void (*com_err_hook) (const char *, long, const char *, va_list);
29.43 +extern void (*set_com_err_hook (void (*) (const char *, long,
29.44 + const char *, va_list)))
29.45 + (const char *, long, const char *, va_list);
29.46 +extern void (*reset_com_err_hook (void)) (const char *, long,
29.47 + const char *, va_list);
29.48 +extern int init_error_table(const char * const *msgs, long base, int count);
29.49 +extern char *(*set_com_err_gettext (char *(*) (const char *)))
29.50 + (const char *);
29.51 +
29.52 +extern errcode_t add_error_table(const struct error_table * et);
29.53 +extern errcode_t remove_error_table(const struct error_table * et);
29.54 +extern void add_to_error_table(struct et_list *new_table);
29.55 +
29.56 +/* Provided for Heimdall compatibility */
29.57 +extern const char *com_right(struct et_list *list, long code);
29.58 +extern const char *com_right_r(struct et_list *list, long code, char *str, size_t len);
29.59 +extern void initialize_error_table_r(struct et_list **list,
29.60 + const char **messages,
29.61 + int num_errors,
29.62 + long base);
29.63 +extern void free_error_table(struct et_list *et);
29.64 +
29.65 +/* Provided for compatibility with other com_err libraries */
29.66 +extern int et_list_lock(void);
29.67 +extern int et_list_unlock(void);
29.68 +
29.69 +#define __COM_ERR_H
29.70 +#define __COM_ERR_H__
29.71 +#endif /* !defined(__COM_ERR_H) && !defined(__COM_ERR_H__)*/
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/libext2fs/include/libext2fs/Makefile Wed Aug 25 01:28:08 2021 +0200
30.3 @@ -0,0 +1,7 @@
30.4 +PKGDIR ?= ../..
30.5 +L4DIR ?= $(PKGDIR)/../../..
30.6 +
30.7 +PKGNAME = libext2fs
30.8 +CONTRIB_HEADERS = 1
30.9 +
30.10 +include $(L4DIR)/mk/include.mk
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/libext2fs/include/libext2fs/ext2fs/bitops.h Wed Aug 25 01:28:08 2021 +0200
31.3 @@ -0,0 +1,703 @@
31.4 +/*
31.5 + * bitops.h --- Bitmap frobbing code. The byte swapping routines are
31.6 + * also included here.
31.7 + *
31.8 + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
31.9 + *
31.10 + * %Begin-Header%
31.11 + * This file may be redistributed under the terms of the GNU Library
31.12 + * General Public License, version 2.
31.13 + * %End-Header%
31.14 + */
31.15 +
31.16 +#ifdef WORDS_BIGENDIAN
31.17 +#define ext2fs_cpu_to_le64(x) ((__force __le64)ext2fs_swab64((__u64)(x)))
31.18 +#define ext2fs_le64_to_cpu(x) ext2fs_swab64((__force __u64)(__le64)(x))
31.19 +#define ext2fs_cpu_to_le32(x) ((__force __le32)ext2fs_swab32((__u32)(x)))
31.20 +#define ext2fs_le32_to_cpu(x) ext2fs_swab32((__force __u32)(__le32)(x))
31.21 +#define ext2fs_cpu_to_le16(x) ((__force __le16)ext2fs_swab16((__u16)(x)))
31.22 +#define ext2fs_le16_to_cpu(x) ext2fs_swab16((__force __u16)(__le16)(x))
31.23 +
31.24 +#define ext2fs_cpu_to_be64(x) ((__force __be64)(__u64)(x))
31.25 +#define ext2fs_be64_to_cpu(x) ((__force __u64)(__be64)(x))
31.26 +#define ext2fs_cpu_to_be32(x) ((__force __be32)(__u32)(x))
31.27 +#define ext2fs_be32_to_cpu(x) ((__force __u32)(__be32)(x))
31.28 +#define ext2fs_cpu_to_be16(x) ((__force __be16)(__u16)(x))
31.29 +#define ext2fs_be16_to_cpu(x) ((__force __u16)(__be16)(x))
31.30 +#else
31.31 +#define ext2fs_cpu_to_le64(x) ((__force __le64)(__u64)(x))
31.32 +#define ext2fs_le64_to_cpu(x) ((__force __u64)(__le64)(x))
31.33 +#define ext2fs_cpu_to_le32(x) ((__force __le32)(__u32)(x))
31.34 +#define ext2fs_le32_to_cpu(x) ((__force __u32)(__le32)(x))
31.35 +#define ext2fs_cpu_to_le16(x) ((__force __le16)(__u16)(x))
31.36 +#define ext2fs_le16_to_cpu(x) ((__force __u16)(__le16)(x))
31.37 +
31.38 +#define ext2fs_cpu_to_be64(x) ((__force __be64)ext2fs_swab64((__u64)(x)))
31.39 +#define ext2fs_be64_to_cpu(x) ext2fs_swab64((__force __u64)(__be64)(x))
31.40 +#define ext2fs_cpu_to_be32(x) ((__force __be32)ext2fs_swab32((__u32)(x)))
31.41 +#define ext2fs_be32_to_cpu(x) ext2fs_swab32((__force __u32)(__be32)(x))
31.42 +#define ext2fs_cpu_to_be16(x) ((__force __be16)ext2fs_swab16((__u16)(x)))
31.43 +#define ext2fs_be16_to_cpu(x) ext2fs_swab16((__force __u16)(__be16)(x))
31.44 +#endif
31.45 +
31.46 +/*
31.47 + * EXT2FS bitmap manipulation routines.
31.48 + */
31.49 +
31.50 +/* Support for sending warning messages from the inline subroutines */
31.51 +extern const char *ext2fs_block_string;
31.52 +extern const char *ext2fs_inode_string;
31.53 +extern const char *ext2fs_mark_string;
31.54 +extern const char *ext2fs_unmark_string;
31.55 +extern const char *ext2fs_test_string;
31.56 +extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
31.57 + const char *description);
31.58 +extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
31.59 + int code, unsigned long arg);
31.60 +
31.61 +#ifdef NO_INLINE_FUNCS
31.62 +extern void ext2fs_fast_set_bit(unsigned int nr,void * addr);
31.63 +extern void ext2fs_fast_clear_bit(unsigned int nr, void * addr);
31.64 +extern void ext2fs_fast_set_bit64(__u64 nr,void * addr);
31.65 +extern void ext2fs_fast_clear_bit64(__u64 nr, void * addr);
31.66 +extern __u16 ext2fs_swab16(__u16 val);
31.67 +extern __u32 ext2fs_swab32(__u32 val);
31.68 +extern __u64 ext2fs_swab64(__u64 val);
31.69 +
31.70 +extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
31.71 +extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
31.72 + blk_t block);
31.73 +extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
31.74 +
31.75 +extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
31.76 +extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
31.77 + ext2_ino_t inode);
31.78 +extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
31.79 +
31.80 +extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
31.81 + blk_t block);
31.82 +extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
31.83 + blk_t block);
31.84 +extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
31.85 + blk_t block);
31.86 +
31.87 +extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
31.88 + ext2_ino_t inode);
31.89 +extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
31.90 + ext2_ino_t inode);
31.91 +extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
31.92 + ext2_ino_t inode);
31.93 +extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
31.94 +extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
31.95 +extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
31.96 +extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
31.97 +
31.98 +extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
31.99 + blk_t block, int num);
31.100 +extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
31.101 + blk_t block, int num);
31.102 +extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
31.103 + blk_t block, int num);
31.104 +#endif
31.105 +
31.106 +/* These functions routines moved to gen_bitmap.c */
31.107 +extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
31.108 + blk_t block, int num);
31.109 +extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
31.110 + blk_t block, int num);
31.111 +extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
31.112 + blk_t block, int num);
31.113 +extern int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap,
31.114 + ext2_ino_t inode, int num);
31.115 +extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
31.116 + __u32 bitno);
31.117 +extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
31.118 + blk_t bitno);
31.119 +extern int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
31.120 + blk_t bitno);
31.121 +extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
31.122 + blk_t block, int num);
31.123 +extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
31.124 +extern __u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap);
31.125 +extern __u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap);
31.126 +
31.127 +/* 64-bit versions */
31.128 +
31.129 +#ifdef NO_INLINE_FUNCS
31.130 +extern int ext2fs_mark_block_bitmap2(ext2fs_block_bitmap bitmap,
31.131 + blk64_t block);
31.132 +extern int ext2fs_unmark_block_bitmap2(ext2fs_block_bitmap bitmap,
31.133 + blk64_t block);
31.134 +extern int ext2fs_test_block_bitmap2(ext2fs_block_bitmap bitmap,
31.135 + blk64_t block);
31.136 +
31.137 +extern int ext2fs_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.138 + ext2_ino_t inode);
31.139 +extern int ext2fs_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.140 + ext2_ino_t inode);
31.141 +extern int ext2fs_test_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.142 + ext2_ino_t inode);
31.143 +
31.144 +extern void ext2fs_fast_mark_block_bitmap2(ext2fs_block_bitmap bitmap,
31.145 + blk64_t block);
31.146 +extern void ext2fs_fast_unmark_block_bitmap2(ext2fs_block_bitmap bitmap,
31.147 + blk64_t block);
31.148 +extern int ext2fs_fast_test_block_bitmap2(ext2fs_block_bitmap bitmap,
31.149 + blk64_t block);
31.150 +
31.151 +extern void ext2fs_fast_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.152 + ext2_ino_t inode);
31.153 +extern void ext2fs_fast_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.154 + ext2_ino_t inode);
31.155 +extern int ext2fs_fast_test_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.156 + ext2_ino_t inode);
31.157 +extern errcode_t ext2fs_find_first_zero_block_bitmap2(ext2fs_block_bitmap bitmap,
31.158 + blk64_t start,
31.159 + blk64_t end,
31.160 + blk64_t *out);
31.161 +extern errcode_t ext2fs_find_first_zero_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.162 + ext2_ino_t start,
31.163 + ext2_ino_t end,
31.164 + ext2_ino_t *out);
31.165 +extern errcode_t ext2fs_find_first_set_block_bitmap2(ext2fs_block_bitmap bitmap,
31.166 + blk64_t start,
31.167 + blk64_t end,
31.168 + blk64_t *out);
31.169 +extern errcode_t ext2fs_find_first_set_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.170 + ext2_ino_t start,
31.171 + ext2_ino_t end,
31.172 + ext2_ino_t *out);
31.173 +extern blk64_t ext2fs_get_block_bitmap_start2(ext2fs_block_bitmap bitmap);
31.174 +extern ext2_ino_t ext2fs_get_inode_bitmap_start2(ext2fs_inode_bitmap bitmap);
31.175 +extern blk64_t ext2fs_get_block_bitmap_end2(ext2fs_block_bitmap bitmap);
31.176 +extern ext2_ino_t ext2fs_get_inode_bitmap_end2(ext2fs_inode_bitmap bitmap);
31.177 +
31.178 +extern int ext2fs_fast_test_block_bitmap_range2(ext2fs_block_bitmap bitmap,
31.179 + blk64_t block,
31.180 + unsigned int num);
31.181 +extern void ext2fs_fast_mark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
31.182 + blk64_t block,
31.183 + unsigned int num);
31.184 +extern void ext2fs_fast_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
31.185 + blk64_t block,
31.186 + unsigned int num);
31.187 +#endif
31.188 +
31.189 +/* These routines moved to gen_bitmap64.c */
31.190 +extern void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap);
31.191 +extern errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
31.192 + ext2fs_generic_bitmap bm1,
31.193 + ext2fs_generic_bitmap bm2);
31.194 +extern void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap);
31.195 +extern int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap,
31.196 + blk64_t bitno);
31.197 +extern int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap,
31.198 + blk64_t bitno);
31.199 +extern int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap,
31.200 + blk64_t bitno);
31.201 +extern int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bitmap,
31.202 + blk64_t block, unsigned int num);
31.203 +extern __u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap);
31.204 +extern __u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap);
31.205 +extern int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bitmap,
31.206 + blk64_t block, unsigned int num);
31.207 +extern void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
31.208 + blk64_t block, unsigned int num);
31.209 +extern void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
31.210 + blk64_t block, unsigned int num);
31.211 +extern errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap,
31.212 + __u64 start, __u64 end,
31.213 + __u64 *out);
31.214 +extern errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap,
31.215 + __u64 start, __u64 end,
31.216 + __u64 *out);
31.217 +
31.218 +/*
31.219 + * The inline routines themselves...
31.220 + *
31.221 + * If NO_INLINE_FUNCS is defined, then we won't try to do inline
31.222 + * functions at all; they will be included as normal functions in
31.223 + * inline.c
31.224 + */
31.225 +#ifdef NO_INLINE_FUNCS
31.226 +#if (defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || \
31.227 + defined(__i586__)))
31.228 + /* This prevents bitops.c from trying to include the C */
31.229 + /* function version of these functions */
31.230 +#define _EXT2_HAVE_ASM_BITOPS_
31.231 +#endif
31.232 +#endif /* NO_INLINE_FUNCS */
31.233 +
31.234 +#if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
31.235 +#ifdef INCLUDE_INLINE_FUNCS
31.236 +#if (__STDC_VERSION__ >= 199901L)
31.237 +#define _INLINE_ extern inline
31.238 +#else
31.239 +#define _INLINE_ inline
31.240 +#endif
31.241 +#else /* !INCLUDE_INLINE FUNCS */
31.242 +#if (__STDC_VERSION__ >= 199901L)
31.243 +#define _INLINE_ inline
31.244 +#else /* not C99 */
31.245 +#ifdef __GNUC__
31.246 +#define _INLINE_ extern __inline__
31.247 +#else /* For Watcom C */
31.248 +#define _INLINE_ extern inline
31.249 +#endif /* __GNUC__ */
31.250 +#endif /* __STDC_VERSION__ >= 199901L */
31.251 +#endif /* INCLUDE_INLINE_FUNCS */
31.252 +
31.253 +/*
31.254 + * Fast bit set/clear functions that doesn't need to return the
31.255 + * previous bit value.
31.256 + */
31.257 +
31.258 +_INLINE_ void ext2fs_fast_set_bit(unsigned int nr,void * addr)
31.259 +{
31.260 + unsigned char *ADDR = (unsigned char *) addr;
31.261 +
31.262 + ADDR += nr >> 3;
31.263 + *ADDR |= (unsigned char) (1 << (nr & 0x07));
31.264 +}
31.265 +
31.266 +_INLINE_ void ext2fs_fast_clear_bit(unsigned int nr, void * addr)
31.267 +{
31.268 + unsigned char *ADDR = (unsigned char *) addr;
31.269 +
31.270 + ADDR += nr >> 3;
31.271 + *ADDR &= (unsigned char) ~(1 << (nr & 0x07));
31.272 +}
31.273 +
31.274 +
31.275 +_INLINE_ void ext2fs_fast_set_bit64(__u64 nr, void * addr)
31.276 +{
31.277 + unsigned char *ADDR = (unsigned char *) addr;
31.278 +
31.279 + ADDR += nr >> 3;
31.280 + *ADDR |= (unsigned char) (1 << (nr & 0x07));
31.281 +}
31.282 +
31.283 +_INLINE_ void ext2fs_fast_clear_bit64(__u64 nr, void * addr)
31.284 +{
31.285 + unsigned char *ADDR = (unsigned char *) addr;
31.286 +
31.287 + ADDR += nr >> 3;
31.288 + *ADDR &= (unsigned char) ~(1 << (nr & 0x07));
31.289 +}
31.290 +
31.291 +
31.292 +#if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
31.293 + (defined(__i386__) || defined(__i486__) || defined(__i586__)))
31.294 +
31.295 +#define _EXT2_HAVE_ASM_BITOPS_
31.296 +#define _EXT2_HAVE_ASM_SWAB_
31.297 +
31.298 +/*
31.299 + * These are done by inline assembly for speed reasons.....
31.300 + *
31.301 + * All bitoperations return 0 if the bit was cleared before the
31.302 + * operation and != 0 if it was not. Bit 0 is the LSB of addr; bit 32
31.303 + * is the LSB of (addr+1).
31.304 + */
31.305 +
31.306 +/*
31.307 + * Some hacks to defeat gcc over-optimizations..
31.308 + */
31.309 +struct __dummy_h { unsigned long a[100]; };
31.310 +#define EXT2FS_ADDR (*(struct __dummy_h *) addr)
31.311 +#define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr)
31.312 +
31.313 +_INLINE_ int ext2fs_set_bit(unsigned int nr, void * addr)
31.314 +{
31.315 + int oldbit;
31.316 +
31.317 + addr = (void *) (((unsigned char *) addr) + (nr >> 3));
31.318 + __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
31.319 + :"=r" (oldbit),"+m" (EXT2FS_ADDR)
31.320 + :"r" (nr & 7));
31.321 + return oldbit;
31.322 +}
31.323 +
31.324 +_INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr)
31.325 +{
31.326 + int oldbit;
31.327 +
31.328 + addr = (void *) (((unsigned char *) addr) + (nr >> 3));
31.329 + __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
31.330 + :"=r" (oldbit),"+m" (EXT2FS_ADDR)
31.331 + :"r" (nr & 7));
31.332 + return oldbit;
31.333 +}
31.334 +
31.335 +_INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr)
31.336 +{
31.337 + int oldbit;
31.338 +
31.339 + addr = (const void *) (((const unsigned char *) addr) + (nr >> 3));
31.340 + __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
31.341 + :"=r" (oldbit)
31.342 + :"m" (EXT2FS_CONST_ADDR),"r" (nr & 7));
31.343 + return oldbit;
31.344 +}
31.345 +
31.346 +_INLINE_ __u32 ext2fs_swab32(__u32 val)
31.347 +{
31.348 +#ifdef EXT2FS_REQUIRE_486
31.349 + __asm__("bswap %0" : "=r" (val) : "0" (val));
31.350 +#else
31.351 + __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
31.352 + "rorl $16,%0\n\t" /* swap words */
31.353 + "xchgb %b0,%h0" /* swap higher bytes */
31.354 + :"=q" (val)
31.355 + : "0" (val));
31.356 +#endif
31.357 + return val;
31.358 +}
31.359 +
31.360 +_INLINE_ __u16 ext2fs_swab16(__u16 val)
31.361 +{
31.362 + __asm__("xchgb %b0,%h0" /* swap bytes */ \
31.363 + : "=q" (val) \
31.364 + : "0" (val)); \
31.365 + return val;
31.366 +}
31.367 +
31.368 +#undef EXT2FS_ADDR
31.369 +
31.370 +#endif /* i386 */
31.371 +
31.372 +
31.373 +#if !defined(_EXT2_HAVE_ASM_SWAB_)
31.374 +
31.375 +_INLINE_ __u16 ext2fs_swab16(__u16 val)
31.376 +{
31.377 + return (val >> 8) | (__u16) (val << 8);
31.378 +}
31.379 +
31.380 +_INLINE_ __u32 ext2fs_swab32(__u32 val)
31.381 +{
31.382 + return ((val>>24) | ((val>>8)&0xFF00) |
31.383 + ((val<<8)&0xFF0000) | (val<<24));
31.384 +}
31.385 +
31.386 +#endif /* !_EXT2_HAVE_ASM_SWAB */
31.387 +
31.388 +_INLINE_ __u64 ext2fs_swab64(__u64 val)
31.389 +{
31.390 + return (ext2fs_swab32((__u32) (val >> 32)) |
31.391 + (((__u64)ext2fs_swab32(val & 0xFFFFFFFFUL)) << 32));
31.392 +}
31.393 +
31.394 +_INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
31.395 + blk_t block)
31.396 +{
31.397 + return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
31.398 + block);
31.399 +}
31.400 +
31.401 +_INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
31.402 + blk_t block)
31.403 +{
31.404 + return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
31.405 + block);
31.406 +}
31.407 +
31.408 +_INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
31.409 + blk_t block)
31.410 +{
31.411 + return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
31.412 + block);
31.413 +}
31.414 +
31.415 +_INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
31.416 + ext2_ino_t inode)
31.417 +{
31.418 + return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
31.419 + inode);
31.420 +}
31.421 +
31.422 +_INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
31.423 + ext2_ino_t inode)
31.424 +{
31.425 + return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
31.426 + inode);
31.427 +}
31.428 +
31.429 +_INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
31.430 + ext2_ino_t inode)
31.431 +{
31.432 + return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
31.433 + inode);
31.434 +}
31.435 +
31.436 +_INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
31.437 + blk_t block)
31.438 +{
31.439 + ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
31.440 +}
31.441 +
31.442 +_INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
31.443 + blk_t block)
31.444 +{
31.445 + ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
31.446 +}
31.447 +
31.448 +_INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
31.449 + blk_t block)
31.450 +{
31.451 + return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
31.452 + block);
31.453 +}
31.454 +
31.455 +_INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
31.456 + ext2_ino_t inode)
31.457 +{
31.458 + ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
31.459 +}
31.460 +
31.461 +_INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
31.462 + ext2_ino_t inode)
31.463 +{
31.464 + ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
31.465 +}
31.466 +
31.467 +_INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
31.468 + ext2_ino_t inode)
31.469 +{
31.470 + return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
31.471 + inode);
31.472 +}
31.473 +
31.474 +_INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
31.475 +{
31.476 + return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
31.477 +}
31.478 +
31.479 +_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
31.480 +{
31.481 + return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
31.482 +}
31.483 +
31.484 +_INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
31.485 +{
31.486 + return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
31.487 +}
31.488 +
31.489 +_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
31.490 +{
31.491 + return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
31.492 +}
31.493 +
31.494 +_INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
31.495 + blk_t block, int num)
31.496 +{
31.497 + return ext2fs_test_block_bitmap_range(bitmap, block, num);
31.498 +}
31.499 +
31.500 +_INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
31.501 + blk_t block, int num)
31.502 +{
31.503 + ext2fs_mark_block_bitmap_range(bitmap, block, num);
31.504 +}
31.505 +
31.506 +_INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
31.507 + blk_t block, int num)
31.508 +{
31.509 + ext2fs_unmark_block_bitmap_range(bitmap, block, num);
31.510 +}
31.511 +
31.512 +/* 64-bit versions */
31.513 +
31.514 +_INLINE_ int ext2fs_mark_block_bitmap2(ext2fs_block_bitmap bitmap,
31.515 + blk64_t block)
31.516 +{
31.517 + return ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap,
31.518 + block);
31.519 +}
31.520 +
31.521 +_INLINE_ int ext2fs_unmark_block_bitmap2(ext2fs_block_bitmap bitmap,
31.522 + blk64_t block)
31.523 +{
31.524 + return ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap, block);
31.525 +}
31.526 +
31.527 +_INLINE_ int ext2fs_test_block_bitmap2(ext2fs_block_bitmap bitmap,
31.528 + blk64_t block)
31.529 +{
31.530 + return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap,
31.531 + block);
31.532 +}
31.533 +
31.534 +_INLINE_ int ext2fs_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.535 + ext2_ino_t inode)
31.536 +{
31.537 + return ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap,
31.538 + inode);
31.539 +}
31.540 +
31.541 +_INLINE_ int ext2fs_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.542 + ext2_ino_t inode)
31.543 +{
31.544 + return ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap,
31.545 + inode);
31.546 +}
31.547 +
31.548 +_INLINE_ int ext2fs_test_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.549 + ext2_ino_t inode)
31.550 +{
31.551 + return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap,
31.552 + inode);
31.553 +}
31.554 +
31.555 +_INLINE_ void ext2fs_fast_mark_block_bitmap2(ext2fs_block_bitmap bitmap,
31.556 + blk64_t block)
31.557 +{
31.558 + ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap, block);
31.559 +}
31.560 +
31.561 +_INLINE_ void ext2fs_fast_unmark_block_bitmap2(ext2fs_block_bitmap bitmap,
31.562 + blk64_t block)
31.563 +{
31.564 + ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap, block);
31.565 +}
31.566 +
31.567 +_INLINE_ int ext2fs_fast_test_block_bitmap2(ext2fs_block_bitmap bitmap,
31.568 + blk64_t block)
31.569 +{
31.570 + return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap,
31.571 + block);
31.572 +}
31.573 +
31.574 +_INLINE_ void ext2fs_fast_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.575 + ext2_ino_t inode)
31.576 +{
31.577 + ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap, inode);
31.578 +}
31.579 +
31.580 +_INLINE_ void ext2fs_fast_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.581 + ext2_ino_t inode)
31.582 +{
31.583 + ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap, inode);
31.584 +}
31.585 +
31.586 +_INLINE_ int ext2fs_fast_test_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.587 + ext2_ino_t inode)
31.588 +{
31.589 + return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap,
31.590 + inode);
31.591 +}
31.592 +
31.593 +_INLINE_ errcode_t ext2fs_find_first_zero_block_bitmap2(ext2fs_block_bitmap bitmap,
31.594 + blk64_t start,
31.595 + blk64_t end,
31.596 + blk64_t *out)
31.597 +{
31.598 + __u64 o;
31.599 + errcode_t rv;
31.600 +
31.601 + rv = ext2fs_find_first_zero_generic_bmap((ext2fs_generic_bitmap) bitmap,
31.602 + start, end, &o);
31.603 + if (!rv)
31.604 + *out = o;
31.605 + return rv;
31.606 +}
31.607 +
31.608 +_INLINE_ errcode_t ext2fs_find_first_zero_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.609 + ext2_ino_t start,
31.610 + ext2_ino_t end,
31.611 + ext2_ino_t *out)
31.612 +{
31.613 + __u64 o;
31.614 + errcode_t rv;
31.615 +
31.616 + rv = ext2fs_find_first_zero_generic_bmap((ext2fs_generic_bitmap) bitmap,
31.617 + start, end, &o);
31.618 + if (!rv)
31.619 + *out = (ext2_ino_t) o;
31.620 + return rv;
31.621 +}
31.622 +
31.623 +_INLINE_ errcode_t ext2fs_find_first_set_block_bitmap2(ext2fs_block_bitmap bitmap,
31.624 + blk64_t start,
31.625 + blk64_t end,
31.626 + blk64_t *out)
31.627 +{
31.628 + __u64 o;
31.629 + errcode_t rv;
31.630 +
31.631 + rv = ext2fs_find_first_set_generic_bmap((ext2fs_generic_bitmap) bitmap,
31.632 + start, end, &o);
31.633 + if (!rv)
31.634 + *out = o;
31.635 + return rv;
31.636 +}
31.637 +
31.638 +_INLINE_ errcode_t ext2fs_find_first_set_inode_bitmap2(ext2fs_inode_bitmap bitmap,
31.639 + ext2_ino_t start,
31.640 + ext2_ino_t end,
31.641 + ext2_ino_t *out)
31.642 +{
31.643 + __u64 o;
31.644 + errcode_t rv;
31.645 +
31.646 + rv = ext2fs_find_first_set_generic_bmap((ext2fs_generic_bitmap) bitmap,
31.647 + start, end, &o);
31.648 + if (!rv)
31.649 + *out = (ext2_ino_t) o;
31.650 + return rv;
31.651 +}
31.652 +
31.653 +_INLINE_ blk64_t ext2fs_get_block_bitmap_start2(ext2fs_block_bitmap bitmap)
31.654 +{
31.655 + return ext2fs_get_generic_bmap_start((ext2fs_generic_bitmap) bitmap);
31.656 +}
31.657 +
31.658 +_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start2(ext2fs_inode_bitmap bitmap)
31.659 +{
31.660 + return (ext2_ino_t) ext2fs_get_generic_bmap_start((ext2fs_generic_bitmap) bitmap);
31.661 +}
31.662 +
31.663 +_INLINE_ blk64_t ext2fs_get_block_bitmap_end2(ext2fs_block_bitmap bitmap)
31.664 +{
31.665 + return ext2fs_get_generic_bmap_end((ext2fs_generic_bitmap) bitmap);
31.666 +}
31.667 +
31.668 +_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end2(ext2fs_inode_bitmap bitmap)
31.669 +{
31.670 + return (ext2_ino_t) ext2fs_get_generic_bmap_end((ext2fs_generic_bitmap) bitmap);
31.671 +}
31.672 +
31.673 +_INLINE_ int ext2fs_fast_test_block_bitmap_range2(ext2fs_block_bitmap bitmap,
31.674 + blk64_t block,
31.675 + unsigned int num)
31.676 +{
31.677 + return ext2fs_test_block_bitmap_range2(bitmap, block, num);
31.678 +}
31.679 +
31.680 +_INLINE_ void ext2fs_fast_mark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
31.681 + blk64_t block,
31.682 + unsigned int num)
31.683 +{
31.684 + ext2fs_mark_block_bitmap_range2(bitmap, block, num);
31.685 +}
31.686 +
31.687 +_INLINE_ void ext2fs_fast_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
31.688 + blk64_t block,
31.689 + unsigned int num)
31.690 +{
31.691 + ext2fs_unmark_block_bitmap_range2(bitmap, block, num);
31.692 +}
31.693 +
31.694 +#undef _INLINE_
31.695 +#endif
31.696 +
31.697 +#ifndef _EXT2_HAVE_ASM_BITOPS_
31.698 +extern int ext2fs_set_bit(unsigned int nr,void * addr);
31.699 +extern int ext2fs_clear_bit(unsigned int nr, void * addr);
31.700 +extern int ext2fs_test_bit(unsigned int nr, const void * addr);
31.701 +#endif
31.702 +
31.703 +extern int ext2fs_set_bit64(__u64 nr,void * addr);
31.704 +extern int ext2fs_clear_bit64(__u64 nr, void * addr);
31.705 +extern int ext2fs_test_bit64(__u64 nr, const void * addr);
31.706 +extern unsigned int ext2fs_bitcount(const void *addr, unsigned int nbytes);
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/libext2fs/include/libext2fs/ext2fs/ext2_err.h Wed Aug 25 01:28:08 2021 +0200
32.3 @@ -0,0 +1,204 @@
32.4 +/*
32.5 + * ext2_err.h:
32.6 + * This file is automatically generated; please do not edit it.
32.7 + */
32.8 +
32.9 +#include <et/com_err.h>
32.10 +
32.11 +#define EXT2_ET_BASE (2133571328L)
32.12 +#define EXT2_ET_MAGIC_EXT2FS_FILSYS (2133571329L)
32.13 +#define EXT2_ET_MAGIC_BADBLOCKS_LIST (2133571330L)
32.14 +#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE (2133571331L)
32.15 +#define EXT2_ET_MAGIC_INODE_SCAN (2133571332L)
32.16 +#define EXT2_ET_MAGIC_IO_CHANNEL (2133571333L)
32.17 +#define EXT2_ET_MAGIC_UNIX_IO_CHANNEL (2133571334L)
32.18 +#define EXT2_ET_MAGIC_IO_MANAGER (2133571335L)
32.19 +#define EXT2_ET_MAGIC_BLOCK_BITMAP (2133571336L)
32.20 +#define EXT2_ET_MAGIC_INODE_BITMAP (2133571337L)
32.21 +#define EXT2_ET_MAGIC_GENERIC_BITMAP (2133571338L)
32.22 +#define EXT2_ET_MAGIC_TEST_IO_CHANNEL (2133571339L)
32.23 +#define EXT2_ET_MAGIC_DBLIST (2133571340L)
32.24 +#define EXT2_ET_MAGIC_ICOUNT (2133571341L)
32.25 +#define EXT2_ET_MAGIC_PQ_IO_CHANNEL (2133571342L)
32.26 +#define EXT2_ET_MAGIC_EXT2_FILE (2133571343L)
32.27 +#define EXT2_ET_MAGIC_E2IMAGE (2133571344L)
32.28 +#define EXT2_ET_MAGIC_INODE_IO_CHANNEL (2133571345L)
32.29 +#define EXT2_ET_MAGIC_EXTENT_HANDLE (2133571346L)
32.30 +#define EXT2_ET_BAD_MAGIC (2133571347L)
32.31 +#define EXT2_ET_REV_TOO_HIGH (2133571348L)
32.32 +#define EXT2_ET_RO_FILSYS (2133571349L)
32.33 +#define EXT2_ET_GDESC_READ (2133571350L)
32.34 +#define EXT2_ET_GDESC_WRITE (2133571351L)
32.35 +#define EXT2_ET_GDESC_BAD_BLOCK_MAP (2133571352L)
32.36 +#define EXT2_ET_GDESC_BAD_INODE_MAP (2133571353L)
32.37 +#define EXT2_ET_GDESC_BAD_INODE_TABLE (2133571354L)
32.38 +#define EXT2_ET_INODE_BITMAP_WRITE (2133571355L)
32.39 +#define EXT2_ET_INODE_BITMAP_READ (2133571356L)
32.40 +#define EXT2_ET_BLOCK_BITMAP_WRITE (2133571357L)
32.41 +#define EXT2_ET_BLOCK_BITMAP_READ (2133571358L)
32.42 +#define EXT2_ET_INODE_TABLE_WRITE (2133571359L)
32.43 +#define EXT2_ET_INODE_TABLE_READ (2133571360L)
32.44 +#define EXT2_ET_NEXT_INODE_READ (2133571361L)
32.45 +#define EXT2_ET_UNEXPECTED_BLOCK_SIZE (2133571362L)
32.46 +#define EXT2_ET_DIR_CORRUPTED (2133571363L)
32.47 +#define EXT2_ET_SHORT_READ (2133571364L)
32.48 +#define EXT2_ET_SHORT_WRITE (2133571365L)
32.49 +#define EXT2_ET_DIR_NO_SPACE (2133571366L)
32.50 +#define EXT2_ET_NO_INODE_BITMAP (2133571367L)
32.51 +#define EXT2_ET_NO_BLOCK_BITMAP (2133571368L)
32.52 +#define EXT2_ET_BAD_INODE_NUM (2133571369L)
32.53 +#define EXT2_ET_BAD_BLOCK_NUM (2133571370L)
32.54 +#define EXT2_ET_EXPAND_DIR_ERR (2133571371L)
32.55 +#define EXT2_ET_TOOSMALL (2133571372L)
32.56 +#define EXT2_ET_BAD_BLOCK_MARK (2133571373L)
32.57 +#define EXT2_ET_BAD_BLOCK_UNMARK (2133571374L)
32.58 +#define EXT2_ET_BAD_BLOCK_TEST (2133571375L)
32.59 +#define EXT2_ET_BAD_INODE_MARK (2133571376L)
32.60 +#define EXT2_ET_BAD_INODE_UNMARK (2133571377L)
32.61 +#define EXT2_ET_BAD_INODE_TEST (2133571378L)
32.62 +#define EXT2_ET_FUDGE_BLOCK_BITMAP_END (2133571379L)
32.63 +#define EXT2_ET_FUDGE_INODE_BITMAP_END (2133571380L)
32.64 +#define EXT2_ET_BAD_IND_BLOCK (2133571381L)
32.65 +#define EXT2_ET_BAD_DIND_BLOCK (2133571382L)
32.66 +#define EXT2_ET_BAD_TIND_BLOCK (2133571383L)
32.67 +#define EXT2_ET_NEQ_BLOCK_BITMAP (2133571384L)
32.68 +#define EXT2_ET_NEQ_INODE_BITMAP (2133571385L)
32.69 +#define EXT2_ET_BAD_DEVICE_NAME (2133571386L)
32.70 +#define EXT2_ET_MISSING_INODE_TABLE (2133571387L)
32.71 +#define EXT2_ET_CORRUPT_SUPERBLOCK (2133571388L)
32.72 +#define EXT2_ET_BAD_GENERIC_MARK (2133571389L)
32.73 +#define EXT2_ET_BAD_GENERIC_UNMARK (2133571390L)
32.74 +#define EXT2_ET_BAD_GENERIC_TEST (2133571391L)
32.75 +#define EXT2_ET_SYMLINK_LOOP (2133571392L)
32.76 +#define EXT2_ET_CALLBACK_NOTHANDLED (2133571393L)
32.77 +#define EXT2_ET_BAD_BLOCK_IN_INODE_TABLE (2133571394L)
32.78 +#define EXT2_ET_UNSUPP_FEATURE (2133571395L)
32.79 +#define EXT2_ET_RO_UNSUPP_FEATURE (2133571396L)
32.80 +#define EXT2_ET_LLSEEK_FAILED (2133571397L)
32.81 +#define EXT2_ET_NO_MEMORY (2133571398L)
32.82 +#define EXT2_ET_INVALID_ARGUMENT (2133571399L)
32.83 +#define EXT2_ET_BLOCK_ALLOC_FAIL (2133571400L)
32.84 +#define EXT2_ET_INODE_ALLOC_FAIL (2133571401L)
32.85 +#define EXT2_ET_NO_DIRECTORY (2133571402L)
32.86 +#define EXT2_ET_TOO_MANY_REFS (2133571403L)
32.87 +#define EXT2_ET_FILE_NOT_FOUND (2133571404L)
32.88 +#define EXT2_ET_FILE_RO (2133571405L)
32.89 +#define EXT2_ET_DB_NOT_FOUND (2133571406L)
32.90 +#define EXT2_ET_DIR_EXISTS (2133571407L)
32.91 +#define EXT2_ET_UNIMPLEMENTED (2133571408L)
32.92 +#define EXT2_ET_CANCEL_REQUESTED (2133571409L)
32.93 +#define EXT2_ET_FILE_TOO_BIG (2133571410L)
32.94 +#define EXT2_ET_JOURNAL_NOT_BLOCK (2133571411L)
32.95 +#define EXT2_ET_NO_JOURNAL_SB (2133571412L)
32.96 +#define EXT2_ET_JOURNAL_TOO_SMALL (2133571413L)
32.97 +#define EXT2_ET_JOURNAL_UNSUPP_VERSION (2133571414L)
32.98 +#define EXT2_ET_LOAD_EXT_JOURNAL (2133571415L)
32.99 +#define EXT2_ET_NO_JOURNAL (2133571416L)
32.100 +#define EXT2_ET_DIRHASH_UNSUPP (2133571417L)
32.101 +#define EXT2_ET_BAD_EA_BLOCK_NUM (2133571418L)
32.102 +#define EXT2_ET_TOO_MANY_INODES (2133571419L)
32.103 +#define EXT2_ET_NOT_IMAGE_FILE (2133571420L)
32.104 +#define EXT2_ET_RES_GDT_BLOCKS (2133571421L)
32.105 +#define EXT2_ET_RESIZE_INODE_CORRUPT (2133571422L)
32.106 +#define EXT2_ET_SET_BMAP_NO_IND (2133571423L)
32.107 +#define EXT2_ET_TDB_SUCCESS (2133571424L)
32.108 +#define EXT2_ET_TDB_ERR_CORRUPT (2133571425L)
32.109 +#define EXT2_ET_TDB_ERR_IO (2133571426L)
32.110 +#define EXT2_ET_TDB_ERR_LOCK (2133571427L)
32.111 +#define EXT2_ET_TDB_ERR_OOM (2133571428L)
32.112 +#define EXT2_ET_TDB_ERR_EXISTS (2133571429L)
32.113 +#define EXT2_ET_TDB_ERR_NOLOCK (2133571430L)
32.114 +#define EXT2_ET_TDB_ERR_EINVAL (2133571431L)
32.115 +#define EXT2_ET_TDB_ERR_NOEXIST (2133571432L)
32.116 +#define EXT2_ET_TDB_ERR_RDONLY (2133571433L)
32.117 +#define EXT2_ET_DBLIST_EMPTY (2133571434L)
32.118 +#define EXT2_ET_RO_BLOCK_ITERATE (2133571435L)
32.119 +#define EXT2_ET_MAGIC_EXTENT_PATH (2133571436L)
32.120 +#define EXT2_ET_MAGIC_GENERIC_BITMAP64 (2133571437L)
32.121 +#define EXT2_ET_MAGIC_BLOCK_BITMAP64 (2133571438L)
32.122 +#define EXT2_ET_MAGIC_INODE_BITMAP64 (2133571439L)
32.123 +#define EXT2_ET_MAGIC_RESERVED_13 (2133571440L)
32.124 +#define EXT2_ET_MAGIC_RESERVED_14 (2133571441L)
32.125 +#define EXT2_ET_MAGIC_RESERVED_15 (2133571442L)
32.126 +#define EXT2_ET_MAGIC_RESERVED_16 (2133571443L)
32.127 +#define EXT2_ET_MAGIC_RESERVED_17 (2133571444L)
32.128 +#define EXT2_ET_MAGIC_RESERVED_18 (2133571445L)
32.129 +#define EXT2_ET_MAGIC_RESERVED_19 (2133571446L)
32.130 +#define EXT2_ET_EXTENT_HEADER_BAD (2133571447L)
32.131 +#define EXT2_ET_EXTENT_INDEX_BAD (2133571448L)
32.132 +#define EXT2_ET_EXTENT_LEAF_BAD (2133571449L)
32.133 +#define EXT2_ET_EXTENT_NO_SPACE (2133571450L)
32.134 +#define EXT2_ET_INODE_NOT_EXTENT (2133571451L)
32.135 +#define EXT2_ET_EXTENT_NO_NEXT (2133571452L)
32.136 +#define EXT2_ET_EXTENT_NO_PREV (2133571453L)
32.137 +#define EXT2_ET_EXTENT_NO_UP (2133571454L)
32.138 +#define EXT2_ET_EXTENT_NO_DOWN (2133571455L)
32.139 +#define EXT2_ET_NO_CURRENT_NODE (2133571456L)
32.140 +#define EXT2_ET_OP_NOT_SUPPORTED (2133571457L)
32.141 +#define EXT2_ET_CANT_INSERT_EXTENT (2133571458L)
32.142 +#define EXT2_ET_CANT_SPLIT_EXTENT (2133571459L)
32.143 +#define EXT2_ET_EXTENT_NOT_FOUND (2133571460L)
32.144 +#define EXT2_ET_EXTENT_NOT_SUPPORTED (2133571461L)
32.145 +#define EXT2_ET_EXTENT_INVALID_LENGTH (2133571462L)
32.146 +#define EXT2_ET_IO_CHANNEL_NO_SUPPORT_64 (2133571463L)
32.147 +#define EXT2_ET_NO_MTAB_FILE (2133571464L)
32.148 +#define EXT2_ET_CANT_USE_LEGACY_BITMAPS (2133571465L)
32.149 +#define EXT2_ET_MMP_MAGIC_INVALID (2133571466L)
32.150 +#define EXT2_ET_MMP_FAILED (2133571467L)
32.151 +#define EXT2_ET_MMP_FSCK_ON (2133571468L)
32.152 +#define EXT2_ET_MMP_BAD_BLOCK (2133571469L)
32.153 +#define EXT2_ET_MMP_UNKNOWN_SEQ (2133571470L)
32.154 +#define EXT2_ET_MMP_CHANGE_ABORT (2133571471L)
32.155 +#define EXT2_ET_MMP_OPEN_DIRECT (2133571472L)
32.156 +#define EXT2_ET_BAD_DESC_SIZE (2133571473L)
32.157 +#define EXT2_ET_INODE_CSUM_INVALID (2133571474L)
32.158 +#define EXT2_ET_INODE_BITMAP_CSUM_INVALID (2133571475L)
32.159 +#define EXT2_ET_EXTENT_CSUM_INVALID (2133571476L)
32.160 +#define EXT2_ET_DIR_NO_SPACE_FOR_CSUM (2133571477L)
32.161 +#define EXT2_ET_DIR_CSUM_INVALID (2133571478L)
32.162 +#define EXT2_ET_EXT_ATTR_CSUM_INVALID (2133571479L)
32.163 +#define EXT2_ET_SB_CSUM_INVALID (2133571480L)
32.164 +#define EXT2_ET_UNKNOWN_CSUM (2133571481L)
32.165 +#define EXT2_ET_MMP_CSUM_INVALID (2133571482L)
32.166 +#define EXT2_ET_FILE_EXISTS (2133571483L)
32.167 +#define EXT2_ET_BLOCK_BITMAP_CSUM_INVALID (2133571484L)
32.168 +#define EXT2_ET_INLINE_DATA_CANT_ITERATE (2133571485L)
32.169 +#define EXT2_ET_EA_BAD_NAME_LEN (2133571486L)
32.170 +#define EXT2_ET_EA_BAD_VALUE_SIZE (2133571487L)
32.171 +#define EXT2_ET_BAD_EA_HASH (2133571488L)
32.172 +#define EXT2_ET_BAD_EA_HEADER (2133571489L)
32.173 +#define EXT2_ET_EA_KEY_NOT_FOUND (2133571490L)
32.174 +#define EXT2_ET_EA_NO_SPACE (2133571491L)
32.175 +#define EXT2_ET_MISSING_EA_FEATURE (2133571492L)
32.176 +#define EXT2_ET_NO_INLINE_DATA (2133571493L)
32.177 +#define EXT2_ET_INLINE_DATA_NO_BLOCK (2133571494L)
32.178 +#define EXT2_ET_INLINE_DATA_NO_SPACE (2133571495L)
32.179 +#define EXT2_ET_MAGIC_EA_HANDLE (2133571496L)
32.180 +#define EXT2_ET_INODE_IS_GARBAGE (2133571497L)
32.181 +#define EXT2_ET_EA_BAD_VALUE_OFFSET (2133571498L)
32.182 +#define EXT2_ET_JOURNAL_FLAGS_WRONG (2133571499L)
32.183 +#define EXT2_ET_UNDO_FILE_CORRUPT (2133571500L)
32.184 +#define EXT2_ET_UNDO_FILE_WRONG (2133571501L)
32.185 +#define EXT2_ET_FILESYSTEM_CORRUPTED (2133571502L)
32.186 +#define EXT2_ET_BAD_CRC (2133571503L)
32.187 +#define EXT2_ET_CORRUPT_JOURNAL_SB (2133571504L)
32.188 +#define EXT2_ET_INODE_CORRUPTED (2133571505L)
32.189 +#define EXT2_ET_EA_INODE_CORRUPTED (2133571506L)
32.190 +
32.191 +/* PAUL: Remove actual error functionality. */
32.192 +
32.193 +#if 0
32.194 +
32.195 +extern const struct error_table et_ext2_error_table;
32.196 +extern void initialize_ext2_error_table(void);
32.197 +
32.198 +/* For compatibility with Heimdal */
32.199 +extern void initialize_ext2_error_table_r(struct et_list **list);
32.200 +
32.201 +#define ERROR_TABLE_BASE_ext2 (2133571328L)
32.202 +
32.203 +/* for compatibility with older versions... */
32.204 +#define init_ext2_err_tbl initialize_ext2_error_table
32.205 +#define ext2_err_base ERROR_TABLE_BASE_ext2
32.206 +
32.207 +#endif
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/libext2fs/include/libext2fs/ext2fs/ext2_ext_attr.h Wed Aug 25 01:28:08 2021 +0200
33.3 @@ -0,0 +1,73 @@
33.4 +/*
33.5 + File: linux/ext2_ext_attr.h
33.6 +
33.7 + On-disk format of extended attributes for the ext2 filesystem.
33.8 +
33.9 + (C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.org>
33.10 +*/
33.11 +
33.12 +#ifndef _EXT2_EXT_ATTR_H
33.13 +#define _EXT2_EXT_ATTR_H
33.14 +/* Magic value in attribute blocks */
33.15 +#define EXT2_EXT_ATTR_MAGIC_v1 0xEA010000
33.16 +#define EXT2_EXT_ATTR_MAGIC 0xEA020000
33.17 +
33.18 +/* Maximum number of references to one attribute block */
33.19 +#define EXT2_EXT_ATTR_REFCOUNT_MAX 1024
33.20 +
33.21 +struct ext2_ext_attr_header {
33.22 + __u32 h_magic; /* magic number for identification */
33.23 + __u32 h_refcount; /* reference count */
33.24 + __u32 h_blocks; /* number of disk blocks used */
33.25 + __u32 h_hash; /* hash value of all attributes */
33.26 + __u32 h_checksum; /* crc32c(uuid+id+xattrs) */
33.27 + /* id = inum if refcount = 1, else blknum */
33.28 + __u32 h_reserved[3]; /* zero right now */
33.29 +};
33.30 +
33.31 +struct ext2_ext_attr_entry {
33.32 + __u8 e_name_len; /* length of name */
33.33 + __u8 e_name_index; /* attribute name index */
33.34 + __u16 e_value_offs; /* offset in disk block of value */
33.35 + __u32 e_value_inum; /* inode in which the value is stored */
33.36 + __u32 e_value_size; /* size of attribute value */
33.37 + __u32 e_hash; /* hash value of name and value */
33.38 +#if 0
33.39 + char e_name[0]; /* attribute name */
33.40 +#endif
33.41 +};
33.42 +
33.43 +#define EXT2_EXT_ATTR_PAD_BITS 2
33.44 +#define EXT2_EXT_ATTR_PAD ((unsigned) 1<<EXT2_EXT_ATTR_PAD_BITS)
33.45 +#define EXT2_EXT_ATTR_ROUND (EXT2_EXT_ATTR_PAD-1)
33.46 +#define EXT2_EXT_ATTR_LEN(name_len) \
33.47 + (((name_len) + EXT2_EXT_ATTR_ROUND + \
33.48 + sizeof(struct ext2_ext_attr_entry)) & ~EXT2_EXT_ATTR_ROUND)
33.49 +#define EXT2_EXT_ATTR_NEXT(entry) \
33.50 + ( (struct ext2_ext_attr_entry *)( \
33.51 + (char *)(entry) + EXT2_EXT_ATTR_LEN((entry)->e_name_len)) )
33.52 +#define EXT2_EXT_ATTR_SIZE(size) \
33.53 + (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
33.54 +#define EXT2_EXT_IS_LAST_ENTRY(entry) (*((__u32 *)(entry)) == 0UL)
33.55 +#define EXT2_EXT_ATTR_NAME(entry) \
33.56 + (((char *) (entry)) + sizeof(struct ext2_ext_attr_entry))
33.57 +#define EXT2_XATTR_LEN(name_len) \
33.58 + (((name_len) + EXT2_EXT_ATTR_ROUND + \
33.59 + sizeof(struct ext2_xattr_entry)) & ~EXT2_EXT_ATTR_ROUND)
33.60 +#define EXT2_XATTR_SIZE(size) \
33.61 + (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
33.62 +
33.63 +#ifdef __KERNEL__
33.64 +# ifdef CONFIG_EXT2_FS_EXT_ATTR
33.65 +extern int ext2_get_ext_attr(struct inode *, const char *, char *, size_t, int);
33.66 +extern int ext2_set_ext_attr(struct inode *, const char *, char *, size_t, int);
33.67 +extern void ext2_ext_attr_free_inode(struct inode *inode);
33.68 +extern void ext2_ext_attr_put_super(struct super_block *sb);
33.69 +extern int ext2_ext_attr_init(void);
33.70 +extern void ext2_ext_attr_done(void);
33.71 +# else
33.72 +# define ext2_get_ext_attr NULL
33.73 +# define ext2_set_ext_attr NULL
33.74 +# endif
33.75 +#endif /* __KERNEL__ */
33.76 +#endif /* _EXT2_EXT_ATTR_H */
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/libext2fs/include/libext2fs/ext2fs/ext2_fs.h Wed Aug 25 01:28:08 2021 +0200
34.3 @@ -0,0 +1,1119 @@
34.4 +/*
34.5 + * linux/include/linux/ext2_fs.h
34.6 + *
34.7 + * Copyright (C) 1992, 1993, 1994, 1995
34.8 + * Remy Card (card@masi.ibp.fr)
34.9 + * Laboratoire MASI - Institut Blaise Pascal
34.10 + * Universite Pierre et Marie Curie (Paris VI)
34.11 + *
34.12 + * from
34.13 + *
34.14 + * linux/include/linux/minix_fs.h
34.15 + *
34.16 + * Copyright (C) 1991, 1992 Linus Torvalds
34.17 + */
34.18 +
34.19 +#ifndef _LINUX_EXT2_FS_H
34.20 +#define _LINUX_EXT2_FS_H
34.21 +
34.22 +#include <ext2fs/ext2_types.h> /* Changed from linux/types.h */
34.23 +
34.24 +#ifndef __GNUC_PREREQ
34.25 +#if defined(__GNUC__) && defined(__GNUC_MINOR__)
34.26 +#define __GNUC_PREREQ(maj, min) \
34.27 + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
34.28 +#else
34.29 +#define __GNUC_PREREQ(maj, min) 0
34.30 +#endif
34.31 +#endif
34.32 +
34.33 +/*
34.34 + * The second extended filesystem constants/structures
34.35 + */
34.36 +
34.37 +/*
34.38 + * Define EXT2FS_DEBUG to produce debug messages
34.39 + */
34.40 +#undef EXT2FS_DEBUG
34.41 +
34.42 +/*
34.43 + * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
34.44 + */
34.45 +#define EXT2_PREALLOCATE
34.46 +#define EXT2_DEFAULT_PREALLOC_BLOCKS 8
34.47 +
34.48 +/*
34.49 + * The second extended file system version
34.50 + */
34.51 +#define EXT2FS_DATE "95/08/09"
34.52 +#define EXT2FS_VERSION "0.5b"
34.53 +
34.54 +/*
34.55 + * Special inode numbers
34.56 + */
34.57 +#define EXT2_BAD_INO 1 /* Bad blocks inode */
34.58 +#define EXT2_ROOT_INO 2 /* Root inode */
34.59 +#define EXT4_USR_QUOTA_INO 3 /* User quota inode */
34.60 +#define EXT4_GRP_QUOTA_INO 4 /* Group quota inode */
34.61 +#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
34.62 +#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
34.63 +#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */
34.64 +#define EXT2_JOURNAL_INO 8 /* Journal inode */
34.65 +#define EXT2_EXCLUDE_INO 9 /* The "exclude" inode, for snapshots */
34.66 +#define EXT4_REPLICA_INO 10 /* Used by non-upstream feature */
34.67 +
34.68 +/* First non-reserved inode for old ext2 filesystems */
34.69 +#define EXT2_GOOD_OLD_FIRST_INO 11
34.70 +
34.71 +/*
34.72 + * The second extended file system magic number
34.73 + */
34.74 +#define EXT2_SUPER_MAGIC 0xEF53
34.75 +
34.76 +#ifdef __KERNEL__
34.77 +#define EXT2_SB(sb) (&((sb)->u.ext2_sb))
34.78 +#else
34.79 +/* Assume that user mode programs are passing in an ext2fs superblock, not
34.80 + * a kernel struct super_block. This will allow us to call the feature-test
34.81 + * macros from user land. */
34.82 +#define EXT2_SB(sb) (sb)
34.83 +#endif
34.84 +
34.85 +/*
34.86 + * Maximal count of links to a file
34.87 + */
34.88 +#define EXT2_LINK_MAX 65000
34.89 +
34.90 +/*
34.91 + * Macro-instructions used to manage several block sizes
34.92 + */
34.93 +#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */
34.94 +#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */
34.95 +#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE)
34.96 +#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE)
34.97 +#ifdef __KERNEL__
34.98 +#define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
34.99 +#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
34.100 +#define EXT2_ADDR_PER_BLOCK_BITS(s) (EXT2_SB(s)->addr_per_block_bits)
34.101 +#define EXT2_INODE_SIZE(s) (EXT2_SB(s)->s_inode_size)
34.102 +#define EXT2_FIRST_INO(s) (EXT2_SB(s)->s_first_ino)
34.103 +#else
34.104 +#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
34.105 +#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
34.106 +#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
34.107 + EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size)
34.108 +#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
34.109 + EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino)
34.110 +#endif
34.111 +#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(__u32))
34.112 +
34.113 +/*
34.114 + * Macro-instructions used to manage allocation clusters
34.115 + */
34.116 +#define EXT2_MIN_CLUSTER_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE
34.117 +#define EXT2_MAX_CLUSTER_LOG_SIZE 29 /* 512MB */
34.118 +#define EXT2_MIN_CLUSTER_SIZE EXT2_MIN_BLOCK_SIZE
34.119 +#define EXT2_MAX_CLUSTER_SIZE (1 << EXT2_MAX_CLUSTER_LOG_SIZE)
34.120 +#define EXT2_CLUSTER_SIZE(s) (EXT2_MIN_BLOCK_SIZE << \
34.121 + (s)->s_log_cluster_size)
34.122 +#define EXT2_CLUSTER_SIZE_BITS(s) ((s)->s_log_cluster_size + 10)
34.123 +
34.124 +/*
34.125 + * Macro-instructions used to manage fragments
34.126 + *
34.127 + * Note: for backwards compatibility only, for the dump program.
34.128 + * Ext2/3/4 will never support fragments....
34.129 + */
34.130 +#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE
34.131 +#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE
34.132 +#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE
34.133 +#define EXT2_FRAG_SIZE(s) EXT2_BLOCK_SIZE(s)
34.134 +#define EXT2_FRAGS_PER_BLOCK(s) 1
34.135 +
34.136 +/*
34.137 + * ACL structures
34.138 + */
34.139 +struct ext2_acl_header /* Header of Access Control Lists */
34.140 +{
34.141 + __u32 aclh_size;
34.142 + __u32 aclh_file_count;
34.143 + __u32 aclh_acle_count;
34.144 + __u32 aclh_first_acle;
34.145 +};
34.146 +
34.147 +struct ext2_acl_entry /* Access Control List Entry */
34.148 +{
34.149 + __u32 acle_size;
34.150 + __u16 acle_perms; /* Access permissions */
34.151 + __u16 acle_type; /* Type of entry */
34.152 + __u16 acle_tag; /* User or group identity */
34.153 + __u16 acle_pad1;
34.154 + __u32 acle_next; /* Pointer on next entry for the */
34.155 + /* same inode or on next free entry */
34.156 +};
34.157 +
34.158 +/*
34.159 + * Structure of a blocks group descriptor
34.160 + */
34.161 +struct ext2_group_desc
34.162 +{
34.163 + __u32 bg_block_bitmap; /* Blocks bitmap block */
34.164 + __u32 bg_inode_bitmap; /* Inodes bitmap block */
34.165 + __u32 bg_inode_table; /* Inodes table block */
34.166 + __u16 bg_free_blocks_count; /* Free blocks count */
34.167 + __u16 bg_free_inodes_count; /* Free inodes count */
34.168 + __u16 bg_used_dirs_count; /* Directories count */
34.169 + __u16 bg_flags;
34.170 + __u32 bg_exclude_bitmap_lo; /* Exclude bitmap for snapshots */
34.171 + __u16 bg_block_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */
34.172 + __u16 bg_inode_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */
34.173 + __u16 bg_itable_unused; /* Unused inodes count */
34.174 + __u16 bg_checksum; /* crc16(s_uuid+group_num+group_desc)*/
34.175 +};
34.176 +
34.177 +/*
34.178 + * Structure of a blocks group descriptor
34.179 + */
34.180 +struct ext4_group_desc
34.181 +{
34.182 + __u32 bg_block_bitmap; /* Blocks bitmap block */
34.183 + __u32 bg_inode_bitmap; /* Inodes bitmap block */
34.184 + __u32 bg_inode_table; /* Inodes table block */
34.185 + __u16 bg_free_blocks_count; /* Free blocks count */
34.186 + __u16 bg_free_inodes_count; /* Free inodes count */
34.187 + __u16 bg_used_dirs_count; /* Directories count */
34.188 + __u16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
34.189 + __u32 bg_exclude_bitmap_lo; /* Exclude bitmap for snapshots */
34.190 + __u16 bg_block_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */
34.191 + __u16 bg_inode_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */
34.192 + __u16 bg_itable_unused; /* Unused inodes count */
34.193 + __u16 bg_checksum; /* crc16(sb_uuid+group+desc) */
34.194 + __u32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
34.195 + __u32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */
34.196 + __u32 bg_inode_table_hi; /* Inodes table block MSB */
34.197 + __u16 bg_free_blocks_count_hi;/* Free blocks count MSB */
34.198 + __u16 bg_free_inodes_count_hi;/* Free inodes count MSB */
34.199 + __u16 bg_used_dirs_count_hi; /* Directories count MSB */
34.200 + __u16 bg_itable_unused_hi; /* Unused inodes count MSB */
34.201 + __u32 bg_exclude_bitmap_hi; /* Exclude bitmap block MSB */
34.202 + __u16 bg_block_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+bitmap) MSB */
34.203 + __u16 bg_inode_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+bitmap) MSB */
34.204 + __u32 bg_reserved;
34.205 +};
34.206 +
34.207 +#define EXT4_BG_INODE_BITMAP_CSUM_HI_END \
34.208 + (offsetof(struct ext4_group_desc, bg_inode_bitmap_csum_hi) + \
34.209 + sizeof(__u16))
34.210 +#define EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION \
34.211 + (offsetof(struct ext4_group_desc, bg_block_bitmap_csum_hi) + \
34.212 + sizeof(__u16))
34.213 +
34.214 +#define EXT2_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not initialized */
34.215 +#define EXT2_BG_BLOCK_UNINIT 0x0002 /* Block bitmap not initialized */
34.216 +#define EXT2_BG_INODE_ZEROED 0x0004 /* On-disk itable initialized to zero */
34.217 +
34.218 +/*
34.219 + * Data structures used by the directory indexing feature
34.220 + *
34.221 + * Note: all of the multibyte integer fields are little endian.
34.222 + */
34.223 +
34.224 +/*
34.225 + * Note: dx_root_info is laid out so that if it should somehow get
34.226 + * overlaid by a dirent the two low bits of the hash version will be
34.227 + * zero. Therefore, the hash version mod 4 should never be 0.
34.228 + * Sincerely, the paranoia department.
34.229 + */
34.230 +struct ext2_dx_root_info {
34.231 + __u32 reserved_zero;
34.232 + __u8 hash_version; /* 0 now, 1 at release */
34.233 + __u8 info_length; /* 8 */
34.234 + __u8 indirect_levels;
34.235 + __u8 unused_flags;
34.236 +};
34.237 +
34.238 +#define EXT2_HASH_LEGACY 0
34.239 +#define EXT2_HASH_HALF_MD4 1
34.240 +#define EXT2_HASH_TEA 2
34.241 +#define EXT2_HASH_LEGACY_UNSIGNED 3 /* reserved for userspace lib */
34.242 +#define EXT2_HASH_HALF_MD4_UNSIGNED 4 /* reserved for userspace lib */
34.243 +#define EXT2_HASH_TEA_UNSIGNED 5 /* reserved for userspace lib */
34.244 +
34.245 +#define EXT2_HASH_FLAG_INCOMPAT 0x1
34.246 +
34.247 +#define EXT4_DX_BLOCK_MASK 0x0fffffff
34.248 +
34.249 +struct ext2_dx_entry {
34.250 + __le32 hash;
34.251 + __le32 block;
34.252 +};
34.253 +
34.254 +struct ext2_dx_countlimit {
34.255 + __le16 limit;
34.256 + __le16 count;
34.257 +};
34.258 +
34.259 +/*
34.260 + * This goes at the end of each htree block.
34.261 + */
34.262 +struct ext2_dx_tail {
34.263 + __le32 dt_reserved;
34.264 + __le32 dt_checksum; /* crc32c(uuid+inum+dxblock) */
34.265 +};
34.266 +
34.267 +/*
34.268 + * Macro-instructions used to manage group descriptors
34.269 + */
34.270 +#define EXT2_MIN_DESC_SIZE 32
34.271 +#define EXT2_MIN_DESC_SIZE_64BIT 64
34.272 +#define EXT2_MAX_DESC_SIZE EXT2_MIN_BLOCK_SIZE
34.273 +#define EXT2_DESC_SIZE(s) \
34.274 + ((EXT2_SB(s)->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) ? \
34.275 + (s)->s_desc_size : EXT2_MIN_DESC_SIZE)
34.276 +
34.277 +#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group)
34.278 +#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group)
34.279 +#define EXT2_CLUSTERS_PER_GROUP(s) (EXT2_SB(s)->s_clusters_per_group)
34.280 +#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
34.281 +/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */
34.282 +#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((((unsigned) 1 << 16) - 8) * \
34.283 + (EXT2_CLUSTER_SIZE(s) / \
34.284 + EXT2_BLOCK_SIZE(s)))
34.285 +#define EXT2_MAX_CLUSTERS_PER_GROUP(s) (((unsigned) 1 << 16) - 8)
34.286 +#define EXT2_MAX_INODES_PER_GROUP(s) (((unsigned) 1 << 16) - \
34.287 + EXT2_INODES_PER_BLOCK(s))
34.288 +#ifdef __KERNEL__
34.289 +#define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block)
34.290 +#define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_desc_per_block_bits)
34.291 +#else
34.292 +#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s))
34.293 +#endif
34.294 +
34.295 +#define EXT2_GROUPS_TO_BLOCKS(s, g) ((blk64_t) EXT2_BLOCKS_PER_GROUP(s) * \
34.296 + (g))
34.297 +#define EXT2_GROUPS_TO_CLUSTERS(s, g) ((blk64_t) EXT2_CLUSTERS_PER_GROUP(s) * \
34.298 + (g))
34.299 +
34.300 +/*
34.301 + * Constants relative to the data blocks
34.302 + */
34.303 +#define EXT2_NDIR_BLOCKS 12
34.304 +#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
34.305 +#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
34.306 +#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
34.307 +#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
34.308 +
34.309 +/*
34.310 + * Inode flags
34.311 + */
34.312 +#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
34.313 +#define EXT2_UNRM_FL 0x00000002 /* Undelete */
34.314 +#define EXT2_COMPR_FL 0x00000004 /* Compress file */
34.315 +#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
34.316 +#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
34.317 +#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
34.318 +#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
34.319 +#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
34.320 +/* Reserved for compression usage... */
34.321 +#define EXT2_DIRTY_FL 0x00000100
34.322 +#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
34.323 +#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */
34.324 + /* nb: was previously EXT2_ECOMPR_FL */
34.325 +#define EXT4_ENCRYPT_FL 0x00000800 /* encrypted inode */
34.326 +/* End compression flags --- maybe not all used */
34.327 +#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
34.328 +#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */
34.329 +#define EXT2_IMAGIC_FL 0x00002000
34.330 +#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
34.331 +#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */
34.332 +#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */
34.333 +#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
34.334 +#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
34.335 +#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
34.336 +#define EXT4_VERITY_FL 0x00100000 /* Verity protected inode */
34.337 +#define EXT4_EA_INODE_FL 0x00200000 /* Inode used for large EA */
34.338 +/* EXT4_EOFBLOCKS_FL 0x00400000 was here */
34.339 +#define FS_NOCOW_FL 0x00800000 /* Do not cow file */
34.340 +#define EXT4_SNAPFILE_FL 0x01000000 /* Inode is a snapshot */
34.341 +#define EXT4_SNAPFILE_DELETED_FL 0x04000000 /* Snapshot is being deleted */
34.342 +#define EXT4_SNAPFILE_SHRUNK_FL 0x08000000 /* Snapshot shrink has completed */
34.343 +#define EXT4_INLINE_DATA_FL 0x10000000 /* Inode has inline data */
34.344 +#define EXT4_PROJINHERIT_FL 0x20000000 /* Create with parents projid */
34.345 +#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
34.346 +
34.347 +#define EXT2_FL_USER_VISIBLE 0x204BDFFF /* User visible flags */
34.348 +#define EXT2_FL_USER_MODIFIABLE 0x204B80FF /* User modifiable flags */
34.349 +
34.350 +/*
34.351 + * ioctl commands
34.352 + */
34.353 +
34.354 +/* Used for online resize */
34.355 +struct ext2_new_group_input {
34.356 + __u32 group; /* Group number for this data */
34.357 + __u32 block_bitmap; /* Absolute block number of block bitmap */
34.358 + __u32 inode_bitmap; /* Absolute block number of inode bitmap */
34.359 + __u32 inode_table; /* Absolute block number of inode table start */
34.360 + __u32 blocks_count; /* Total number of blocks in this group */
34.361 + __u16 reserved_blocks; /* Number of reserved blocks in this group */
34.362 + __u16 unused; /* Number of reserved GDT blocks in group */
34.363 +};
34.364 +
34.365 +struct ext4_new_group_input {
34.366 + __u32 group; /* Group number for this data */
34.367 + __u64 block_bitmap; /* Absolute block number of block bitmap */
34.368 + __u64 inode_bitmap; /* Absolute block number of inode bitmap */
34.369 + __u64 inode_table; /* Absolute block number of inode table start */
34.370 + __u32 blocks_count; /* Total number of blocks in this group */
34.371 + __u16 reserved_blocks; /* Number of reserved blocks in this group */
34.372 + __u16 unused;
34.373 +};
34.374 +
34.375 +#ifdef __GNU__ /* Needed for the Hurd */
34.376 +#define _IOT_ext2_new_group_input _IOT (_IOTS(__u32), 5, _IOTS(__u16), 2, 0, 0)
34.377 +#endif
34.378 +
34.379 +#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
34.380 +#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
34.381 +#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
34.382 +#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
34.383 +#define EXT2_IOC_GETVERSION_NEW _IOR('f', 3, long)
34.384 +#define EXT2_IOC_SETVERSION_NEW _IOW('f', 4, long)
34.385 +#define EXT2_IOC_GROUP_EXTEND _IOW('f', 7, unsigned long)
34.386 +#define EXT2_IOC_GROUP_ADD _IOW('f', 8,struct ext2_new_group_input)
34.387 +#define EXT4_IOC_GROUP_ADD _IOW('f', 8,struct ext4_new_group_input)
34.388 +#define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64)
34.389 +
34.390 +/*
34.391 + * Structure of an inode on the disk
34.392 + */
34.393 +struct ext2_inode {
34.394 +/*00*/ __u16 i_mode; /* File mode */
34.395 + __u16 i_uid; /* Low 16 bits of Owner Uid */
34.396 + __u32 i_size; /* Size in bytes */
34.397 + __u32 i_atime; /* Access time */
34.398 + __u32 i_ctime; /* Inode change time */
34.399 +/*10*/ __u32 i_mtime; /* Modification time */
34.400 + __u32 i_dtime; /* Deletion Time */
34.401 + __u16 i_gid; /* Low 16 bits of Group Id */
34.402 + __u16 i_links_count; /* Links count */
34.403 + __u32 i_blocks; /* Blocks count */
34.404 +/*20*/ __u32 i_flags; /* File flags */
34.405 + union {
34.406 + struct {
34.407 + __u32 l_i_version; /* was l_i_reserved1 */
34.408 + } linux1;
34.409 + struct {
34.410 + __u32 h_i_translator;
34.411 + } hurd1;
34.412 + } osd1; /* OS dependent 1 */
34.413 +/*28*/ __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
34.414 +/*64*/ __u32 i_generation; /* File version (for NFS) */
34.415 + __u32 i_file_acl; /* File ACL */
34.416 + __u32 i_size_high;
34.417 +/*70*/ __u32 i_faddr; /* Fragment address */
34.418 + union {
34.419 + struct {
34.420 + __u16 l_i_blocks_hi;
34.421 + __u16 l_i_file_acl_high;
34.422 + __u16 l_i_uid_high; /* these 2 fields */
34.423 + __u16 l_i_gid_high; /* were reserved2[0] */
34.424 + __u16 l_i_checksum_lo; /* crc32c(uuid+inum+inode) */
34.425 + __u16 l_i_reserved;
34.426 + } linux2;
34.427 + struct {
34.428 + __u8 h_i_frag; /* Fragment number */
34.429 + __u8 h_i_fsize; /* Fragment size */
34.430 + __u16 h_i_mode_high;
34.431 + __u16 h_i_uid_high;
34.432 + __u16 h_i_gid_high;
34.433 + __u32 h_i_author;
34.434 + } hurd2;
34.435 + } osd2; /* OS dependent 2 */
34.436 +};
34.437 +
34.438 +/*
34.439 + * Permanent part of an large inode on the disk
34.440 + */
34.441 +struct ext2_inode_large {
34.442 +/*00*/ __u16 i_mode; /* File mode */
34.443 + __u16 i_uid; /* Low 16 bits of Owner Uid */
34.444 + __u32 i_size; /* Size in bytes */
34.445 + __u32 i_atime; /* Access time */
34.446 + __u32 i_ctime; /* Inode Change time */
34.447 +/*10*/ __u32 i_mtime; /* Modification time */
34.448 + __u32 i_dtime; /* Deletion Time */
34.449 + __u16 i_gid; /* Low 16 bits of Group Id */
34.450 + __u16 i_links_count; /* Links count */
34.451 + __u32 i_blocks; /* Blocks count */
34.452 +/*20*/ __u32 i_flags; /* File flags */
34.453 + union {
34.454 + struct {
34.455 + __u32 l_i_version; /* was l_i_reserved1 */
34.456 + } linux1;
34.457 + struct {
34.458 + __u32 h_i_translator;
34.459 + } hurd1;
34.460 + } osd1; /* OS dependent 1 */
34.461 +/*28*/ __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
34.462 +/*64*/ __u32 i_generation; /* File version (for NFS) */
34.463 + __u32 i_file_acl; /* File ACL */
34.464 + __u32 i_size_high;
34.465 +/*70*/ __u32 i_faddr; /* Fragment address */
34.466 + union {
34.467 + struct {
34.468 + __u16 l_i_blocks_hi;
34.469 + __u16 l_i_file_acl_high;
34.470 + __u16 l_i_uid_high; /* these 2 fields */
34.471 + __u16 l_i_gid_high; /* were reserved2[0] */
34.472 + __u16 l_i_checksum_lo; /* crc32c(uuid+inum+inode) */
34.473 + __u16 l_i_reserved;
34.474 + } linux2;
34.475 + struct {
34.476 + __u8 h_i_frag; /* Fragment number */
34.477 + __u8 h_i_fsize; /* Fragment size */
34.478 + __u16 h_i_mode_high;
34.479 + __u16 h_i_uid_high;
34.480 + __u16 h_i_gid_high;
34.481 + __u32 h_i_author;
34.482 + } hurd2;
34.483 + } osd2; /* OS dependent 2 */
34.484 +/*80*/ __u16 i_extra_isize;
34.485 + __u16 i_checksum_hi; /* crc32c(uuid+inum+inode) */
34.486 + __u32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
34.487 + __u32 i_mtime_extra; /* extra Modification time (nsec << 2 | epoch) */
34.488 + __u32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
34.489 +/*90*/ __u32 i_crtime; /* File creation time */
34.490 + __u32 i_crtime_extra; /* extra File creation time (nsec << 2 | epoch)*/
34.491 + __u32 i_version_hi; /* high 32 bits for 64-bit version */
34.492 +/*9c*/ __u32 i_projid; /* Project ID */
34.493 +};
34.494 +
34.495 +#define EXT4_INODE_CSUM_HI_EXTRA_END \
34.496 + (offsetof(struct ext2_inode_large, i_checksum_hi) + sizeof(__u16) - \
34.497 + EXT2_GOOD_OLD_INODE_SIZE)
34.498 +
34.499 +#define EXT4_EPOCH_BITS 2
34.500 +#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
34.501 +
34.502 +#define i_checksum_lo osd2.linux2.l_i_checksum_lo
34.503 +
34.504 +#define inode_includes(size, field) \
34.505 + (size >= (sizeof(((struct ext2_inode_large *)0)->field) + \
34.506 + offsetof(struct ext2_inode_large, field)))
34.507 +
34.508 +#if defined(__KERNEL__) || defined(__linux__)
34.509 +#define i_reserved1 osd1.linux1.l_i_reserved1
34.510 +#define i_frag osd2.linux2.l_i_frag
34.511 +#define i_fsize osd2.linux2.l_i_fsize
34.512 +#define i_uid_low i_uid
34.513 +#define i_gid_low i_gid
34.514 +#define i_uid_high osd2.linux2.l_i_uid_high
34.515 +#define i_gid_high osd2.linux2.l_i_gid_high
34.516 +#else
34.517 +#if defined(__GNU__)
34.518 +
34.519 +#define i_translator osd1.hurd1.h_i_translator
34.520 +#define i_frag osd2.hurd2.h_i_frag;
34.521 +#define i_fsize osd2.hurd2.h_i_fsize;
34.522 +#define i_uid_high osd2.hurd2.h_i_uid_high
34.523 +#define i_gid_high osd2.hurd2.h_i_gid_high
34.524 +#define i_author osd2.hurd2.h_i_author
34.525 +
34.526 +#endif /* __GNU__ */
34.527 +#endif /* defined(__KERNEL__) || defined(__linux__) */
34.528 +
34.529 +#define inode_uid(inode) ((inode).i_uid | (inode).osd2.linux2.l_i_uid_high << 16)
34.530 +#define inode_gid(inode) ((inode).i_gid | (inode).osd2.linux2.l_i_gid_high << 16)
34.531 +#define inode_projid(inode) ((inode).i_projid)
34.532 +#define ext2fs_set_i_uid_high(inode,x) ((inode).osd2.linux2.l_i_uid_high = (x))
34.533 +#define ext2fs_set_i_gid_high(inode,x) ((inode).osd2.linux2.l_i_gid_high = (x))
34.534 +
34.535 +static inline
34.536 +struct ext2_inode *EXT2_INODE(struct ext2_inode_large *large_inode)
34.537 +{
34.538 + return (struct ext2_inode *) large_inode;
34.539 +}
34.540 +
34.541 +/*
34.542 + * File system states
34.543 + */
34.544 +#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
34.545 +#define EXT2_ERROR_FS 0x0002 /* Errors detected */
34.546 +#define EXT3_ORPHAN_FS 0x0004 /* Orphans being recovered */
34.547 +
34.548 +/*
34.549 + * Misc. filesystem flags
34.550 + */
34.551 +#define EXT2_FLAGS_SIGNED_HASH 0x0001 /* Signed dirhash in use */
34.552 +#define EXT2_FLAGS_UNSIGNED_HASH 0x0002 /* Unsigned dirhash in use */
34.553 +#define EXT2_FLAGS_TEST_FILESYS 0x0004 /* OK for use on development code */
34.554 +#define EXT2_FLAGS_IS_SNAPSHOT 0x0010 /* This is a snapshot image */
34.555 +#define EXT2_FLAGS_FIX_SNAPSHOT 0x0020 /* Snapshot inodes corrupted */
34.556 +#define EXT2_FLAGS_FIX_EXCLUDE 0x0040 /* Exclude bitmaps corrupted */
34.557 +
34.558 +/*
34.559 + * Mount flags
34.560 + */
34.561 +#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
34.562 +#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
34.563 +#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
34.564 +#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
34.565 +#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
34.566 +#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
34.567 +#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
34.568 +#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
34.569 +
34.570 +#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
34.571 +#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
34.572 +#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \
34.573 + EXT2_MOUNT_##opt)
34.574 +/*
34.575 + * Maximal mount counts between two filesystem checks
34.576 + */
34.577 +#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
34.578 +#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
34.579 +
34.580 +/*
34.581 + * Behaviour when detecting errors
34.582 + */
34.583 +#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
34.584 +#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
34.585 +#define EXT2_ERRORS_PANIC 3 /* Panic */
34.586 +#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
34.587 +
34.588 +#if (__GNUC__ >= 4)
34.589 +#define ext4_offsetof(TYPE,MEMBER) __builtin_offsetof(TYPE,MEMBER)
34.590 +#else
34.591 +#define ext4_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
34.592 +#endif
34.593 +
34.594 +/* Metadata checksum algorithms */
34.595 +#define EXT2_CRC32C_CHKSUM 1
34.596 +
34.597 +/* Encryption algorithms, key size and key reference len */
34.598 +#define EXT4_ENCRYPTION_MODE_INVALID 0
34.599 +#define EXT4_ENCRYPTION_MODE_AES_256_XTS 1
34.600 +#define EXT4_ENCRYPTION_MODE_AES_256_GCM 2
34.601 +#define EXT4_ENCRYPTION_MODE_AES_256_CBC 3
34.602 +#define EXT4_ENCRYPTION_MODE_AES_256_CTS 4
34.603 +
34.604 +#define EXT4_AES_256_XTS_KEY_SIZE 64
34.605 +#define EXT4_AES_256_GCM_KEY_SIZE 32
34.606 +#define EXT4_AES_256_CBC_KEY_SIZE 32
34.607 +#define EXT4_AES_256_CTS_KEY_SIZE 32
34.608 +#define EXT4_MAX_KEY_SIZE 64
34.609 +
34.610 +#define EXT4_KEY_DESCRIPTOR_SIZE 8
34.611 +#define EXT4_CRYPTO_BLOCK_SIZE 16
34.612 +
34.613 +/* Password derivation constants */
34.614 +#define EXT4_MAX_PASSPHRASE_SIZE 1024
34.615 +#define EXT4_MAX_SALT_SIZE 256
34.616 +#define EXT4_PBKDF2_ITERATIONS 0xFFFF
34.617 +
34.618 +#define EXT2_LABEL_LEN 16
34.619 +
34.620 +/*
34.621 + * Policy provided via an ioctl on the topmost directory. This
34.622 + * structure is also in the kernel.
34.623 + */
34.624 +struct ext4_encryption_policy {
34.625 + char version;
34.626 + char contents_encryption_mode;
34.627 + char filenames_encryption_mode;
34.628 + char flags;
34.629 + char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE];
34.630 +} __attribute__((__packed__));
34.631 +
34.632 +struct ext4_encryption_key {
34.633 + __u32 mode;
34.634 + char raw[EXT4_MAX_KEY_SIZE];
34.635 + __u32 size;
34.636 +} __attribute__((__packed__));
34.637 +
34.638 +/*
34.639 + * Structure of the super block
34.640 + */
34.641 +struct ext2_super_block {
34.642 +/*000*/ __u32 s_inodes_count; /* Inodes count */
34.643 + __u32 s_blocks_count; /* Blocks count */
34.644 + __u32 s_r_blocks_count; /* Reserved blocks count */
34.645 + __u32 s_free_blocks_count; /* Free blocks count */
34.646 +/*010*/ __u32 s_free_inodes_count; /* Free inodes count */
34.647 + __u32 s_first_data_block; /* First Data Block */
34.648 + __u32 s_log_block_size; /* Block size */
34.649 + __u32 s_log_cluster_size; /* Allocation cluster size */
34.650 +/*020*/ __u32 s_blocks_per_group; /* # Blocks per group */
34.651 + __u32 s_clusters_per_group; /* # Fragments per group */
34.652 + __u32 s_inodes_per_group; /* # Inodes per group */
34.653 + __u32 s_mtime; /* Mount time */
34.654 +/*030*/ __u32 s_wtime; /* Write time */
34.655 + __u16 s_mnt_count; /* Mount count */
34.656 + __s16 s_max_mnt_count; /* Maximal mount count */
34.657 + __u16 s_magic; /* Magic signature */
34.658 + __u16 s_state; /* File system state */
34.659 + __u16 s_errors; /* Behaviour when detecting errors */
34.660 + __u16 s_minor_rev_level; /* minor revision level */
34.661 +/*040*/ __u32 s_lastcheck; /* time of last check */
34.662 + __u32 s_checkinterval; /* max. time between checks */
34.663 + __u32 s_creator_os; /* OS */
34.664 + __u32 s_rev_level; /* Revision level */
34.665 +/*050*/ __u16 s_def_resuid; /* Default uid for reserved blocks */
34.666 + __u16 s_def_resgid; /* Default gid for reserved blocks */
34.667 + /*
34.668 + * These fields are for EXT2_DYNAMIC_REV superblocks only.
34.669 + *
34.670 + * Note: the difference between the compatible feature set and
34.671 + * the incompatible feature set is that if there is a bit set
34.672 + * in the incompatible feature set that the kernel doesn't
34.673 + * know about, it should refuse to mount the filesystem.
34.674 + *
34.675 + * e2fsck's requirements are more strict; if it doesn't know
34.676 + * about a feature in either the compatible or incompatible
34.677 + * feature set, it must abort and not try to meddle with
34.678 + * things it doesn't understand...
34.679 + */
34.680 + __u32 s_first_ino; /* First non-reserved inode */
34.681 + __u16 s_inode_size; /* size of inode structure */
34.682 + __u16 s_block_group_nr; /* block group # of this superblock */
34.683 + __u32 s_feature_compat; /* compatible feature set */
34.684 +/*060*/ __u32 s_feature_incompat; /* incompatible feature set */
34.685 + __u32 s_feature_ro_compat; /* readonly-compatible feature set */
34.686 +/*068*/ __u8 s_uuid[16]; /* 128-bit uuid for volume */
34.687 +/*078*/ char s_volume_name[EXT2_LABEL_LEN]; /* volume name */
34.688 +/*088*/ char s_last_mounted[64]; /* directory where last mounted */
34.689 +/*0c8*/ __u32 s_algorithm_usage_bitmap; /* For compression */
34.690 + /*
34.691 + * Performance hints. Directory preallocation should only
34.692 + * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
34.693 + */
34.694 + __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
34.695 + __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
34.696 + __u16 s_reserved_gdt_blocks; /* Per group table for online growth */
34.697 + /*
34.698 + * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
34.699 + */
34.700 +/*0d0*/ __u8 s_journal_uuid[16]; /* uuid of journal superblock */
34.701 +/*0e0*/ __u32 s_journal_inum; /* inode number of journal file */
34.702 + __u32 s_journal_dev; /* device number of journal file */
34.703 + __u32 s_last_orphan; /* start of list of inodes to delete */
34.704 +/*0ec*/ __u32 s_hash_seed[4]; /* HTREE hash seed */
34.705 +/*0fc*/ __u8 s_def_hash_version; /* Default hash version to use */
34.706 + __u8 s_jnl_backup_type; /* Default type of journal backup */
34.707 + __u16 s_desc_size; /* Group desc. size: INCOMPAT_64BIT */
34.708 +/*100*/ __u32 s_default_mount_opts; /* default EXT2_MOUNT_* flags used */
34.709 + __u32 s_first_meta_bg; /* First metablock group */
34.710 + __u32 s_mkfs_time; /* When the filesystem was created */
34.711 +/*10c*/ __u32 s_jnl_blocks[17]; /* Backup of the journal inode */
34.712 +/*150*/ __u32 s_blocks_count_hi; /* Blocks count high 32bits */
34.713 + __u32 s_r_blocks_count_hi; /* Reserved blocks count high 32 bits*/
34.714 + __u32 s_free_blocks_hi; /* Free blocks count */
34.715 + __u16 s_min_extra_isize; /* All inodes have at least # bytes */
34.716 + __u16 s_want_extra_isize; /* New inodes should reserve # bytes */
34.717 +/*160*/ __u32 s_flags; /* Miscellaneous flags */
34.718 + __u16 s_raid_stride; /* RAID stride in blocks */
34.719 + __u16 s_mmp_update_interval; /* # seconds to wait in MMP checking */
34.720 + __u64 s_mmp_block; /* Block for multi-mount protection */
34.721 +/*170*/ __u32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/
34.722 + __u8 s_log_groups_per_flex; /* FLEX_BG group size */
34.723 + __u8 s_checksum_type; /* metadata checksum algorithm */
34.724 + __u8 s_encryption_level; /* versioning level for encryption */
34.725 + __u8 s_reserved_pad; /* Padding to next 32bits */
34.726 + __u64 s_kbytes_written; /* nr of lifetime kilobytes written */
34.727 +/*180*/ __u32 s_snapshot_inum; /* Inode number of active snapshot */
34.728 + __u32 s_snapshot_id; /* sequential ID of active snapshot */
34.729 + __u64 s_snapshot_r_blocks_count; /* active snapshot reserved blocks */
34.730 +/*190*/ __u32 s_snapshot_list; /* inode number of disk snapshot list */
34.731 +#define EXT4_S_ERR_START ext4_offsetof(struct ext2_super_block, s_error_count)
34.732 + __u32 s_error_count; /* number of fs errors */
34.733 + __u32 s_first_error_time; /* first time an error happened */
34.734 + __u32 s_first_error_ino; /* inode involved in first error */
34.735 +/*1a0*/ __u64 s_first_error_block; /* block involved in first error */
34.736 + __u8 s_first_error_func[32]; /* function where the error happened */
34.737 +/*1c8*/ __u32 s_first_error_line; /* line number where error happened */
34.738 + __u32 s_last_error_time; /* most recent time of an error */
34.739 +/*1d0*/ __u32 s_last_error_ino; /* inode involved in last error */
34.740 + __u32 s_last_error_line; /* line number where error happened */
34.741 + __u64 s_last_error_block; /* block involved of last error */
34.742 +/*1e0*/ __u8 s_last_error_func[32]; /* function where the error happened */
34.743 +#define EXT4_S_ERR_END ext4_offsetof(struct ext2_super_block, s_mount_opts)
34.744 +/*200*/ __u8 s_mount_opts[64];
34.745 +/*240*/ __u32 s_usr_quota_inum; /* inode number of user quota file */
34.746 + __u32 s_grp_quota_inum; /* inode number of group quota file */
34.747 + __u32 s_overhead_blocks; /* overhead blocks/clusters in fs */
34.748 +/*24c*/ __u32 s_backup_bgs[2]; /* If sparse_super2 enabled */
34.749 +/*254*/ __u8 s_encrypt_algos[4]; /* Encryption algorithms in use */
34.750 +/*258*/ __u8 s_encrypt_pw_salt[16]; /* Salt used for string2key algorithm */
34.751 +/*268*/ __le32 s_lpf_ino; /* Location of the lost+found inode */
34.752 + __le32 s_prj_quota_inum; /* inode for tracking project quota */
34.753 +/*270*/ __le32 s_checksum_seed; /* crc32c(orig_uuid) if csum_seed set */
34.754 + __le32 s_reserved[98]; /* Padding to the end of the block */
34.755 +/*3fc*/ __u32 s_checksum; /* crc32c(superblock) */
34.756 +};
34.757 +
34.758 +#define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START)
34.759 +
34.760 +/*
34.761 + * Codes for operating systems
34.762 + */
34.763 +#define EXT2_OS_LINUX 0
34.764 +#define EXT2_OS_HURD 1
34.765 +#define EXT2_OBSO_OS_MASIX 2
34.766 +#define EXT2_OS_FREEBSD 3
34.767 +#define EXT2_OS_LITES 4
34.768 +
34.769 +/*
34.770 + * Revision levels
34.771 + */
34.772 +#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
34.773 +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
34.774 +
34.775 +#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
34.776 +#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
34.777 +
34.778 +#define EXT2_GOOD_OLD_INODE_SIZE 128
34.779 +
34.780 +/*
34.781 + * Journal inode backup types
34.782 + */
34.783 +#define EXT3_JNL_BACKUP_BLOCKS 1
34.784 +
34.785 +/*
34.786 + * Feature set definitions
34.787 + */
34.788 +
34.789 +#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
34.790 + ( EXT2_SB(sb)->s_feature_compat & (mask) )
34.791 +#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
34.792 + ( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
34.793 +#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
34.794 + ( EXT2_SB(sb)->s_feature_incompat & (mask) )
34.795 +
34.796 +#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
34.797 +#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
34.798 +#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
34.799 +#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
34.800 +#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010
34.801 +#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
34.802 +#define EXT2_FEATURE_COMPAT_LAZY_BG 0x0040
34.803 +/* #define EXT2_FEATURE_COMPAT_EXCLUDE_INODE 0x0080 not used, legacy */
34.804 +#define EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP 0x0100
34.805 +#define EXT4_FEATURE_COMPAT_SPARSE_SUPER2 0x0200
34.806 +
34.807 +
34.808 +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
34.809 +#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
34.810 +/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */
34.811 +#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008
34.812 +#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
34.813 +#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
34.814 +#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
34.815 +#define EXT4_FEATURE_RO_COMPAT_HAS_SNAPSHOT 0x0080
34.816 +#define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100
34.817 +#define EXT4_FEATURE_RO_COMPAT_BIGALLOC 0x0200
34.818 +/*
34.819 + * METADATA_CSUM implies GDT_CSUM. When METADATA_CSUM is set, group
34.820 + * descriptor checksums use the same algorithm as all other data
34.821 + * structures' checksums.
34.822 + */
34.823 +#define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400
34.824 +#define EXT4_FEATURE_RO_COMPAT_REPLICA 0x0800
34.825 +#define EXT4_FEATURE_RO_COMPAT_READONLY 0x1000
34.826 +#define EXT4_FEATURE_RO_COMPAT_PROJECT 0x2000 /* Project quota */
34.827 +#define EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS 0x4000
34.828 +#define EXT4_FEATURE_RO_COMPAT_VERITY 0x8000
34.829 +
34.830 +#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
34.831 +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
34.832 +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
34.833 +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
34.834 +#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
34.835 +#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
34.836 +#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
34.837 +#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
34.838 +#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
34.839 +#define EXT4_FEATURE_INCOMPAT_EA_INODE 0x0400
34.840 +#define EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000
34.841 +#define EXT4_FEATURE_INCOMPAT_CSUM_SEED 0x2000
34.842 +#define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */
34.843 +#define EXT4_FEATURE_INCOMPAT_INLINE_DATA 0x8000 /* data in inode */
34.844 +#define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000
34.845 +
34.846 +#define EXT4_FEATURE_COMPAT_FUNCS(name, ver, flagname) \
34.847 +static inline int ext2fs_has_feature_##name(struct ext2_super_block *sb) \
34.848 +{ \
34.849 + return ((EXT2_SB(sb)->s_feature_compat & \
34.850 + EXT##ver##_FEATURE_COMPAT_##flagname) != 0); \
34.851 +} \
34.852 +static inline void ext2fs_set_feature_##name(struct ext2_super_block *sb) \
34.853 +{ \
34.854 + EXT2_SB(sb)->s_feature_compat |= \
34.855 + EXT##ver##_FEATURE_COMPAT_##flagname; \
34.856 +} \
34.857 +static inline void ext2fs_clear_feature_##name(struct ext2_super_block *sb) \
34.858 +{ \
34.859 + EXT2_SB(sb)->s_feature_compat &= \
34.860 + ~EXT##ver##_FEATURE_COMPAT_##flagname; \
34.861 +}
34.862 +
34.863 +#define EXT4_FEATURE_RO_COMPAT_FUNCS(name, ver, flagname) \
34.864 +static inline int ext2fs_has_feature_##name(struct ext2_super_block *sb) \
34.865 +{ \
34.866 + return ((EXT2_SB(sb)->s_feature_ro_compat & \
34.867 + EXT##ver##_FEATURE_RO_COMPAT_##flagname) != 0); \
34.868 +} \
34.869 +static inline void ext2fs_set_feature_##name(struct ext2_super_block *sb) \
34.870 +{ \
34.871 + EXT2_SB(sb)->s_feature_ro_compat |= \
34.872 + EXT##ver##_FEATURE_RO_COMPAT_##flagname; \
34.873 +} \
34.874 +static inline void ext2fs_clear_feature_##name(struct ext2_super_block *sb) \
34.875 +{ \
34.876 + EXT2_SB(sb)->s_feature_ro_compat &= \
34.877 + ~EXT##ver##_FEATURE_RO_COMPAT_##flagname; \
34.878 +}
34.879 +
34.880 +#define EXT4_FEATURE_INCOMPAT_FUNCS(name, ver, flagname) \
34.881 +static inline int ext2fs_has_feature_##name(struct ext2_super_block *sb) \
34.882 +{ \
34.883 + return ((EXT2_SB(sb)->s_feature_incompat & \
34.884 + EXT##ver##_FEATURE_INCOMPAT_##flagname) != 0); \
34.885 +} \
34.886 +static inline void ext2fs_set_feature_##name(struct ext2_super_block *sb) \
34.887 +{ \
34.888 + EXT2_SB(sb)->s_feature_incompat |= \
34.889 + EXT##ver##_FEATURE_INCOMPAT_##flagname; \
34.890 +} \
34.891 +static inline void ext2fs_clear_feature_##name(struct ext2_super_block *sb) \
34.892 +{ \
34.893 + EXT2_SB(sb)->s_feature_incompat &= \
34.894 + ~EXT##ver##_FEATURE_INCOMPAT_##flagname; \
34.895 +}
34.896 +
34.897 +EXT4_FEATURE_COMPAT_FUNCS(dir_prealloc, 2, DIR_PREALLOC)
34.898 +EXT4_FEATURE_COMPAT_FUNCS(imagic_inodes, 2, IMAGIC_INODES)
34.899 +EXT4_FEATURE_COMPAT_FUNCS(journal, 3, HAS_JOURNAL)
34.900 +EXT4_FEATURE_COMPAT_FUNCS(xattr, 2, EXT_ATTR)
34.901 +EXT4_FEATURE_COMPAT_FUNCS(resize_inode, 2, RESIZE_INODE)
34.902 +EXT4_FEATURE_COMPAT_FUNCS(dir_index, 2, DIR_INDEX)
34.903 +EXT4_FEATURE_COMPAT_FUNCS(lazy_bg, 2, LAZY_BG)
34.904 +EXT4_FEATURE_COMPAT_FUNCS(exclude_bitmap, 2, EXCLUDE_BITMAP)
34.905 +EXT4_FEATURE_COMPAT_FUNCS(sparse_super2, 4, SPARSE_SUPER2)
34.906 +
34.907 +EXT4_FEATURE_RO_COMPAT_FUNCS(sparse_super, 2, SPARSE_SUPER)
34.908 +EXT4_FEATURE_RO_COMPAT_FUNCS(large_file, 2, LARGE_FILE)
34.909 +EXT4_FEATURE_RO_COMPAT_FUNCS(huge_file, 4, HUGE_FILE)
34.910 +EXT4_FEATURE_RO_COMPAT_FUNCS(gdt_csum, 4, GDT_CSUM)
34.911 +EXT4_FEATURE_RO_COMPAT_FUNCS(dir_nlink, 4, DIR_NLINK)
34.912 +EXT4_FEATURE_RO_COMPAT_FUNCS(extra_isize, 4, EXTRA_ISIZE)
34.913 +EXT4_FEATURE_RO_COMPAT_FUNCS(has_snapshot, 4, HAS_SNAPSHOT)
34.914 +EXT4_FEATURE_RO_COMPAT_FUNCS(quota, 4, QUOTA)
34.915 +EXT4_FEATURE_RO_COMPAT_FUNCS(bigalloc, 4, BIGALLOC)
34.916 +EXT4_FEATURE_RO_COMPAT_FUNCS(metadata_csum, 4, METADATA_CSUM)
34.917 +EXT4_FEATURE_RO_COMPAT_FUNCS(replica, 4, REPLICA)
34.918 +EXT4_FEATURE_RO_COMPAT_FUNCS(readonly, 4, READONLY)
34.919 +EXT4_FEATURE_RO_COMPAT_FUNCS(project, 4, PROJECT)
34.920 +EXT4_FEATURE_RO_COMPAT_FUNCS(shared_blocks, 4, SHARED_BLOCKS)
34.921 +EXT4_FEATURE_RO_COMPAT_FUNCS(verity, 4, VERITY)
34.922 +
34.923 +EXT4_FEATURE_INCOMPAT_FUNCS(compression, 2, COMPRESSION)
34.924 +EXT4_FEATURE_INCOMPAT_FUNCS(filetype, 2, FILETYPE)
34.925 +EXT4_FEATURE_INCOMPAT_FUNCS(journal_needs_recovery, 3, RECOVER)
34.926 +EXT4_FEATURE_INCOMPAT_FUNCS(journal_dev, 3, JOURNAL_DEV)
34.927 +EXT4_FEATURE_INCOMPAT_FUNCS(meta_bg, 2, META_BG)
34.928 +EXT4_FEATURE_INCOMPAT_FUNCS(extents, 3, EXTENTS)
34.929 +EXT4_FEATURE_INCOMPAT_FUNCS(64bit, 4, 64BIT)
34.930 +EXT4_FEATURE_INCOMPAT_FUNCS(mmp, 4, MMP)
34.931 +EXT4_FEATURE_INCOMPAT_FUNCS(flex_bg, 4, FLEX_BG)
34.932 +EXT4_FEATURE_INCOMPAT_FUNCS(ea_inode, 4, EA_INODE)
34.933 +EXT4_FEATURE_INCOMPAT_FUNCS(dirdata, 4, DIRDATA)
34.934 +EXT4_FEATURE_INCOMPAT_FUNCS(csum_seed, 4, CSUM_SEED)
34.935 +EXT4_FEATURE_INCOMPAT_FUNCS(largedir, 4, LARGEDIR)
34.936 +EXT4_FEATURE_INCOMPAT_FUNCS(inline_data, 4, INLINE_DATA)
34.937 +EXT4_FEATURE_INCOMPAT_FUNCS(encrypt, 4, ENCRYPT)
34.938 +
34.939 +#define EXT2_FEATURE_COMPAT_SUPP 0
34.940 +#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
34.941 + EXT4_FEATURE_INCOMPAT_MMP| \
34.942 + EXT4_FEATURE_INCOMPAT_LARGEDIR| \
34.943 + EXT4_FEATURE_INCOMPAT_EA_INODE)
34.944 +#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
34.945 + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
34.946 + EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \
34.947 + EXT2_FEATURE_RO_COMPAT_BTREE_DIR| \
34.948 + EXT4_FEATURE_RO_COMPAT_VERITY)
34.949 +
34.950 +/*
34.951 + * Default values for user and/or group using reserved blocks
34.952 + */
34.953 +#define EXT2_DEF_RESUID 0
34.954 +#define EXT2_DEF_RESGID 0
34.955 +
34.956 +/*
34.957 + * Default mount options
34.958 + */
34.959 +#define EXT2_DEFM_DEBUG 0x0001
34.960 +#define EXT2_DEFM_BSDGROUPS 0x0002
34.961 +#define EXT2_DEFM_XATTR_USER 0x0004
34.962 +#define EXT2_DEFM_ACL 0x0008
34.963 +#define EXT2_DEFM_UID16 0x0010
34.964 +#define EXT3_DEFM_JMODE 0x0060
34.965 +#define EXT3_DEFM_JMODE_DATA 0x0020
34.966 +#define EXT3_DEFM_JMODE_ORDERED 0x0040
34.967 +#define EXT3_DEFM_JMODE_WBACK 0x0060
34.968 +#define EXT4_DEFM_NOBARRIER 0x0100
34.969 +#define EXT4_DEFM_BLOCK_VALIDITY 0x0200
34.970 +#define EXT4_DEFM_DISCARD 0x0400
34.971 +#define EXT4_DEFM_NODELALLOC 0x0800
34.972 +
34.973 +/*
34.974 + * Structure of a directory entry
34.975 + */
34.976 +#define EXT2_NAME_LEN 255
34.977 +
34.978 +struct ext2_dir_entry {
34.979 + __u32 inode; /* Inode number */
34.980 + __u16 rec_len; /* Directory entry length */
34.981 + __u16 name_len; /* Name length */
34.982 + char name[EXT2_NAME_LEN]; /* File name */
34.983 +};
34.984 +
34.985 +/*
34.986 + * The new version of the directory entry. Since EXT2 structures are
34.987 + * stored in intel byte order, and the name_len field could never be
34.988 + * bigger than 255 chars, it's safe to reclaim the extra byte for the
34.989 + * file_type field.
34.990 + *
34.991 + * This structure is deprecated due to endian issues. Please use struct
34.992 + * ext2_dir_entry and accessor functions
34.993 + * ext2fs_dirent_name_len
34.994 + * ext2fs_dirent_set_name_len
34.995 + * ext2fs_dirent_file_type
34.996 + * ext2fs_dirent_set_file_type
34.997 + * to get and set name_len and file_type fields.
34.998 + */
34.999 +struct ext2_dir_entry_2 {
34.1000 + __u32 inode; /* Inode number */
34.1001 + __u16 rec_len; /* Directory entry length */
34.1002 + __u8 name_len; /* Name length */
34.1003 + __u8 file_type;
34.1004 + char name[EXT2_NAME_LEN]; /* File name */
34.1005 +};
34.1006 +
34.1007 +/*
34.1008 + * This is a bogus directory entry at the end of each leaf block that
34.1009 + * records checksums.
34.1010 + */
34.1011 +struct ext2_dir_entry_tail {
34.1012 + __u32 det_reserved_zero1; /* Pretend to be unused */
34.1013 + __u16 det_rec_len; /* 12 */
34.1014 + __u16 det_reserved_name_len; /* 0xDE00, fake namelen/filetype */
34.1015 + __u32 det_checksum; /* crc32c(uuid+inode+dirent) */
34.1016 +};
34.1017 +
34.1018 +/*
34.1019 + * Ext2 directory file types. Only the low 3 bits are used. The
34.1020 + * other bits are reserved for now.
34.1021 + */
34.1022 +#define EXT2_FT_UNKNOWN 0
34.1023 +#define EXT2_FT_REG_FILE 1
34.1024 +#define EXT2_FT_DIR 2
34.1025 +#define EXT2_FT_CHRDEV 3
34.1026 +#define EXT2_FT_BLKDEV 4
34.1027 +#define EXT2_FT_FIFO 5
34.1028 +#define EXT2_FT_SOCK 6
34.1029 +#define EXT2_FT_SYMLINK 7
34.1030 +
34.1031 +#define EXT2_FT_MAX 8
34.1032 +
34.1033 +/*
34.1034 + * Annoyingly, e2fsprogs always swab16s ext2_dir_entry.name_len, so we
34.1035 + * have to build ext2_dir_entry_tail with that assumption too. This
34.1036 + * constant helps to build the dir_entry_tail to look like it has an
34.1037 + * "invalid" file type.
34.1038 + */
34.1039 +#define EXT2_DIR_NAME_LEN_CSUM 0xDE00
34.1040 +
34.1041 +/*
34.1042 + * EXT2_DIR_PAD defines the directory entries boundaries
34.1043 + *
34.1044 + * NOTE: It must be a multiple of 4
34.1045 + */
34.1046 +#define EXT2_DIR_ENTRY_HEADER_LEN 8
34.1047 +#define EXT2_DIR_PAD 4
34.1048 +#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
34.1049 +#define EXT2_DIR_REC_LEN(name_len) (((name_len) + \
34.1050 + EXT2_DIR_ENTRY_HEADER_LEN + \
34.1051 + EXT2_DIR_ROUND) & \
34.1052 + ~EXT2_DIR_ROUND)
34.1053 +
34.1054 +/*
34.1055 + * Constants for ext4's extended time encoding
34.1056 + */
34.1057 +#define EXT4_EPOCH_BITS 2
34.1058 +#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
34.1059 +#define EXT4_NSEC_MASK (~0UL << EXT4_EPOCH_BITS)
34.1060 +
34.1061 +/*
34.1062 + * This structure is used for multiple mount protection. It is written
34.1063 + * into the block number saved in the s_mmp_block field in the superblock.
34.1064 + * Programs that check MMP should assume that if SEQ_FSCK (or any unknown
34.1065 + * code above SEQ_MAX) is present then it is NOT safe to use the filesystem,
34.1066 + * regardless of how old the timestamp is.
34.1067 + *
34.1068 + * The timestamp in the MMP structure will be updated by e2fsck at some
34.1069 + * arbitrary intervals (start of passes, after every few groups of inodes
34.1070 + * in pass1 and pass1b). There is no guarantee that e2fsck is updating
34.1071 + * the MMP block in a timely manner, and the updates it does are purely
34.1072 + * for the convenience of the sysadmin and not for automatic validation.
34.1073 + *
34.1074 + * Note: Only the mmp_seq value is used to determine whether the MMP block
34.1075 + * is being updated. The mmp_time, mmp_nodename, and mmp_bdevname
34.1076 + * fields are only for informational purposes for the administrator,
34.1077 + * due to clock skew between nodes and hostname HA service takeover.
34.1078 + */
34.1079 +#define EXT4_MMP_MAGIC 0x004D4D50U /* ASCII for MMP */
34.1080 +#define EXT4_MMP_SEQ_CLEAN 0xFF4D4D50U /* mmp_seq value for clean unmount */
34.1081 +#define EXT4_MMP_SEQ_FSCK 0xE24D4D50U /* mmp_seq value when being fscked */
34.1082 +#define EXT4_MMP_SEQ_MAX 0xE24D4D4FU /* maximum valid mmp_seq value */
34.1083 +
34.1084 +/* Not endian-annotated; it's swapped at read/write time */
34.1085 +struct mmp_struct {
34.1086 + __u32 mmp_magic; /* Magic number for MMP */
34.1087 + __u32 mmp_seq; /* Sequence no. updated periodically */
34.1088 + __u64 mmp_time; /* Time last updated */
34.1089 + char mmp_nodename[64]; /* Node which last updated MMP block */
34.1090 + char mmp_bdevname[32]; /* Bdev which last updated MMP block */
34.1091 + __u16 mmp_check_interval; /* Changed mmp_check_interval */
34.1092 + __u16 mmp_pad1;
34.1093 + __u32 mmp_pad2[226];
34.1094 + __u32 mmp_checksum; /* crc32c(uuid+mmp_block) */
34.1095 +};
34.1096 +
34.1097 +/*
34.1098 + * Default interval for MMP update in seconds.
34.1099 + */
34.1100 +#define EXT4_MMP_UPDATE_INTERVAL 5
34.1101 +
34.1102 +/*
34.1103 + * Maximum interval for MMP update in seconds.
34.1104 + */
34.1105 +#define EXT4_MMP_MAX_UPDATE_INTERVAL 300
34.1106 +
34.1107 +/*
34.1108 + * Minimum interval for MMP checking in seconds.
34.1109 + */
34.1110 +#define EXT4_MMP_MIN_CHECK_INTERVAL 5
34.1111 +
34.1112 +/*
34.1113 + * Minimum size of inline data.
34.1114 + */
34.1115 +#define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__u32) * EXT2_N_BLOCKS))
34.1116 +
34.1117 +/*
34.1118 + * Size of a parent inode in inline data directory.
34.1119 + */
34.1120 +#define EXT4_INLINE_DATA_DOTDOT_SIZE (4)
34.1121 +
34.1122 +#endif /* _LINUX_EXT2_FS_H */
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/libext2fs/include/libext2fs/ext2fs/ext2_io.h Wed Aug 25 01:28:08 2021 +0200
35.3 @@ -0,0 +1,147 @@
35.4 +/*
35.5 + * io.h --- the I/O manager abstraction
35.6 + *
35.7 + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
35.8 + *
35.9 + * %Begin-Header%
35.10 + * This file may be redistributed under the terms of the GNU Library
35.11 + * General Public License, version 2.
35.12 + * %End-Header%
35.13 + */
35.14 +
35.15 +#ifndef _EXT2FS_EXT2_IO_H
35.16 +#define _EXT2FS_EXT2_IO_H
35.17 +
35.18 +#include <ext2fs/ext2_types.h>
35.19 +
35.20 +/*
35.21 + * ext2_loff_t is defined here since unix_io.c needs it.
35.22 + */
35.23 +#if defined(__GNUC__) || defined(HAS_LONG_LONG)
35.24 +typedef long long ext2_loff_t;
35.25 +#else
35.26 +typedef long ext2_loff_t;
35.27 +#endif
35.28 +
35.29 +/* llseek.c */
35.30 +ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int);
35.31 +
35.32 +typedef struct struct_io_manager *io_manager;
35.33 +typedef struct struct_io_channel *io_channel;
35.34 +typedef struct struct_io_stats *io_stats;
35.35 +
35.36 +#define CHANNEL_FLAGS_WRITETHROUGH 0x01
35.37 +#define CHANNEL_FLAGS_DISCARD_ZEROES 0x02
35.38 +#define CHANNEL_FLAGS_BLOCK_DEVICE 0x04
35.39 +
35.40 +#define io_channel_discard_zeroes_data(i) (i->flags & CHANNEL_FLAGS_DISCARD_ZEROES)
35.41 +
35.42 +struct struct_io_channel {
35.43 + errcode_t magic;
35.44 + io_manager manager;
35.45 + char *name;
35.46 + int block_size;
35.47 + errcode_t (*read_error)(io_channel channel,
35.48 + unsigned long block,
35.49 + int count,
35.50 + void *data,
35.51 + size_t size,
35.52 + int actual_bytes_read,
35.53 + errcode_t error);
35.54 + errcode_t (*write_error)(io_channel channel,
35.55 + unsigned long block,
35.56 + int count,
35.57 + const void *data,
35.58 + size_t size,
35.59 + int actual_bytes_written,
35.60 + errcode_t error);
35.61 + int refcount;
35.62 + int flags;
35.63 + long reserved[14];
35.64 + void *private_data;
35.65 + void *app_data;
35.66 + int align;
35.67 +};
35.68 +
35.69 +struct struct_io_stats {
35.70 + int num_fields;
35.71 + int reserved;
35.72 + unsigned long long bytes_read;
35.73 + unsigned long long bytes_written;
35.74 +};
35.75 +
35.76 +struct struct_io_manager {
35.77 + errcode_t magic;
35.78 + const char *name;
35.79 + errcode_t (*open)(const char *name, int flags, io_channel *channel);
35.80 + errcode_t (*close)(io_channel channel);
35.81 + errcode_t (*set_blksize)(io_channel channel, int blksize);
35.82 + errcode_t (*read_blk)(io_channel channel, unsigned long block,
35.83 + int count, void *data);
35.84 + errcode_t (*write_blk)(io_channel channel, unsigned long block,
35.85 + int count, const void *data);
35.86 + errcode_t (*flush)(io_channel channel);
35.87 + errcode_t (*write_byte)(io_channel channel, unsigned long offset,
35.88 + int count, const void *data);
35.89 + errcode_t (*set_option)(io_channel channel, const char *option,
35.90 + const char *arg);
35.91 + errcode_t (*get_stats)(io_channel channel, io_stats *io_stats);
35.92 + errcode_t (*read_blk64)(io_channel channel, unsigned long long block,
35.93 + int count, void *data);
35.94 + errcode_t (*write_blk64)(io_channel channel, unsigned long long block,
35.95 + int count, const void *data);
35.96 + errcode_t (*discard)(io_channel channel, unsigned long long block,
35.97 + unsigned long long count);
35.98 + errcode_t (*cache_readahead)(io_channel channel,
35.99 + unsigned long long block,
35.100 + unsigned long long count);
35.101 + errcode_t (*zeroout)(io_channel channel, unsigned long long block,
35.102 + unsigned long long count);
35.103 + long reserved[14];
35.104 +};
35.105 +
35.106 +#define IO_FLAG_RW 0x0001
35.107 +#define IO_FLAG_EXCLUSIVE 0x0002
35.108 +#define IO_FLAG_DIRECT_IO 0x0004
35.109 +#define IO_FLAG_FORCE_BOUNCE 0x0008
35.110 +
35.111 +/*
35.112 + * Convenience functions....
35.113 + */
35.114 +#define io_channel_close(c) ((c)->manager->close((c)))
35.115 +#define io_channel_set_blksize(c,s) ((c)->manager->set_blksize((c),s))
35.116 +#define io_channel_read_blk(c,b,n,d) ((c)->manager->read_blk((c),b,n,d))
35.117 +#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d))
35.118 +#define io_channel_flush(c) ((c)->manager->flush((c)))
35.119 +#define io_channel_bumpcount(c) ((c)->refcount++)
35.120 +
35.121 +/* io_manager.c */
35.122 +extern errcode_t io_channel_set_options(io_channel channel,
35.123 + const char *options);
35.124 +extern errcode_t io_channel_write_byte(io_channel channel,
35.125 + unsigned long offset,
35.126 + int count, const void *data);
35.127 +extern errcode_t io_channel_read_blk64(io_channel channel,
35.128 + unsigned long long block,
35.129 + int count, void *data);
35.130 +extern errcode_t io_channel_write_blk64(io_channel channel,
35.131 + unsigned long long block,
35.132 + int count, const void *data);
35.133 +extern errcode_t io_channel_discard(io_channel channel,
35.134 + unsigned long long block,
35.135 + unsigned long long count);
35.136 +extern errcode_t io_channel_zeroout(io_channel channel,
35.137 + unsigned long long block,
35.138 + unsigned long long count);
35.139 +extern errcode_t io_channel_alloc_buf(io_channel channel,
35.140 + int count, void *ptr);
35.141 +extern errcode_t io_channel_cache_readahead(io_channel io,
35.142 + unsigned long long block,
35.143 + unsigned long long count);
35.144 +
35.145 +/* unix_io.c */
35.146 +extern io_manager unix_io_manager;
35.147 +extern io_manager unixfd_io_manager;
35.148 +
35.149 +#endif /* _EXT2FS_EXT2_IO_H */
35.150 +
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/libext2fs/include/libext2fs/ext2fs/ext2_types.h Wed Aug 25 01:28:08 2021 +0200
36.3 @@ -0,0 +1,205 @@
36.4 +/*
36.5 + * If linux/types.h is already been included, assume it has defined
36.6 + * everything we need. (cross fingers) Other header files may have
36.7 + * also defined the types that we need.
36.8 + */
36.9 +#if (!defined(_LINUX_TYPES_H) && !defined(_BLKID_TYPES_H) && \
36.10 + !defined(_EXT2_TYPES_H))
36.11 +#define _EXT2_TYPES_H
36.12 +
36.13 +#define __S8_TYPEDEF __signed__ char
36.14 +#define __U8_TYPEDEF unsigned char
36.15 +#define __S16_TYPEDEF __signed__ short
36.16 +#define __U16_TYPEDEF unsigned short
36.17 +#define __S32_TYPEDEF __signed__ int
36.18 +#define __U32_TYPEDEF unsigned int
36.19 +#define __S64_TYPEDEF __signed__ long long
36.20 +#define __U64_TYPEDEF unsigned long long
36.21 +
36.22 +#ifndef HAVE___U8
36.23 +#define HAVE___U8
36.24 +#ifdef __U8_TYPEDEF
36.25 +typedef __U8_TYPEDEF __u8;
36.26 +#else
36.27 +typedef unsigned char __u8;
36.28 +#endif
36.29 +#endif /* HAVE___U8 */
36.30 +
36.31 +#ifndef HAVE___S8
36.32 +#define HAVE___S8
36.33 +#ifdef __S8_TYPEDEF
36.34 +typedef __S8_TYPEDEF __s8;
36.35 +#else
36.36 +typedef signed char __s8;
36.37 +#endif
36.38 +#endif /* HAVE___S8 */
36.39 +
36.40 +#ifndef HAVE___U16
36.41 +#define HAVE___U16
36.42 +#ifdef __U16_TYPEDEF
36.43 +typedef __U16_TYPEDEF __u16;
36.44 +#else
36.45 +#if (4 == 2)
36.46 +typedef unsigned int __u16;
36.47 +#else
36.48 +#if (2 == 2)
36.49 +typedef unsigned short __u16;
36.50 +#else
36.51 +#undef HAVE___U16
36.52 + ?==error: undefined 16 bit type
36.53 +#endif /* SIZEOF_SHORT == 2 */
36.54 +#endif /* SIZEOF_INT == 2 */
36.55 +#endif /* __U16_TYPEDEF */
36.56 +#endif /* HAVE___U16 */
36.57 +
36.58 +#ifndef HAVE___S16
36.59 +#define HAVE___S16
36.60 +#ifdef __S16_TYPEDEF
36.61 +typedef __S16_TYPEDEF __s16;
36.62 +#else
36.63 +#if (4 == 2)
36.64 +typedef int __s16;
36.65 +#else
36.66 +#if (2 == 2)
36.67 +typedef short __s16;
36.68 +#else
36.69 +#undef HAVE___S16
36.70 + ?==error: undefined 16 bit type
36.71 +#endif /* SIZEOF_SHORT == 2 */
36.72 +#endif /* SIZEOF_INT == 2 */
36.73 +#endif /* __S16_TYPEDEF */
36.74 +#endif /* HAVE___S16 */
36.75 +
36.76 +#ifndef HAVE___U32
36.77 +#define HAVE___U32
36.78 +#ifdef __U32_TYPEDEF
36.79 +typedef __U32_TYPEDEF __u32;
36.80 +#else
36.81 +#if (4 == 4)
36.82 +typedef unsigned int __u32;
36.83 +#else
36.84 +#if (4 == 4)
36.85 +typedef unsigned long __u32;
36.86 +#else
36.87 +#if (2 == 4)
36.88 +typedef unsigned short __u32;
36.89 +#else
36.90 +#undef HAVE___U32
36.91 + ?== error: undefined 32 bit type
36.92 +#endif /* SIZEOF_SHORT == 4 */
36.93 +#endif /* SIZEOF_LONG == 4 */
36.94 +#endif /* SIZEOF_INT == 4 */
36.95 +#endif /* __U32_TYPEDEF */
36.96 +#endif /* HAVE___U32 */
36.97 +
36.98 +#ifndef HAVE___S32
36.99 +#define HAVE___S32
36.100 +#ifdef __S32_TYPEDEF
36.101 +typedef __S32_TYPEDEF __s32;
36.102 +#else
36.103 +#if (4 == 4)
36.104 +typedef int __s32;
36.105 +#else
36.106 +#if (4 == 4)
36.107 +typedef long __s32;
36.108 +#else
36.109 +#if (2 == 4)
36.110 +typedef short __s32;
36.111 +#else
36.112 +#undef HAVE___S32
36.113 + ?== error: undefined 32 bit type
36.114 +#endif /* SIZEOF_SHORT == 4 */
36.115 +#endif /* SIZEOF_LONG == 4 */
36.116 +#endif /* SIZEOF_INT == 4 */
36.117 +#endif /* __S32_TYPEDEF */
36.118 +#endif /* HAVE___S32 */
36.119 +
36.120 +#ifndef HAVE___U64
36.121 +#define HAVE___U64
36.122 +#ifdef __U64_TYPEDEF
36.123 +typedef __U64_TYPEDEF __u64;
36.124 +#else
36.125 +#if (4 == 8)
36.126 +typedef unsigned int __u64;
36.127 +#else
36.128 +#if (8 == 8)
36.129 +typedef unsigned long long __u64;
36.130 +#else
36.131 +#if (4 == 8)
36.132 +typedef unsigned long __u64;
36.133 +#else
36.134 +#undef HAVE___U64
36.135 + ?== error: undefined 64 bit type
36.136 +#endif /* SIZEOF_LONG_LONG == 8 */
36.137 +#endif /* SIZEOF_LONG == 8 */
36.138 +#endif /* SIZEOF_INT == 8 */
36.139 +#endif /* __U64_TYPEDEF */
36.140 +#endif /* HAVE___U64 */
36.141 +
36.142 +#ifndef HAVE___S64
36.143 +#define HAVE___S64
36.144 +#ifdef __S64_TYPEDEF
36.145 +typedef __S64_TYPEDEF __s64;
36.146 +#else
36.147 +#if (4 == 8)
36.148 +typedef int __s64;
36.149 +#else
36.150 +#if (8 == 8)
36.151 +#if defined(__GNUC__)
36.152 +typedef __signed__ long long __s64;
36.153 +#else
36.154 +typedef signed long long __s64;
36.155 +#endif /* __GNUC__ */
36.156 +#else
36.157 +#if (4 == 8)
36.158 +typedef long __s64;
36.159 +#else
36.160 +#undef HAVE___S64
36.161 + ?== error: undefined 64 bit type
36.162 +#endif /* SIZEOF_LONG_LONG == 8 */
36.163 +#endif /* SIZEOF_LONG == 8 */
36.164 +#endif /* SIZEOF_INT == 8 */
36.165 +#endif /* __S64_TYPEDEF */
36.166 +#endif /* HAVE___S64 */
36.167 +
36.168 +#undef __S8_TYPEDEF
36.169 +#undef __U8_TYPEDEF
36.170 +#undef __S16_TYPEDEF
36.171 +#undef __U16_TYPEDEF
36.172 +#undef __S32_TYPEDEF
36.173 +#undef __U32_TYPEDEF
36.174 +#undef __S64_TYPEDEF
36.175 +#undef __U64_TYPEDEF
36.176 +
36.177 +#endif /* _*_TYPES_H */
36.178 +
36.179 +#include <stdint.h>
36.180 +
36.181 +/* endian checking stuff */
36.182 +#ifndef EXT2_ENDIAN_H_
36.183 +#define EXT2_ENDIAN_H_
36.184 +
36.185 +#ifdef __CHECKER__
36.186 +# ifndef __bitwise
36.187 +# define __bitwise __attribute__((bitwise))
36.188 +# endif
36.189 +#define __force __attribute__((force))
36.190 +#else
36.191 +# ifndef __bitwise
36.192 +# define __bitwise
36.193 +# endif
36.194 +#define __force
36.195 +#endif
36.196 +
36.197 +typedef __u16 __bitwise __le16;
36.198 +typedef __u32 __bitwise __le32;
36.199 +typedef __u64 __bitwise __le64;
36.200 +typedef __u16 __bitwise __be16;
36.201 +typedef __u32 __bitwise __be32;
36.202 +typedef __u64 __bitwise __be64;
36.203 +
36.204 +#endif /* EXT2_ENDIAN_H_ */
36.205 +
36.206 +/* These defines are needed for the public ext2fs.h header file */
36.207 +#define HAVE_SYS_TYPES_H 1
36.208 +#undef WORDS_BIGENDIAN
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/libext2fs/include/libext2fs/ext2fs/ext2fs.h Wed Aug 25 01:28:08 2021 +0200
37.3 @@ -0,0 +1,2048 @@
37.4 +/*
37.5 + * ext2fs.h --- ext2fs
37.6 + *
37.7 + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
37.8 + *
37.9 + * %Begin-Header%
37.10 + * This file may be redistributed under the terms of the GNU Library
37.11 + * General Public License, version 2.
37.12 + * %End-Header%
37.13 + */
37.14 +
37.15 +#ifndef _EXT2FS_EXT2FS_H
37.16 +#define _EXT2FS_EXT2FS_H
37.17 +
37.18 +#ifdef __GNUC__
37.19 +#define EXT2FS_ATTR(x) __attribute__(x)
37.20 +#else
37.21 +#define EXT2FS_ATTR(x)
37.22 +#endif
37.23 +
37.24 +#ifdef CONFIG_TDB
37.25 +#define EXT2FS_NO_TDB_UNUSED
37.26 +#else
37.27 +#define EXT2FS_NO_TDB_UNUSED EXT2FS_ATTR((unused))
37.28 +#endif
37.29 +
37.30 +#ifdef __cplusplus
37.31 +extern "C" {
37.32 +#endif
37.33 +
37.34 +/*
37.35 + * Non-GNU C compilers won't necessarily understand inline
37.36 + */
37.37 +#if (!defined(__GNUC__) && !defined(__WATCOMC__))
37.38 +#define NO_INLINE_FUNCS
37.39 +#endif
37.40 +
37.41 +/*
37.42 + * Where the master copy of the superblock is located, and how big
37.43 + * superblocks are supposed to be. We define SUPERBLOCK_SIZE because
37.44 + * the size of the superblock structure is not necessarily trustworthy
37.45 + * (some versions have the padding set up so that the superblock is
37.46 + * 1032 bytes long).
37.47 + */
37.48 +#define SUPERBLOCK_OFFSET 1024
37.49 +#define SUPERBLOCK_SIZE 1024
37.50 +
37.51 +#define UUID_STR_SIZE 37
37.52 +
37.53 +/*
37.54 + * The last ext2fs revision level that this version of the library is
37.55 + * able to support.
37.56 + */
37.57 +#define EXT2_LIB_CURRENT_REV EXT2_DYNAMIC_REV
37.58 +
37.59 +#ifdef HAVE_SYS_TYPES_H
37.60 +#include <sys/types.h>
37.61 +#endif
37.62 +
37.63 +#include <stdio.h>
37.64 +#include <stdlib.h>
37.65 +#include <string.h>
37.66 +#include <time.h>
37.67 +#include <errno.h>
37.68 +
37.69 +#if EXT2_FLAT_INCLUDES
37.70 +#include "e2_types.h"
37.71 +#include "ext2_fs.h"
37.72 +#include "ext3_extents.h"
37.73 +#else
37.74 +#include <ext2fs/ext2_types.h>
37.75 +#include <ext2fs/ext2_fs.h>
37.76 +#include <ext2fs/ext3_extents.h>
37.77 +#endif /* EXT2_FLAT_INCLUDES */
37.78 +
37.79 +typedef __u32 __bitwise ext2_ino_t;
37.80 +typedef __u32 __bitwise blk_t;
37.81 +typedef __u64 __bitwise blk64_t;
37.82 +typedef __u32 __bitwise dgrp_t;
37.83 +typedef __u32 __bitwise ext2_off_t;
37.84 +typedef __u64 __bitwise ext2_off64_t;
37.85 +typedef __s64 __bitwise e2_blkcnt_t;
37.86 +typedef __u32 __bitwise ext2_dirhash_t;
37.87 +
37.88 +#if EXT2_FLAT_INCLUDES
37.89 +#include "com_err.h"
37.90 +#include "ext2_io.h"
37.91 +#include "ext2_err.h"
37.92 +#include "ext2_ext_attr.h"
37.93 +#else
37.94 +#include <et/com_err.h>
37.95 +#include <ext2fs/ext2_io.h>
37.96 +#include <ext2fs/ext2_err.h>
37.97 +#include <ext2fs/ext2_ext_attr.h>
37.98 +#endif
37.99 +
37.100 +#include "hashmap.h"
37.101 +
37.102 +/*
37.103 + * Portability help for Microsoft Visual C++
37.104 + */
37.105 +#ifdef _MSC_VER
37.106 +#define EXT2_QSORT_TYPE int __cdecl
37.107 +#else
37.108 +#define EXT2_QSORT_TYPE int
37.109 +#endif
37.110 +
37.111 +typedef struct struct_ext2_filsys *ext2_filsys;
37.112 +
37.113 +#define EXT2FS_MARK_ERROR 0
37.114 +#define EXT2FS_UNMARK_ERROR 1
37.115 +#define EXT2FS_TEST_ERROR 2
37.116 +
37.117 +typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap;
37.118 +typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap;
37.119 +typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap;
37.120 +
37.121 +#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s)
37.122 +
37.123 +
37.124 +/*
37.125 + * Badblocks list definitions
37.126 + */
37.127 +
37.128 +typedef struct ext2_struct_u32_list *ext2_badblocks_list;
37.129 +typedef struct ext2_struct_u32_iterate *ext2_badblocks_iterate;
37.130 +
37.131 +typedef struct ext2_struct_u32_list *ext2_u32_list;
37.132 +typedef struct ext2_struct_u32_iterate *ext2_u32_iterate;
37.133 +
37.134 +/* old */
37.135 +typedef struct ext2_struct_u32_list *badblocks_list;
37.136 +typedef struct ext2_struct_u32_iterate *badblocks_iterate;
37.137 +
37.138 +#define BADBLOCKS_FLAG_DIRTY 1
37.139 +
37.140 +/*
37.141 + * ext2_dblist structure and abstractions (see dblist.c)
37.142 + */
37.143 +struct ext2_db_entry2 {
37.144 + ext2_ino_t ino;
37.145 + blk64_t blk;
37.146 + e2_blkcnt_t blockcnt;
37.147 +};
37.148 +
37.149 +/* Ye Olde 32-bit version */
37.150 +struct ext2_db_entry {
37.151 + ext2_ino_t ino;
37.152 + blk_t blk;
37.153 + int blockcnt;
37.154 +};
37.155 +
37.156 +typedef struct ext2_struct_dblist *ext2_dblist;
37.157 +
37.158 +#define DBLIST_ABORT 1
37.159 +
37.160 +/*
37.161 + * ext2_fileio definitions
37.162 + */
37.163 +
37.164 +#define EXT2_FILE_WRITE 0x0001
37.165 +#define EXT2_FILE_CREATE 0x0002
37.166 +
37.167 +#define EXT2_FILE_MASK 0x00FF
37.168 +
37.169 +#define EXT2_FILE_BUF_DIRTY 0x4000
37.170 +#define EXT2_FILE_BUF_VALID 0x2000
37.171 +
37.172 +typedef struct ext2_file *ext2_file_t;
37.173 +
37.174 +#define EXT2_SEEK_SET 0
37.175 +#define EXT2_SEEK_CUR 1
37.176 +#define EXT2_SEEK_END 2
37.177 +
37.178 +/*
37.179 + * Flags for the ext2_filsys structure and for ext2fs_open()
37.180 + */
37.181 +#define EXT2_FLAG_RW 0x01
37.182 +#define EXT2_FLAG_CHANGED 0x02
37.183 +#define EXT2_FLAG_DIRTY 0x04
37.184 +#define EXT2_FLAG_VALID 0x08
37.185 +#define EXT2_FLAG_IB_DIRTY 0x10
37.186 +#define EXT2_FLAG_BB_DIRTY 0x20
37.187 +#define EXT2_FLAG_SWAP_BYTES 0x40
37.188 +#define EXT2_FLAG_SWAP_BYTES_READ 0x80
37.189 +#define EXT2_FLAG_SWAP_BYTES_WRITE 0x100
37.190 +#define EXT2_FLAG_MASTER_SB_ONLY 0x200
37.191 +#define EXT2_FLAG_FORCE 0x400
37.192 +#define EXT2_FLAG_SUPER_ONLY 0x800
37.193 +#define EXT2_FLAG_JOURNAL_DEV_OK 0x1000
37.194 +#define EXT2_FLAG_IMAGE_FILE 0x2000
37.195 +#define EXT2_FLAG_EXCLUSIVE 0x4000
37.196 +#define EXT2_FLAG_SOFTSUPP_FEATURES 0x8000
37.197 +#define EXT2_FLAG_NOFREE_ON_ERROR 0x10000
37.198 +#define EXT2_FLAG_64BITS 0x20000
37.199 +#define EXT2_FLAG_PRINT_PROGRESS 0x40000
37.200 +#define EXT2_FLAG_DIRECT_IO 0x80000
37.201 +#define EXT2_FLAG_SKIP_MMP 0x100000
37.202 +#define EXT2_FLAG_IGNORE_CSUM_ERRORS 0x200000
37.203 +#define EXT2_FLAG_SHARE_DUP 0x400000
37.204 +#define EXT2_FLAG_IGNORE_SB_ERRORS 0x800000
37.205 +
37.206 +/*
37.207 + * Special flag in the ext2 inode i_flag field that means that this is
37.208 + * a new inode. (So that ext2_write_inode() can clear extra fields.)
37.209 + */
37.210 +#define EXT2_NEW_INODE_FL 0x80000000
37.211 +
37.212 +/*
37.213 + * Flags for mkjournal
37.214 + */
37.215 +#define EXT2_MKJOURNAL_V1_SUPER 0x0000001 /* create V1 superblock (deprecated) */
37.216 +#define EXT2_MKJOURNAL_LAZYINIT 0x0000002 /* don't zero journal inode before use*/
37.217 +#define EXT2_MKJOURNAL_NO_MNT_CHECK 0x0000004 /* don't check mount status */
37.218 +
37.219 +struct blk_alloc_ctx;
37.220 +struct opaque_ext2_group_desc;
37.221 +
37.222 +struct struct_ext2_filsys {
37.223 + errcode_t magic;
37.224 + io_channel io;
37.225 + int flags;
37.226 + char * device_name;
37.227 + struct ext2_super_block * super;
37.228 + unsigned int blocksize;
37.229 + int fragsize;
37.230 + dgrp_t group_desc_count;
37.231 + unsigned long desc_blocks;
37.232 + struct opaque_ext2_group_desc * group_desc;
37.233 + unsigned int inode_blocks_per_group;
37.234 + ext2fs_inode_bitmap inode_map;
37.235 + ext2fs_block_bitmap block_map;
37.236 + /* XXX FIXME-64: not 64-bit safe, but not used? */
37.237 + errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
37.238 + errcode_t (*check_directory)(ext2_filsys fs, ext2_ino_t ino);
37.239 + errcode_t (*write_bitmaps)(ext2_filsys fs);
37.240 + errcode_t (*read_inode)(ext2_filsys fs, ext2_ino_t ino,
37.241 + struct ext2_inode *inode);
37.242 + errcode_t (*write_inode)(ext2_filsys fs, ext2_ino_t ino,
37.243 + struct ext2_inode *inode);
37.244 + ext2_badblocks_list badblocks;
37.245 + ext2_dblist dblist;
37.246 + __u32 stride; /* for mke2fs */
37.247 + struct ext2_super_block * orig_super;
37.248 + struct ext2_image_hdr * image_header;
37.249 + __u32 umask;
37.250 + time_t now;
37.251 + int cluster_ratio_bits;
37.252 + __u16 default_bitmap_type;
37.253 + __u16 pad;
37.254 + /*
37.255 + * Reserved for future expansion
37.256 + */
37.257 + __u32 reserved[5];
37.258 +
37.259 + /*
37.260 + * Reserved for the use of the calling application.
37.261 + */
37.262 + void * priv_data;
37.263 +
37.264 + /*
37.265 + * Inode cache
37.266 + */
37.267 + struct ext2_inode_cache *icache;
37.268 + io_channel image_io;
37.269 +
37.270 + /*
37.271 + * More callback functions
37.272 + */
37.273 + errcode_t (*get_alloc_block)(ext2_filsys fs, blk64_t goal,
37.274 + blk64_t *ret);
37.275 + errcode_t (*get_alloc_block2)(ext2_filsys fs, blk64_t goal,
37.276 + blk64_t *ret, struct blk_alloc_ctx *ctx);
37.277 + void (*block_alloc_stats)(ext2_filsys fs, blk64_t blk, int inuse);
37.278 +
37.279 + /*
37.280 + * Buffers for Multiple mount protection(MMP) block.
37.281 + */
37.282 + void *mmp_buf;
37.283 + void *mmp_cmp;
37.284 + int mmp_fd;
37.285 +
37.286 + /*
37.287 + * Time at which e2fsck last updated the MMP block.
37.288 + */
37.289 + long mmp_last_written;
37.290 +
37.291 + /* progress operation functions */
37.292 + struct ext2fs_progress_ops *progress_ops;
37.293 +
37.294 + /* Precomputed FS UUID checksum for seeding other checksums */
37.295 + __u32 csum_seed;
37.296 +
37.297 + io_channel journal_io;
37.298 + char *journal_name;
37.299 +
37.300 + /* New block range allocation hooks */
37.301 + errcode_t (*new_range)(ext2_filsys fs, int flags, blk64_t goal,
37.302 + blk64_t len, blk64_t *pblk, blk64_t *plen);
37.303 + void (*block_alloc_stats_range)(ext2_filsys fs, blk64_t blk, blk_t num,
37.304 + int inuse);
37.305 +
37.306 + /* hashmap for SHA of data blocks */
37.307 + struct ext2fs_hashmap* block_sha_map;
37.308 +};
37.309 +
37.310 +#if EXT2_FLAT_INCLUDES
37.311 +#include "e2_bitops.h"
37.312 +#else
37.313 +#include <ext2fs/bitops.h>
37.314 +#endif
37.315 +
37.316 +/*
37.317 + * 64-bit bitmap backend types
37.318 + */
37.319 +#define EXT2FS_BMAP64_BITARRAY 1
37.320 +#define EXT2FS_BMAP64_RBTREE 2
37.321 +#define EXT2FS_BMAP64_AUTODIR 3
37.322 +
37.323 +/*
37.324 + * Return flags for the block iterator functions
37.325 + */
37.326 +#define BLOCK_CHANGED 1
37.327 +#define BLOCK_ABORT 2
37.328 +#define BLOCK_ERROR 4
37.329 +#define BLOCK_INLINE_DATA_CHANGED 8
37.330 +
37.331 +/*
37.332 + * Block interate flags
37.333 + *
37.334 + * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the interator
37.335 + * function should be called on blocks where the block number is zero.
37.336 + * This is used by ext2fs_expand_dir() to be able to add a new block
37.337 + * to an inode. It can also be used for programs that want to be able
37.338 + * to deal with files that contain "holes".
37.339 + *
37.340 + * BLOCK_FLAG_DEPTH_TRAVERSE indicates that the iterator function for
37.341 + * the indirect, doubly indirect, etc. blocks should be called after
37.342 + * all of the blocks contained in the indirect blocks are processed.
37.343 + * This is useful if you are going to be deallocating blocks from an
37.344 + * inode.
37.345 + *
37.346 + * BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be
37.347 + * called for data blocks only.
37.348 + *
37.349 + * BLOCK_FLAG_READ_ONLY is a promise by the caller that it will not
37.350 + * modify returned block number.
37.351 + *
37.352 + * BLOCK_FLAG_NO_LARGE is for internal use only. It informs
37.353 + * ext2fs_block_iterate2 that large files won't be accepted.
37.354 + */
37.355 +#define BLOCK_FLAG_APPEND 1
37.356 +#define BLOCK_FLAG_HOLE 1
37.357 +#define BLOCK_FLAG_DEPTH_TRAVERSE 2
37.358 +#define BLOCK_FLAG_DATA_ONLY 4
37.359 +#define BLOCK_FLAG_READ_ONLY 8
37.360 +
37.361 +#define BLOCK_FLAG_NO_LARGE 0x1000
37.362 +
37.363 +/*
37.364 + * Magic "block count" return values for the block iterator function.
37.365 + */
37.366 +#define BLOCK_COUNT_IND (-1)
37.367 +#define BLOCK_COUNT_DIND (-2)
37.368 +#define BLOCK_COUNT_TIND (-3)
37.369 +#define BLOCK_COUNT_TRANSLATOR (-4)
37.370 +
37.371 +#define BLOCK_ALLOC_UNKNOWN 0
37.372 +#define BLOCK_ALLOC_DATA 1
37.373 +#define BLOCK_ALLOC_METADATA 2
37.374 +
37.375 +struct blk_alloc_ctx {
37.376 + ext2_ino_t ino;
37.377 + struct ext2_inode *inode;
37.378 + blk64_t lblk;
37.379 + int flags;
37.380 +};
37.381 +
37.382 +/*
37.383 + * Flags for ext2fs_move_blocks
37.384 + */
37.385 +#if 0
37.386 +#define EXT2_BMOVE_GET_DBLIST 0x0001
37.387 +#define EXT2_BMOVE_DEBUG 0x0002
37.388 +#endif
37.389 +
37.390 +/*
37.391 + * Generic (non-filesystem layout specific) extents structure
37.392 + */
37.393 +
37.394 +#define EXT2_EXTENT_FLAGS_LEAF 0x0001
37.395 +#define EXT2_EXTENT_FLAGS_UNINIT 0x0002
37.396 +#define EXT2_EXTENT_FLAGS_SECOND_VISIT 0x0004
37.397 +
37.398 +struct ext2fs_extent {
37.399 + blk64_t e_pblk; /* first physical block */
37.400 + blk64_t e_lblk; /* first logical block extent covers */
37.401 + __u32 e_len; /* number of blocks covered by extent */
37.402 + __u32 e_flags; /* extent flags */
37.403 +};
37.404 +
37.405 +typedef struct ext2_extent_handle *ext2_extent_handle_t;
37.406 +typedef struct ext2_extent_path *ext2_extent_path_t;
37.407 +
37.408 +/*
37.409 + * Flags used by ext2fs_extent_get()
37.410 + */
37.411 +#define EXT2_EXTENT_CURRENT 0x0000
37.412 +#define EXT2_EXTENT_MOVE_MASK 0x000F
37.413 +#define EXT2_EXTENT_ROOT 0x0001
37.414 +#define EXT2_EXTENT_LAST_LEAF 0x0002
37.415 +#define EXT2_EXTENT_FIRST_SIB 0x0003
37.416 +#define EXT2_EXTENT_LAST_SIB 0x0004
37.417 +#define EXT2_EXTENT_NEXT_SIB 0x0005
37.418 +#define EXT2_EXTENT_PREV_SIB 0x0006
37.419 +#define EXT2_EXTENT_NEXT_LEAF 0x0007
37.420 +#define EXT2_EXTENT_PREV_LEAF 0x0008
37.421 +#define EXT2_EXTENT_NEXT 0x0009
37.422 +#define EXT2_EXTENT_PREV 0x000A
37.423 +#define EXT2_EXTENT_UP 0x000B
37.424 +#define EXT2_EXTENT_DOWN 0x000C
37.425 +#define EXT2_EXTENT_DOWN_AND_LAST 0x000D
37.426 +
37.427 +/*
37.428 + * Flags used by ext2fs_extent_insert()
37.429 + */
37.430 +#define EXT2_EXTENT_INSERT_AFTER 0x0001 /* insert after handle loc'n */
37.431 +#define EXT2_EXTENT_INSERT_NOSPLIT 0x0002 /* insert may not cause split */
37.432 +
37.433 +/*
37.434 + * Flags used by ext2fs_extent_delete()
37.435 + */
37.436 +#define EXT2_EXTENT_DELETE_KEEP_EMPTY 0x001 /* keep node if last extent gone */
37.437 +
37.438 +/*
37.439 + * Flags used by ext2fs_extent_set_bmap()
37.440 + */
37.441 +#define EXT2_EXTENT_SET_BMAP_UNINIT 0x0001
37.442 +
37.443 +/*
37.444 + * Data structure returned by ext2fs_extent_get_info()
37.445 + */
37.446 +struct ext2_extent_info {
37.447 + int curr_entry;
37.448 + int curr_level;
37.449 + int num_entries;
37.450 + int max_entries;
37.451 + int max_depth;
37.452 + int bytes_avail;
37.453 + blk64_t max_lblk;
37.454 + blk64_t max_pblk;
37.455 + __u32 max_len;
37.456 + __u32 max_uninit_len;
37.457 +};
37.458 +
37.459 +/*
37.460 + * Flags for directory block reading and writing functions
37.461 + */
37.462 +#define EXT2_DIRBLOCK_V2_STRUCT 0x0001
37.463 +
37.464 +/*
37.465 + * Return flags for the directory iterator functions
37.466 + */
37.467 +#define DIRENT_CHANGED 1
37.468 +#define DIRENT_ABORT 2
37.469 +#define DIRENT_ERROR 3
37.470 +
37.471 +/*
37.472 + * Directory iterator flags
37.473 + */
37.474 +
37.475 +#define DIRENT_FLAG_INCLUDE_EMPTY 1
37.476 +#define DIRENT_FLAG_INCLUDE_REMOVED 2
37.477 +#define DIRENT_FLAG_INCLUDE_CSUM 4
37.478 +#define DIRENT_FLAG_INCLUDE_INLINE_DATA 8
37.479 +
37.480 +#define DIRENT_DOT_FILE 1
37.481 +#define DIRENT_DOT_DOT_FILE 2
37.482 +#define DIRENT_OTHER_FILE 3
37.483 +#define DIRENT_DELETED_FILE 4
37.484 +#define DIRENT_CHECKSUM 5
37.485 +
37.486 +/*
37.487 + * Inode scan definitions
37.488 + */
37.489 +typedef struct ext2_struct_inode_scan *ext2_inode_scan;
37.490 +
37.491 +/*
37.492 + * ext2fs_scan flags
37.493 + */
37.494 +#define EXT2_SF_CHK_BADBLOCKS 0x0001
37.495 +#define EXT2_SF_BAD_INODE_BLK 0x0002
37.496 +#define EXT2_SF_BAD_EXTRA_BYTES 0x0004
37.497 +#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008
37.498 +#define EXT2_SF_DO_LAZY 0x0010
37.499 +#define EXT2_SF_WARN_GARBAGE_INODES 0x0020
37.500 +
37.501 +/*
37.502 + * ext2fs_check_if_mounted flags
37.503 + */
37.504 +#define EXT2_MF_MOUNTED 1
37.505 +#define EXT2_MF_ISROOT 2
37.506 +#define EXT2_MF_READONLY 4
37.507 +#define EXT2_MF_SWAP 8
37.508 +#define EXT2_MF_BUSY 16
37.509 +
37.510 +/*
37.511 + * Ext2/linux mode flags. We define them here so that we don't need
37.512 + * to depend on the OS's sys/stat.h, since we may be compiling on a
37.513 + * non-Linux system.
37.514 + */
37.515 +#define LINUX_S_IFMT 00170000
37.516 +#define LINUX_S_IFSOCK 0140000
37.517 +#define LINUX_S_IFLNK 0120000
37.518 +#define LINUX_S_IFREG 0100000
37.519 +#define LINUX_S_IFBLK 0060000
37.520 +#define LINUX_S_IFDIR 0040000
37.521 +#define LINUX_S_IFCHR 0020000
37.522 +#define LINUX_S_IFIFO 0010000
37.523 +#define LINUX_S_ISUID 0004000
37.524 +#define LINUX_S_ISGID 0002000
37.525 +#define LINUX_S_ISVTX 0001000
37.526 +
37.527 +#define LINUX_S_IRWXU 00700
37.528 +#define LINUX_S_IRUSR 00400
37.529 +#define LINUX_S_IWUSR 00200
37.530 +#define LINUX_S_IXUSR 00100
37.531 +
37.532 +#define LINUX_S_IRWXG 00070
37.533 +#define LINUX_S_IRGRP 00040
37.534 +#define LINUX_S_IWGRP 00020
37.535 +#define LINUX_S_IXGRP 00010
37.536 +
37.537 +#define LINUX_S_IRWXO 00007
37.538 +#define LINUX_S_IROTH 00004
37.539 +#define LINUX_S_IWOTH 00002
37.540 +#define LINUX_S_IXOTH 00001
37.541 +
37.542 +#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK)
37.543 +#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG)
37.544 +#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR)
37.545 +#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR)
37.546 +#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK)
37.547 +#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO)
37.548 +#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK)
37.549 +
37.550 +/*
37.551 + * ext2 size of an inode
37.552 + */
37.553 +#define EXT2_I_SIZE(i) ((i)->i_size | ((__u64) (i)->i_size_high << 32))
37.554 +
37.555 +/*
37.556 + * ext2_icount_t abstraction
37.557 + */
37.558 +#define EXT2_ICOUNT_OPT_INCREMENT 0x01
37.559 +#define EXT2_ICOUNT_OPT_FULLMAP 0x02
37.560 +
37.561 +typedef struct ext2_icount *ext2_icount_t;
37.562 +
37.563 +/*
37.564 + * Flags for ext2fs_bmap
37.565 + */
37.566 +#define BMAP_ALLOC 0x0001
37.567 +#define BMAP_SET 0x0002
37.568 +#define BMAP_UNINIT 0x0004
37.569 +#define BMAP_ZERO 0x0008
37.570 +
37.571 +/*
37.572 + * Returned flags from ext2fs_bmap
37.573 + */
37.574 +#define BMAP_RET_UNINIT 0x0001
37.575 +
37.576 +/*
37.577 + * Flags for imager.c functions
37.578 + */
37.579 +#define IMAGER_FLAG_INODEMAP 1
37.580 +#define IMAGER_FLAG_SPARSEWRITE 2
37.581 +
37.582 +/*
37.583 + * For checking structure magic numbers...
37.584 + */
37.585 +
37.586 +#define EXT2_CHECK_MAGIC(struct, code) \
37.587 + if ((struct)->magic != (code)) return (code)
37.588 +
37.589 +/*
37.590 + * Features supported by this version of the library
37.591 + */
37.592 +#define EXT2_LIB_FEATURE_COMPAT_SUPP (EXT2_FEATURE_COMPAT_DIR_PREALLOC|\
37.593 + EXT2_FEATURE_COMPAT_IMAGIC_INODES|\
37.594 + EXT3_FEATURE_COMPAT_HAS_JOURNAL|\
37.595 + EXT2_FEATURE_COMPAT_RESIZE_INODE|\
37.596 + EXT2_FEATURE_COMPAT_DIR_INDEX|\
37.597 + EXT2_FEATURE_COMPAT_EXT_ATTR|\
37.598 + EXT4_FEATURE_COMPAT_SPARSE_SUPER2)
37.599 +
37.600 +#ifdef CONFIG_MMP
37.601 +#define EXT4_LIB_INCOMPAT_MMP EXT4_FEATURE_INCOMPAT_MMP
37.602 +#else
37.603 +#define EXT4_LIB_INCOMPAT_MMP (0)
37.604 +#endif
37.605 +
37.606 +#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
37.607 + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
37.608 + EXT2_FEATURE_INCOMPAT_META_BG|\
37.609 + EXT3_FEATURE_INCOMPAT_RECOVER|\
37.610 + EXT3_FEATURE_INCOMPAT_EXTENTS|\
37.611 + EXT4_FEATURE_INCOMPAT_FLEX_BG|\
37.612 + EXT4_FEATURE_INCOMPAT_EA_INODE|\
37.613 + EXT4_LIB_INCOMPAT_MMP|\
37.614 + EXT4_FEATURE_INCOMPAT_64BIT|\
37.615 + EXT4_FEATURE_INCOMPAT_INLINE_DATA|\
37.616 + EXT4_FEATURE_INCOMPAT_ENCRYPT|\
37.617 + EXT4_FEATURE_INCOMPAT_CSUM_SEED|\
37.618 + EXT4_FEATURE_INCOMPAT_LARGEDIR)
37.619 +
37.620 +#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
37.621 + EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
37.622 + EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\
37.623 + EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\
37.624 + EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|\
37.625 + EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\
37.626 + EXT4_FEATURE_RO_COMPAT_BIGALLOC|\
37.627 + EXT4_FEATURE_RO_COMPAT_QUOTA|\
37.628 + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\
37.629 + EXT4_FEATURE_RO_COMPAT_READONLY |\
37.630 + EXT4_FEATURE_RO_COMPAT_PROJECT |\
37.631 + EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS |\
37.632 + EXT4_FEATURE_RO_COMPAT_VERITY)
37.633 +
37.634 +/*
37.635 + * These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed
37.636 + * to ext2fs_openfs()
37.637 + */
37.638 +#define EXT2_LIB_SOFTSUPP_INCOMPAT (0)
37.639 +#define EXT2_LIB_SOFTSUPP_RO_COMPAT (EXT4_FEATURE_RO_COMPAT_REPLICA)
37.640 +
37.641 +
37.642 +/* Translate a block number to a cluster number */
37.643 +#define EXT2FS_CLUSTER_RATIO(fs) (1 << (fs)->cluster_ratio_bits)
37.644 +#define EXT2FS_CLUSTER_MASK(fs) (EXT2FS_CLUSTER_RATIO(fs) - 1)
37.645 +#define EXT2FS_B2C(fs, blk) ((blk) >> (fs)->cluster_ratio_bits)
37.646 +/* Translate a cluster number to a block number */
37.647 +#define EXT2FS_C2B(fs, cluster) ((cluster) << (fs)->cluster_ratio_bits)
37.648 +/* Translate # of blks to # of clusters */
37.649 +#define EXT2FS_NUM_B2C(fs, blks) (((blks) + EXT2FS_CLUSTER_MASK(fs)) >> \
37.650 + (fs)->cluster_ratio_bits)
37.651 +
37.652 +#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
37.653 +typedef struct stat64 ext2fs_struct_stat;
37.654 +#else
37.655 +typedef struct stat ext2fs_struct_stat;
37.656 +#endif
37.657 +
37.658 +/*
37.659 + * For ext2fs_close2() and ext2fs_flush2(), this flag allows you to
37.660 + * avoid the fsync call.
37.661 + */
37.662 +#define EXT2_FLAG_FLUSH_NO_SYNC 1
37.663 +
37.664 +/*
37.665 + * Modify and iterate extended attributes
37.666 + */
37.667 +struct ext2_xattr_handle;
37.668 +#define XATTR_ABORT 1
37.669 +#define XATTR_CHANGED 2
37.670 +
37.671 +/*
37.672 + * function prototypes
37.673 + */
37.674 +static inline int ext2fs_has_group_desc_csum(ext2_filsys fs)
37.675 +{
37.676 + return ext2fs_has_feature_metadata_csum(fs->super) ||
37.677 + ext2fs_has_feature_gdt_csum(fs->super);
37.678 +}
37.679 +
37.680 +/* The LARGE_FILE feature should be set if we have stored files 2GB+ in size */
37.681 +static inline int ext2fs_needs_large_file_feature(unsigned long long file_size)
37.682 +{
37.683 + return file_size >= 0x80000000ULL;
37.684 +}
37.685 +
37.686 +/* alloc.c */
37.687 +extern void ext2fs_clear_block_uninit(ext2_filsys fs, dgrp_t group);
37.688 +extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode,
37.689 + ext2fs_inode_bitmap map, ext2_ino_t *ret);
37.690 +extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
37.691 + ext2fs_block_bitmap map, blk_t *ret);
37.692 +extern errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal,
37.693 + ext2fs_block_bitmap map, blk64_t *ret);
37.694 +extern errcode_t ext2fs_new_block3(ext2_filsys fs, blk64_t goal,
37.695 + ext2fs_block_bitmap map, blk64_t *ret,
37.696 + struct blk_alloc_ctx *ctx);
37.697 +extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start,
37.698 + blk_t finish, int num,
37.699 + ext2fs_block_bitmap map,
37.700 + blk_t *ret);
37.701 +extern errcode_t ext2fs_get_free_blocks2(ext2_filsys fs, blk64_t start,
37.702 + blk64_t finish, int num,
37.703 + ext2fs_block_bitmap map,
37.704 + blk64_t *ret);
37.705 +extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
37.706 + char *block_buf, blk_t *ret);
37.707 +extern errcode_t ext2fs_alloc_block2(ext2_filsys fs, blk64_t goal,
37.708 + char *block_buf, blk64_t *ret);
37.709 +extern errcode_t ext2fs_alloc_block3(ext2_filsys fs, blk64_t goal,
37.710 + char *block_buf, blk64_t *ret,
37.711 + struct blk_alloc_ctx *ctx);
37.712 +
37.713 +extern void ext2fs_set_alloc_block_callback(ext2_filsys fs,
37.714 + errcode_t (*func)(ext2_filsys fs,
37.715 + blk64_t goal,
37.716 + blk64_t *ret),
37.717 + errcode_t (**old)(ext2_filsys fs,
37.718 + blk64_t goal,
37.719 + blk64_t *ret));
37.720 +blk64_t ext2fs_find_inode_goal(ext2_filsys fs, ext2_ino_t ino,
37.721 + struct ext2_inode *inode, blk64_t lblk);
37.722 +extern void ext2fs_set_new_range_callback(ext2_filsys fs,
37.723 + errcode_t (*func)(ext2_filsys fs, int flags, blk64_t goal,
37.724 + blk64_t len, blk64_t *pblk, blk64_t *plen),
37.725 + errcode_t (**old)(ext2_filsys fs, int flags, blk64_t goal,
37.726 + blk64_t len, blk64_t *pblk, blk64_t *plen));
37.727 +extern void ext2fs_set_block_alloc_stats_range_callback(ext2_filsys fs,
37.728 + void (*func)(ext2_filsys fs, blk64_t blk,
37.729 + blk_t num, int inuse),
37.730 + void (**old)(ext2_filsys fs, blk64_t blk,
37.731 + blk_t num, int inuse));
37.732 +#define EXT2_NEWRANGE_FIXED_GOAL (0x1)
37.733 +#define EXT2_NEWRANGE_MIN_LENGTH (0x2)
37.734 +#define EXT2_NEWRANGE_ALL_FLAGS (0x3)
37.735 +errcode_t ext2fs_new_range(ext2_filsys fs, int flags, blk64_t goal,
37.736 + blk64_t len, ext2fs_block_bitmap map, blk64_t *pblk,
37.737 + blk64_t *plen);
37.738 +#define EXT2_ALLOCRANGE_FIXED_GOAL (0x1)
37.739 +#define EXT2_ALLOCRANGE_ZERO_BLOCKS (0x2)
37.740 +#define EXT2_ALLOCRANGE_ALL_FLAGS (0x3)
37.741 +errcode_t ext2fs_alloc_range(ext2_filsys fs, int flags, blk64_t goal,
37.742 + blk_t len, blk64_t *ret);
37.743 +
37.744 +/* alloc_sb.c */
37.745 +extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
37.746 + dgrp_t group,
37.747 + ext2fs_block_bitmap bmap);
37.748 +extern void ext2fs_set_block_alloc_stats_callback(ext2_filsys fs,
37.749 + void (*func)(ext2_filsys fs,
37.750 + blk64_t blk,
37.751 + int inuse),
37.752 + void (**old)(ext2_filsys fs,
37.753 + blk64_t blk,
37.754 + int inuse));
37.755 +
37.756 +/* alloc_stats.c */
37.757 +void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse);
37.758 +void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
37.759 + int inuse, int isdir);
37.760 +void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse);
37.761 +void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse);
37.762 +void ext2fs_block_alloc_stats_range(ext2_filsys fs, blk64_t blk,
37.763 + blk_t num, int inuse);
37.764 +
37.765 +/* alloc_tables.c */
37.766 +extern errcode_t ext2fs_allocate_tables(ext2_filsys fs);
37.767 +extern errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
37.768 + ext2fs_block_bitmap bmap);
37.769 +
37.770 +/* badblocks.c */
37.771 +extern errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size);
37.772 +extern errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk);
37.773 +extern int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk);
37.774 +extern int ext2fs_u32_list_test(ext2_u32_list bb, blk_t blk);
37.775 +extern errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
37.776 + ext2_u32_iterate *ret);
37.777 +extern int ext2fs_u32_list_iterate(ext2_u32_iterate iter, blk_t *blk);
37.778 +extern void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter);
37.779 +extern errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest);
37.780 +extern int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2);
37.781 +
37.782 +extern errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret,
37.783 + int size);
37.784 +extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb,
37.785 + blk_t blk);
37.786 +extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb,
37.787 + blk_t blk);
37.788 +extern int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk);
37.789 +extern void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk);
37.790 +extern errcode_t
37.791 + ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
37.792 + ext2_badblocks_iterate *ret);
37.793 +extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter,
37.794 + blk_t *blk);
37.795 +extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter);
37.796 +extern errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
37.797 + ext2_badblocks_list *dest);
37.798 +extern int ext2fs_badblocks_equal(ext2_badblocks_list bb1,
37.799 + ext2_badblocks_list bb2);
37.800 +extern int ext2fs_u32_list_count(ext2_u32_list bb);
37.801 +
37.802 +/* bb_compat */
37.803 +extern errcode_t badblocks_list_create(badblocks_list *ret, int size);
37.804 +extern errcode_t badblocks_list_add(badblocks_list bb, blk_t blk);
37.805 +extern int badblocks_list_test(badblocks_list bb, blk_t blk);
37.806 +extern errcode_t badblocks_list_iterate_begin(badblocks_list bb,
37.807 + badblocks_iterate *ret);
37.808 +extern int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk);
37.809 +extern void badblocks_list_iterate_end(badblocks_iterate iter);
37.810 +extern void badblocks_list_free(badblocks_list bb);
37.811 +
37.812 +/* bb_inode.c */
37.813 +extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs,
37.814 + ext2_badblocks_list bb_list);
37.815 +
37.816 +/* bitmaps.c */
37.817 +extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap);
37.818 +extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap);
37.819 +extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
37.820 + ext2fs_generic_bitmap *dest);
37.821 +extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
37.822 +extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
37.823 +extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
37.824 +extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs);
37.825 +extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
37.826 + const char *descr,
37.827 + ext2fs_block_bitmap *ret);
37.828 +extern errcode_t ext2fs_allocate_subcluster_bitmap(ext2_filsys fs,
37.829 + const char *descr,
37.830 + ext2fs_block_bitmap *ret);
37.831 +extern int ext2fs_get_bitmap_granularity(ext2fs_block_bitmap bitmap);
37.832 +extern errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
37.833 + const char *descr,
37.834 + ext2fs_inode_bitmap *ret);
37.835 +extern errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
37.836 + ext2_ino_t end, ext2_ino_t *oend);
37.837 +extern errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
37.838 + blk_t end, blk_t *oend);
37.839 +extern errcode_t ext2fs_fudge_block_bitmap_end2(ext2fs_block_bitmap bitmap,
37.840 + blk64_t end, blk64_t *oend);
37.841 +extern void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap);
37.842 +extern void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap);
37.843 +extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs);
37.844 +extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs);
37.845 +extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
37.846 + ext2fs_inode_bitmap bmap);
37.847 +extern errcode_t ext2fs_resize_inode_bitmap2(__u64 new_end,
37.848 + __u64 new_real_end,
37.849 + ext2fs_inode_bitmap bmap);
37.850 +extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
37.851 + ext2fs_block_bitmap bmap);
37.852 +extern errcode_t ext2fs_resize_block_bitmap2(__u64 new_end,
37.853 + __u64 new_real_end,
37.854 + ext2fs_block_bitmap bmap);
37.855 +extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
37.856 + ext2fs_block_bitmap bm2);
37.857 +extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
37.858 + ext2fs_inode_bitmap bm2);
37.859 +extern errcode_t ext2fs_set_inode_bitmap_range(ext2fs_inode_bitmap bmap,
37.860 + ext2_ino_t start, unsigned int num,
37.861 + void *in);
37.862 +extern errcode_t ext2fs_set_inode_bitmap_range2(ext2fs_inode_bitmap bmap,
37.863 + __u64 start, size_t num,
37.864 + void *in);
37.865 +extern errcode_t ext2fs_get_inode_bitmap_range(ext2fs_inode_bitmap bmap,
37.866 + ext2_ino_t start, unsigned int num,
37.867 + void *out);
37.868 +extern errcode_t ext2fs_get_inode_bitmap_range2(ext2fs_inode_bitmap bmap,
37.869 + __u64 start, size_t num,
37.870 + void *out);
37.871 +extern errcode_t ext2fs_set_block_bitmap_range(ext2fs_block_bitmap bmap,
37.872 + blk_t start, unsigned int num,
37.873 + void *in);
37.874 +extern errcode_t ext2fs_set_block_bitmap_range2(ext2fs_block_bitmap bmap,
37.875 + blk64_t start, size_t num,
37.876 + void *in);
37.877 +extern errcode_t ext2fs_get_block_bitmap_range(ext2fs_block_bitmap bmap,
37.878 + blk_t start, unsigned int num,
37.879 + void *out);
37.880 +extern errcode_t ext2fs_get_block_bitmap_range2(ext2fs_block_bitmap bmap,
37.881 + blk64_t start, size_t num,
37.882 + void *out);
37.883 +
37.884 +/* blknum.c */
37.885 +extern __u32 ext2fs_inode_bitmap_checksum(ext2_filsys fs, dgrp_t group);
37.886 +extern __u32 ext2fs_block_bitmap_checksum(ext2_filsys fs, dgrp_t group);
37.887 +extern dgrp_t ext2fs_group_of_blk2(ext2_filsys fs, blk64_t);
37.888 +extern blk64_t ext2fs_group_first_block2(ext2_filsys fs, dgrp_t group);
37.889 +extern blk64_t ext2fs_group_last_block2(ext2_filsys fs, dgrp_t group);
37.890 +extern int ext2fs_group_blocks_count(ext2_filsys fs, dgrp_t group);
37.891 +extern blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs,
37.892 + struct ext2_inode *inode);
37.893 +extern blk64_t ext2fs_inode_i_blocks(ext2_filsys fs,
37.894 + struct ext2_inode *inode);
37.895 +extern blk64_t ext2fs_blocks_count(struct ext2_super_block *super);
37.896 +extern void ext2fs_blocks_count_set(struct ext2_super_block *super,
37.897 + blk64_t blk);
37.898 +extern void ext2fs_blocks_count_add(struct ext2_super_block *super,
37.899 + blk64_t blk);
37.900 +extern blk64_t ext2fs_r_blocks_count(struct ext2_super_block *super);
37.901 +extern void ext2fs_r_blocks_count_set(struct ext2_super_block *super,
37.902 + blk64_t blk);
37.903 +extern void ext2fs_r_blocks_count_add(struct ext2_super_block *super,
37.904 + blk64_t blk);
37.905 +extern blk64_t ext2fs_free_blocks_count(struct ext2_super_block *super);
37.906 +extern void ext2fs_free_blocks_count_set(struct ext2_super_block *super,
37.907 + blk64_t blk);
37.908 +extern void ext2fs_free_blocks_count_add(struct ext2_super_block *super,
37.909 + blk64_t blk);
37.910 +/* Block group descriptor accessor functions */
37.911 +extern struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs,
37.912 + struct opaque_ext2_group_desc *gdp,
37.913 + dgrp_t group);
37.914 +extern blk64_t ext2fs_block_bitmap_csum(ext2_filsys fs, dgrp_t group);
37.915 +extern blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group);
37.916 +extern void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group,
37.917 + blk64_t blk);
37.918 +extern __u32 ext2fs_inode_bitmap_csum(ext2_filsys fs, dgrp_t group);
37.919 +extern blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group);
37.920 +extern void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group,
37.921 + blk64_t blk);
37.922 +extern blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group);
37.923 +extern void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group,
37.924 + blk64_t blk);
37.925 +extern __u32 ext2fs_bg_free_blocks_count(ext2_filsys fs, dgrp_t group);
37.926 +extern void ext2fs_bg_free_blocks_count_set(ext2_filsys fs, dgrp_t group,
37.927 + __u32 n);
37.928 +extern __u32 ext2fs_bg_free_inodes_count(ext2_filsys fs, dgrp_t group);
37.929 +extern void ext2fs_bg_free_inodes_count_set(ext2_filsys fs, dgrp_t group,
37.930 + __u32 n);
37.931 +extern __u32 ext2fs_bg_used_dirs_count(ext2_filsys fs, dgrp_t group);
37.932 +extern void ext2fs_bg_used_dirs_count_set(ext2_filsys fs, dgrp_t group,
37.933 + __u32 n);
37.934 +extern __u32 ext2fs_bg_itable_unused(ext2_filsys fs, dgrp_t group);
37.935 +extern void ext2fs_bg_itable_unused_set(ext2_filsys fs, dgrp_t group,
37.936 + __u32 n);
37.937 +extern __u16 ext2fs_bg_flags(ext2_filsys fs, dgrp_t group);
37.938 +extern void ext2fs_bg_flags_zap(ext2_filsys fs, dgrp_t group);
37.939 +extern int ext2fs_bg_flags_test(ext2_filsys fs, dgrp_t group, __u16 bg_flag);
37.940 +extern void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags);
37.941 +extern void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags);
37.942 +extern __u16 ext2fs_bg_checksum(ext2_filsys fs, dgrp_t group);
37.943 +extern void ext2fs_bg_checksum_set(ext2_filsys fs, dgrp_t group, __u16 checksum);
37.944 +extern blk64_t ext2fs_file_acl_block(ext2_filsys fs,
37.945 + const struct ext2_inode *inode);
37.946 +extern void ext2fs_file_acl_block_set(ext2_filsys fs,
37.947 + struct ext2_inode *inode, blk64_t blk);
37.948 +extern errcode_t ext2fs_inode_size_set(ext2_filsys fs, struct ext2_inode *inode,
37.949 + ext2_off64_t size);
37.950 +
37.951 +/* block.c */
37.952 +extern errcode_t ext2fs_block_iterate(ext2_filsys fs,
37.953 + ext2_ino_t ino,
37.954 + int flags,
37.955 + char *block_buf,
37.956 + int (*func)(ext2_filsys fs,
37.957 + blk_t *blocknr,
37.958 + int blockcnt,
37.959 + void *priv_data),
37.960 + void *priv_data);
37.961 +errcode_t ext2fs_block_iterate2(ext2_filsys fs,
37.962 + ext2_ino_t ino,
37.963 + int flags,
37.964 + char *block_buf,
37.965 + int (*func)(ext2_filsys fs,
37.966 + blk_t *blocknr,
37.967 + e2_blkcnt_t blockcnt,
37.968 + blk_t ref_blk,
37.969 + int ref_offset,
37.970 + void *priv_data),
37.971 + void *priv_data);
37.972 +errcode_t ext2fs_block_iterate3(ext2_filsys fs,
37.973 + ext2_ino_t ino,
37.974 + int flags,
37.975 + char *block_buf,
37.976 + int (*func)(ext2_filsys fs,
37.977 + blk64_t *blocknr,
37.978 + e2_blkcnt_t blockcnt,
37.979 + blk64_t ref_blk,
37.980 + int ref_offset,
37.981 + void *priv_data),
37.982 + void *priv_data);
37.983 +
37.984 +/* bmap.c */
37.985 +extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
37.986 + struct ext2_inode *inode,
37.987 + char *block_buf, int bmap_flags,
37.988 + blk_t block, blk_t *phys_blk);
37.989 +extern errcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino,
37.990 + struct ext2_inode *inode,
37.991 + char *block_buf, int bmap_flags, blk64_t block,
37.992 + int *ret_flags, blk64_t *phys_blk);
37.993 +errcode_t ext2fs_map_cluster_block(ext2_filsys fs, ext2_ino_t ino,
37.994 + struct ext2_inode *inode, blk64_t lblk,
37.995 + blk64_t *pblk);
37.996 +
37.997 +#if 0
37.998 +/* bmove.c */
37.999 +extern errcode_t ext2fs_move_blocks(ext2_filsys fs,
37.1000 + ext2fs_block_bitmap reserve,
37.1001 + ext2fs_block_bitmap alloc_map,
37.1002 + int flags);
37.1003 +#endif
37.1004 +
37.1005 +/* check_desc.c */
37.1006 +extern errcode_t ext2fs_check_desc(ext2_filsys fs);
37.1007 +
37.1008 +/* closefs.c */
37.1009 +extern errcode_t ext2fs_close(ext2_filsys fs);
37.1010 +extern errcode_t ext2fs_close2(ext2_filsys fs, int flags);
37.1011 +extern errcode_t ext2fs_close_free(ext2_filsys *fs);
37.1012 +extern errcode_t ext2fs_flush(ext2_filsys fs);
37.1013 +extern errcode_t ext2fs_flush2(ext2_filsys fs, int flags);
37.1014 +extern int ext2fs_bg_has_super(ext2_filsys fs, dgrp_t group_block);
37.1015 +extern errcode_t ext2fs_super_and_bgd_loc2(ext2_filsys fs,
37.1016 + dgrp_t group,
37.1017 + blk64_t *ret_super_blk,
37.1018 + blk64_t *ret_old_desc_blk,
37.1019 + blk64_t *ret_new_desc_blk,
37.1020 + blk_t *ret_used_blks);
37.1021 +extern int ext2fs_super_and_bgd_loc(ext2_filsys fs,
37.1022 + dgrp_t group,
37.1023 + blk_t *ret_super_blk,
37.1024 + blk_t *ret_old_desc_blk,
37.1025 + blk_t *ret_new_desc_blk,
37.1026 + int *ret_meta_bg);
37.1027 +extern void ext2fs_update_dynamic_rev(ext2_filsys fs);
37.1028 +
37.1029 +/* crc32c.c */
37.1030 +extern __u32 ext2fs_crc32_be(__u32 crc, unsigned char const *p, size_t len);
37.1031 +extern __u32 ext2fs_crc32c_le(__u32 crc, unsigned char const *p, size_t len);
37.1032 +
37.1033 +/* csum.c */
37.1034 +extern void ext2fs_init_csum_seed(ext2_filsys fs);
37.1035 +extern errcode_t ext2fs_mmp_csum_set(ext2_filsys fs, struct mmp_struct *mmp);
37.1036 +extern int ext2fs_mmp_csum_verify(ext2_filsys, struct mmp_struct *mmp);
37.1037 +extern int ext2fs_verify_csum_type(ext2_filsys fs, struct ext2_super_block *sb);
37.1038 +extern errcode_t ext2fs_superblock_csum_set(ext2_filsys fs,
37.1039 + struct ext2_super_block *sb);
37.1040 +extern int ext2fs_superblock_csum_verify(ext2_filsys fs,
37.1041 + struct ext2_super_block *sb);
37.1042 +extern errcode_t ext2fs_ext_attr_block_csum_set(ext2_filsys fs,
37.1043 + ext2_ino_t inum, blk64_t block,
37.1044 + struct ext2_ext_attr_header *hdr);
37.1045 +extern int ext2fs_ext_attr_block_csum_verify(ext2_filsys fs, ext2_ino_t inum,
37.1046 + blk64_t block,
37.1047 + struct ext2_ext_attr_header *hdr);
37.1048 +#define EXT2_DIRENT_TAIL(block, blocksize) \
37.1049 + ((struct ext2_dir_entry_tail *)(((char *)(block)) + \
37.1050 + (blocksize) - sizeof(struct ext2_dir_entry_tail)))
37.1051 +
37.1052 +extern void ext2fs_initialize_dirent_tail(ext2_filsys fs,
37.1053 + struct ext2_dir_entry_tail *t);
37.1054 +extern int ext2fs_dirent_has_tail(ext2_filsys fs,
37.1055 + struct ext2_dir_entry *dirent);
37.1056 +extern int ext2fs_dirent_csum_verify(ext2_filsys fs, ext2_ino_t inum,
37.1057 + struct ext2_dir_entry *dirent);
37.1058 +extern int ext2fs_dir_block_csum_verify(ext2_filsys fs, ext2_ino_t inum,
37.1059 + struct ext2_dir_entry *dirent);
37.1060 +extern errcode_t ext2fs_dir_block_csum_set(ext2_filsys fs, ext2_ino_t inum,
37.1061 + struct ext2_dir_entry *dirent);
37.1062 +extern errcode_t ext2fs_get_dx_countlimit(ext2_filsys fs,
37.1063 + struct ext2_dir_entry *dirent,
37.1064 + struct ext2_dx_countlimit **cc,
37.1065 + int *offset);
37.1066 +extern errcode_t ext2fs_extent_block_csum_set(ext2_filsys fs,
37.1067 + ext2_ino_t inum,
37.1068 + struct ext3_extent_header *eh);
37.1069 +extern int ext2fs_extent_block_csum_verify(ext2_filsys fs,
37.1070 + ext2_ino_t inum,
37.1071 + struct ext3_extent_header *eh);
37.1072 +extern errcode_t ext2fs_block_bitmap_csum_set(ext2_filsys fs, dgrp_t group,
37.1073 + char *bitmap, int size);
37.1074 +extern int ext2fs_block_bitmap_csum_verify(ext2_filsys fs, dgrp_t group,
37.1075 + char *bitmap, int size);
37.1076 +extern errcode_t ext2fs_inode_bitmap_csum_set(ext2_filsys fs, dgrp_t group,
37.1077 + char *bitmap, int size);
37.1078 +extern int ext2fs_inode_bitmap_csum_verify(ext2_filsys fs, dgrp_t group,
37.1079 + char *bitmap, int size);
37.1080 +extern errcode_t ext2fs_inode_csum_set(ext2_filsys fs, ext2_ino_t inum,
37.1081 + struct ext2_inode_large *inode);
37.1082 +extern int ext2fs_inode_csum_verify(ext2_filsys fs, ext2_ino_t inum,
37.1083 + struct ext2_inode_large *inode);
37.1084 +extern void ext2fs_group_desc_csum_set(ext2_filsys fs, dgrp_t group);
37.1085 +extern int ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group);
37.1086 +extern errcode_t ext2fs_set_gdt_csum(ext2_filsys fs);
37.1087 +extern __u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group);
37.1088 +
37.1089 +/* dblist.c */
37.1090 +extern errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist);
37.1091 +extern errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino,
37.1092 + blk_t blk, int blockcnt);
37.1093 +extern errcode_t ext2fs_add_dir_block2(ext2_dblist dblist, ext2_ino_t ino,
37.1094 + blk64_t blk, e2_blkcnt_t blockcnt);
37.1095 +extern void ext2fs_dblist_sort(ext2_dblist dblist,
37.1096 + EXT2_QSORT_TYPE (*sortfunc)(const void *,
37.1097 + const void *));
37.1098 +extern void ext2fs_dblist_sort2(ext2_dblist dblist,
37.1099 + EXT2_QSORT_TYPE (*sortfunc)(const void *,
37.1100 + const void *));
37.1101 +extern errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
37.1102 + int (*func)(ext2_filsys fs, struct ext2_db_entry *db_info,
37.1103 + void *priv_data),
37.1104 + void *priv_data);
37.1105 +extern errcode_t ext2fs_dblist_iterate2(ext2_dblist dblist,
37.1106 + int (*func)(ext2_filsys fs, struct ext2_db_entry2 *db_info,
37.1107 + void *priv_data),
37.1108 + void *priv_data);
37.1109 +extern errcode_t ext2fs_dblist_iterate3(ext2_dblist dblist,
37.1110 + int (*func)(ext2_filsys fs, struct ext2_db_entry2 *db_info,
37.1111 + void *priv_data),
37.1112 + unsigned long long start,
37.1113 + unsigned long long count,
37.1114 + void *priv_data);
37.1115 +extern errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino,
37.1116 + blk_t blk, int blockcnt);
37.1117 +extern errcode_t ext2fs_set_dir_block2(ext2_dblist dblist, ext2_ino_t ino,
37.1118 + blk64_t blk, e2_blkcnt_t blockcnt);
37.1119 +extern errcode_t ext2fs_copy_dblist(ext2_dblist src,
37.1120 + ext2_dblist *dest);
37.1121 +extern int ext2fs_dblist_count(ext2_dblist dblist);
37.1122 +extern blk64_t ext2fs_dblist_count2(ext2_dblist dblist);
37.1123 +extern errcode_t ext2fs_dblist_get_last(ext2_dblist dblist,
37.1124 + struct ext2_db_entry **entry);
37.1125 +extern errcode_t ext2fs_dblist_get_last2(ext2_dblist dblist,
37.1126 + struct ext2_db_entry2 **entry);
37.1127 +extern errcode_t ext2fs_dblist_drop_last(ext2_dblist dblist);
37.1128 +
37.1129 +/* dblist_dir.c */
37.1130 +extern errcode_t
37.1131 + ext2fs_dblist_dir_iterate(ext2_dblist dblist,
37.1132 + int flags,
37.1133 + char *block_buf,
37.1134 + int (*func)(ext2_ino_t dir,
37.1135 + int entry,
37.1136 + struct ext2_dir_entry *dirent,
37.1137 + int offset,
37.1138 + int blocksize,
37.1139 + char *buf,
37.1140 + void *priv_data),
37.1141 + void *priv_data);
37.1142 +
37.1143 +#if 0
37.1144 +/* digest_encode.c */
37.1145 +#define EXT2FS_DIGEST_SIZE EXT2FS_SHA256_LENGTH
37.1146 +extern int ext2fs_digest_encode(const char *src, int len, char *dst);
37.1147 +extern int ext2fs_digest_decode(const char *src, int len, char *dst);
37.1148 +#endif
37.1149 +
37.1150 +/* dirblock.c */
37.1151 +extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
37.1152 + void *buf);
37.1153 +extern errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
37.1154 + void *buf, int flags);
37.1155 +extern errcode_t ext2fs_read_dir_block3(ext2_filsys fs, blk64_t block,
37.1156 + void *buf, int flags);
37.1157 +extern errcode_t ext2fs_read_dir_block4(ext2_filsys fs, blk64_t block,
37.1158 + void *buf, int flags, ext2_ino_t ino);
37.1159 +extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
37.1160 + void *buf);
37.1161 +extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
37.1162 + void *buf, int flags);
37.1163 +extern errcode_t ext2fs_write_dir_block3(ext2_filsys fs, blk64_t block,
37.1164 + void *buf, int flags);
37.1165 +extern errcode_t ext2fs_write_dir_block4(ext2_filsys fs, blk64_t block,
37.1166 + void *buf, int flags, ext2_ino_t ino);
37.1167 +
37.1168 +/* dirhash.c */
37.1169 +extern errcode_t ext2fs_dirhash(int version, const char *name, int len,
37.1170 + const __u32 *seed,
37.1171 + ext2_dirhash_t *ret_hash,
37.1172 + ext2_dirhash_t *ret_minor_hash);
37.1173 +
37.1174 +
37.1175 +/* dir_iterate.c */
37.1176 +extern errcode_t ext2fs_get_rec_len(ext2_filsys fs,
37.1177 + struct ext2_dir_entry *dirent,
37.1178 + unsigned int *rec_len);
37.1179 +extern errcode_t ext2fs_set_rec_len(ext2_filsys fs,
37.1180 + unsigned int len,
37.1181 + struct ext2_dir_entry *dirent);
37.1182 +extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
37.1183 + ext2_ino_t dir,
37.1184 + int flags,
37.1185 + char *block_buf,
37.1186 + int (*func)(struct ext2_dir_entry *dirent,
37.1187 + int offset,
37.1188 + int blocksize,
37.1189 + char *buf,
37.1190 + void *priv_data),
37.1191 + void *priv_data);
37.1192 +extern errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
37.1193 + ext2_ino_t dir,
37.1194 + int flags,
37.1195 + char *block_buf,
37.1196 + int (*func)(ext2_ino_t dir,
37.1197 + int entry,
37.1198 + struct ext2_dir_entry *dirent,
37.1199 + int offset,
37.1200 + int blocksize,
37.1201 + char *buf,
37.1202 + void *priv_data),
37.1203 + void *priv_data);
37.1204 +
37.1205 +/* dupfs.c */
37.1206 +extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest);
37.1207 +
37.1208 +/* expanddir.c */
37.1209 +extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir);
37.1210 +
37.1211 +/* ext_attr.c */
37.1212 +extern __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry,
37.1213 + void *data);
37.1214 +extern errcode_t ext2fs_ext_attr_hash_entry2(ext2_filsys fs,
37.1215 + struct ext2_ext_attr_entry *entry,
37.1216 + void *data, __u32 *hash);
37.1217 +extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf);
37.1218 +extern errcode_t ext2fs_read_ext_attr2(ext2_filsys fs, blk64_t block,
37.1219 + void *buf);
37.1220 +extern errcode_t ext2fs_read_ext_attr3(ext2_filsys fs, blk64_t block,
37.1221 + void *buf, ext2_ino_t inum);
37.1222 +extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block,
37.1223 + void *buf);
37.1224 +extern errcode_t ext2fs_write_ext_attr2(ext2_filsys fs, blk64_t block,
37.1225 + void *buf);
37.1226 +extern errcode_t ext2fs_write_ext_attr3(ext2_filsys fs, blk64_t block,
37.1227 + void *buf, ext2_ino_t inum);
37.1228 +extern errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
37.1229 + char *block_buf,
37.1230 + int adjust, __u32 *newcount);
37.1231 +extern errcode_t ext2fs_adjust_ea_refcount2(ext2_filsys fs, blk64_t blk,
37.1232 + char *block_buf,
37.1233 + int adjust, __u32 *newcount);
37.1234 +extern errcode_t ext2fs_adjust_ea_refcount3(ext2_filsys fs, blk64_t blk,
37.1235 + char *block_buf,
37.1236 + int adjust, __u32 *newcount,
37.1237 + ext2_ino_t inum);
37.1238 +errcode_t ext2fs_xattrs_write(struct ext2_xattr_handle *handle);
37.1239 +errcode_t ext2fs_xattrs_read(struct ext2_xattr_handle *handle);
37.1240 +errcode_t ext2fs_xattrs_iterate(struct ext2_xattr_handle *h,
37.1241 + int (*func)(char *name, char *value,
37.1242 + size_t value_len, void *data),
37.1243 + void *data);
37.1244 +errcode_t ext2fs_xattr_get(struct ext2_xattr_handle *h, const char *key,
37.1245 + void **value, size_t *value_len);
37.1246 +errcode_t ext2fs_xattr_set(struct ext2_xattr_handle *handle,
37.1247 + const char *key,
37.1248 + const void *value,
37.1249 + size_t value_len);
37.1250 +errcode_t ext2fs_xattr_remove(struct ext2_xattr_handle *handle,
37.1251 + const char *key);
37.1252 +errcode_t ext2fs_xattrs_open(ext2_filsys fs, ext2_ino_t ino,
37.1253 + struct ext2_xattr_handle **handle);
37.1254 +errcode_t ext2fs_xattrs_close(struct ext2_xattr_handle **handle);
37.1255 +errcode_t ext2fs_free_ext_attr(ext2_filsys fs, ext2_ino_t ino,
37.1256 + struct ext2_inode_large *inode);
37.1257 +errcode_t ext2fs_xattrs_count(struct ext2_xattr_handle *handle, size_t *count);
37.1258 +errcode_t ext2fs_xattr_inode_max_size(ext2_filsys fs, ext2_ino_t ino,
37.1259 + size_t *size);
37.1260 +#define XATTR_HANDLE_FLAG_RAW 0x0001
37.1261 +errcode_t ext2fs_xattrs_flags(struct ext2_xattr_handle *handle,
37.1262 + unsigned int *new_flags, unsigned int *old_flags);
37.1263 +extern void ext2fs_ext_attr_block_rehash(struct ext2_ext_attr_header *header,
37.1264 + struct ext2_ext_attr_entry *end);
37.1265 +extern __u32 ext2fs_get_ea_inode_hash(struct ext2_inode *inode);
37.1266 +extern void ext2fs_set_ea_inode_hash(struct ext2_inode *inode, __u32 hash);
37.1267 +extern __u64 ext2fs_get_ea_inode_ref(struct ext2_inode *inode);
37.1268 +extern void ext2fs_set_ea_inode_ref(struct ext2_inode *inode, __u64 ref_count);
37.1269 +
37.1270 +/* extent.c */
37.1271 +extern errcode_t ext2fs_extent_header_verify(void *ptr, int size);
37.1272 +extern errcode_t ext2fs_extent_open(ext2_filsys fs, ext2_ino_t ino,
37.1273 + ext2_extent_handle_t *handle);
37.1274 +extern errcode_t ext2fs_extent_open2(ext2_filsys fs, ext2_ino_t ino,
37.1275 + struct ext2_inode *inode,
37.1276 + ext2_extent_handle_t *ret_handle);
37.1277 +extern void ext2fs_extent_free(ext2_extent_handle_t handle);
37.1278 +extern errcode_t ext2fs_extent_get(ext2_extent_handle_t handle,
37.1279 + int flags, struct ext2fs_extent *extent);
37.1280 +extern errcode_t ext2fs_extent_node_split(ext2_extent_handle_t handle);
37.1281 +extern errcode_t ext2fs_extent_replace(ext2_extent_handle_t handle, int flags,
37.1282 + struct ext2fs_extent *extent);
37.1283 +extern errcode_t ext2fs_extent_insert(ext2_extent_handle_t handle, int flags,
37.1284 + struct ext2fs_extent *extent);
37.1285 +extern errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,
37.1286 + blk64_t logical, blk64_t physical,
37.1287 + int flags);
37.1288 +extern errcode_t ext2fs_extent_delete(ext2_extent_handle_t handle, int flags);
37.1289 +extern errcode_t ext2fs_extent_get_info(ext2_extent_handle_t handle,
37.1290 + struct ext2_extent_info *info);
37.1291 +extern errcode_t ext2fs_extent_goto(ext2_extent_handle_t handle,
37.1292 + blk64_t blk);
37.1293 +extern errcode_t ext2fs_extent_goto2(ext2_extent_handle_t handle,
37.1294 + int leaf_level, blk64_t blk);
37.1295 +extern errcode_t ext2fs_extent_fix_parents(ext2_extent_handle_t handle);
37.1296 +size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle);
37.1297 +
37.1298 +/* fallocate.c */
37.1299 +#define EXT2_FALLOCATE_ZERO_BLOCKS (0x1)
37.1300 +#define EXT2_FALLOCATE_FORCE_INIT (0x2)
37.1301 +#define EXT2_FALLOCATE_FORCE_UNINIT (0x4)
37.1302 +#define EXT2_FALLOCATE_INIT_BEYOND_EOF (0x8)
37.1303 +#define EXT2_FALLOCATE_ALL_FLAGS (0xF)
37.1304 +errcode_t ext2fs_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino,
37.1305 + struct ext2_inode *inode, blk64_t goal,
37.1306 + blk64_t start, blk64_t len);
37.1307 +
37.1308 +/* fileio.c */
37.1309 +extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
37.1310 + struct ext2_inode *inode,
37.1311 + int flags, ext2_file_t *ret);
37.1312 +extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
37.1313 + int flags, ext2_file_t *ret);
37.1314 +extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file);
37.1315 +struct ext2_inode *ext2fs_file_get_inode(ext2_file_t file);
37.1316 +extern ext2_ino_t ext2fs_file_get_inode_num(ext2_file_t file);
37.1317 +extern errcode_t ext2fs_file_close(ext2_file_t file);
37.1318 +extern errcode_t ext2fs_file_flush(ext2_file_t file);
37.1319 +extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
37.1320 + unsigned int wanted, unsigned int *got);
37.1321 +extern errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
37.1322 + unsigned int nbytes, unsigned int *written);
37.1323 +extern errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
37.1324 + int whence, __u64 *ret_pos);
37.1325 +extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
37.1326 + int whence, ext2_off_t *ret_pos);
37.1327 +errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size);
37.1328 +extern ext2_off_t ext2fs_file_get_size(ext2_file_t file);
37.1329 +extern errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size);
37.1330 +extern errcode_t ext2fs_file_set_size2(ext2_file_t file, ext2_off64_t size);
37.1331 +
37.1332 +/* finddev.c */
37.1333 +extern char *ext2fs_find_block_device(dev_t device);
37.1334 +
37.1335 +/* flushb.c */
37.1336 +extern errcode_t ext2fs_sync_device(int fd, int flushb);
37.1337 +
37.1338 +/* freefs.c */
37.1339 +extern void ext2fs_free(ext2_filsys fs);
37.1340 +extern void ext2fs_free_dblist(ext2_dblist dblist);
37.1341 +extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb);
37.1342 +extern void ext2fs_u32_list_free(ext2_u32_list bb);
37.1343 +
37.1344 +/* gen_bitmap.c */
37.1345 +extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap);
37.1346 +extern errcode_t ext2fs_make_generic_bitmap(errcode_t magic, ext2_filsys fs,
37.1347 + __u32 start, __u32 end,
37.1348 + __u32 real_end,
37.1349 + const char *descr, char *init_map,
37.1350 + ext2fs_generic_bitmap *ret);
37.1351 +extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
37.1352 + __u32 end,
37.1353 + __u32 real_end,
37.1354 + const char *descr,
37.1355 + ext2fs_generic_bitmap *ret);
37.1356 +extern errcode_t ext2fs_copy_generic_bitmap(ext2fs_generic_bitmap src,
37.1357 + ext2fs_generic_bitmap *dest);
37.1358 +extern void ext2fs_clear_generic_bitmap(ext2fs_generic_bitmap bitmap);
37.1359 +extern errcode_t ext2fs_fudge_generic_bitmap_end(ext2fs_inode_bitmap bitmap,
37.1360 + errcode_t magic,
37.1361 + errcode_t neq,
37.1362 + ext2_ino_t end,
37.1363 + ext2_ino_t *oend);
37.1364 +extern void ext2fs_set_generic_bitmap_padding(ext2fs_generic_bitmap map);
37.1365 +extern errcode_t ext2fs_resize_generic_bitmap(errcode_t magic,
37.1366 + __u32 new_end,
37.1367 + __u32 new_real_end,
37.1368 + ext2fs_generic_bitmap bmap);
37.1369 +extern errcode_t ext2fs_compare_generic_bitmap(errcode_t magic, errcode_t neq,
37.1370 + ext2fs_generic_bitmap bm1,
37.1371 + ext2fs_generic_bitmap bm2);
37.1372 +extern errcode_t ext2fs_get_generic_bitmap_range(ext2fs_generic_bitmap bmap,
37.1373 + errcode_t magic,
37.1374 + __u32 start, __u32 num,
37.1375 + void *out);
37.1376 +extern errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap,
37.1377 + errcode_t magic,
37.1378 + __u32 start, __u32 num,
37.1379 + void *in);
37.1380 +extern errcode_t ext2fs_find_first_zero_generic_bitmap(ext2fs_generic_bitmap bitmap,
37.1381 + __u32 start, __u32 end,
37.1382 + __u32 *out);
37.1383 +extern errcode_t ext2fs_find_first_set_generic_bitmap(ext2fs_generic_bitmap bitmap,
37.1384 + __u32 start, __u32 end,
37.1385 + __u32 *out);
37.1386 +
37.1387 +/* gen_bitmap64.c */
37.1388 +void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap);
37.1389 +errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
37.1390 + int type, __u64 start, __u64 end,
37.1391 + __u64 real_end,
37.1392 + const char *descr,
37.1393 + ext2fs_generic_bitmap *ret);
37.1394 +errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src,
37.1395 + ext2fs_generic_bitmap *dest);
37.1396 +void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap);
37.1397 +errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap,
37.1398 + errcode_t neq,
37.1399 + __u64 end, __u64 *oend);
37.1400 +void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap);
37.1401 +errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap,
37.1402 + __u64 new_end,
37.1403 + __u64 new_real_end);
37.1404 +errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
37.1405 + ext2fs_generic_bitmap bm1,
37.1406 + ext2fs_generic_bitmap bm2);
37.1407 +errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bmap,
37.1408 + __u64 start, unsigned int num,
37.1409 + void *out);
37.1410 +errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap,
37.1411 + __u64 start, unsigned int num,
37.1412 + void *in);
37.1413 +errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs,
37.1414 + ext2fs_block_bitmap *bitmap);
37.1415 +
37.1416 +/* get_num_dirs.c */
37.1417 +extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs);
37.1418 +
37.1419 +/* getsize.c */
37.1420 +extern errcode_t ext2fs_get_device_size(const char *file, int blocksize,
37.1421 + blk_t *retblocks);
37.1422 +extern errcode_t ext2fs_get_device_size2(const char *file, int blocksize,
37.1423 + blk64_t *retblocks);
37.1424 +
37.1425 +/* getsectsize.c */
37.1426 +extern int ext2fs_get_dio_alignment(int fd);
37.1427 +errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize);
37.1428 +errcode_t ext2fs_get_device_phys_sectsize(const char *file, int *sectsize);
37.1429 +
37.1430 +/* i_block.c */
37.1431 +errcode_t ext2fs_iblk_add_blocks(ext2_filsys fs, struct ext2_inode *inode,
37.1432 + blk64_t num_blocks);
37.1433 +errcode_t ext2fs_iblk_sub_blocks(ext2_filsys fs, struct ext2_inode *inode,
37.1434 + blk64_t num_blocks);
37.1435 +errcode_t ext2fs_iblk_set(ext2_filsys fs, struct ext2_inode *inode, blk64_t b);
37.1436 +
37.1437 +/* imager.c */
37.1438 +extern errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags);
37.1439 +extern errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags);
37.1440 +extern errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags);
37.1441 +extern errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags);
37.1442 +extern errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags);
37.1443 +extern errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags);
37.1444 +
37.1445 +/* ind_block.c */
37.1446 +errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf);
37.1447 +errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf);
37.1448 +
37.1449 +/* initialize.c */
37.1450 +extern errcode_t ext2fs_initialize(const char *name, int flags,
37.1451 + struct ext2_super_block *param,
37.1452 + io_manager manager, ext2_filsys *ret_fs);
37.1453 +
37.1454 +/* icount.c */
37.1455 +extern void ext2fs_free_icount(ext2_icount_t icount);
37.1456 +extern errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir,
37.1457 + int flags, ext2_icount_t *ret);
37.1458 +extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags,
37.1459 + unsigned int size,
37.1460 + ext2_icount_t hint, ext2_icount_t *ret);
37.1461 +extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags,
37.1462 + unsigned int size,
37.1463 + ext2_icount_t *ret);
37.1464 +extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino,
37.1465 + __u16 *ret);
37.1466 +extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
37.1467 + __u16 *ret);
37.1468 +extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
37.1469 + __u16 *ret);
37.1470 +extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
37.1471 + __u16 count);
37.1472 +extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
37.1473 +errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
37.1474 +
37.1475 +/* inline.c */
37.1476 +
37.1477 +extern errcode_t ext2fs_get_memalign(unsigned long size,
37.1478 + unsigned long align, void *ptr);
37.1479 +
37.1480 +/* inline_data.c */
37.1481 +extern errcode_t ext2fs_inline_data_init(ext2_filsys fs, ext2_ino_t ino);
37.1482 +extern errcode_t ext2fs_inline_data_size(ext2_filsys fs, ext2_ino_t ino,
37.1483 + size_t *size);
37.1484 +extern errcode_t ext2fs_inline_data_get(ext2_filsys fs, ext2_ino_t ino,
37.1485 + struct ext2_inode *inode,
37.1486 + void *buf, size_t *size);
37.1487 +extern errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino,
37.1488 + struct ext2_inode *inode,
37.1489 + void *buf, size_t size);
37.1490 +
37.1491 +/* inode.c */
37.1492 +extern errcode_t ext2fs_create_inode_cache(ext2_filsys fs,
37.1493 + unsigned int cache_size);
37.1494 +extern void ext2fs_free_inode_cache(struct ext2_inode_cache *icache);
37.1495 +extern errcode_t ext2fs_flush_icache(ext2_filsys fs);
37.1496 +extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan,
37.1497 + ext2_ino_t *ino,
37.1498 + struct ext2_inode *inode,
37.1499 + int bufsize);
37.1500 +#define EXT2_INODE_SCAN_DEFAULT_BUFFER_BLOCKS 8
37.1501 +extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
37.1502 + ext2_inode_scan *ret_scan);
37.1503 +extern void ext2fs_close_inode_scan(ext2_inode_scan scan);
37.1504 +extern errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
37.1505 + struct ext2_inode *inode);
37.1506 +extern errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
37.1507 + int group);
37.1508 +extern void ext2fs_set_inode_callback
37.1509 + (ext2_inode_scan scan,
37.1510 + errcode_t (*done_group)(ext2_filsys fs,
37.1511 + ext2_inode_scan scan,
37.1512 + dgrp_t group,
37.1513 + void * priv_data),
37.1514 + void *done_group_data);
37.1515 +extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
37.1516 + int clear_flags);
37.1517 +extern errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
37.1518 + struct ext2_inode * inode,
37.1519 + int bufsize);
37.1520 +extern errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino,
37.1521 + struct ext2_inode * inode);
37.1522 +extern errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
37.1523 + struct ext2_inode * inode,
37.1524 + int bufsize);
37.1525 +extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
37.1526 + struct ext2_inode * inode);
37.1527 +extern errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
37.1528 + struct ext2_inode * inode);
37.1529 +extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
37.1530 +extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino);
37.1531 +
37.1532 +/* inode_io.c */
37.1533 +extern io_manager inode_io_manager;
37.1534 +extern errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
37.1535 + char **name);
37.1536 +extern errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
37.1537 + struct ext2_inode *inode,
37.1538 + char **name);
37.1539 +
37.1540 +/* ismounted.c */
37.1541 +extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
37.1542 +extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
37.1543 + char *mtpt, int mtlen);
37.1544 +
37.1545 +/* punch.c */
37.1546 +/*
37.1547 + * NOTE: This function removes from an inode the blocks "start", "end", and
37.1548 + * every block in between.
37.1549 + */
37.1550 +extern errcode_t ext2fs_punch(ext2_filsys fs, ext2_ino_t ino,
37.1551 + struct ext2_inode *inode,
37.1552 + char *block_buf, blk64_t start,
37.1553 + blk64_t end);
37.1554 +
37.1555 +/* namei.c */
37.1556 +extern errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
37.1557 + int namelen, char *buf, ext2_ino_t *inode);
37.1558 +extern errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
37.1559 + const char *name, ext2_ino_t *inode);
37.1560 +errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
37.1561 + const char *name, ext2_ino_t *inode);
37.1562 +extern errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
37.1563 + ext2_ino_t inode, ext2_ino_t *res_inode);
37.1564 +
37.1565 +/* native.c */
37.1566 +int ext2fs_native_flag(void);
37.1567 +
37.1568 +/* newdir.c */
37.1569 +extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
37.1570 + ext2_ino_t parent_ino, char **block);
37.1571 +extern errcode_t ext2fs_new_dir_inline_data(ext2_filsys fs, ext2_ino_t dir_ino,
37.1572 + ext2_ino_t parent_ino, __u32 *iblock);
37.1573 +
37.1574 +/* mkdir.c */
37.1575 +extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
37.1576 + const char *name);
37.1577 +
37.1578 +/* mkjournal.c */
37.1579 +extern errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num,
37.1580 + blk_t *ret_blk, int *ret_count);
37.1581 +extern errcode_t ext2fs_zero_blocks2(ext2_filsys fs, blk64_t blk, int num,
37.1582 + blk64_t *ret_blk, int *ret_count);
37.1583 +extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
37.1584 + __u32 num_blocks, int flags,
37.1585 + char **ret_jsb);
37.1586 +extern errcode_t ext2fs_add_journal_device(ext2_filsys fs,
37.1587 + ext2_filsys journal_dev);
37.1588 +extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks,
37.1589 + int flags);
37.1590 +extern errcode_t ext2fs_add_journal_inode2(ext2_filsys fs, blk_t num_blocks,
37.1591 + blk64_t goal, int flags);
37.1592 +extern int ext2fs_default_journal_size(__u64 num_blocks);
37.1593 +extern int ext2fs_journal_sb_start(int blocksize);
37.1594 +
37.1595 +/* openfs.c */
37.1596 +extern errcode_t ext2fs_open(const char *name, int flags, int superblock,
37.1597 + unsigned int block_size, io_manager manager,
37.1598 + ext2_filsys *ret_fs);
37.1599 +extern errcode_t ext2fs_open2(const char *name, const char *io_options,
37.1600 + int flags, int superblock,
37.1601 + unsigned int block_size, io_manager manager,
37.1602 + ext2_filsys *ret_fs);
37.1603 +/*
37.1604 + * The dgrp_t argument to these two functions is not actually a group number
37.1605 + * but a block number offset within a group table! Convert with the formula
37.1606 + * (group_number / groups_per_block).
37.1607 + */
37.1608 +extern blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs,
37.1609 + blk64_t group_block, dgrp_t i);
37.1610 +extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block,
37.1611 + dgrp_t i);
37.1612 +errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io);
37.1613 +errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io);
37.1614 +errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io);
37.1615 +
37.1616 +/* get_pathname.c */
37.1617 +extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
37.1618 + char **name);
37.1619 +
37.1620 +/* link.c */
37.1621 +errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
37.1622 + ext2_ino_t ino, int flags);
37.1623 +errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name,
37.1624 + ext2_ino_t ino, int flags);
37.1625 +
37.1626 +/* symlink.c */
37.1627 +errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino,
37.1628 + const char *name, const char *target);
37.1629 +int ext2fs_is_fast_symlink(struct ext2_inode *inode);
37.1630 +
37.1631 +/* mmp.c */
37.1632 +errcode_t ext2fs_mmp_read(ext2_filsys fs, blk64_t mmp_blk, void *buf);
37.1633 +errcode_t ext2fs_mmp_write(ext2_filsys fs, blk64_t mmp_blk, void *buf);
37.1634 +errcode_t ext2fs_mmp_clear(ext2_filsys fs);
37.1635 +errcode_t ext2fs_mmp_init(ext2_filsys fs);
37.1636 +errcode_t ext2fs_mmp_start(ext2_filsys fs);
37.1637 +errcode_t ext2fs_mmp_update(ext2_filsys fs);
37.1638 +errcode_t ext2fs_mmp_update2(ext2_filsys fs, int immediately);
37.1639 +errcode_t ext2fs_mmp_stop(ext2_filsys fs);
37.1640 +unsigned ext2fs_mmp_new_seq(void);
37.1641 +
37.1642 +/* read_bb.c */
37.1643 +extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs,
37.1644 + ext2_badblocks_list *bb_list);
37.1645 +
37.1646 +/* read_bb_file.c */
37.1647 +extern errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f,
37.1648 + ext2_badblocks_list *bb_list,
37.1649 + void *priv_data,
37.1650 + void (*invalid)(ext2_filsys fs,
37.1651 + blk_t blk,
37.1652 + char *badstr,
37.1653 + void *priv_data));
37.1654 +extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
37.1655 + ext2_badblocks_list *bb_list,
37.1656 + void (*invalid)(ext2_filsys fs,
37.1657 + blk_t blk));
37.1658 +
37.1659 +/* res_gdt.c */
37.1660 +extern errcode_t ext2fs_create_resize_inode(ext2_filsys fs);
37.1661 +
37.1662 +/*sha256.c */
37.1663 +#define EXT2FS_SHA256_LENGTH 32
37.1664 +#if 0
37.1665 +extern void ext2fs_sha256(const unsigned char *in, unsigned long in_size,
37.1666 + unsigned char out[EXT2FS_SHA256_LENGTH]);
37.1667 +#endif
37.1668 +
37.1669 +/* sha512.c */
37.1670 +#define EXT2FS_SHA512_LENGTH 64
37.1671 +extern void ext2fs_sha512(const unsigned char *in, unsigned long in_size,
37.1672 + unsigned char out[EXT2FS_SHA512_LENGTH]);
37.1673 +
37.1674 +/* swapfs.c */
37.1675 +extern errcode_t ext2fs_dirent_swab_in2(ext2_filsys fs, char *buf, size_t size,
37.1676 + int flags);
37.1677 +extern errcode_t ext2fs_dirent_swab_in(ext2_filsys fs, char *buf, int flags);
37.1678 +extern errcode_t ext2fs_dirent_swab_out2(ext2_filsys fs, char *buf, size_t size,
37.1679 + int flags);
37.1680 +extern errcode_t ext2fs_dirent_swab_out(ext2_filsys fs, char *buf, int flags);
37.1681 +extern void ext2fs_swap_ext_attr(char *to, char *from, int bufsize,
37.1682 + int has_header);
37.1683 +extern void ext2fs_swap_ext_attr_header(struct ext2_ext_attr_header *to_header,
37.1684 + struct ext2_ext_attr_header *from_hdr);
37.1685 +extern void ext2fs_swap_ext_attr_entry(struct ext2_ext_attr_entry *to_entry,
37.1686 + struct ext2_ext_attr_entry *from_entry);
37.1687 +extern void ext2fs_swap_super(struct ext2_super_block * super);
37.1688 +extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp);
37.1689 +extern void ext2fs_swap_group_desc2(ext2_filsys, struct ext2_group_desc *gdp);
37.1690 +extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
37.1691 + struct ext2_inode_large *f, int hostorder,
37.1692 + int bufsize);
37.1693 +extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t,
37.1694 + struct ext2_inode *f, int hostorder);
37.1695 +extern void ext2fs_swap_mmp(struct mmp_struct *mmp);
37.1696 +
37.1697 +/* unix_io.c */
37.1698 +extern int ext2fs_open_file(const char *pathname, int flags, mode_t mode);
37.1699 +extern int ext2fs_stat(const char *path, ext2fs_struct_stat *buf);
37.1700 +extern int ext2fs_fstat(int fd, ext2fs_struct_stat *buf);
37.1701 +
37.1702 +/* valid_blk.c */
37.1703 +extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
37.1704 +extern int ext2fs_inode_has_valid_blocks2(ext2_filsys fs,
37.1705 + struct ext2_inode *inode);
37.1706 +
37.1707 +/* version.c */
37.1708 +extern int ext2fs_parse_version_string(const char *ver_string);
37.1709 +extern int ext2fs_get_library_version(const char **ver_string,
37.1710 + const char **date_string);
37.1711 +
37.1712 +/* write_bb_file.c */
37.1713 +extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
37.1714 + unsigned int flags,
37.1715 + FILE *f);
37.1716 +
37.1717 +
37.1718 +/* inline functions */
37.1719 +#ifdef NO_INLINE_FUNCS
37.1720 +extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr);
37.1721 +extern errcode_t ext2fs_get_memzero(unsigned long size, void *ptr);
37.1722 +extern errcode_t ext2fs_get_array(unsigned long count,
37.1723 + unsigned long size, void *ptr);
37.1724 +extern errcode_t ext2fs_get_arrayzero(unsigned long count,
37.1725 + unsigned long size, void *ptr);
37.1726 +extern errcode_t ext2fs_free_mem(void *ptr);
37.1727 +extern errcode_t ext2fs_resize_mem(unsigned long old_size,
37.1728 + unsigned long size, void *ptr);
37.1729 +extern void ext2fs_mark_super_dirty(ext2_filsys fs);
37.1730 +extern void ext2fs_mark_changed(ext2_filsys fs);
37.1731 +extern int ext2fs_test_changed(ext2_filsys fs);
37.1732 +extern void ext2fs_mark_valid(ext2_filsys fs);
37.1733 +extern void ext2fs_unmark_valid(ext2_filsys fs);
37.1734 +extern int ext2fs_test_valid(ext2_filsys fs);
37.1735 +extern void ext2fs_mark_ib_dirty(ext2_filsys fs);
37.1736 +extern void ext2fs_mark_bb_dirty(ext2_filsys fs);
37.1737 +extern int ext2fs_test_ib_dirty(ext2_filsys fs);
37.1738 +extern int ext2fs_test_bb_dirty(ext2_filsys fs);
37.1739 +extern dgrp_t ext2fs_group_of_blk(ext2_filsys fs, blk_t blk);
37.1740 +extern dgrp_t ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino);
37.1741 +extern blk_t ext2fs_group_first_block(ext2_filsys fs, dgrp_t group);
37.1742 +extern blk_t ext2fs_group_last_block(ext2_filsys fs, dgrp_t group);
37.1743 +extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
37.1744 + struct ext2_inode *inode);
37.1745 +extern int ext2fs_htree_intnode_maxrecs(ext2_filsys fs, int blocks);
37.1746 +extern unsigned int ext2fs_div_ceil(unsigned int a, unsigned int b);
37.1747 +extern __u64 ext2fs_div64_ceil(__u64 a, __u64 b);
37.1748 +extern int ext2fs_dirent_name_len(const struct ext2_dir_entry *entry);
37.1749 +extern void ext2fs_dirent_set_name_len(struct ext2_dir_entry *entry, int len);
37.1750 +extern int ext2fs_dirent_file_type(const struct ext2_dir_entry *entry);
37.1751 +extern void ext2fs_dirent_set_file_type(struct ext2_dir_entry *entry, int type);
37.1752 +extern struct ext2_inode *ext2fs_inode(struct ext2_inode_large * large_inode);
37.1753 +extern const struct ext2_inode *ext2fs_const_inode(const struct ext2_inode_large * large_inode);
37.1754 +
37.1755 +#endif
37.1756 +
37.1757 +/*
37.1758 + * The actual inlined functions definitions themselves...
37.1759 + *
37.1760 + * If NO_INLINE_FUNCS is defined, then we won't try to do inline
37.1761 + * functions at all!
37.1762 + */
37.1763 +#if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
37.1764 +#ifdef INCLUDE_INLINE_FUNCS
37.1765 +#define _INLINE_ extern
37.1766 +#else
37.1767 +#if (__STDC_VERSION__ >= 199901L)
37.1768 +#define _INLINE_ inline
37.1769 +#else
37.1770 +#ifdef __GNUC__
37.1771 +#define _INLINE_ extern __inline__
37.1772 +#else /* For Watcom C */
37.1773 +#define _INLINE_ extern inline
37.1774 +#endif /* __GNUC__ */
37.1775 +#endif /* __STDC_VERSION__ >= 199901L */
37.1776 +#endif
37.1777 +
37.1778 +#ifndef EXT2_CUSTOM_MEMORY_ROUTINES
37.1779 +#include <string.h>
37.1780 +/*
37.1781 + * Allocate memory. The 'ptr' arg must point to a pointer.
37.1782 + */
37.1783 +_INLINE_ errcode_t ext2fs_get_mem(unsigned long size, void *ptr)
37.1784 +{
37.1785 + void *pp;
37.1786 +
37.1787 + pp = malloc(size);
37.1788 + if (!pp)
37.1789 + return EXT2_ET_NO_MEMORY;
37.1790 + memcpy(ptr, &pp, sizeof (pp));
37.1791 + return 0;
37.1792 +}
37.1793 +
37.1794 +_INLINE_ errcode_t ext2fs_get_memzero(unsigned long size, void *ptr)
37.1795 +{
37.1796 + void *pp;
37.1797 +
37.1798 + pp = malloc(size);
37.1799 + if (!pp)
37.1800 + return EXT2_ET_NO_MEMORY;
37.1801 + memset(pp, 0, size);
37.1802 + memcpy(ptr, &pp, sizeof(pp));
37.1803 + return 0;
37.1804 +}
37.1805 +
37.1806 +_INLINE_ errcode_t ext2fs_get_array(unsigned long count, unsigned long size, void *ptr)
37.1807 +{
37.1808 + if (count && (~0UL)/count < size)
37.1809 + return EXT2_ET_NO_MEMORY;
37.1810 + return ext2fs_get_mem(count*size, ptr);
37.1811 +}
37.1812 +
37.1813 +_INLINE_ errcode_t ext2fs_get_arrayzero(unsigned long count,
37.1814 + unsigned long size, void *ptr)
37.1815 +{
37.1816 + void *pp;
37.1817 +
37.1818 + if (count && (~0UL)/count < size)
37.1819 + return EXT2_ET_NO_MEMORY;
37.1820 + pp = calloc(count, size);
37.1821 + if (!pp)
37.1822 + return EXT2_ET_NO_MEMORY;
37.1823 + memcpy(ptr, &pp, sizeof(pp));
37.1824 + return 0;
37.1825 +}
37.1826 +
37.1827 +/*
37.1828 + * Free memory. The 'ptr' arg must point to a pointer.
37.1829 + */
37.1830 +_INLINE_ errcode_t ext2fs_free_mem(void *ptr)
37.1831 +{
37.1832 + void *p;
37.1833 +
37.1834 + memcpy(&p, ptr, sizeof(p));
37.1835 + free(p);
37.1836 + p = 0;
37.1837 + memcpy(ptr, &p, sizeof(p));
37.1838 + return 0;
37.1839 +}
37.1840 +
37.1841 +/*
37.1842 + * Resize memory. The 'ptr' arg must point to a pointer.
37.1843 + */
37.1844 +_INLINE_ errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_size,
37.1845 + unsigned long size, void *ptr)
37.1846 +{
37.1847 + void *p;
37.1848 +
37.1849 + /* Use "memcpy" for pointer assignments here to avoid problems
37.1850 + * with C99 strict type aliasing rules. */
37.1851 + memcpy(&p, ptr, sizeof(p));
37.1852 + p = realloc(p, size);
37.1853 + if (!p)
37.1854 + return EXT2_ET_NO_MEMORY;
37.1855 + memcpy(ptr, &p, sizeof(p));
37.1856 + return 0;
37.1857 +}
37.1858 +#endif /* Custom memory routines */
37.1859 +
37.1860 +/*
37.1861 + * Mark a filesystem superblock as dirty
37.1862 + */
37.1863 +_INLINE_ void ext2fs_mark_super_dirty(ext2_filsys fs)
37.1864 +{
37.1865 + fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_CHANGED;
37.1866 +}
37.1867 +
37.1868 +/*
37.1869 + * Mark a filesystem as changed
37.1870 + */
37.1871 +_INLINE_ void ext2fs_mark_changed(ext2_filsys fs)
37.1872 +{
37.1873 + fs->flags |= EXT2_FLAG_CHANGED;
37.1874 +}
37.1875 +
37.1876 +/*
37.1877 + * Check to see if a filesystem has changed
37.1878 + */
37.1879 +_INLINE_ int ext2fs_test_changed(ext2_filsys fs)
37.1880 +{
37.1881 + return (fs->flags & EXT2_FLAG_CHANGED);
37.1882 +}
37.1883 +
37.1884 +/*
37.1885 + * Mark a filesystem as valid
37.1886 + */
37.1887 +_INLINE_ void ext2fs_mark_valid(ext2_filsys fs)
37.1888 +{
37.1889 + fs->flags |= EXT2_FLAG_VALID;
37.1890 +}
37.1891 +
37.1892 +/*
37.1893 + * Mark a filesystem as NOT valid
37.1894 + */
37.1895 +_INLINE_ void ext2fs_unmark_valid(ext2_filsys fs)
37.1896 +{
37.1897 + fs->flags &= ~EXT2_FLAG_VALID;
37.1898 +}
37.1899 +
37.1900 +/*
37.1901 + * Check to see if a filesystem is valid
37.1902 + */
37.1903 +_INLINE_ int ext2fs_test_valid(ext2_filsys fs)
37.1904 +{
37.1905 + return (fs->flags & EXT2_FLAG_VALID);
37.1906 +}
37.1907 +
37.1908 +/*
37.1909 + * Mark the inode bitmap as dirty
37.1910 + */
37.1911 +_INLINE_ void ext2fs_mark_ib_dirty(ext2_filsys fs)
37.1912 +{
37.1913 + fs->flags |= EXT2_FLAG_IB_DIRTY | EXT2_FLAG_CHANGED;
37.1914 +}
37.1915 +
37.1916 +/*
37.1917 + * Mark the block bitmap as dirty
37.1918 + */
37.1919 +_INLINE_ void ext2fs_mark_bb_dirty(ext2_filsys fs)
37.1920 +{
37.1921 + fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_CHANGED;
37.1922 +}
37.1923 +
37.1924 +/*
37.1925 + * Check to see if a filesystem's inode bitmap is dirty
37.1926 + */
37.1927 +_INLINE_ int ext2fs_test_ib_dirty(ext2_filsys fs)
37.1928 +{
37.1929 + return (fs->flags & EXT2_FLAG_IB_DIRTY);
37.1930 +}
37.1931 +
37.1932 +/*
37.1933 + * Check to see if a filesystem's block bitmap is dirty
37.1934 + */
37.1935 +_INLINE_ int ext2fs_test_bb_dirty(ext2_filsys fs)
37.1936 +{
37.1937 + return (fs->flags & EXT2_FLAG_BB_DIRTY);
37.1938 +}
37.1939 +
37.1940 +/*
37.1941 + * Return the group # of a block
37.1942 + */
37.1943 +_INLINE_ dgrp_t ext2fs_group_of_blk(ext2_filsys fs, blk_t blk)
37.1944 +{
37.1945 + return ext2fs_group_of_blk2(fs, blk);
37.1946 +}
37.1947 +/*
37.1948 + * Return the group # of an inode number
37.1949 + */
37.1950 +_INLINE_ dgrp_t ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino)
37.1951 +{
37.1952 + return (ino - 1) / fs->super->s_inodes_per_group;
37.1953 +}
37.1954 +
37.1955 +/*
37.1956 + * Return the first block (inclusive) in a group
37.1957 + */
37.1958 +_INLINE_ blk_t ext2fs_group_first_block(ext2_filsys fs, dgrp_t group)
37.1959 +{
37.1960 + return (blk_t) ext2fs_group_first_block2(fs, group);
37.1961 +}
37.1962 +
37.1963 +/*
37.1964 + * Return the last block (inclusive) in a group
37.1965 + */
37.1966 +_INLINE_ blk_t ext2fs_group_last_block(ext2_filsys fs, dgrp_t group)
37.1967 +{
37.1968 + return (blk_t) ext2fs_group_last_block2(fs, group);
37.1969 +}
37.1970 +
37.1971 +_INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
37.1972 + struct ext2_inode *inode)
37.1973 +{
37.1974 + return (blk_t) ext2fs_inode_data_blocks2(fs, inode);
37.1975 +}
37.1976 +
37.1977 +_INLINE_ int ext2fs_htree_intnode_maxrecs(ext2_filsys fs, int blocks)
37.1978 +{
37.1979 + return blocks * ((fs->blocksize - 8) / sizeof(struct ext2_dx_entry));
37.1980 +}
37.1981 +
37.1982 +/*
37.1983 + * This is an efficient, overflow safe way of calculating ceil((1.0 * a) / b)
37.1984 + */
37.1985 +_INLINE_ unsigned int ext2fs_div_ceil(unsigned int a, unsigned int b)
37.1986 +{
37.1987 + if (!a)
37.1988 + return 0;
37.1989 + return ((a - 1) / b) + 1;
37.1990 +}
37.1991 +
37.1992 +_INLINE_ __u64 ext2fs_div64_ceil(__u64 a, __u64 b)
37.1993 +{
37.1994 + if (!a)
37.1995 + return 0;
37.1996 + return ((a - 1) / b) + 1;
37.1997 +}
37.1998 +
37.1999 +_INLINE_ int ext2fs_dirent_name_len(const struct ext2_dir_entry *entry)
37.2000 +{
37.2001 + return entry->name_len & 0xff;
37.2002 +}
37.2003 +
37.2004 +_INLINE_ void ext2fs_dirent_set_name_len(struct ext2_dir_entry *entry, int len)
37.2005 +{
37.2006 + entry->name_len = (entry->name_len & 0xff00) | (len & 0xff);
37.2007 +}
37.2008 +
37.2009 +_INLINE_ int ext2fs_dirent_file_type(const struct ext2_dir_entry *entry)
37.2010 +{
37.2011 + return entry->name_len >> 8;
37.2012 +}
37.2013 +
37.2014 +_INLINE_ void ext2fs_dirent_set_file_type(struct ext2_dir_entry *entry, int type)
37.2015 +{
37.2016 + entry->name_len = (entry->name_len & 0xff) | (type << 8);
37.2017 +}
37.2018 +
37.2019 +_INLINE_ struct ext2_inode *ext2fs_inode(struct ext2_inode_large * large_inode)
37.2020 +{
37.2021 + /* It is always safe to convert large inode to a small inode */
37.2022 + return (struct ext2_inode *) large_inode;
37.2023 +}
37.2024 +
37.2025 +_INLINE_ const struct ext2_inode *
37.2026 +ext2fs_const_inode(const struct ext2_inode_large * large_inode)
37.2027 +{
37.2028 + /* It is always safe to convert large inode to a small inode */
37.2029 + return (const struct ext2_inode *) large_inode;
37.2030 +}
37.2031 +
37.2032 +#undef _INLINE_
37.2033 +#endif
37.2034 +
37.2035 +/* htree levels for ext4 */
37.2036 +#define EXT4_HTREE_LEVEL_COMPAT 2
37.2037 +#define EXT4_HTREE_LEVEL 3
37.2038 +
37.2039 +static inline unsigned int ext2_dir_htree_level(ext2_filsys fs)
37.2040 +{
37.2041 + if (ext2fs_has_feature_largedir(fs->super))
37.2042 + return EXT4_HTREE_LEVEL;
37.2043 +
37.2044 + return EXT4_HTREE_LEVEL_COMPAT;
37.2045 +}
37.2046 +
37.2047 +#ifdef __cplusplus
37.2048 +}
37.2049 +#endif
37.2050 +
37.2051 +#endif /* _EXT2FS_EXT2FS_H */
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/libext2fs/include/libext2fs/ext2fs/ext2fsP.h Wed Aug 25 01:28:08 2021 +0200
38.3 @@ -0,0 +1,191 @@
38.4 +/*
38.5 + * ext2fsP.h --- private header file for ext2 library
38.6 + *
38.7 + * Copyright (C) 1997 Theodore Ts'o.
38.8 + *
38.9 + * %Begin-Header%
38.10 + * This file may be redistributed under the terms of the GNU Library
38.11 + * General Public License, version 2.
38.12 + * %End-Header%
38.13 + */
38.14 +
38.15 +#if HAVE_SYS_STAT_H
38.16 +#include <sys/stat.h>
38.17 +#endif
38.18 +
38.19 +#include "ext2fs.h"
38.20 +
38.21 +#define EXT2FS_MAX_NESTED_LINKS 8
38.22 +
38.23 +static inline int ext2fsP_is_disk_device(mode_t mode)
38.24 +{
38.25 +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
38.26 + return S_ISBLK(mode) || S_ISCHR(mode);
38.27 +#else
38.28 + return S_ISBLK(mode);
38.29 +#endif
38.30 +}
38.31 +
38.32 +/*
38.33 + * Badblocks list
38.34 + */
38.35 +struct ext2_struct_u32_list {
38.36 + int magic;
38.37 + int num;
38.38 + int size;
38.39 + __u32 *list;
38.40 + int badblocks_flags;
38.41 +};
38.42 +
38.43 +struct ext2_struct_u32_iterate {
38.44 + int magic;
38.45 + ext2_u32_list bb;
38.46 + int ptr;
38.47 +};
38.48 +
38.49 +
38.50 +/*
38.51 + * Directory block iterator definition
38.52 + */
38.53 +struct ext2_struct_dblist {
38.54 + int magic;
38.55 + ext2_filsys fs;
38.56 + unsigned long long size;
38.57 + unsigned long long count;
38.58 + int sorted;
38.59 + struct ext2_db_entry2 * list;
38.60 +};
38.61 +
38.62 +/*
38.63 + * For directory iterators
38.64 + */
38.65 +struct dir_context {
38.66 + ext2_ino_t dir;
38.67 + int flags;
38.68 + char *buf;
38.69 + unsigned int buflen;
38.70 + int (*func)(ext2_ino_t dir,
38.71 + int entry,
38.72 + struct ext2_dir_entry *dirent,
38.73 + int offset,
38.74 + int blocksize,
38.75 + char *buf,
38.76 + void *priv_data);
38.77 + void *priv_data;
38.78 + errcode_t errcode;
38.79 +};
38.80 +
38.81 +/*
38.82 + * Inode cache structure
38.83 + */
38.84 +struct ext2_inode_cache {
38.85 + void * buffer;
38.86 + blk64_t buffer_blk;
38.87 + int cache_last;
38.88 + unsigned int cache_size;
38.89 + int refcount;
38.90 + struct ext2_inode_cache_ent *cache;
38.91 +};
38.92 +
38.93 +struct ext2_inode_cache_ent {
38.94 + ext2_ino_t ino;
38.95 + struct ext2_inode *inode;
38.96 +};
38.97 +
38.98 +/* Function prototypes */
38.99 +
38.100 +extern int ext2fs_process_dir_block(ext2_filsys fs,
38.101 + blk64_t *blocknr,
38.102 + e2_blkcnt_t blockcnt,
38.103 + blk64_t ref_block,
38.104 + int ref_offset,
38.105 + void *priv_data);
38.106 +
38.107 +extern errcode_t ext2fs_inline_data_ea_remove(ext2_filsys fs, ext2_ino_t ino);
38.108 +extern errcode_t ext2fs_inline_data_expand(ext2_filsys fs, ext2_ino_t ino);
38.109 +extern int ext2fs_inline_data_dir_iterate(ext2_filsys fs,
38.110 + ext2_ino_t ino,
38.111 + void *priv_data);
38.112 +
38.113 +/* Generic numeric progress meter */
38.114 +
38.115 +struct ext2fs_numeric_progress_struct {
38.116 + __u64 max;
38.117 + int log_max;
38.118 + int skip_progress;
38.119 +};
38.120 +
38.121 +/*
38.122 + * progress callback functions
38.123 + */
38.124 +struct ext2fs_progress_ops {
38.125 + void (*init)(ext2_filsys fs,
38.126 + struct ext2fs_numeric_progress_struct * progress,
38.127 + const char *label, __u64 max);
38.128 + void (*update)(ext2_filsys fs,
38.129 + struct ext2fs_numeric_progress_struct * progress,
38.130 + __u64 val);
38.131 + void (*close)(ext2_filsys fs,
38.132 + struct ext2fs_numeric_progress_struct * progress,
38.133 + const char *message);
38.134 +};
38.135 +
38.136 +extern struct ext2fs_progress_ops ext2fs_numeric_progress_ops;
38.137 +
38.138 +extern void ext2fs_numeric_progress_init(ext2_filsys fs,
38.139 + struct ext2fs_numeric_progress_struct * progress,
38.140 + const char *label, __u64 max);
38.141 +extern void ext2fs_numeric_progress_update(ext2_filsys fs,
38.142 + struct ext2fs_numeric_progress_struct * progress,
38.143 + __u64 val);
38.144 +extern void ext2fs_numeric_progress_close(ext2_filsys fs,
38.145 + struct ext2fs_numeric_progress_struct * progress,
38.146 + const char *message);
38.147 +
38.148 +/*
38.149 + * 64-bit bitmap support
38.150 + */
38.151 +
38.152 +extern errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
38.153 + int type, __u64 start, __u64 end,
38.154 + __u64 real_end,
38.155 + const char * description,
38.156 + ext2fs_generic_bitmap *bmap);
38.157 +
38.158 +extern void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap);
38.159 +
38.160 +extern errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src,
38.161 + ext2fs_generic_bitmap *dest);
38.162 +
38.163 +extern errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap,
38.164 + __u64 new_end,
38.165 + __u64 new_real_end);
38.166 +extern errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap,
38.167 + errcode_t neq,
38.168 + __u64 end, __u64 *oend);
38.169 +extern int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap,
38.170 + __u64 arg);
38.171 +extern int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap,
38.172 + __u64 arg);
38.173 +extern int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap,
38.174 + __u64 arg);
38.175 +extern errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bitmap,
38.176 + __u64 start, unsigned int num,
38.177 + void *in);
38.178 +extern errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bitmap,
38.179 + __u64 start, unsigned int num,
38.180 + void *out);
38.181 +extern void ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap,const char *func);
38.182 +
38.183 +extern int ext2fs_mem_is_zero(const char *mem, size_t len);
38.184 +
38.185 +extern int ext2fs_file_block_offset_too_big(ext2_filsys fs,
38.186 + struct ext2_inode *inode,
38.187 + blk64_t offset);
38.188 +
38.189 +/* atexit support */
38.190 +typedef void (*ext2_exit_fn)(void *);
38.191 +errcode_t ext2fs_add_exit_fn(ext2_exit_fn fn, void *data);
38.192 +errcode_t ext2fs_remove_exit_fn(ext2_exit_fn fn, void *data);
38.193 +
38.194 +#define EXT2FS_BUILD_BUG_ON(cond) ((void)sizeof(char[1 - 2*!!(cond)]))
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/libext2fs/include/libext2fs/ext2fs/ext3_extents.h Wed Aug 25 01:28:08 2021 +0200
39.3 @@ -0,0 +1,127 @@
39.4 +/*
39.5 + * Copyright (c) 2003,2004 Cluster File Systems, Inc, info@clusterfs.com
39.6 + * Written by Alex Tomas <alex@clusterfs.com>
39.7 + *
39.8 + * %Begin-Header%
39.9 + * This file may be redistributed under the terms of the GNU Library
39.10 + * General Public License, version 2.
39.11 + * %End-Header%
39.12 + */
39.13 +
39.14 +#ifndef _LINUX_EXT3_EXTENTS
39.15 +#define _LINUX_EXT3_EXTENTS
39.16 +
39.17 +/*
39.18 + * ext3_inode has i_block array (total 60 bytes)
39.19 + * first 4 bytes are used to store:
39.20 + * - tree depth (0 mean there is no tree yet. all extents in the inode)
39.21 + * - number of alive extents in the inode
39.22 + */
39.23 +
39.24 +/*
39.25 + * This is extent tail on-disk structure.
39.26 + * All other extent structures are 12 bytes long. It turns out that
39.27 + * block_size % 12 >= 4 for at least all powers of 2 greater than 512, which
39.28 + * covers all valid ext4 block sizes. Therefore, this tail structure can be
39.29 + * crammed into the end of the block without having to rebalance the tree.
39.30 + */
39.31 +struct ext3_extent_tail {
39.32 + __le32 et_checksum; /* crc32c(uuid+inum+extent_block) */
39.33 +};
39.34 +
39.35 +/*
39.36 + * this is extent on-disk structure
39.37 + * it's used at the bottom of the tree
39.38 + */
39.39 +struct ext3_extent {
39.40 + __le32 ee_block; /* first logical block extent covers */
39.41 + __le16 ee_len; /* number of blocks covered by extent */
39.42 + __le16 ee_start_hi; /* high 16 bits of physical block */
39.43 + __le32 ee_start; /* low 32 bigs of physical block */
39.44 +};
39.45 +
39.46 +/*
39.47 + * this is index on-disk structure
39.48 + * it's used at all the levels, but the bottom
39.49 + */
39.50 +struct ext3_extent_idx {
39.51 + __le32 ei_block; /* index covers logical blocks from 'block' */
39.52 + __le32 ei_leaf; /* pointer to the physical block of the next *
39.53 + * level. leaf or next index could bet here */
39.54 + __le16 ei_leaf_hi; /* high 16 bits of physical block */
39.55 + __le16 ei_unused;
39.56 +};
39.57 +
39.58 +/*
39.59 + * each block (leaves and indexes), even inode-stored has header
39.60 + */
39.61 +struct ext3_extent_header {
39.62 + __le16 eh_magic; /* probably will support different formats */
39.63 + __le16 eh_entries; /* number of valid entries */
39.64 + __le16 eh_max; /* capacity of store in entries */
39.65 + __le16 eh_depth; /* has tree real underlying blocks? */
39.66 + __le32 eh_generation; /* generation of the tree */
39.67 +};
39.68 +
39.69 +#define EXT3_EXT_MAGIC 0xf30a
39.70 +
39.71 +/*
39.72 + * array of ext3_ext_path contains path to some extent
39.73 + * creation/lookup routines use it for traversal/splitting/etc
39.74 + * truncate uses it to simulate recursive walking
39.75 + */
39.76 +struct ext3_ext_path {
39.77 + __u32 p_block;
39.78 + __u16 p_depth;
39.79 + struct ext3_extent *p_ext;
39.80 + struct ext3_extent_idx *p_idx;
39.81 + struct ext3_extent_header *p_hdr;
39.82 + struct buffer_head *p_bh;
39.83 +};
39.84 +
39.85 +/*
39.86 + * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
39.87 + * initialized extent. This is 2^15 and not (2^16 - 1), since we use the
39.88 + * MSB of ee_len field in the extent datastructure to signify if this
39.89 + * particular extent is an initialized extent or an uninitialized (i.e.
39.90 + * preallocated).
39.91 + * EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an
39.92 + * uninitialized extent.
39.93 + * If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an
39.94 + * uninitialized one. In other words, if MSB of ee_len is set, it is an
39.95 + * uninitialized extent with only one special scenario when ee_len = 0x8000.
39.96 + * In this case we can not have an uninitialized extent of zero length and
39.97 + * thus we make it as a special case of initialized extent with 0x8000 length.
39.98 + * This way we get better extent-to-group alignment for initialized extents.
39.99 + * Hence, the maximum number of blocks we can have in an *initialized*
39.100 + * extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767).
39.101 + */
39.102 +#define EXT_INIT_MAX_LEN (1UL << 15)
39.103 +#define EXT_UNINIT_MAX_LEN (EXT_INIT_MAX_LEN - 1)
39.104 +#define EXT_MAX_EXTENT_LBLK (((__u64) 1 << 32) - 1)
39.105 +#define EXT_MAX_EXTENT_PBLK (((__u64) 1 << 48) - 1)
39.106 +
39.107 +#define EXT_FIRST_EXTENT(__hdr__) \
39.108 + ((struct ext3_extent *) (((char *) (__hdr__)) + \
39.109 + sizeof(struct ext3_extent_header)))
39.110 +#define EXT_FIRST_INDEX(__hdr__) \
39.111 + ((struct ext3_extent_idx *) (((char *) (__hdr__)) + \
39.112 + sizeof(struct ext3_extent_header)))
39.113 +#define EXT_HAS_FREE_INDEX(__path__) \
39.114 + (ext2fs_le16_to_cpu((__path__)->p_hdr->eh_entries) < \
39.115 + ext2fs_le16_to_cpu((__path__)->p_hdr->eh_max))
39.116 +#define EXT_LAST_EXTENT(__hdr__) \
39.117 + (EXT_FIRST_EXTENT((__hdr__)) + \
39.118 + ext2fs_le16_to_cpu((__hdr__)->eh_entries) - 1)
39.119 +#define EXT_LAST_INDEX(__hdr__) \
39.120 + (EXT_FIRST_INDEX((__hdr__)) + \
39.121 + ext2fs_le16_to_cpu((__hdr__)->eh_entries) - 1)
39.122 +#define EXT_MAX_EXTENT(__hdr__) \
39.123 + (EXT_FIRST_EXTENT((__hdr__)) + \
39.124 + ext2fs_le16_to_cpu((__hdr__)->eh_max) - 1)
39.125 +#define EXT_MAX_INDEX(__hdr__) \
39.126 + (EXT_FIRST_INDEX((__hdr__)) + \
39.127 + ext2fs_le16_to_cpu((__hdr__)->eh_max) - 1)
39.128 +
39.129 +#endif /* _LINUX_EXT3_EXTENTS */
39.130 +
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/libext2fs/include/libext2fs/ext2fs/ext4_acl.h Wed Aug 25 01:28:08 2021 +0200
40.3 @@ -0,0 +1,62 @@
40.4 +/*
40.5 + * Ext4's on-disk acl format. From linux/fs/ext4/acl.h
40.6 + */
40.7 +
40.8 +#define EXT4_ACL_VERSION 0x0001
40.9 +
40.10 +/* 23.2.5 acl_tag_t values */
40.11 +
40.12 +#define ACL_UNDEFINED_TAG (0x00)
40.13 +#define ACL_USER_OBJ (0x01)
40.14 +#define ACL_USER (0x02)
40.15 +#define ACL_GROUP_OBJ (0x04)
40.16 +#define ACL_GROUP (0x08)
40.17 +#define ACL_MASK (0x10)
40.18 +#define ACL_OTHER (0x20)
40.19 +
40.20 +/* 23.3.6 acl_type_t values */
40.21 +
40.22 +#define ACL_TYPE_ACCESS (0x8000)
40.23 +#define ACL_TYPE_DEFAULT (0x4000)
40.24 +
40.25 +/* 23.2.7 ACL qualifier constants */
40.26 +
40.27 +#define ACL_UNDEFINED_ID ((id_t)-1)
40.28 +
40.29 +typedef struct {
40.30 + __le16 e_tag;
40.31 + __le16 e_perm;
40.32 + __le32 e_id;
40.33 + } ext4_acl_entry;
40.34 +
40.35 +typedef struct {
40.36 + __le16 e_tag;
40.37 + __le16 e_perm;
40.38 +} ext4_acl_entry_short;
40.39 +
40.40 +typedef struct {
40.41 + __le32 a_version;
40.42 +} ext4_acl_header;
40.43 +
40.44 +
40.45 +/* Supported ACL a_version fields */
40.46 + #define POSIX_ACL_XATTR_VERSION 0x0002
40.47 +
40.48 +typedef struct {
40.49 + __le16 e_tag;
40.50 + __le16 e_perm;
40.51 + __le32 e_id;
40.52 +} posix_acl_xattr_entry;
40.53 +
40.54 +typedef struct {
40.55 + __le32 a_version;
40.56 +#if __GNUC_PREREQ (4, 8)
40.57 +#pragma GCC diagnostic push
40.58 +#pragma GCC diagnostic ignored "-Wpedantic"
40.59 +#endif
40.60 + posix_acl_xattr_entry a_entries[0];
40.61 +#if __GNUC_PREREQ (4, 8)
40.62 +#pragma GCC diagnostic pop
40.63 +#endif
40.64 +} posix_acl_xattr_header;
40.65 +
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/libext2fs/include/libext2fs/ext2fs/hashmap.h Wed Aug 25 01:28:08 2021 +0200
41.3 @@ -0,0 +1,54 @@
41.4 +#ifndef HASHMAP_H
41.5 +# define HASHMAP_H
41.6 +
41.7 +# include <stdlib.h>
41.8 +# include <stdint.h>
41.9 +
41.10 +#ifndef __GNUC_PREREQ
41.11 +#if defined(__GNUC__) && defined(__GNUC_MINOR__)
41.12 +#define __GNUC_PREREQ(maj, min) \
41.13 + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
41.14 +#else
41.15 +#define __GNUC_PREREQ(maj, min) 0
41.16 +#endif
41.17 +#endif
41.18 +
41.19 +struct ext2fs_hashmap {
41.20 + uint32_t size;
41.21 + uint32_t(*hash)(const void *key, size_t len);
41.22 + void(*free)(void*);
41.23 + struct ext2fs_hashmap_entry *first;
41.24 + struct ext2fs_hashmap_entry *last;
41.25 + struct ext2fs_hashmap_entry {
41.26 + void *data;
41.27 + const void *key;
41.28 + size_t key_len;
41.29 + struct ext2fs_hashmap_entry *next;
41.30 + struct ext2fs_hashmap_entry *list_next;
41.31 + struct ext2fs_hashmap_entry *list_prev;
41.32 +#if __GNUC_PREREQ (4, 8)
41.33 +#pragma GCC diagnostic push
41.34 +#pragma GCC diagnostic ignored "-Wpedantic"
41.35 +#endif
41.36 + } *entries[0];
41.37 +#if __GNUC_PREREQ (4, 8)
41.38 +#pragma GCC diagnostic pop
41.39 +#endif
41.40 +};
41.41 +
41.42 +struct ext2fs_hashmap *ext2fs_hashmap_create(
41.43 + uint32_t(*hash_fct)(const void*, size_t),
41.44 + void(*free_fct)(void*), size_t size);
41.45 +void ext2fs_hashmap_add(struct ext2fs_hashmap *h, void *data, const void *key,
41.46 + size_t key_len);
41.47 +void *ext2fs_hashmap_lookup(struct ext2fs_hashmap *h, const void *key,
41.48 + size_t key_len);
41.49 +void *ext2fs_hashmap_iter_in_order(struct ext2fs_hashmap *h,
41.50 + struct ext2fs_hashmap_entry **it);
41.51 +void ext2fs_hashmap_del(struct ext2fs_hashmap *h,
41.52 + struct ext2fs_hashmap_entry *e);
41.53 +void ext2fs_hashmap_free(struct ext2fs_hashmap *h);
41.54 +
41.55 +uint32_t ext2fs_djb2_hash(const void *str, size_t size);
41.56 +
41.57 +#endif /* !HASHMAP_H */
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/libext2fs/include/libext2fs/ext2fs/kernel-jbd.h Wed Aug 25 01:28:08 2021 +0200
42.3 @@ -0,0 +1,461 @@
42.4 +/*
42.5 + * linux/include/linux/jbd.h
42.6 + *
42.7 + * Written by Stephen C. Tweedie <sct@redhat.com>
42.8 + *
42.9 + * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved
42.10 + *
42.11 + * This file is part of the Linux kernel and is made available under
42.12 + * the terms of the GNU General Public License, version 2, or at your
42.13 + * option, any later version, incorporated herein by reference.
42.14 + *
42.15 + * Definitions for transaction data structures for the buffer cache
42.16 + * filesystem journaling support.
42.17 + */
42.18 +
42.19 +#ifndef _LINUX_JBD_H
42.20 +#define _LINUX_JBD_H
42.21 +
42.22 +#include "jfs_compat.h"
42.23 +#define JFS_DEBUG
42.24 +#define jfs_debug jbd_debug
42.25 +
42.26 +#ifndef __GNUC__
42.27 +#define __FUNCTION__ ""
42.28 +#endif
42.29 +
42.30 +#define journal_oom_retry 1
42.31 +
42.32 +#ifdef __STDC__
42.33 +#ifdef CONFIG_JBD_DEBUG
42.34 +/*
42.35 + * Define JBD_EXPENSIVE_CHECKING to enable more expensive internal
42.36 + * consistency checks. By default we don't do this unless
42.37 + * CONFIG_JBD_DEBUG is on.
42.38 + */
42.39 +#define JBD_EXPENSIVE_CHECKING
42.40 +extern int journal_enable_debug;
42.41 +
42.42 +#define jbd_debug(n, f, a...) \
42.43 + do { \
42.44 + if ((n) <= journal_enable_debug) { \
42.45 + printk (KERN_DEBUG "(%s, %d): %s: ", \
42.46 + __FILE__, __LINE__, __FUNCTION__); \
42.47 + printk (f, ## a); \
42.48 + } \
42.49 + } while (0)
42.50 +#else
42.51 +#ifdef __GNUC__
42.52 +#if defined(__KERNEL__) || !defined(CONFIG_JBD_DEBUG)
42.53 +#define jbd_debug(f, a...) /**/
42.54 +#else
42.55 +extern int journal_enable_debug;
42.56 +#define jbd_debug(n, f, a...) \
42.57 + do { \
42.58 + if ((n) <= journal_enable_debug) { \
42.59 + printf("(%s, %d): %s: ", \
42.60 + __FILE__, __LINE__, __func__); \
42.61 + printf(f, ## a); \
42.62 + } \
42.63 + } while (0)
42.64 +#endif /*__KERNEL__ */
42.65 +#else
42.66 +#define jbd_debug(f, ...) /**/
42.67 +#endif
42.68 +#endif
42.69 +#else
42.70 +#define jbd_debug(x) /* AIX doesn't do STDC */
42.71 +#endif
42.72 +
42.73 +extern void * __jbd_kmalloc (char *where, size_t size, int flags, int retry);
42.74 +#define jbd_kmalloc(size, flags) \
42.75 + __jbd_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry)
42.76 +#define jbd_rep_kmalloc(size, flags) \
42.77 + __jbd_kmalloc(__FUNCTION__, (size), (flags), 1)
42.78 +
42.79 +#define JFS_MIN_JOURNAL_BLOCKS 1024
42.80 +
42.81 +/*
42.82 + * Internal structures used by the logging mechanism:
42.83 + */
42.84 +
42.85 +#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
42.86 +
42.87 +/*
42.88 + * On-disk structures
42.89 + */
42.90 +
42.91 +/*
42.92 + * Descriptor block types:
42.93 + */
42.94 +
42.95 +#define JFS_DESCRIPTOR_BLOCK 1
42.96 +#define JFS_COMMIT_BLOCK 2
42.97 +#define JFS_SUPERBLOCK_V1 3
42.98 +#define JFS_SUPERBLOCK_V2 4
42.99 +#define JFS_REVOKE_BLOCK 5
42.100 +
42.101 +/*
42.102 + * Standard header for all descriptor blocks:
42.103 + */
42.104 +typedef struct journal_header_s
42.105 +{
42.106 + __u32 h_magic;
42.107 + __u32 h_blocktype;
42.108 + __u32 h_sequence;
42.109 +} journal_header_t;
42.110 +
42.111 +/*
42.112 + * Checksum types.
42.113 + */
42.114 +#define JBD2_CRC32_CHKSUM 1
42.115 +#define JBD2_MD5_CHKSUM 2
42.116 +#define JBD2_SHA1_CHKSUM 3
42.117 +#define JBD2_CRC32C_CHKSUM 4
42.118 +
42.119 +#define JBD2_CRC32_CHKSUM_SIZE 4
42.120 +
42.121 +#define JBD2_CHECKSUM_BYTES (32 / sizeof(__u32))
42.122 +/*
42.123 + * Commit block header for storing transactional checksums:
42.124 + *
42.125 + * NOTE: If FEATURE_COMPAT_CHECKSUM (checksum v1) is set, the h_chksum*
42.126 + * fields are used to store a checksum of the descriptor and data blocks.
42.127 + *
42.128 + * If FEATURE_INCOMPAT_CSUM_V2 (checksum v2) is set, then the h_chksum
42.129 + * field is used to store crc32c(uuid+commit_block). Each journal metadata
42.130 + * block gets its own checksum, and data block checksums are stored in
42.131 + * journal_block_tag (in the descriptor). The other h_chksum* fields are
42.132 + * not used.
42.133 + *
42.134 + * If FEATURE_INCOMPAT_CSUM_V3 is set, the descriptor block uses
42.135 + * journal_block_tag3_t to store a full 32-bit checksum. Everything else
42.136 + * is the same as v2.
42.137 + *
42.138 + * Checksum v1, v2, and v3 are mutually exclusive features.
42.139 + */
42.140 +struct commit_header {
42.141 + __u32 h_magic;
42.142 + __u32 h_blocktype;
42.143 + __u32 h_sequence;
42.144 + unsigned char h_chksum_type;
42.145 + unsigned char h_chksum_size;
42.146 + unsigned char h_padding[2];
42.147 + __u32 h_chksum[JBD2_CHECKSUM_BYTES];
42.148 + __u64 h_commit_sec;
42.149 + __u32 h_commit_nsec;
42.150 +};
42.151 +
42.152 +/*
42.153 + * The block tag: used to describe a single buffer in the journal
42.154 + */
42.155 +typedef struct journal_block_tag3_s
42.156 +{
42.157 + __u32 t_blocknr; /* The on-disk block number */
42.158 + __u32 t_flags; /* See below */
42.159 + __u32 t_blocknr_high; /* most-significant high 32bits. */
42.160 + __u32 t_checksum; /* crc32c(uuid+seq+block) */
42.161 +} journal_block_tag3_t;
42.162 +
42.163 +typedef struct journal_block_tag_s
42.164 +{
42.165 + __u32 t_blocknr; /* The on-disk block number */
42.166 + __u16 t_checksum; /* truncated crc32c(uuid+seq+block) */
42.167 + __u16 t_flags; /* See below */
42.168 + __u32 t_blocknr_high; /* most-significant high 32bits. */
42.169 +} journal_block_tag_t;
42.170 +
42.171 +/* Tail of descriptor block, for checksumming */
42.172 +struct journal_block_tail {
42.173 + __be32 t_checksum;
42.174 +};
42.175 +
42.176 +/*
42.177 + * The revoke descriptor: used on disk to describe a series of blocks to
42.178 + * be revoked from the log
42.179 + */
42.180 +typedef struct journal_revoke_header_s
42.181 +{
42.182 + journal_header_t r_header;
42.183 + int r_count; /* Count of bytes used in the block */
42.184 +} journal_revoke_header_t;
42.185 +
42.186 +/* Tail of revoke block, for checksumming */
42.187 +struct journal_revoke_tail {
42.188 + __be32 r_checksum;
42.189 +};
42.190 +
42.191 +/* Definitions for the journal tag flags word: */
42.192 +#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */
42.193 +#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */
42.194 +#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */
42.195 +#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */
42.196 +
42.197 +
42.198 +#define UUID_SIZE 16
42.199 +#define JFS_USERS_MAX 48
42.200 +#define JFS_USERS_SIZE (UUID_SIZE * JFS_USERS_MAX)
42.201 +/*
42.202 + * The journal superblock. All fields are in big-endian byte order.
42.203 + */
42.204 +typedef struct journal_superblock_s
42.205 +{
42.206 +/* 0x0000 */
42.207 + journal_header_t s_header;
42.208 +
42.209 +/* 0x000C */
42.210 + /* Static information describing the journal */
42.211 + __u32 s_blocksize; /* journal device blocksize */
42.212 + __u32 s_maxlen; /* total blocks in journal file */
42.213 + __u32 s_first; /* first block of log information */
42.214 +
42.215 +/* 0x0018 */
42.216 + /* Dynamic information describing the current state of the log */
42.217 + __u32 s_sequence; /* first commit ID expected in log */
42.218 + __u32 s_start; /* blocknr of start of log */
42.219 +
42.220 +/* 0x0020 */
42.221 + /* Error value, as set by journal_abort(). */
42.222 + __s32 s_errno;
42.223 +
42.224 +/* 0x0024 */
42.225 + /* Remaining fields are only valid in a version-2 superblock */
42.226 + __u32 s_feature_compat; /* compatible feature set */
42.227 + __u32 s_feature_incompat; /* incompatible feature set */
42.228 + __u32 s_feature_ro_compat; /* readonly-compatible feature set */
42.229 +/* 0x0030 */
42.230 + __u8 s_uuid[16]; /* 128-bit uuid for journal */
42.231 +
42.232 +/* 0x0040 */
42.233 + __u32 s_nr_users; /* Nr of filesystems sharing log */
42.234 +
42.235 + __u32 s_dynsuper; /* Blocknr of dynamic superblock copy*/
42.236 +
42.237 +/* 0x0048 */
42.238 + __u32 s_max_transaction; /* Limit of journal blocks per trans.*/
42.239 + __u32 s_max_trans_data; /* Limit of data blocks per trans. */
42.240 +
42.241 +/* 0x0050 */
42.242 + __u8 s_checksum_type; /* checksum type */
42.243 + __u8 s_padding2[3];
42.244 + __u32 s_padding[42];
42.245 + __u32 s_checksum; /* crc32c(superblock) */
42.246 +
42.247 +/* 0x0100 */
42.248 + __u8 s_users[JFS_USERS_SIZE]; /* ids of all fs'es sharing the log */
42.249 +
42.250 +/* 0x0400 */
42.251 +} journal_superblock_t;
42.252 +
42.253 +#define JFS_HAS_COMPAT_FEATURE(j,mask) \
42.254 + ((j)->j_format_version >= 2 && \
42.255 + ((j)->j_superblock->s_feature_compat & ext2fs_cpu_to_be32((mask))))
42.256 +#define JFS_HAS_RO_COMPAT_FEATURE(j,mask) \
42.257 + ((j)->j_format_version >= 2 && \
42.258 + ((j)->j_superblock->s_feature_ro_compat & ext2fs_cpu_to_be32((mask))))
42.259 +#define JFS_HAS_INCOMPAT_FEATURE(j,mask) \
42.260 + ((j)->j_format_version >= 2 && \
42.261 + ((j)->j_superblock->s_feature_incompat & ext2fs_cpu_to_be32((mask))))
42.262 +
42.263 +#define JFS_FEATURE_COMPAT_CHECKSUM 0x00000001
42.264 +
42.265 +#define JFS_FEATURE_INCOMPAT_REVOKE 0x00000001
42.266 +#define JFS_FEATURE_INCOMPAT_64BIT 0x00000002
42.267 +#define JFS_FEATURE_INCOMPAT_ASYNC_COMMIT 0x00000004
42.268 +#define JFS_FEATURE_INCOMPAT_CSUM_V2 0x00000008
42.269 +#define JFS_FEATURE_INCOMPAT_CSUM_V3 0x00000010
42.270 +
42.271 +/* Features known to this kernel version: */
42.272 +#define JFS_KNOWN_COMPAT_FEATURES 0
42.273 +#define JFS_KNOWN_ROCOMPAT_FEATURES 0
42.274 +#define JFS_KNOWN_INCOMPAT_FEATURES (JFS_FEATURE_INCOMPAT_REVOKE|\
42.275 + JFS_FEATURE_INCOMPAT_ASYNC_COMMIT|\
42.276 + JFS_FEATURE_INCOMPAT_64BIT|\
42.277 + JFS_FEATURE_INCOMPAT_CSUM_V2|\
42.278 + JFS_FEATURE_INCOMPAT_CSUM_V3)
42.279 +
42.280 +#ifdef NO_INLINE_FUNCS
42.281 +extern size_t journal_tag_bytes(journal_t *journal);
42.282 +extern int journal_has_csum_v2or3(journal_t *journal);
42.283 +extern int tid_gt(tid_t x, tid_t y) EXT2FS_ATTR((unused));
42.284 +extern int tid_geq(tid_t x, tid_t y) EXT2FS_ATTR((unused));
42.285 +#endif
42.286 +
42.287 +#if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
42.288 +#ifdef E2FSCK_INCLUDE_INLINE_FUNCS
42.289 +#if (__STDC_VERSION__ >= 199901L)
42.290 +#define _INLINE_ extern inline
42.291 +#else
42.292 +#define _INLINE_ inline
42.293 +#endif
42.294 +#else /* !E2FSCK_INCLUDE_INLINE FUNCS */
42.295 +#if (__STDC_VERSION__ >= 199901L)
42.296 +#define _INLINE_ inline
42.297 +#else /* not C99 */
42.298 +#ifdef __GNUC__
42.299 +#define _INLINE_ extern __inline__
42.300 +#else /* For Watcom C */
42.301 +#define _INLINE_ extern inline
42.302 +#endif /* __GNUC__ */
42.303 +#endif /* __STDC_VERSION__ >= 199901L */
42.304 +#endif /* INCLUDE_INLINE_FUNCS */
42.305 +
42.306 +/* journal feature predicate functions */
42.307 +#define JFS_FEATURE_COMPAT_FUNCS(name, flagname) \
42.308 +_INLINE_ int jfs_has_feature_##name(journal_t *j); \
42.309 +_INLINE_ int jfs_has_feature_##name(journal_t *j) \
42.310 +{ \
42.311 + return ((j)->j_format_version >= 2 && \
42.312 + ((j)->j_superblock->s_feature_compat & \
42.313 + ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname)) != 0); \
42.314 +} \
42.315 +_INLINE_ void jfs_set_feature_##name(journal_t *j); \
42.316 +_INLINE_ void jfs_set_feature_##name(journal_t *j) \
42.317 +{ \
42.318 + (j)->j_superblock->s_feature_compat |= \
42.319 + ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname); \
42.320 +} \
42.321 +_INLINE_ void jfs_clear_feature_##name(journal_t *j); \
42.322 +_INLINE_ void jfs_clear_feature_##name(journal_t *j) \
42.323 +{ \
42.324 + (j)->j_superblock->s_feature_compat &= \
42.325 + ~ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname); \
42.326 +}
42.327 +
42.328 +#define JFS_FEATURE_RO_COMPAT_FUNCS(name, flagname) \
42.329 +_INLINE_ int jfs_has_feature_##name(journal_t *j); \
42.330 +_INLINE_ int jfs_has_feature_##name(journal_t *j) \
42.331 +{ \
42.332 + return ((j)->j_format_version >= 2 && \
42.333 + ((j)->j_superblock->s_feature_ro_compat & \
42.334 + ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname)) != 0); \
42.335 +} \
42.336 +_INLINE_ void jfs_set_feature_##name(journal_t *j); \
42.337 +_INLINE_ void jfs_set_feature_##name(journal_t *j) \
42.338 +{ \
42.339 + (j)->j_superblock->s_feature_ro_compat |= \
42.340 + ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname); \
42.341 +} \
42.342 +_INLINE_ void jfs_clear_feature_##name(journal_t *j); \
42.343 +_INLINE_ void jfs_clear_feature_##name(journal_t *j) \
42.344 +{ \
42.345 + (j)->j_superblock->s_feature_ro_compat &= \
42.346 + ~ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname); \
42.347 +}
42.348 +
42.349 +#define JFS_FEATURE_INCOMPAT_FUNCS(name, flagname) \
42.350 +_INLINE_ int jfs_has_feature_##name(journal_t *j); \
42.351 +_INLINE_ int jfs_has_feature_##name(journal_t *j) \
42.352 +{ \
42.353 + return ((j)->j_format_version >= 2 && \
42.354 + ((j)->j_superblock->s_feature_incompat & \
42.355 + ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname)) != 0); \
42.356 +} \
42.357 +_INLINE_ void jfs_set_feature_##name(journal_t *j); \
42.358 +_INLINE_ void jfs_set_feature_##name(journal_t *j) \
42.359 +{ \
42.360 + (j)->j_superblock->s_feature_incompat |= \
42.361 + ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname); \
42.362 +} \
42.363 +_INLINE_ void jfs_clear_feature_##name(journal_t *j); \
42.364 +_INLINE_ void jfs_clear_feature_##name(journal_t *j) \
42.365 +{ \
42.366 + (j)->j_superblock->s_feature_incompat &= \
42.367 + ~ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname); \
42.368 +}
42.369 +
42.370 +#else
42.371 +#define JFS_FEATURE_COMPAT_FUNCS(name, flagname) \
42.372 +extern int jfs_has_feature_##name(journal_t *j); \
42.373 +extern void jfs_set_feature_##name(journal_t *j); \
42.374 +extern void jfs_clear_feature_##name(journal_t *j);
42.375 +
42.376 +#define JFS_FEATURE_RO_COMPAT_FUNCS(name, flagname) \
42.377 +extern int jfs_has_feature_##name(journal_t *j); \
42.378 +extern void jfs_set_feature_##name(journal_t *j); \
42.379 +extern void jfs_clear_feature_##name(journal_t *j);
42.380 +
42.381 +#define JFS_FEATURE_INCOMPAT_FUNCS(name, flagname) \
42.382 +extern int jfs_has_feature_##name(journal_t *j); \
42.383 +extern void jfs_set_feature_##name(journal_t *j); \
42.384 +extern void jfs_clear_feature_##name(journal_t *j);
42.385 +
42.386 +#endif /* (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) */
42.387 +
42.388 +JFS_FEATURE_COMPAT_FUNCS(checksum, CHECKSUM)
42.389 +
42.390 +JFS_FEATURE_INCOMPAT_FUNCS(revoke, REVOKE)
42.391 +JFS_FEATURE_INCOMPAT_FUNCS(64bit, 64BIT)
42.392 +JFS_FEATURE_INCOMPAT_FUNCS(async_commit, ASYNC_COMMIT)
42.393 +JFS_FEATURE_INCOMPAT_FUNCS(csum2, CSUM_V2)
42.394 +JFS_FEATURE_INCOMPAT_FUNCS(csum3, CSUM_V3)
42.395 +
42.396 +#if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
42.397 +/*
42.398 + * helper functions to deal with 32 or 64bit block numbers.
42.399 + */
42.400 +_INLINE_ size_t journal_tag_bytes(journal_t *journal)
42.401 +{
42.402 + size_t sz;
42.403 +
42.404 + if (jfs_has_feature_csum3(journal))
42.405 + return sizeof(journal_block_tag3_t);
42.406 +
42.407 + sz = sizeof(journal_block_tag_t);
42.408 +
42.409 + if (jfs_has_feature_csum2(journal))
42.410 + sz += sizeof(__u16);
42.411 +
42.412 + if (jfs_has_feature_64bit(journal))
42.413 + return sz;
42.414 +
42.415 + return sz - sizeof(__u32);
42.416 +}
42.417 +
42.418 +_INLINE_ int journal_has_csum_v2or3(journal_t *journal)
42.419 +{
42.420 + if (jfs_has_feature_csum2(journal) || jfs_has_feature_csum3(journal))
42.421 + return 1;
42.422 +
42.423 + return 0;
42.424 +}
42.425 +
42.426 +/* Comparison functions for transaction IDs: perform comparisons using
42.427 + * modulo arithmetic so that they work over sequence number wraps. */
42.428 +
42.429 +_INLINE_ int tid_gt(tid_t x, tid_t y)
42.430 +{
42.431 + int difference = (x - y);
42.432 + return (difference > 0);
42.433 +}
42.434 +
42.435 +_INLINE_ int tid_geq(tid_t x, tid_t y)
42.436 +{
42.437 + int difference = (x - y);
42.438 + return (difference >= 0);
42.439 +}
42.440 +#endif /* (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) */
42.441 +
42.442 +#undef _INLINE_
42.443 +
42.444 +extern int journal_blocks_per_page(struct inode *inode);
42.445 +
42.446 +/*
42.447 + * Definitions which augment the buffer_head layer
42.448 + */
42.449 +
42.450 +/* journaling buffer types */
42.451 +#define BJ_None 0 /* Not journaled */
42.452 +#define BJ_SyncData 1 /* Normal data: flush before commit */
42.453 +#define BJ_AsyncData 2 /* writepage data: wait on it before commit */
42.454 +#define BJ_Metadata 3 /* Normal journaled metadata */
42.455 +#define BJ_Forget 4 /* Buffer superceded by this transaction */
42.456 +#define BJ_IO 5 /* Buffer is for temporary IO use */
42.457 +#define BJ_Shadow 6 /* Buffer contents being shadowed to the log */
42.458 +#define BJ_LogCtl 7 /* Buffer contains log descriptors */
42.459 +#define BJ_Reserved 8 /* Buffer is reserved for access by journal */
42.460 +#define BJ_Types 9
42.461 +
42.462 +extern int jbd_blocks_per_page(struct inode *inode);
42.463 +
42.464 +#endif /* _LINUX_JBD_H */
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/libext2fs/include/libsupport/Makefile Wed Aug 25 01:28:08 2021 +0200
43.3 @@ -0,0 +1,7 @@
43.4 +PKGDIR ?= ../..
43.5 +L4DIR ?= $(PKGDIR)/../../..
43.6 +
43.7 +PKGNAME = libsupport
43.8 +CONTRIB_HEADERS = 1
43.9 +
43.10 +include $(L4DIR)/mk/include.mk
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44.2 +++ b/libext2fs/include/libsupport/support/quotaio.h Wed Aug 25 01:28:08 2021 +0200
44.3 @@ -0,0 +1,265 @@
44.4 +/** quotaio.h
44.5 + *
44.6 + * Interface to the quota library.
44.7 + *
44.8 + * The quota library provides interface for creating and updating the quota
44.9 + * files and the ext4 superblock fields. It supports the new VFS_V1 quota
44.10 + * format. The quota library also provides support for keeping track of quotas
44.11 + * in memory.
44.12 + * The typical way to use the quota library is as follows:
44.13 + * {
44.14 + * quota_ctx_t qctx;
44.15 + *
44.16 + * quota_init_context(&qctx, fs, QUOTA_ALL_BIT);
44.17 + * {
44.18 + * quota_compute_usage(qctx);
44.19 + * AND/OR
44.20 + * quota_data_add/quota_data_sub/quota_data_inodes();
44.21 + * }
44.22 + * quota_write_inode(qctx, USRQUOTA);
44.23 + * quota_write_inode(qctx, GRPQUOTA);
44.24 + * quota_release_context(&qctx);
44.25 + * }
44.26 + *
44.27 + * This initial version does not support reading the quota files. This support
44.28 + * will be added in near future.
44.29 + *
44.30 + * Aditya Kali <adityakali@google.com>
44.31 + * Header of IO operations for quota utilities
44.32 + *
44.33 + * Jan Kara <jack@suse.cz>
44.34 + */
44.35 +
44.36 +#ifndef GUARD_QUOTAIO_H
44.37 +#define GUARD_QUOTAIO_H
44.38 +
44.39 +#include <limits.h>
44.40 +#include <sys/types.h>
44.41 +#include <sys/stat.h>
44.42 +
44.43 +#include "ext2fs/ext2_fs.h"
44.44 +#include "ext2fs/ext2fs.h"
44.45 +#include "dqblk_v2.h"
44.46 +
44.47 +typedef int64_t qsize_t; /* Type in which we store size limitations */
44.48 +
44.49 +enum quota_type {
44.50 + USRQUOTA = 0,
44.51 + GRPQUOTA = 1,
44.52 + PRJQUOTA = 2,
44.53 + MAXQUOTAS = 3,
44.54 +};
44.55 +
44.56 +#if MAXQUOTAS > 32
44.57 +#error "cannot have more than 32 quota types to fit in qtype_bits"
44.58 +#endif
44.59 +
44.60 +#define QUOTA_USR_BIT (1 << USRQUOTA)
44.61 +#define QUOTA_GRP_BIT (1 << GRPQUOTA)
44.62 +#define QUOTA_PRJ_BIT (1 << PRJQUOTA)
44.63 +#define QUOTA_ALL_BIT (QUOTA_USR_BIT | QUOTA_GRP_BIT | QUOTA_PRJ_BIT)
44.64 +
44.65 +typedef struct quota_ctx *quota_ctx_t;
44.66 +struct dict_t;
44.67 +
44.68 +struct quota_ctx {
44.69 + ext2_filsys fs;
44.70 + struct dict_t *quota_dict[MAXQUOTAS];
44.71 + struct quota_handle *quota_file[MAXQUOTAS];
44.72 +};
44.73 +
44.74 +/*
44.75 + * Definitions of magics and versions of current quota files
44.76 + */
44.77 +#define INITQMAGICS {\
44.78 + 0xd9c01f11, /* USRQUOTA */\
44.79 + 0xd9c01927, /* GRPQUOTA */\
44.80 + 0xd9c03f14 /* PRJQUOTA */\
44.81 +}
44.82 +
44.83 +/* Size of blocks in which are counted size limits in generic utility parts */
44.84 +#define QUOTABLOCK_BITS 10
44.85 +#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
44.86 +#define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS)
44.87 +
44.88 +/* Quota format type IDs */
44.89 +#define QFMT_VFS_OLD 1
44.90 +#define QFMT_VFS_V0 2
44.91 +#define QFMT_VFS_V1 4
44.92 +
44.93 +/*
44.94 + * The following constants define the default amount of time given a user
44.95 + * before the soft limits are treated as hard limits (usually resulting
44.96 + * in an allocation failure). The timer is started when the user crosses
44.97 + * their soft limit, it is reset when they go below their soft limit.
44.98 + */
44.99 +#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */
44.100 +#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */
44.101 +
44.102 +#define IOFL_INFODIRTY 0x01 /* Did info change? */
44.103 +
44.104 +struct quotafile_ops;
44.105 +
44.106 +/* Generic information about quotafile */
44.107 +struct util_dqinfo {
44.108 + time_t dqi_bgrace; /* Block grace time for given quotafile */
44.109 + time_t dqi_igrace; /* Inode grace time for given quotafile */
44.110 + union {
44.111 + struct v2_mem_dqinfo v2_mdqi;
44.112 + } u; /* Format specific info about quotafile */
44.113 +};
44.114 +
44.115 +struct quota_file {
44.116 + ext2_filsys fs;
44.117 + ext2_ino_t ino;
44.118 + ext2_file_t e2_file;
44.119 +};
44.120 +
44.121 +/* Structure for one opened quota file */
44.122 +struct quota_handle {
44.123 + enum quota_type qh_type; /* Type of quotafile */
44.124 + int qh_fmt; /* Quotafile format */
44.125 + int qh_file_flags;
44.126 + int qh_io_flags; /* IO flags for file */
44.127 + struct quota_file qh_qf;
44.128 + unsigned int (*e2fs_read)(struct quota_file *qf, ext2_loff_t offset,
44.129 + void *buf, unsigned int size);
44.130 + unsigned int (*e2fs_write)(struct quota_file *qf, ext2_loff_t offset,
44.131 + void *buf, unsigned int size);
44.132 + struct quotafile_ops *qh_ops; /* Operations on quotafile */
44.133 + struct util_dqinfo qh_info; /* Generic quotafile info */
44.134 +};
44.135 +
44.136 +/* Utility quota block */
44.137 +struct util_dqblk {
44.138 + qsize_t dqb_ihardlimit;
44.139 + qsize_t dqb_isoftlimit;
44.140 + qsize_t dqb_curinodes;
44.141 + qsize_t dqb_bhardlimit;
44.142 + qsize_t dqb_bsoftlimit;
44.143 + qsize_t dqb_curspace;
44.144 + time_t dqb_btime;
44.145 + time_t dqb_itime;
44.146 + union {
44.147 + struct v2_mem_dqblk v2_mdqb;
44.148 + } u; /* Format specific dquot information */
44.149 +};
44.150 +
44.151 +/* Structure for one loaded quota */
44.152 +struct dquot {
44.153 + struct dquot *dq_next; /* Pointer to next dquot in the list */
44.154 + qid_t dq_id; /* ID dquot belongs to */
44.155 + int dq_flags; /* Some flags for utils */
44.156 + struct quota_handle *dq_h; /* Handle of quotafile for this dquot */
44.157 + struct util_dqblk dq_dqb; /* Parsed data of dquot */
44.158 +};
44.159 +
44.160 +#define DQF_SEEN 0x0001
44.161 +
44.162 +/* Structure of quotafile operations */
44.163 +struct quotafile_ops {
44.164 + /* Check whether quotafile is in our format */
44.165 + int (*check_file) (struct quota_handle *h, int type, int fmt);
44.166 + /* Open quotafile */
44.167 + int (*init_io) (struct quota_handle *h);
44.168 + /* Create new quotafile */
44.169 + int (*new_io) (struct quota_handle *h);
44.170 + /* Write all changes and close quotafile */
44.171 + int (*end_io) (struct quota_handle *h);
44.172 + /* Write info about quotafile */
44.173 + int (*write_info) (struct quota_handle *h);
44.174 + /* Read dquot into memory */
44.175 + struct dquot *(*read_dquot) (struct quota_handle *h, qid_t id);
44.176 + /* Write given dquot to disk */
44.177 + int (*commit_dquot) (struct dquot *dquot);
44.178 + /* Scan quotafile and call callback on every structure */
44.179 + int (*scan_dquots) (struct quota_handle *h,
44.180 + int (*process_dquot) (struct dquot *dquot,
44.181 + void *data),
44.182 + void *data);
44.183 + /* Function to print format specific file information */
44.184 + int (*report) (struct quota_handle *h, int verbose);
44.185 +};
44.186 +
44.187 +/* This might go into a special header file but that sounds a bit silly... */
44.188 +extern struct quotafile_ops quotafile_ops_meta;
44.189 +
44.190 +/* Open existing quotafile of given type (and verify its format) on given
44.191 + * filesystem. */
44.192 +errcode_t quota_file_open(quota_ctx_t qctx, struct quota_handle *h,
44.193 + ext2_ino_t qf_ino, enum quota_type type,
44.194 + int fmt, int flags);
44.195 +
44.196 +
44.197 +/* Create new quotafile of specified format on given filesystem */
44.198 +errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs,
44.199 + enum quota_type qtype, int fmt);
44.200 +
44.201 +/* Close quotafile */
44.202 +errcode_t quota_file_close(quota_ctx_t qctx, struct quota_handle *h);
44.203 +
44.204 +/* Get empty quota structure */
44.205 +struct dquot *get_empty_dquot(void);
44.206 +
44.207 +errcode_t quota_inode_truncate(ext2_filsys fs, ext2_ino_t ino);
44.208 +
44.209 +const char *quota_type2name(enum quota_type qtype);
44.210 +ext2_ino_t quota_type2inum(enum quota_type qtype, struct ext2_super_block *);
44.211 +
44.212 +void update_grace_times(struct dquot *q);
44.213 +
44.214 +/* size for the buffer returned by quota_get_qf_name(); must be greater
44.215 + than maxlen of extensions[] and fmtnames[] (plus 2) found in quotaio.c */
44.216 +#define QUOTA_NAME_LEN 16
44.217 +
44.218 +const char *quota_get_qf_name(enum quota_type, int fmt, char *buf);
44.219 +
44.220 +/* In mkquota.c */
44.221 +errcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs,
44.222 + unsigned int qtype_bits);
44.223 +void quota_data_inodes(quota_ctx_t qctx, struct ext2_inode_large *inode,
44.224 + ext2_ino_t ino, int adjust);
44.225 +void quota_data_add(quota_ctx_t qctx, struct ext2_inode_large *inode,
44.226 + ext2_ino_t ino, qsize_t space);
44.227 +void quota_data_sub(quota_ctx_t qctx, struct ext2_inode_large *inode,
44.228 + ext2_ino_t ino, qsize_t space);
44.229 +errcode_t quota_write_inode(quota_ctx_t qctx, enum quota_type qtype);
44.230 +errcode_t quota_update_limits(quota_ctx_t qctx, ext2_ino_t qf_ino,
44.231 + enum quota_type type);
44.232 +errcode_t quota_compute_usage(quota_ctx_t qctx);
44.233 +void quota_release_context(quota_ctx_t *qctx);
44.234 +errcode_t quota_remove_inode(ext2_filsys fs, enum quota_type qtype);
44.235 +int quota_file_exists(ext2_filsys fs, enum quota_type qtype);
44.236 +void quota_set_sb_inum(ext2_filsys fs, ext2_ino_t ino, enum quota_type qtype);
44.237 +errcode_t quota_compare_and_update(quota_ctx_t qctx, enum quota_type qtype,
44.238 + int *usage_inconsistent);
44.239 +int parse_quota_opts(const char *opts, int (*func)(char *));
44.240 +
44.241 +/* parse_qtype.c */
44.242 +int parse_quota_types(const char *in_str, unsigned int *qtype_bits,
44.243 + char **err_token);
44.244 +
44.245 +/*
44.246 + * Return pointer to reserved inode field in superblock for given quota type.
44.247 + *
44.248 + * This allows the caller to get or set the quota inode by type without the
44.249 + * need for the quota array to be contiguous in the superblock.
44.250 + */
44.251 +static inline ext2_ino_t *quota_sb_inump(struct ext2_super_block *sb,
44.252 + enum quota_type qtype)
44.253 +{
44.254 + switch (qtype) {
44.255 + case USRQUOTA:
44.256 + return &sb->s_usr_quota_inum;
44.257 + case GRPQUOTA:
44.258 + return &sb->s_grp_quota_inum;
44.259 + case PRJQUOTA:
44.260 + return &sb->s_prj_quota_inum;
44.261 + default:
44.262 + return NULL;
44.263 + }
44.264 +
44.265 + return NULL;
44.266 +}
44.267 +
44.268 +#endif /* GUARD_QUOTAIO_H */
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/libext2fs/include/libuuid/uuid/uuid.h Wed Aug 25 01:28:08 2021 +0200
45.3 @@ -0,0 +1,103 @@
45.4 +/*
45.5 + * Public include file for the UUID library
45.6 + *
45.7 + * Copyright (C) 1996, 1997, 1998 Theodore Ts'o.
45.8 + *
45.9 + * %Begin-Header%
45.10 + * Redistribution and use in source and binary forms, with or without
45.11 + * modification, are permitted provided that the following conditions
45.12 + * are met:
45.13 + * 1. Redistributions of source code must retain the above copyright
45.14 + * notice, and the entire permission notice in its entirety,
45.15 + * including the disclaimer of warranties.
45.16 + * 2. Redistributions in binary form must reproduce the above copyright
45.17 + * notice, this list of conditions and the following disclaimer in the
45.18 + * documentation and/or other materials provided with the distribution.
45.19 + * 3. The name of the author may not be used to endorse or promote
45.20 + * products derived from this software without specific prior
45.21 + * written permission.
45.22 + *
45.23 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
45.24 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
45.25 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
45.26 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
45.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
45.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
45.29 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
45.30 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
45.31 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45.32 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
45.33 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
45.34 + * DAMAGE.
45.35 + * %End-Header%
45.36 + */
45.37 +
45.38 +#ifndef _UUID_UUID_H
45.39 +#define _UUID_UUID_H
45.40 +
45.41 +#include <sys/types.h>
45.42 +#ifndef _WIN32
45.43 +#include <sys/time.h>
45.44 +#endif
45.45 +#include <time.h>
45.46 +
45.47 +typedef unsigned char uuid_t[16];
45.48 +
45.49 +/* UUID Variant definitions */
45.50 +#define UUID_VARIANT_NCS 0
45.51 +#define UUID_VARIANT_DCE 1
45.52 +#define UUID_VARIANT_MICROSOFT 2
45.53 +#define UUID_VARIANT_OTHER 3
45.54 +
45.55 +/* UUID Type definitions */
45.56 +#define UUID_TYPE_DCE_TIME 1
45.57 +#define UUID_TYPE_DCE_RANDOM 4
45.58 +
45.59 +/* Allow UUID constants to be defined */
45.60 +#ifdef __GNUC__
45.61 +#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
45.62 + static const uuid_t name __attribute__ ((unused)) = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
45.63 +#else
45.64 +#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
45.65 + static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
45.66 +#endif
45.67 +
45.68 +#ifdef __cplusplus
45.69 +extern "C" {
45.70 +#endif
45.71 +
45.72 +/* clear.c */
45.73 +void uuid_clear(uuid_t uu);
45.74 +
45.75 +/* compare.c */
45.76 +int uuid_compare(const uuid_t uu1, const uuid_t uu2);
45.77 +
45.78 +/* copy.c */
45.79 +void uuid_copy(uuid_t dst, const uuid_t src);
45.80 +
45.81 +/* gen_uuid.c */
45.82 +void uuid_generate(uuid_t out);
45.83 +void uuid_generate_random(uuid_t out);
45.84 +void uuid_generate_time(uuid_t out);
45.85 +
45.86 +/* isnull.c */
45.87 +int uuid_is_null(const uuid_t uu);
45.88 +
45.89 +/* parse.c */
45.90 +int uuid_parse(const char *in, uuid_t uu);
45.91 +
45.92 +/* unparse.c */
45.93 +void uuid_unparse(const uuid_t uu, char *out);
45.94 +void uuid_unparse_lower(const uuid_t uu, char *out);
45.95 +void uuid_unparse_upper(const uuid_t uu, char *out);
45.96 +
45.97 +/* uuid_time.c */
45.98 +time_t uuid_time(const uuid_t uu, struct timeval *ret_tv);
45.99 +int uuid_type(const uuid_t uu);
45.100 +int uuid_variant(const uuid_t uu);
45.101 +
45.102 +#ifdef __cplusplus
45.103 +}
45.104 +#endif
45.105 +
45.106 +#endif /* _UUID_UUID_H */
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/libext2fs/include/libuuid/uuid/uuid_types.h Wed Aug 25 01:28:08 2021 +0200
46.3 @@ -0,0 +1,50 @@
46.4 +/*
46.5 + * If linux/types.h is already been included, assume it has defined
46.6 + * everything we need. (cross fingers) Other header files may have
46.7 + * also defined the types that we need.
46.8 + */
46.9 +#if (!defined(_STDINT_H) && !defined(_UUID_STDINT_H))
46.10 +#define _UUID_STDINT_H
46.11 +
46.12 +typedef unsigned char uint8_t;
46.13 +typedef signed char int8_t;
46.14 +
46.15 +#if (4 == 8)
46.16 +typedef int int64_t;
46.17 +typedef unsigned int uint64_t;
46.18 +#elif (4 == 8)
46.19 +typedef long int64_t;
46.20 +typedef unsigned long uint64_t;
46.21 +#elif (8 == 8)
46.22 +#if defined(__GNUC__)
46.23 +typedef __signed__ long long int64_t;
46.24 +#else
46.25 +typedef signed long long int64_t;
46.26 +#endif
46.27 +typedef unsigned long long uint64_t;
46.28 +#endif
46.29 +
46.30 +#if (4 == 2)
46.31 +typedef int int16_t;
46.32 +typedef unsigned int uint16_t;
46.33 +#elif (2 == 2)
46.34 +typedef short int16_t;
46.35 +typedef unsigned short uint16_t;
46.36 +#else
46.37 + ?==error: undefined 16 bit type
46.38 +#endif
46.39 +
46.40 +#if (4 == 4)
46.41 +typedef int int32_t;
46.42 +typedef unsigned int uint32_t;
46.43 +#elif (4 == 4)
46.44 +typedef long int32_t;
46.45 +typedef unsigned long uint32_t;
46.46 +#elif (2 == 4)
46.47 +typedef short int32_t;
46.48 +typedef unsigned short uint32_t;
46.49 +#else
46.50 + ?== error: undefined 32 bit type
46.51 +#endif
46.52 +
46.53 +#endif
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/libext2fs/lib/Makefile Wed Aug 25 01:28:08 2021 +0200
47.3 @@ -0,0 +1,11 @@
47.4 +PKGDIR ?= ..
47.5 +L4DIR ?= $(PKGDIR)/../../..
47.6 +
47.7 +TARGET := libuuid libblkid libsupport libet libe2p libext2fs
47.8 +
47.9 +include $(L4DIR)/mk/subdir.mk
47.10 +
47.11 +libblkid: libuuid
47.12 +libsupport: libblkid
47.13 +libe2p: libet libsupport
47.14 +libext2fs: libet libe2p
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/libext2fs/lib/config.h Wed Aug 25 01:28:08 2021 +0200
48.3 @@ -0,0 +1,63 @@
48.4 +#include <sys/types.h>
48.5 +
48.6 +/* Definitions based on the current status of L4Re. */
48.7 +
48.8 +#define HAVE_ERRNO_H 1
48.9 +#define HAVE_EXT2_IOCTLS 1
48.10 +#define HAVE_FALLOCATE 1
48.11 +#define HAVE_FALLOCATE64 1
48.12 +#define HAVE_FCNTL 1
48.13 +#define HAVE_FSTAT64 1
48.14 +#define HAVE_FSYNC 1
48.15 +#define HAVE_GETHOSTNAME 1
48.16 +#define HAVE_GETPAGESIZE 1
48.17 +#define HAVE_LSEEK64 1
48.18 +#define HAVE_LSEEK64_PROTOTYPE 1
48.19 +#define HAVE_LSEEK64_PROTOTYPE 1
48.20 +#define HAVE_MALLOC_H 1
48.21 +#define HAVE_MEMALIGN 1
48.22 +#define HAVE_NETINET_IN_H 1
48.23 +#define HAVE_OPEN64 1
48.24 +#define HAVE_POSIX_MEMALIGN 1
48.25 +#define HAVE_PREAD 1
48.26 +#define HAVE_PREAD64 1
48.27 +#define HAVE_PREAD64 1
48.28 +#define HAVE_PWRITE 1
48.29 +#define HAVE_PWRITE64 1
48.30 +#define HAVE_PWRITE64 1
48.31 +#define HAVE_SECURE_GETENV 1
48.32 +#define HAVE_SRANDOM 1
48.33 +#define HAVE_STDLIB_H 1
48.34 +#define HAVE_STRNLEN 1
48.35 +#define HAVE_SYS_IOCTL_H 1
48.36 +#define HAVE_SYS_MOUNT_H 1
48.37 +#define HAVE_SYS_RESOURCE_H 1
48.38 +#define HAVE_SYS_STAT_H 1
48.39 +#define HAVE_SYS_SYSMACROS_H 1
48.40 +#define HAVE_SYS_TIME_H 1
48.41 +#define HAVE_SYS_TYPES_H 1
48.42 +#define HAVE_UNISTD_H 1
48.43 +#define HAVE_VALLOC 1
48.44 +#define TLS __thread
48.45 +
48.46 +#if 0
48.47 +#define HAVE_LINUX_FALLOC_H 1
48.48 +#define HAVE_LINUX_FD_H 1
48.49 +#define HAVE_LINUX_LOOP_H 1
48.50 +#define HAVE_LINUX_MAJOR_H 1
48.51 +#define HAVE_LINUX_TYPES_H 1
48.52 +#define HAVE_MNTENT_H 1
48.53 +#define HAVE_PRCTL 1
48.54 +#define HAVE_SETMNTENT 1
48.55 +#define HAVE_SYS_PRCTL_H 1
48.56 +#endif
48.57 +
48.58 +/* libext2fs metadata. */
48.59 +
48.60 +#define VERSION "0.14.1"
48.61 +
48.62 +/* Machine-specific definitions. See <bits/types.h> and <bits/typesizes.h>. */
48.63 +
48.64 +#define SIZEOF_LONG (__WORDSIZE / 8)
48.65 +#define SIZEOF_LONG_LONG 8
48.66 +#define SIZEOF_OFF_T (__WORDSIZE / 8)
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/libext2fs/lib/config.h.in Wed Aug 25 01:28:08 2021 +0200
49.3 @@ -0,0 +1,899 @@
49.4 +/* lib/config.h.in. Generated from configure.ac by autoheader. */
49.5 +
49.6 +/* Define if building universal (internal helper macro) */
49.7 +#undef AC_APPLE_UNIVERSAL_BUILD
49.8 +
49.9 +/* Define to 1 if debugging the blkid library */
49.10 +#undef CONFIG_BLKID_DEBUG
49.11 +
49.12 +/* Define to 1 to compile findfs */
49.13 +#undef CONFIG_BUILD_FINDFS
49.14 +
49.15 +/* Define to 1 if debugging ext3/4 journal code */
49.16 +#undef CONFIG_JBD_DEBUG
49.17 +
49.18 +/* Define to 1 to enable mmp support */
49.19 +#undef CONFIG_MMP
49.20 +
49.21 +/* Define to 1 to enable tdb support */
49.22 +#undef CONFIG_TDB
49.23 +
49.24 +/* Define to 1 if the testio I/O manager should be enabled */
49.25 +#undef CONFIG_TESTIO_DEBUG
49.26 +
49.27 +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
49.28 + systems. This function is required for `alloca.c' support on those systems.
49.29 + */
49.30 +#undef CRAY_STACKSEG_END
49.31 +
49.32 +/* Define to 1 if using `alloca.c'. */
49.33 +#undef C_ALLOCA
49.34 +
49.35 +/* Define to 1 to disable use of backtrace */
49.36 +#undef DISABLE_BACKTRACE
49.37 +
49.38 +/* Define to 1 to enable bitmap stats. */
49.39 +#undef ENABLE_BMAP_STATS
49.40 +
49.41 +/* Define to 1 to enable bitmap stats. */
49.42 +#undef ENABLE_BMAP_STATS_OPS
49.43 +
49.44 +/* Define to 1 if translation of program messages to the user's native
49.45 + language is requested. */
49.46 +#undef ENABLE_NLS
49.47 +
49.48 +/* Define to 1 if you have the `add_key' function. */
49.49 +#undef HAVE_ADD_KEY
49.50 +
49.51 +/* Define to 1 if you have `alloca', as a function or macro. */
49.52 +#undef HAVE_ALLOCA
49.53 +
49.54 +/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
49.55 + */
49.56 +#undef HAVE_ALLOCA_H
49.57 +
49.58 +/* Define to 1 if you have the `argz_count' function. */
49.59 +#undef HAVE_ARGZ_COUNT
49.60 +
49.61 +/* Define to 1 if you have the <argz.h> header file. */
49.62 +#undef HAVE_ARGZ_H
49.63 +
49.64 +/* Define to 1 if you have the `argz_next' function. */
49.65 +#undef HAVE_ARGZ_NEXT
49.66 +
49.67 +/* Define to 1 if you have the `argz_stringify' function. */
49.68 +#undef HAVE_ARGZ_STRINGIFY
49.69 +
49.70 +/* Define to 1 if you have the `asprintf' function. */
49.71 +#undef HAVE_ASPRINTF
49.72 +
49.73 +/* Define to 1 if you have the <attr/xattr.h> header file. */
49.74 +#undef HAVE_ATTR_XATTR_H
49.75 +
49.76 +/* Define to 1 if you have the `backtrace' function. */
49.77 +#undef HAVE_BACKTRACE
49.78 +
49.79 +/* Define to 1 if you have the `blkid_probe_enable_partitions' function. */
49.80 +#undef HAVE_BLKID_PROBE_ENABLE_PARTITIONS
49.81 +
49.82 +/* Define to 1 if you have the `blkid_probe_get_topology' function. */
49.83 +#undef HAVE_BLKID_PROBE_GET_TOPOLOGY
49.84 +
49.85 +/* Define to 1 if the compiler understands __builtin_expect. */
49.86 +#undef HAVE_BUILTIN_EXPECT
49.87 +
49.88 +/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the
49.89 + CoreFoundation framework. */
49.90 +#undef HAVE_CFLOCALECOPYCURRENT
49.91 +
49.92 +/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in
49.93 + the CoreFoundation framework. */
49.94 +#undef HAVE_CFPREFERENCESCOPYAPPVALUE
49.95 +
49.96 +/* Define to 1 if you have the `chflags' function. */
49.97 +#undef HAVE_CHFLAGS
49.98 +
49.99 +/* Define if the GNU dcgettext() function is already present or preinstalled.
49.100 + */
49.101 +#undef HAVE_DCGETTEXT
49.102 +
49.103 +/* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you
49.104 + don't. */
49.105 +#undef HAVE_DECL_FEOF_UNLOCKED
49.106 +
49.107 +/* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if
49.108 + you don't. */
49.109 +#undef HAVE_DECL_FGETS_UNLOCKED
49.110 +
49.111 +/* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you
49.112 + don't. */
49.113 +#undef HAVE_DECL_GETC_UNLOCKED
49.114 +
49.115 +/* Define to 1 if you have the declaration of `_snprintf', and to 0 if you
49.116 + don't. */
49.117 +#undef HAVE_DECL__SNPRINTF
49.118 +
49.119 +/* Define to 1 if you have the declaration of `_snwprintf', and to 0 if you
49.120 + don't. */
49.121 +#undef HAVE_DECL__SNWPRINTF
49.122 +
49.123 +/* Define to 1 if you have the <dirent.h> header file. */
49.124 +#undef HAVE_DIRENT_H
49.125 +
49.126 +/* Define to 1 if you have the `dlopen' function. */
49.127 +#undef HAVE_DLOPEN
49.128 +
49.129 +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
49.130 +#undef HAVE_DOPRNT
49.131 +
49.132 +/* Define to 1 if you have the <errno.h> header file. */
49.133 +#undef HAVE_ERRNO_H
49.134 +
49.135 +/* Define to 1 if you have the <execinfo.h> header file. */
49.136 +#undef HAVE_EXECINFO_H
49.137 +
49.138 +/* Define to 1 if Ext2 ioctls present */
49.139 +#undef HAVE_EXT2_IOCTLS
49.140 +
49.141 +/* Define to 1 if you have the `fadvise64' function. */
49.142 +#undef HAVE_FADVISE64
49.143 +
49.144 +/* Define to 1 if you have the `fallocate' function. */
49.145 +#undef HAVE_FALLOCATE
49.146 +
49.147 +/* Define to 1 if you have the `fallocate64' function. */
49.148 +#undef HAVE_FALLOCATE64
49.149 +
49.150 +/* Define to 1 if you have the `fchown' function. */
49.151 +#undef HAVE_FCHOWN
49.152 +
49.153 +/* Define to 1 if you have the `fcntl' function. */
49.154 +#undef HAVE_FCNTL
49.155 +
49.156 +/* Define to 1 if you have the `fdatasync' function. */
49.157 +#undef HAVE_FDATASYNC
49.158 +
49.159 +/* Define to 1 if you have the <features.h> header file. */
49.160 +#undef HAVE_FEATURES_H
49.161 +
49.162 +/* Define to 1 if you have the `fstat64' function. */
49.163 +#undef HAVE_FSTAT64
49.164 +
49.165 +/* Define to 1 if you have the `fsync' function. */
49.166 +#undef HAVE_FSYNC
49.167 +
49.168 +/* Define to 1 if you have the `ftruncate64' function. */
49.169 +#undef HAVE_FTRUNCATE64
49.170 +
49.171 +/* Define to 1 if you have the <fuse.h> header file. */
49.172 +#undef HAVE_FUSE_H
49.173 +
49.174 +/* Define to 1 if you have the `futimes' function. */
49.175 +#undef HAVE_FUTIMES
49.176 +
49.177 +/* Define to 1 if you have the `fwprintf' function. */
49.178 +#undef HAVE_FWPRINTF
49.179 +
49.180 +/* Define to 1 if you have the `getcwd' function. */
49.181 +#undef HAVE_GETCWD
49.182 +
49.183 +/* Define to 1 if you have the `getdtablesize' function. */
49.184 +#undef HAVE_GETDTABLESIZE
49.185 +
49.186 +/* Define to 1 if you have the `getegid' function. */
49.187 +#undef HAVE_GETEGID
49.188 +
49.189 +/* Define to 1 if you have the `geteuid' function. */
49.190 +#undef HAVE_GETEUID
49.191 +
49.192 +/* Define to 1 if you have the `getgid' function. */
49.193 +#undef HAVE_GETGID
49.194 +
49.195 +/* Define to 1 if you have the `gethostname' function. */
49.196 +#undef HAVE_GETHOSTNAME
49.197 +
49.198 +/* Define to 1 if you have the `getmntinfo' function. */
49.199 +#undef HAVE_GETMNTINFO
49.200 +
49.201 +/* Define to 1 if you have the <getopt.h> header file. */
49.202 +#undef HAVE_GETOPT_H
49.203 +
49.204 +/* Define to 1 if you have the `getpagesize' function. */
49.205 +#undef HAVE_GETPAGESIZE
49.206 +
49.207 +/* Define to 1 if you have the `getpwuid_r' function. */
49.208 +#undef HAVE_GETPWUID_R
49.209 +
49.210 +/* Define to 1 if you have the `getrlimit' function. */
49.211 +#undef HAVE_GETRLIMIT
49.212 +
49.213 +/* Define to 1 if you have the `getrusage' function. */
49.214 +#undef HAVE_GETRUSAGE
49.215 +
49.216 +/* Define if the GNU gettext() function is already present or preinstalled. */
49.217 +#undef HAVE_GETTEXT
49.218 +
49.219 +/* Define to 1 if you have the `getuid' function. */
49.220 +#undef HAVE_GETUID
49.221 +
49.222 +/* Define if you have the iconv() function and it works. */
49.223 +#undef HAVE_ICONV
49.224 +
49.225 +/* Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>. */
49.226 +#undef HAVE_INTMAX_T
49.227 +
49.228 +/* Define to 1 if the system has the type `intptr_t'. */
49.229 +#undef HAVE_INTPTR_T
49.230 +
49.231 +/* Define to 1 if you have the <inttypes.h> header file. */
49.232 +#undef HAVE_INTTYPES_H
49.233 +
49.234 +/* Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, and
49.235 + declares uintmax_t. */
49.236 +#undef HAVE_INTTYPES_H_WITH_UINTMAX
49.237 +
49.238 +/* Define to 1 if you have the `jrand48' function. */
49.239 +#undef HAVE_JRAND48
49.240 +
49.241 +/* Define to 1 if you have the `keyctl' function. */
49.242 +#undef HAVE_KEYCTL
49.243 +
49.244 +/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
49.245 +#undef HAVE_LANGINFO_CODESET
49.246 +
49.247 +/* Define if your <locale.h> file defines LC_MESSAGES. */
49.248 +#undef HAVE_LC_MESSAGES
49.249 +
49.250 +/* Define to 1 if you have the <limits.h> header file. */
49.251 +#undef HAVE_LIMITS_H
49.252 +
49.253 +/* Define to 1 if you have the <linux/falloc.h> header file. */
49.254 +#undef HAVE_LINUX_FALLOC_H
49.255 +
49.256 +/* Define to 1 if you have the <linux/fd.h> header file. */
49.257 +#undef HAVE_LINUX_FD_H
49.258 +
49.259 +/* Define to 1 if you have the <linux/fsmap.h> header file. */
49.260 +#undef HAVE_LINUX_FSMAP_H
49.261 +
49.262 +/* Define to 1 if you have the <linux/loop.h> header file. */
49.263 +#undef HAVE_LINUX_LOOP_H
49.264 +
49.265 +/* Define to 1 if you have the <linux/major.h> header file. */
49.266 +#undef HAVE_LINUX_MAJOR_H
49.267 +
49.268 +/* Define to 1 if you have the <linux/types.h> header file. */
49.269 +#undef HAVE_LINUX_TYPES_H
49.270 +
49.271 +/* Define to 1 if you have the `llistxattr' function. */
49.272 +#undef HAVE_LLISTXATTR
49.273 +
49.274 +/* Define to 1 if you have the `llseek' function. */
49.275 +#undef HAVE_LLSEEK
49.276 +
49.277 +/* Define to 1 if llseek declared in unistd.h */
49.278 +#undef HAVE_LLSEEK_PROTOTYPE
49.279 +
49.280 +/* Define to 1 if the system has the type 'long long int'. */
49.281 +#undef HAVE_LONG_LONG_INT
49.282 +
49.283 +/* Define to 1 if you have the `lseek64' function. */
49.284 +#undef HAVE_LSEEK64
49.285 +
49.286 +/* Define to 1 if lseek64 declared in unistd.h */
49.287 +#undef HAVE_LSEEK64_PROTOTYPE
49.288 +
49.289 +/* Define to 1 if you have the <magic.h> header file. */
49.290 +#undef HAVE_MAGIC_H
49.291 +
49.292 +/* Define to 1 if you have the `mallinfo' function. */
49.293 +#undef HAVE_MALLINFO
49.294 +
49.295 +/* Define to 1 if you have the <malloc.h> header file. */
49.296 +#undef HAVE_MALLOC_H
49.297 +
49.298 +/* Define to 1 if you have the `mbrtowc' function. */
49.299 +#undef HAVE_MBRTOWC
49.300 +
49.301 +/* Define to 1 if you have the `mbstowcs' function. */
49.302 +#undef HAVE_MBSTOWCS
49.303 +
49.304 +/* Define to 1 if you have the `memalign' function. */
49.305 +#undef HAVE_MEMALIGN
49.306 +
49.307 +/* Define to 1 if you have the <memory.h> header file. */
49.308 +#undef HAVE_MEMORY_H
49.309 +
49.310 +/* Define to 1 if you have the `mempcpy' function. */
49.311 +#undef HAVE_MEMPCPY
49.312 +
49.313 +/* Define to 1 if you have the `mmap' function. */
49.314 +#undef HAVE_MMAP
49.315 +
49.316 +/* Define to 1 if you have the <mntent.h> header file. */
49.317 +#undef HAVE_MNTENT_H
49.318 +
49.319 +/* Define to 1 if you have the `msync' function. */
49.320 +#undef HAVE_MSYNC
49.321 +
49.322 +/* Define to 1 if you have the `munmap' function. */
49.323 +#undef HAVE_MUNMAP
49.324 +
49.325 +/* Define to 1 if you have the `nanosleep' function. */
49.326 +#undef HAVE_NANOSLEEP
49.327 +
49.328 +/* Define to 1 if you have the <netinet/in.h> header file. */
49.329 +#undef HAVE_NETINET_IN_H
49.330 +
49.331 +/* Define to 1 if you have the <net/if_dl.h> header file. */
49.332 +#undef HAVE_NET_IF_DL_H
49.333 +
49.334 +/* Define to 1 if you have the <net/if.h> header file. */
49.335 +#undef HAVE_NET_IF_H
49.336 +
49.337 +/* Define to 1 if you have the `newlocale' function. */
49.338 +#undef HAVE_NEWLOCALE
49.339 +
49.340 +/* Define to 1 if you have the `open64' function. */
49.341 +#undef HAVE_OPEN64
49.342 +
49.343 +/* Define to 1 if optreset for getopt is present */
49.344 +#undef HAVE_OPTRESET
49.345 +
49.346 +/* Define to 1 if you have the `pathconf' function. */
49.347 +#undef HAVE_PATHCONF
49.348 +
49.349 +/* Define to 1 if you have the <paths.h> header file. */
49.350 +#undef HAVE_PATHS_H
49.351 +
49.352 +/* Define to 1 if you have the `posix_fadvise' function. */
49.353 +#undef HAVE_POSIX_FADVISE
49.354 +
49.355 +/* Define to 1 if you have the `posix_fadvise64' function. */
49.356 +#undef HAVE_POSIX_FADVISE64
49.357 +
49.358 +/* Define to 1 if you have the `posix_memalign' function. */
49.359 +#undef HAVE_POSIX_MEMALIGN
49.360 +
49.361 +/* Define if your printf() function supports format strings with positions. */
49.362 +#undef HAVE_POSIX_PRINTF
49.363 +
49.364 +/* Define to 1 if you have the `prctl' function. */
49.365 +#undef HAVE_PRCTL
49.366 +
49.367 +/* Define to 1 if you have the `pread' function. */
49.368 +#undef HAVE_PREAD
49.369 +
49.370 +/* Define to 1 if you have the `pread64' function. */
49.371 +#undef HAVE_PREAD64
49.372 +
49.373 +/* Define to 1 if you have the <pthread.h> header file. */
49.374 +#undef HAVE_PTHREAD_H
49.375 +
49.376 +/* Define if the <pthread.h> defines PTHREAD_MUTEX_RECURSIVE. */
49.377 +#undef HAVE_PTHREAD_MUTEX_RECURSIVE
49.378 +
49.379 +/* Define if the POSIX multithreading library has read/write locks. */
49.380 +#undef HAVE_PTHREAD_RWLOCK
49.381 +
49.382 +/* Define to 1 if you have the `putenv' function. */
49.383 +#undef HAVE_PUTENV
49.384 +
49.385 +/* Define to 1 if you have the `pwrite' function. */
49.386 +#undef HAVE_PWRITE
49.387 +
49.388 +/* Define to 1 if you have the `pwrite64' function. */
49.389 +#undef HAVE_PWRITE64
49.390 +
49.391 +/* Define to 1 if dirent has d_reclen */
49.392 +#undef HAVE_RECLEN_DIRENT
49.393 +
49.394 +/* Define to 1 if if struct sockaddr contains sa_len */
49.395 +#undef HAVE_SA_LEN
49.396 +
49.397 +/* Define to 1 if you have the `secure_getenv' function. */
49.398 +#undef HAVE_SECURE_GETENV
49.399 +
49.400 +/* Define to 1 if you have the <semaphore.h> header file. */
49.401 +#undef HAVE_SEMAPHORE_H
49.402 +
49.403 +/* Define to 1 if sem_init() exists */
49.404 +#undef HAVE_SEM_INIT
49.405 +
49.406 +/* Define to 1 if you have the `setenv' function. */
49.407 +#undef HAVE_SETENV
49.408 +
49.409 +/* Define to 1 if you have the <setjmp.h> header file. */
49.410 +#undef HAVE_SETJMP_H
49.411 +
49.412 +/* Define to 1 if you have the `setlocale' function. */
49.413 +#undef HAVE_SETLOCALE
49.414 +
49.415 +/* Define to 1 if you have the `setmntent' function. */
49.416 +#undef HAVE_SETMNTENT
49.417 +
49.418 +/* Define to 1 if you have the `setresgid' function. */
49.419 +#undef HAVE_SETRESGID
49.420 +
49.421 +/* Define to 1 if you have the `setresuid' function. */
49.422 +#undef HAVE_SETRESUID
49.423 +
49.424 +/* Define to 1 if you have the <signal.h> header file. */
49.425 +#undef HAVE_SIGNAL_H
49.426 +
49.427 +/* Define to 1 if you have the `snprintf' function. */
49.428 +#undef HAVE_SNPRINTF
49.429 +
49.430 +/* Define to 1 if you have the `srandom' function. */
49.431 +#undef HAVE_SRANDOM
49.432 +
49.433 +/* Define to 1 if struct stat has st_flags */
49.434 +#undef HAVE_STAT_FLAGS
49.435 +
49.436 +/* Define to 1 if you have the <stdarg.h> header file. */
49.437 +#undef HAVE_STDARG_H
49.438 +
49.439 +/* Define to 1 if you have the <stddef.h> header file. */
49.440 +#undef HAVE_STDDEF_H
49.441 +
49.442 +/* Define to 1 if you have the <stdint.h> header file. */
49.443 +#undef HAVE_STDINT_H
49.444 +
49.445 +/* Define if <stdint.h> exists, doesn't clash with <sys/types.h>, and declares
49.446 + uintmax_t. */
49.447 +#undef HAVE_STDINT_H_WITH_UINTMAX
49.448 +
49.449 +/* Define to 1 if you have the <stdlib.h> header file. */
49.450 +#undef HAVE_STDLIB_H
49.451 +
49.452 +/* Define to 1 if you have the `stpcpy' function. */
49.453 +#undef HAVE_STPCPY
49.454 +
49.455 +/* Define to 1 if you have the `strcasecmp' function. */
49.456 +#undef HAVE_STRCASECMP
49.457 +
49.458 +/* Define to 1 if you have the `strdup' function. */
49.459 +#undef HAVE_STRDUP
49.460 +
49.461 +/* Define to 1 if you have the <strings.h> header file. */
49.462 +#undef HAVE_STRINGS_H
49.463 +
49.464 +/* Define to 1 if you have the <string.h> header file. */
49.465 +#undef HAVE_STRING_H
49.466 +
49.467 +/* Define to 1 if you have the `strnlen' function. */
49.468 +#undef HAVE_STRNLEN
49.469 +
49.470 +/* Define to 1 if you have the `strptime' function. */
49.471 +#undef HAVE_STRPTIME
49.472 +
49.473 +/* Define to 1 if you have the `strtoul' function. */
49.474 +#undef HAVE_STRTOUL
49.475 +
49.476 +/* Define to 1 if you have the `strtoull' function. */
49.477 +#undef HAVE_STRTOULL
49.478 +
49.479 +/* Define to 1 if `st_atim' is a member of `struct stat'. */
49.480 +#undef HAVE_STRUCT_STAT_ST_ATIM
49.481 +
49.482 +/* Define to 1 if you have the `symlink' function. */
49.483 +#undef HAVE_SYMLINK
49.484 +
49.485 +/* Define to 1 if you have the `sync_file_range' function. */
49.486 +#undef HAVE_SYNC_FILE_RANGE
49.487 +
49.488 +/* Define to 1 if you have the `sysconf' function. */
49.489 +#undef HAVE_SYSCONF
49.490 +
49.491 +/* Define to 1 if you have the <sys/acl.h> header file. */
49.492 +#undef HAVE_SYS_ACL_H
49.493 +
49.494 +/* Define to 1 if you have the <sys/disklabel.h> header file. */
49.495 +#undef HAVE_SYS_DISKLABEL_H
49.496 +
49.497 +/* Define to 1 if you have the <sys/disk.h> header file. */
49.498 +#undef HAVE_SYS_DISK_H
49.499 +
49.500 +/* Define to 1 if you have the <sys/file.h> header file. */
49.501 +#undef HAVE_SYS_FILE_H
49.502 +
49.503 +/* Define to 1 if you have the <sys/ioctl.h> header file. */
49.504 +#undef HAVE_SYS_IOCTL_H
49.505 +
49.506 +/* Define to 1 if you have the <sys/key.h> header file. */
49.507 +#undef HAVE_SYS_KEY_H
49.508 +
49.509 +/* Define to 1 if you have the <sys/mkdev.h> header file. */
49.510 +#undef HAVE_SYS_MKDEV_H
49.511 +
49.512 +/* Define to 1 if you have the <sys/mman.h> header file. */
49.513 +#undef HAVE_SYS_MMAN_H
49.514 +
49.515 +/* Define to 1 if you have the <sys/mount.h> header file. */
49.516 +#undef HAVE_SYS_MOUNT_H
49.517 +
49.518 +/* Define to 1 if you have the <sys/param.h> header file. */
49.519 +#undef HAVE_SYS_PARAM_H
49.520 +
49.521 +/* Define to 1 if you have the <sys/prctl.h> header file. */
49.522 +#undef HAVE_SYS_PRCTL_H
49.523 +
49.524 +/* Define to 1 if you have the <sys/resource.h> header file. */
49.525 +#undef HAVE_SYS_RESOURCE_H
49.526 +
49.527 +/* Define to 1 if you have the <sys/select.h> header file. */
49.528 +#undef HAVE_SYS_SELECT_H
49.529 +
49.530 +/* Define to 1 if you have the <sys/socket.h> header file. */
49.531 +#undef HAVE_SYS_SOCKET_H
49.532 +
49.533 +/* Define to 1 if you have the <sys/sockio.h> header file. */
49.534 +#undef HAVE_SYS_SOCKIO_H
49.535 +
49.536 +/* Define to 1 if you have the <sys/stat.h> header file. */
49.537 +#undef HAVE_SYS_STAT_H
49.538 +
49.539 +/* Define to 1 if you have the <sys/syscall.h> header file. */
49.540 +#undef HAVE_SYS_SYSCALL_H
49.541 +
49.542 +/* Define to 1 if you have the <sys/sysctl.h> header file. */
49.543 +#undef HAVE_SYS_SYSCTL_H
49.544 +
49.545 +/* Define to 1 if you have the <sys/sysmacros.h> header file. */
49.546 +#undef HAVE_SYS_SYSMACROS_H
49.547 +
49.548 +/* Define to 1 if you have the <sys/time.h> header file. */
49.549 +#undef HAVE_SYS_TIME_H
49.550 +
49.551 +/* Define to 1 if you have the <sys/types.h> header file. */
49.552 +#undef HAVE_SYS_TYPES_H
49.553 +
49.554 +/* Define to 1 if you have the <sys/un.h> header file. */
49.555 +#undef HAVE_SYS_UN_H
49.556 +
49.557 +/* Define to 1 if you have the <sys/wait.h> header file. */
49.558 +#undef HAVE_SYS_WAIT_H
49.559 +
49.560 +/* Define to 1 if you have the <sys/xattr.h> header file. */
49.561 +#undef HAVE_SYS_XATTR_H
49.562 +
49.563 +/* Define to 1 if you have the <termios.h> header file. */
49.564 +#undef HAVE_TERMIOS_H
49.565 +
49.566 +/* Define to 1 if you have the <termio.h> header file. */
49.567 +#undef HAVE_TERMIO_H
49.568 +
49.569 +/* Define to 1 if you have the `tsearch' function. */
49.570 +#undef HAVE_TSEARCH
49.571 +
49.572 +/* Define to 1 if ssize_t declared */
49.573 +#undef HAVE_TYPE_SSIZE_T
49.574 +
49.575 +/* Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>. */
49.576 +#undef HAVE_UINTMAX_T
49.577 +
49.578 +/* Define to 1 if you have the <unistd.h> header file. */
49.579 +#undef HAVE_UNISTD_H
49.580 +
49.581 +/* Define to 1 if the system has the type 'unsigned long long int'. */
49.582 +#undef HAVE_UNSIGNED_LONG_LONG_INT
49.583 +
49.584 +/* Define to 1 if you have the `uselocale' function. */
49.585 +#undef HAVE_USELOCALE
49.586 +
49.587 +/* Define to 1 if you have the `usleep' function. */
49.588 +#undef HAVE_USLEEP
49.589 +
49.590 +/* Define to 1 if you have the `utime' function. */
49.591 +#undef HAVE_UTIME
49.592 +
49.593 +/* Define to 1 if you have the `utimes' function. */
49.594 +#undef HAVE_UTIMES
49.595 +
49.596 +/* Define to 1 if you have the <utime.h> header file. */
49.597 +#undef HAVE_UTIME_H
49.598 +
49.599 +/* Define to 1 if you have the `valloc' function. */
49.600 +#undef HAVE_VALLOC
49.601 +
49.602 +/* Define to 1 or 0, depending whether the compiler supports simple visibility
49.603 + declarations. */
49.604 +#undef HAVE_VISIBILITY
49.605 +
49.606 +/* Define to 1 if you have the `vprintf' function. */
49.607 +#undef HAVE_VPRINTF
49.608 +
49.609 +/* Define if you have the 'wchar_t' type. */
49.610 +#undef HAVE_WCHAR_T
49.611 +
49.612 +/* Define to 1 if you have the `wcrtomb' function. */
49.613 +#undef HAVE_WCRTOMB
49.614 +
49.615 +/* Define to 1 if you have the `wcslen' function. */
49.616 +#undef HAVE_WCSLEN
49.617 +
49.618 +/* Define to 1 if you have the `wcsnlen' function. */
49.619 +#undef HAVE_WCSNLEN
49.620 +
49.621 +/* Define if you have the 'wint_t' type. */
49.622 +#undef HAVE_WINT_T
49.623 +
49.624 +/* Define to 1 if O_NOATIME works. */
49.625 +#undef HAVE_WORKING_O_NOATIME
49.626 +
49.627 +/* Define to 1 if O_NOFOLLOW works. */
49.628 +#undef HAVE_WORKING_O_NOFOLLOW
49.629 +
49.630 +/* Define to 1 if you have the `__fsetlocking' function. */
49.631 +#undef HAVE___FSETLOCKING
49.632 +
49.633 +/* Define to 1 if you have the `__secure_getenv' function. */
49.634 +#undef HAVE___SECURE_GETENV
49.635 +
49.636 +/* Define as const if the declaration of iconv() needs const. */
49.637 +#undef ICONV_CONST
49.638 +
49.639 +/* Define if integer division by zero raises signal SIGFPE. */
49.640 +#undef INTDIV0_RAISES_SIGFPE
49.641 +
49.642 +/* package name for gettext */
49.643 +#undef PACKAGE
49.644 +
49.645 +/* Define to the address where bug reports for this package should be sent. */
49.646 +#undef PACKAGE_BUGREPORT
49.647 +
49.648 +/* Define to the full name of this package. */
49.649 +#undef PACKAGE_NAME
49.650 +
49.651 +/* Define to the full name and version of this package. */
49.652 +#undef PACKAGE_STRING
49.653 +
49.654 +/* Define to the one symbol short name of this package. */
49.655 +#undef PACKAGE_TARNAME
49.656 +
49.657 +/* Define to the home page for this package. */
49.658 +#undef PACKAGE_URL
49.659 +
49.660 +/* Define to the version of this package. */
49.661 +#undef PACKAGE_VERSION
49.662 +
49.663 +/* Define if <inttypes.h> exists and defines unusable PRI* macros. */
49.664 +#undef PRI_MACROS_BROKEN
49.665 +
49.666 +/* Define if the pthread_in_use() detection is hard. */
49.667 +#undef PTHREAD_IN_USE_DETECTION_HARD
49.668 +
49.669 +/* The size of `int', as computed by sizeof. */
49.670 +#undef SIZEOF_INT
49.671 +
49.672 +/* The size of `long', as computed by sizeof. */
49.673 +#undef SIZEOF_LONG
49.674 +
49.675 +/* The size of `long long', as computed by sizeof. */
49.676 +#undef SIZEOF_LONG_LONG
49.677 +
49.678 +/* The size of `off_t', as computed by sizeof. */
49.679 +#undef SIZEOF_OFF_T
49.680 +
49.681 +/* The size of `short', as computed by sizeof. */
49.682 +#undef SIZEOF_SHORT
49.683 +
49.684 +/* The size of `time_t', as computed by sizeof. */
49.685 +#undef SIZEOF_TIME_T
49.686 +
49.687 +/* Define as the maximum value of type 'size_t', if the system doesn't define
49.688 + it. */
49.689 +#ifndef SIZE_MAX
49.690 +# undef SIZE_MAX
49.691 +#endif
49.692 +
49.693 +/* If using the C implementation of alloca, define if you know the
49.694 + direction of stack growth for your system; otherwise it will be
49.695 + automatically deduced at runtime.
49.696 + STACK_DIRECTION > 0 => grows toward higher addresses
49.697 + STACK_DIRECTION < 0 => grows toward lower addresses
49.698 + STACK_DIRECTION = 0 => direction of growth unknown */
49.699 +#undef STACK_DIRECTION
49.700 +
49.701 +/* Define to 1 if you have the ANSI C header files. */
49.702 +#undef STDC_HEADERS
49.703 +
49.704 +/* If the compiler supports a TLS storage class define it to that here */
49.705 +#undef TLS
49.706 +
49.707 +/* Define if the POSIX multithreading library can be used. */
49.708 +#undef USE_POSIX_THREADS
49.709 +
49.710 +/* Define if references to the POSIX multithreading library should be made
49.711 + weak. */
49.712 +#undef USE_POSIX_THREADS_WEAK
49.713 +
49.714 +/* Define if the GNU Pth multithreading library can be used. */
49.715 +#undef USE_PTH_THREADS
49.716 +
49.717 +/* Define if references to the GNU Pth multithreading library should be made
49.718 + weak. */
49.719 +#undef USE_PTH_THREADS_WEAK
49.720 +
49.721 +/* Define if the old Solaris multithreading library can be used. */
49.722 +#undef USE_SOLARIS_THREADS
49.723 +
49.724 +/* Define if references to the old Solaris multithreading library should be
49.725 + made weak. */
49.726 +#undef USE_SOLARIS_THREADS_WEAK
49.727 +
49.728 +/* Enable extensions on AIX 3, Interix. */
49.729 +#ifndef _ALL_SOURCE
49.730 +# undef _ALL_SOURCE
49.731 +#endif
49.732 +/* Enable GNU extensions on systems that have them. */
49.733 +#ifndef _GNU_SOURCE
49.734 +# undef _GNU_SOURCE
49.735 +#endif
49.736 +/* Enable threading extensions on Solaris. */
49.737 +#ifndef _POSIX_PTHREAD_SEMANTICS
49.738 +# undef _POSIX_PTHREAD_SEMANTICS
49.739 +#endif
49.740 +/* Enable extensions on HP NonStop. */
49.741 +#ifndef _TANDEM_SOURCE
49.742 +# undef _TANDEM_SOURCE
49.743 +#endif
49.744 +/* Enable general extensions on Solaris. */
49.745 +#ifndef __EXTENSIONS__
49.746 +# undef __EXTENSIONS__
49.747 +#endif
49.748 +
49.749 +
49.750 +/* Define to 1 to build uuidd */
49.751 +#undef USE_UUIDD
49.752 +
49.753 +/* Define if the native Windows multithreading API can be used. */
49.754 +#undef USE_WINDOWS_THREADS
49.755 +
49.756 +/* version for gettext */
49.757 +#undef VERSION
49.758 +
49.759 +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
49.760 + significant byte first (like Motorola and SPARC, unlike Intel). */
49.761 +#if defined AC_APPLE_UNIVERSAL_BUILD
49.762 +# if defined __BIG_ENDIAN__
49.763 +# define WORDS_BIGENDIAN 1
49.764 +# endif
49.765 +#else
49.766 +# ifndef WORDS_BIGENDIAN
49.767 +# undef WORDS_BIGENDIAN
49.768 +# endif
49.769 +#endif
49.770 +
49.771 +/* Define to 1 if Apple Darwin libintl workaround is needed */
49.772 +#undef _INTL_REDIRECT_MACROS
49.773 +
49.774 +/* Define to 1 if on MINIX. */
49.775 +#undef _MINIX
49.776 +
49.777 +/* Define to 2 if the system does not provide POSIX.1 features except with
49.778 + this defined. */
49.779 +#undef _POSIX_1_SOURCE
49.780 +
49.781 +/* Define to 1 if you need to in order for `stat' and other things to work. */
49.782 +#undef _POSIX_SOURCE
49.783 +
49.784 +/* Please see the Gnulib manual for how to use these macros.
49.785 +
49.786 + Suppress extern inline with HP-UX cc, as it appears to be broken; see
49.787 + <http://lists.gnu.org/archive/html/bug-texinfo/2013-02/msg00030.html>.
49.788 +
49.789 + Suppress extern inline with Sun C in standards-conformance mode, as it
49.790 + mishandles inline functions that call each other. E.g., for 'inline void f
49.791 + (void) { } inline void g (void) { f (); }', c99 incorrectly complains
49.792 + 'reference to static identifier "f" in extern inline function'.
49.793 + This bug was observed with Sun C 5.12 SunOS_i386 2011/11/16.
49.794 +
49.795 + Suppress the use of extern inline on Apple's platforms, as Libc at least
49.796 + through Libc-825.26 (2013-04-09) is incompatible with it; see, e.g.,
49.797 + <http://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html>.
49.798 + Perhaps Apple will fix this some day. */
49.799 +#if ((__GNUC__ \
49.800 + ? defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ \
49.801 + : (199901L <= __STDC_VERSION__ \
49.802 + && !defined __HP_cc \
49.803 + && !(defined __SUNPRO_C && __STDC__))) \
49.804 + && !defined __APPLE__)
49.805 +# define _GL_INLINE inline
49.806 +# define _GL_EXTERN_INLINE extern inline
49.807 +#elif (2 < __GNUC__ + (7 <= __GNUC_MINOR__) && !defined __STRICT_ANSI__ \
49.808 + && !defined __APPLE__)
49.809 +# if __GNUC_GNU_INLINE__
49.810 + /* __gnu_inline__ suppresses a GCC 4.2 diagnostic. */
49.811 +# define _GL_INLINE extern inline __attribute__ ((__gnu_inline__))
49.812 +# else
49.813 +# define _GL_INLINE extern inline
49.814 +# endif
49.815 +# define _GL_EXTERN_INLINE extern
49.816 +#else
49.817 +# define _GL_INLINE static _GL_UNUSED
49.818 +# define _GL_EXTERN_INLINE static _GL_UNUSED
49.819 +#endif
49.820 +
49.821 +#if 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
49.822 +# if defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__
49.823 +# define _GL_INLINE_HEADER_CONST_PRAGMA
49.824 +# else
49.825 +# define _GL_INLINE_HEADER_CONST_PRAGMA \
49.826 + _Pragma ("GCC diagnostic ignored \"-Wsuggest-attribute=const\"")
49.827 +# endif
49.828 + /* Suppress GCC's bogus "no previous prototype for 'FOO'"
49.829 + and "no previous declaration for 'FOO'" diagnostics,
49.830 + when FOO is an inline function in the header; see
49.831 + <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54113>. */
49.832 +# define _GL_INLINE_HEADER_BEGIN \
49.833 + _Pragma ("GCC diagnostic push") \
49.834 + _Pragma ("GCC diagnostic ignored \"-Wmissing-prototypes\"") \
49.835 + _Pragma ("GCC diagnostic ignored \"-Wmissing-declarations\"") \
49.836 + _GL_INLINE_HEADER_CONST_PRAGMA
49.837 +# define _GL_INLINE_HEADER_END \
49.838 + _Pragma ("GCC diagnostic pop")
49.839 +#else
49.840 +# define _GL_INLINE_HEADER_BEGIN
49.841 +# define _GL_INLINE_HEADER_END
49.842 +#endif
49.843 +
49.844 +/* Define to `__inline__' or `__inline' if that's what the C compiler
49.845 + calls it, or to nothing if 'inline' is not supported under any name. */
49.846 +#ifndef __cplusplus
49.847 +#undef inline
49.848 +#endif
49.849 +
49.850 +/* Define as the type of the result of subtracting two pointers, if the system
49.851 + doesn't define it. */
49.852 +#undef ptrdiff_t
49.853 +
49.854 +/* Define to `unsigned int' if <sys/types.h> does not define. */
49.855 +#undef size_t
49.856 +
49.857 +/* Define to unsigned long or unsigned long long if <stdint.h> and
49.858 + <inttypes.h> don't define. */
49.859 +#undef uintmax_t
49.860 +
49.861 +#include <dirpaths.h>
49.862 +
49.863 +
49.864 +#define __libc_lock_t gl_lock_t
49.865 +#define __libc_lock_define gl_lock_define
49.866 +#define __libc_lock_define_initialized gl_lock_define_initialized
49.867 +#define __libc_lock_init gl_lock_init
49.868 +#define __libc_lock_lock gl_lock_lock
49.869 +#define __libc_lock_unlock gl_lock_unlock
49.870 +#define __libc_lock_recursive_t gl_recursive_lock_t
49.871 +#define __libc_lock_define_recursive gl_recursive_lock_define
49.872 +#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized
49.873 +#define __libc_lock_init_recursive gl_recursive_lock_init
49.874 +#define __libc_lock_lock_recursive gl_recursive_lock_lock
49.875 +#define __libc_lock_unlock_recursive gl_recursive_lock_unlock
49.876 +#define glthread_in_use libintl_thread_in_use
49.877 +#define glthread_lock_init_func libintl_lock_init_func
49.878 +#define glthread_lock_lock_func libintl_lock_lock_func
49.879 +#define glthread_lock_unlock_func libintl_lock_unlock_func
49.880 +#define glthread_lock_destroy_func libintl_lock_destroy_func
49.881 +#define glthread_rwlock_init_multithreaded libintl_rwlock_init_multithreaded
49.882 +#define glthread_rwlock_init_func libintl_rwlock_init_func
49.883 +#define glthread_rwlock_rdlock_multithreaded libintl_rwlock_rdlock_multithreaded
49.884 +#define glthread_rwlock_rdlock_func libintl_rwlock_rdlock_func
49.885 +#define glthread_rwlock_wrlock_multithreaded libintl_rwlock_wrlock_multithreaded
49.886 +#define glthread_rwlock_wrlock_func libintl_rwlock_wrlock_func
49.887 +#define glthread_rwlock_unlock_multithreaded libintl_rwlock_unlock_multithreaded
49.888 +#define glthread_rwlock_unlock_func libintl_rwlock_unlock_func
49.889 +#define glthread_rwlock_destroy_multithreaded libintl_rwlock_destroy_multithreaded
49.890 +#define glthread_rwlock_destroy_func libintl_rwlock_destroy_func
49.891 +#define glthread_recursive_lock_init_multithreaded libintl_recursive_lock_init_multithreaded
49.892 +#define glthread_recursive_lock_init_func libintl_recursive_lock_init_func
49.893 +#define glthread_recursive_lock_lock_multithreaded libintl_recursive_lock_lock_multithreaded
49.894 +#define glthread_recursive_lock_lock_func libintl_recursive_lock_lock_func
49.895 +#define glthread_recursive_lock_unlock_multithreaded libintl_recursive_lock_unlock_multithreaded
49.896 +#define glthread_recursive_lock_unlock_func libintl_recursive_lock_unlock_func
49.897 +#define glthread_recursive_lock_destroy_multithreaded libintl_recursive_lock_destroy_multithreaded
49.898 +#define glthread_recursive_lock_destroy_func libintl_recursive_lock_destroy_func
49.899 +#define glthread_once_func libintl_once_func
49.900 +#define glthread_once_singlethreaded libintl_once_singlethreaded
49.901 +#define glthread_once_multithreaded libintl_once_multithreaded
49.902 +
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/libext2fs/lib/libblkid/Makefile Wed Aug 25 01:28:08 2021 +0200
50.3 @@ -0,0 +1,19 @@
50.4 +PKGDIR ?= ../..
50.5 +L4DIR ?= $(PKGDIR)/../../..
50.6 +
50.7 +TARGET = libblkid.a libblkid.so
50.8 +PC_FILENAME = libblkid
50.9 +SRC_C = \
50.10 + cache.c dev.c devname.c devno.c getsize.c llseek.c probe.c \
50.11 + read.c resolve.c save.c tag.c tst_types.c version.c
50.12 +
50.13 +REQUIRES_LIBS = libuuid
50.14 +
50.15 +PRIVATE_INCDIR += \
50.16 + $(PKGDIR)/lib $(PKGDIR)/lib/libblkid \
50.17 + $(PKGDIR)/include/libblkid \
50.18 + $(PKGDIR)/include/libuuid
50.19 +
50.20 +CONTRIB_INCDIR = libblkid
50.21 +
50.22 +include $(L4DIR)/mk/lib.mk
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/libext2fs/lib/libblkid/blkidP.h Wed Aug 25 01:28:08 2021 +0200
51.3 @@ -0,0 +1,204 @@
51.4 +/*
51.5 + * blkidP.h - Internal interfaces for libblkid
51.6 + *
51.7 + * Copyright (C) 2001 Andreas Dilger
51.8 + * Copyright (C) 2003 Theodore Ts'o
51.9 + *
51.10 + * %Begin-Header%
51.11 + * This file may be redistributed under the terms of the
51.12 + * GNU Lesser General Public License.
51.13 + * %End-Header%
51.14 + */
51.15 +
51.16 +#ifndef _BLKID_BLKIDP_H
51.17 +#define _BLKID_BLKIDP_H
51.18 +
51.19 +#include <sys/types.h>
51.20 +#include <stdio.h>
51.21 +#if HAVE_SYS_TYPES_H
51.22 +#include <sys/types.h>
51.23 +#endif
51.24 +#if HAVE_SYS_STAT_H
51.25 +#include <sys/stat.h>
51.26 +#endif
51.27 +
51.28 +#include <blkid/blkid.h>
51.29 +
51.30 +#include <blkid/list.h>
51.31 +
51.32 +#ifdef __GNUC__
51.33 +#define __BLKID_ATTR(x) __attribute__(x)
51.34 +#else
51.35 +#define __BLKID_ATTR(x)
51.36 +#endif
51.37 +
51.38 +
51.39 +/*
51.40 + * This describes the attributes of a specific device.
51.41 + * We can traverse all of the tags by bid_tags (linking to the tag bit_names).
51.42 + * The bid_label and bid_uuid fields are shortcuts to the LABEL and UUID tag
51.43 + * values, if they exist.
51.44 + */
51.45 +struct blkid_struct_dev
51.46 +{
51.47 + struct list_head bid_devs; /* All devices in the cache */
51.48 + struct list_head bid_tags; /* All tags for this device */
51.49 + blkid_cache bid_cache; /* Dev belongs to this cache */
51.50 + char *bid_name; /* Device inode pathname */
51.51 + char *bid_type; /* Preferred device TYPE */
51.52 + int bid_pri; /* Device priority */
51.53 + dev_t bid_devno; /* Device major/minor number */
51.54 + time_t bid_time; /* Last update time of device */
51.55 + unsigned int bid_flags; /* Device status bitflags */
51.56 + char *bid_label; /* Shortcut to device LABEL */
51.57 + char *bid_uuid; /* Shortcut to binary UUID */
51.58 +};
51.59 +
51.60 +#define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */
51.61 +#define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */
51.62 +
51.63 +/*
51.64 + * Each tag defines a NAME=value pair for a particular device. The tags
51.65 + * are linked via bit_names for a single device, so that traversing the
51.66 + * names list will get you a list of all tags associated with a device.
51.67 + * They are also linked via bit_values for all devices, so one can easily
51.68 + * search all tags with a given NAME for a specific value.
51.69 + */
51.70 +struct blkid_struct_tag
51.71 +{
51.72 + struct list_head bit_tags; /* All tags for this device */
51.73 + struct list_head bit_names; /* All tags with given NAME */
51.74 + char *bit_name; /* NAME of tag (shared) */
51.75 + char *bit_val; /* value of tag */
51.76 + blkid_dev bit_dev; /* pointer to device */
51.77 +};
51.78 +typedef struct blkid_struct_tag *blkid_tag;
51.79 +
51.80 +/*
51.81 + * Minimum number of seconds between device probes, even when reading
51.82 + * from the cache. This is to avoid re-probing all devices which were
51.83 + * just probed by another program that does not share the cache.
51.84 + */
51.85 +#define BLKID_PROBE_MIN 2
51.86 +
51.87 +/*
51.88 + * Time in seconds an entry remains verified in the in-memory cache
51.89 + * before being reverified (in case of long-running processes that
51.90 + * keep a cache in memory and continue to use it for a long time).
51.91 + */
51.92 +#define BLKID_PROBE_INTERVAL 200
51.93 +
51.94 +/* This describes an entire blkid cache file and probed devices.
51.95 + * We can traverse all of the found devices via bic_list.
51.96 + * We can traverse all of the tag types by bic_tags, which hold empty tags
51.97 + * for each tag type. Those tags can be used as list_heads for iterating
51.98 + * through all devices with a specific tag type (e.g. LABEL).
51.99 + */
51.100 +struct blkid_struct_cache
51.101 +{
51.102 + struct list_head bic_devs; /* List head of all devices */
51.103 + struct list_head bic_tags; /* List head of all tag types */
51.104 + time_t bic_time; /* Last probe time */
51.105 + time_t bic_ftime; /* Mod time of the cachefile */
51.106 + unsigned int bic_flags; /* Status flags of the cache */
51.107 + char *bic_filename; /* filename of cache */
51.108 +};
51.109 +
51.110 +#define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */
51.111 +#define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */
51.112 +
51.113 +extern char *blkid_strdup(const char *s);
51.114 +extern char *blkid_strndup(const char *s, const int length);
51.115 +
51.116 +#define BLKID_CACHE_FILE "/etc/blkid.tab"
51.117 +
51.118 +#define BLKID_ERR_IO 5
51.119 +#define BLKID_ERR_PROC 9
51.120 +#define BLKID_ERR_MEM 12
51.121 +#define BLKID_ERR_CACHE 14
51.122 +#define BLKID_ERR_DEV 19
51.123 +#define BLKID_ERR_PARAM 22
51.124 +#define BLKID_ERR_BIG 27
51.125 +
51.126 +/*
51.127 + * Priority settings for different types of devices
51.128 + */
51.129 +#define BLKID_PRI_DM 40
51.130 +#define BLKID_PRI_EVMS 30
51.131 +#define BLKID_PRI_LVM 20
51.132 +#define BLKID_PRI_MD 10
51.133 +
51.134 +#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG)
51.135 +#define CONFIG_BLKID_DEBUG
51.136 +#endif
51.137 +
51.138 +#define DEBUG_CACHE 0x0001
51.139 +#define DEBUG_DUMP 0x0002
51.140 +#define DEBUG_DEV 0x0004
51.141 +#define DEBUG_DEVNAME 0x0008
51.142 +#define DEBUG_DEVNO 0x0010
51.143 +#define DEBUG_PROBE 0x0020
51.144 +#define DEBUG_READ 0x0040
51.145 +#define DEBUG_RESOLVE 0x0080
51.146 +#define DEBUG_SAVE 0x0100
51.147 +#define DEBUG_TAG 0x0200
51.148 +#define DEBUG_INIT 0x8000
51.149 +#define DEBUG_ALL 0xFFFF
51.150 +
51.151 +#ifdef CONFIG_BLKID_DEBUG
51.152 +#include <stdio.h>
51.153 +extern int blkid_debug_mask;
51.154 +#define DBG(m,x) if ((m) & blkid_debug_mask) x;
51.155 +#else
51.156 +#define DBG(m,x)
51.157 +#endif
51.158 +
51.159 +#ifdef CONFIG_BLKID_DEBUG
51.160 +extern void blkid_debug_dump_dev(blkid_dev dev);
51.161 +extern void blkid_debug_dump_tag(blkid_tag tag);
51.162 +#endif
51.163 +
51.164 +static inline int blkidP_is_disk_device(mode_t mode)
51.165 +{
51.166 +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
51.167 + return S_ISBLK(mode) || S_ISCHR(mode);
51.168 +#else
51.169 + return S_ISBLK(mode);
51.170 +#endif
51.171 +}
51.172 +
51.173 +/* devno.c */
51.174 +struct dir_list {
51.175 + char *name;
51.176 + struct dir_list *next;
51.177 +};
51.178 +extern void blkid__scan_dir(const char *, dev_t, struct dir_list **, char **);
51.179 +
51.180 +/* lseek.c */
51.181 +extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence);
51.182 +
51.183 +/* read.c */
51.184 +extern void blkid_read_cache(blkid_cache cache);
51.185 +
51.186 +/* save.c */
51.187 +extern int blkid_flush_cache(blkid_cache cache);
51.188 +
51.189 +/*
51.190 + * Functions to create and find a specific tag type: tag.c
51.191 + */
51.192 +extern void blkid_free_tag(blkid_tag tag);
51.193 +extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type);
51.194 +extern int blkid_set_tag(blkid_dev dev, const char *name,
51.195 + const char *value, const int vlength);
51.196 +
51.197 +/*
51.198 + * Functions to create and find a specific tag type: dev.c
51.199 + */
51.200 +extern blkid_dev blkid_new_dev(void);
51.201 +extern void blkid_free_dev(blkid_dev dev);
51.202 +
51.203 +#ifdef __cplusplus
51.204 +}
51.205 +#endif
51.206 +
51.207 +#endif /* _BLKID_BLKIDP_H */
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/libext2fs/lib/libblkid/cache.c Wed Aug 25 01:28:08 2021 +0200
52.3 @@ -0,0 +1,209 @@
52.4 +/*
52.5 + * cache.c - allocation/initialization/free routines for cache
52.6 + *
52.7 + * Copyright (C) 2001 Andreas Dilger
52.8 + * Copyright (C) 2003 Theodore Ts'o
52.9 + *
52.10 + * %Begin-Header%
52.11 + * This file may be redistributed under the terms of the
52.12 + * GNU Lesser General Public License.
52.13 + * %End-Header%
52.14 + */
52.15 +
52.16 +#include "config.h"
52.17 +#if HAVE_UNISTD_H
52.18 +#include <unistd.h>
52.19 +#endif
52.20 +#ifdef HAVE_ERRNO_H
52.21 +#include <errno.h>
52.22 +#endif
52.23 +#include <stdlib.h>
52.24 +#include <string.h>
52.25 +#ifdef HAVE_SYS_PRCTL_H
52.26 +#include <sys/prctl.h>
52.27 +#else
52.28 +#define PR_GET_DUMPABLE 3
52.29 +#endif
52.30 +#if (!defined(HAVE_PRCTL) && defined(linux))
52.31 +#include <sys/syscall.h>
52.32 +#endif
52.33 +#ifdef HAVE_SYS_STAT_H
52.34 +#include <sys/stat.h>
52.35 +#endif
52.36 +#include "blkidP.h"
52.37 +
52.38 +int blkid_debug_mask = 0;
52.39 +
52.40 +
52.41 +static char *safe_getenv(const char *arg)
52.42 +{
52.43 + if ((getuid() != geteuid()) || (getgid() != getegid()))
52.44 + return NULL;
52.45 +#if HAVE_PRCTL
52.46 + if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
52.47 + return NULL;
52.48 +#else
52.49 +#if (defined(linux) && defined(SYS_prctl))
52.50 + if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
52.51 + return NULL;
52.52 +#endif
52.53 +#endif
52.54 +
52.55 +#if defined(HAVE_SECURE_GETENV)
52.56 + return secure_getenv(arg);
52.57 +#elif defined(HAVE___SECURE_GETENV)
52.58 + return __secure_getenv(arg);
52.59 +#else
52.60 + return getenv(arg);
52.61 +#endif
52.62 +}
52.63 +
52.64 +#if 0 /* ifdef CONFIG_BLKID_DEBUG */
52.65 +static blkid_debug_dump_cache(int mask, blkid_cache cache)
52.66 +{
52.67 + struct list_head *p;
52.68 +
52.69 + if (!cache) {
52.70 + printf("cache: NULL\n");
52.71 + return;
52.72 + }
52.73 +
52.74 + printf("cache: time = %lu\n", cache->bic_time);
52.75 + printf("cache: flags = 0x%08X\n", cache->bic_flags);
52.76 +
52.77 + list_for_each(p, &cache->bic_devs) {
52.78 + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
52.79 + blkid_debug_dump_dev(dev);
52.80 + }
52.81 +}
52.82 +#endif
52.83 +
52.84 +int blkid_get_cache(blkid_cache *ret_cache, const char *filename)
52.85 +{
52.86 + blkid_cache cache;
52.87 +
52.88 +#ifdef CONFIG_BLKID_DEBUG
52.89 + if (!(blkid_debug_mask & DEBUG_INIT)) {
52.90 + char *dstr = getenv("BLKID_DEBUG");
52.91 +
52.92 + if (dstr)
52.93 + blkid_debug_mask = strtoul(dstr, 0, 0);
52.94 + blkid_debug_mask |= DEBUG_INIT;
52.95 + }
52.96 +#endif
52.97 +
52.98 + DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n",
52.99 + filename ? filename : "default cache"));
52.100 +
52.101 + if (!(cache = (blkid_cache) calloc(1, sizeof(struct blkid_struct_cache))))
52.102 + return -BLKID_ERR_MEM;
52.103 +
52.104 + INIT_LIST_HEAD(&cache->bic_devs);
52.105 + INIT_LIST_HEAD(&cache->bic_tags);
52.106 +
52.107 + if (filename && !strlen(filename))
52.108 + filename = 0;
52.109 + if (!filename)
52.110 + filename = safe_getenv("BLKID_FILE");
52.111 + if (!filename)
52.112 + filename = BLKID_CACHE_FILE;
52.113 + cache->bic_filename = blkid_strdup(filename);
52.114 +
52.115 + blkid_read_cache(cache);
52.116 +
52.117 + *ret_cache = cache;
52.118 + return 0;
52.119 +}
52.120 +
52.121 +void blkid_put_cache(blkid_cache cache)
52.122 +{
52.123 + if (!cache)
52.124 + return;
52.125 +
52.126 + (void) blkid_flush_cache(cache);
52.127 +
52.128 + DBG(DEBUG_CACHE, printf("freeing cache struct\n"));
52.129 +
52.130 + /* DBG(DEBUG_CACHE, blkid_debug_dump_cache(cache)); */
52.131 +
52.132 + while (!list_empty(&cache->bic_devs)) {
52.133 + blkid_dev dev = list_entry(cache->bic_devs.next,
52.134 + struct blkid_struct_dev,
52.135 + bid_devs);
52.136 + blkid_free_dev(dev);
52.137 + }
52.138 +
52.139 + while (!list_empty(&cache->bic_tags)) {
52.140 + blkid_tag tag = list_entry(cache->bic_tags.next,
52.141 + struct blkid_struct_tag,
52.142 + bit_tags);
52.143 +
52.144 + while (!list_empty(&tag->bit_names)) {
52.145 + blkid_tag bad = list_entry(tag->bit_names.next,
52.146 + struct blkid_struct_tag,
52.147 + bit_names);
52.148 +
52.149 + DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n",
52.150 + bad->bit_name, bad->bit_val));
52.151 + blkid_free_tag(bad);
52.152 + }
52.153 + blkid_free_tag(tag);
52.154 + }
52.155 + free(cache->bic_filename);
52.156 +
52.157 + free(cache);
52.158 +}
52.159 +
52.160 +void blkid_gc_cache(blkid_cache cache)
52.161 +{
52.162 + struct list_head *p, *pnext;
52.163 + struct stat st;
52.164 +
52.165 + if (!cache)
52.166 + return;
52.167 +
52.168 + list_for_each_safe(p, pnext, &cache->bic_devs) {
52.169 + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
52.170 + if (stat(dev->bid_name, &st) < 0) {
52.171 + DBG(DEBUG_CACHE,
52.172 + printf("freeing %s\n", dev->bid_name));
52.173 + blkid_free_dev(dev);
52.174 + cache->bic_flags |= BLKID_BIC_FL_CHANGED;
52.175 + } else {
52.176 + DBG(DEBUG_CACHE,
52.177 + printf("Device %s exists\n", dev->bid_name));
52.178 + }
52.179 + }
52.180 +}
52.181 +
52.182 +
52.183 +#ifdef TEST_PROGRAM
52.184 +int main(int argc, char** argv)
52.185 +{
52.186 + blkid_cache cache = NULL;
52.187 + int ret;
52.188 +
52.189 + blkid_debug_mask = DEBUG_ALL;
52.190 + if ((argc > 2)) {
52.191 + fprintf(stderr, "Usage: %s [filename] \n", argv[0]);
52.192 + exit(1);
52.193 + }
52.194 +
52.195 + if ((ret = blkid_get_cache(&cache, argv[1])) < 0) {
52.196 + fprintf(stderr, "error %d parsing cache file %s\n", ret,
52.197 + argv[1] ? argv[1] : BLKID_CACHE_FILE);
52.198 + exit(1);
52.199 + }
52.200 + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
52.201 + fprintf(stderr, "%s: error creating cache (%d)\n",
52.202 + argv[0], ret);
52.203 + exit(1);
52.204 + }
52.205 + if ((ret = blkid_probe_all(cache) < 0))
52.206 + fprintf(stderr, "error probing devices\n");
52.207 +
52.208 + blkid_put_cache(cache);
52.209 +
52.210 + return ret;
52.211 +}
52.212 +#endif
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/libext2fs/lib/libblkid/dev.c Wed Aug 25 01:28:08 2021 +0200
53.3 @@ -0,0 +1,254 @@
53.4 +/*
53.5 + * dev.c - allocation/initialization/free routines for dev
53.6 + *
53.7 + * Copyright (C) 2001 Andreas Dilger
53.8 + * Copyright (C) 2003 Theodore Ts'o
53.9 + *
53.10 + * %Begin-Header%
53.11 + * This file may be redistributed under the terms of the
53.12 + * GNU Lesser General Public License.
53.13 + * %End-Header%
53.14 + */
53.15 +
53.16 +#include "config.h"
53.17 +#include <stdlib.h>
53.18 +#include <string.h>
53.19 +#include <stdint.h>
53.20 +
53.21 +#include "blkidP.h"
53.22 +
53.23 +blkid_dev blkid_new_dev(void)
53.24 +{
53.25 + blkid_dev dev;
53.26 +
53.27 + if (!(dev = (blkid_dev) calloc(1, sizeof(struct blkid_struct_dev))))
53.28 + return NULL;
53.29 +
53.30 + INIT_LIST_HEAD(&dev->bid_devs);
53.31 + INIT_LIST_HEAD(&dev->bid_tags);
53.32 +
53.33 + return dev;
53.34 +}
53.35 +
53.36 +void blkid_free_dev(blkid_dev dev)
53.37 +{
53.38 + if (!dev)
53.39 + return;
53.40 +
53.41 + DBG(DEBUG_DEV,
53.42 + printf(" freeing dev %s (%s)\n", dev->bid_name, dev->bid_type ?
53.43 + dev->bid_type : "(null)"));
53.44 + DBG(DEBUG_DEV, blkid_debug_dump_dev(dev));
53.45 +
53.46 + list_del(&dev->bid_devs);
53.47 + while (!list_empty(&dev->bid_tags)) {
53.48 + blkid_tag tag = list_entry(dev->bid_tags.next,
53.49 + struct blkid_struct_tag,
53.50 + bit_tags);
53.51 + blkid_free_tag(tag);
53.52 + }
53.53 + free(dev->bid_name);
53.54 + free(dev);
53.55 +}
53.56 +
53.57 +/*
53.58 + * Given a blkid device, return its name
53.59 + */
53.60 +extern const char *blkid_dev_devname(blkid_dev dev)
53.61 +{
53.62 + return dev->bid_name;
53.63 +}
53.64 +
53.65 +#ifdef CONFIG_BLKID_DEBUG
53.66 +void blkid_debug_dump_dev(blkid_dev dev)
53.67 +{
53.68 + struct list_head *p;
53.69 +
53.70 + if (!dev) {
53.71 + printf(" dev: NULL\n");
53.72 + return;
53.73 + }
53.74 +
53.75 + printf(" dev: name = %s\n", dev->bid_name);
53.76 + printf(" dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno);
53.77 + printf(" dev: TIME=\"%ld\"\n", (long)dev->bid_time);
53.78 + printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
53.79 + printf(" dev: flags = 0x%08X\n", dev->bid_flags);
53.80 +
53.81 + list_for_each(p, &dev->bid_tags) {
53.82 + blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
53.83 + if (tag)
53.84 + printf(" tag: %s=\"%s\"\n", tag->bit_name,
53.85 + tag->bit_val);
53.86 + else
53.87 + printf(" tag: NULL\n");
53.88 + }
53.89 + printf("\n");
53.90 +}
53.91 +#endif
53.92 +
53.93 +/*
53.94 + * dev iteration routines for the public libblkid interface.
53.95 + *
53.96 + * These routines do not expose the list.h implementation, which are a
53.97 + * contamination of the namespace, and which force us to reveal far, far
53.98 + * too much of our internal implementation. I'm not convinced I want
53.99 + * to keep list.h in the long term, anyway. It's fine for kernel
53.100 + * programming, but performance is not the #1 priority for this
53.101 + * library, and I really don't like the tradeoff of type-safety for
53.102 + * performance for this application. [tytso:20030125.2007EST]
53.103 + */
53.104 +
53.105 +/*
53.106 + * This series of functions iterate over all devices in a blkid cache
53.107 + */
53.108 +#define DEV_ITERATE_MAGIC 0x01a5284c
53.109 +
53.110 +struct blkid_struct_dev_iterate {
53.111 + int magic;
53.112 + blkid_cache cache;
53.113 + char *search_type;
53.114 + char *search_value;
53.115 + struct list_head *p;
53.116 +};
53.117 +
53.118 +extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache)
53.119 +{
53.120 + blkid_dev_iterate iter;
53.121 +
53.122 + iter = malloc(sizeof(struct blkid_struct_dev_iterate));
53.123 + if (iter) {
53.124 + iter->magic = DEV_ITERATE_MAGIC;
53.125 + iter->cache = cache;
53.126 + iter->p = cache->bic_devs.next;
53.127 + iter->search_type = 0;
53.128 + iter->search_value = 0;
53.129 + }
53.130 + return (iter);
53.131 +}
53.132 +
53.133 +extern int blkid_dev_set_search(blkid_dev_iterate iter,
53.134 + char *search_type, char *search_value)
53.135 +{
53.136 + char *new_type, *new_value;
53.137 +
53.138 + if (!iter || iter->magic != DEV_ITERATE_MAGIC || !search_type ||
53.139 + !search_value)
53.140 + return -1;
53.141 + new_type = malloc(strlen(search_type)+1);
53.142 + new_value = malloc(strlen(search_value)+1);
53.143 + if (!new_type || !new_value) {
53.144 + free(new_type);
53.145 + free(new_value);
53.146 + return -1;
53.147 + }
53.148 + strcpy(new_type, search_type);
53.149 + strcpy(new_value, search_value);
53.150 + free(iter->search_type);
53.151 + free(iter->search_value);
53.152 + iter->search_type = new_type;
53.153 + iter->search_value = new_value;
53.154 + return 0;
53.155 +}
53.156 +
53.157 +/*
53.158 + * Return 0 on success, -1 on error
53.159 + */
53.160 +extern int blkid_dev_next(blkid_dev_iterate iter,
53.161 + blkid_dev *ret_dev)
53.162 +{
53.163 + blkid_dev dev;
53.164 +
53.165 + *ret_dev = 0;
53.166 + if (!iter || iter->magic != DEV_ITERATE_MAGIC)
53.167 + return -1;
53.168 + while (iter->p != &iter->cache->bic_devs) {
53.169 + dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
53.170 + iter->p = iter->p->next;
53.171 + if (iter->search_type &&
53.172 + !blkid_dev_has_tag(dev, iter->search_type,
53.173 + iter->search_value))
53.174 + continue;
53.175 + *ret_dev = dev;
53.176 + return 0;
53.177 + }
53.178 + return -1;
53.179 +}
53.180 +
53.181 +extern void blkid_dev_iterate_end(blkid_dev_iterate iter)
53.182 +{
53.183 + if (!iter || iter->magic != DEV_ITERATE_MAGIC)
53.184 + return;
53.185 + iter->magic = 0;
53.186 + free(iter);
53.187 +}
53.188 +
53.189 +#ifdef TEST_PROGRAM
53.190 +#ifdef HAVE_GETOPT_H
53.191 +#include <getopt.h>
53.192 +#else
53.193 +extern char *optarg;
53.194 +extern int optind;
53.195 +#endif
53.196 +
53.197 +void usage(char *prog)
53.198 +{
53.199 + fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog);
53.200 + fprintf(stderr, "\tList all devices and exit\n");
53.201 + exit(1);
53.202 +}
53.203 +
53.204 +int main(int argc, char **argv)
53.205 +{
53.206 + blkid_dev_iterate iter;
53.207 + blkid_cache cache = NULL;
53.208 + blkid_dev dev;
53.209 + int c, ret;
53.210 + char *tmp;
53.211 + char *file = NULL;
53.212 + char *search_type = NULL;
53.213 + char *search_value = NULL;
53.214 +
53.215 + while ((c = getopt (argc, argv, "m:f:")) != EOF)
53.216 + switch (c) {
53.217 + case 'f':
53.218 + file = optarg;
53.219 + break;
53.220 + case 'm':
53.221 + blkid_debug_mask = strtoul (optarg, &tmp, 0);
53.222 + if (*tmp) {
53.223 + fprintf(stderr, "Invalid debug mask: %s\n",
53.224 + optarg);
53.225 + exit(1);
53.226 + }
53.227 + break;
53.228 + case '?':
53.229 + usage(argv[0]);
53.230 + }
53.231 + if (argc >= optind+2) {
53.232 + search_type = argv[optind];
53.233 + search_value = argv[optind+1];
53.234 + optind += 2;
53.235 + }
53.236 + if (argc != optind)
53.237 + usage(argv[0]);
53.238 +
53.239 + if ((ret = blkid_get_cache(&cache, file)) != 0) {
53.240 + fprintf(stderr, "%s: error creating cache (%d)\n",
53.241 + argv[0], ret);
53.242 + exit(1);
53.243 + }
53.244 +
53.245 + iter = blkid_dev_iterate_begin(cache);
53.246 + if (search_type)
53.247 + blkid_dev_set_search(iter, search_type, search_value);
53.248 + while (blkid_dev_next(iter, &dev) == 0) {
53.249 + printf("Device: %s\n", blkid_dev_devname(dev));
53.250 + }
53.251 + blkid_dev_iterate_end(iter);
53.252 +
53.253 +
53.254 + blkid_put_cache(cache);
53.255 + return (0);
53.256 +}
53.257 +#endif
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/libext2fs/lib/libblkid/devname.c Wed Aug 25 01:28:08 2021 +0200
54.3 @@ -0,0 +1,561 @@
54.4 +/*
54.5 + * devname.c - get a dev by its device inode name
54.6 + *
54.7 + * Copyright (C) Andries Brouwer
54.8 + * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o
54.9 + * Copyright (C) 2001 Andreas Dilger
54.10 + *
54.11 + * %Begin-Header%
54.12 + * This file may be redistributed under the terms of the
54.13 + * GNU Lesser General Public License.
54.14 + * %End-Header%
54.15 + */
54.16 +
54.17 +#define _GNU_SOURCE 1
54.18 +
54.19 +#include "config.h"
54.20 +#include <stdio.h>
54.21 +#include <string.h>
54.22 +#include <limits.h>
54.23 +#if HAVE_UNISTD_H
54.24 +#include <unistd.h>
54.25 +#endif
54.26 +#include <stdlib.h>
54.27 +#include <string.h>
54.28 +#include <ctype.h>
54.29 +#if HAVE_SYS_TYPES_H
54.30 +#include <sys/types.h>
54.31 +#endif
54.32 +#include <dirent.h>
54.33 +#if HAVE_SYS_STAT_H
54.34 +#include <sys/stat.h>
54.35 +#endif
54.36 +#if HAVE_ERRNO_H
54.37 +#include <errno.h>
54.38 +#endif
54.39 +#if HAVE_SYS_MKDEV_H
54.40 +#include <sys/mkdev.h>
54.41 +#endif
54.42 +#ifdef HAVE_SYS_SYSMACROS_H
54.43 +#include <sys/sysmacros.h>
54.44 +#endif
54.45 +#include <time.h>
54.46 +
54.47 +#include "blkidP.h"
54.48 +
54.49 +/*
54.50 + * Find a dev struct in the cache by device name, if available.
54.51 + *
54.52 + * If there is no entry with the specified device name, and the create
54.53 + * flag is set, then create an empty device entry.
54.54 + */
54.55 +blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
54.56 +{
54.57 + blkid_dev dev = NULL, tmp;
54.58 + struct list_head *p, *pnext;
54.59 +
54.60 + if (!cache || !devname)
54.61 + return NULL;
54.62 +
54.63 + list_for_each(p, &cache->bic_devs) {
54.64 + tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
54.65 + if (strcmp(tmp->bid_name, devname))
54.66 + continue;
54.67 +
54.68 + DBG(DEBUG_DEVNAME,
54.69 + printf("found devname %s in cache\n", tmp->bid_name));
54.70 + dev = tmp;
54.71 + break;
54.72 + }
54.73 +
54.74 + if (!dev && (flags & BLKID_DEV_CREATE)) {
54.75 + if (access(devname, F_OK) < 0)
54.76 + return NULL;
54.77 + dev = blkid_new_dev();
54.78 + if (!dev)
54.79 + return NULL;
54.80 + dev->bid_time = INT_MIN;
54.81 + dev->bid_name = blkid_strdup(devname);
54.82 + dev->bid_cache = cache;
54.83 + list_add_tail(&dev->bid_devs, &cache->bic_devs);
54.84 + cache->bic_flags |= BLKID_BIC_FL_CHANGED;
54.85 + }
54.86 +
54.87 + if (flags & BLKID_DEV_VERIFY) {
54.88 + dev = blkid_verify(cache, dev);
54.89 + if (!dev || !(dev->bid_flags & BLKID_BID_FL_VERIFIED))
54.90 + return dev;
54.91 + /*
54.92 + * If the device is verified, then search the blkid
54.93 + * cache for any entries that match on the type, uuid,
54.94 + * and label, and verify them; if a cache entry can
54.95 + * not be verified, then it's stale and so we remove
54.96 + * it.
54.97 + */
54.98 + list_for_each_safe(p, pnext, &cache->bic_devs) {
54.99 + blkid_dev dev2;
54.100 + dev2 = list_entry(p, struct blkid_struct_dev, bid_devs);
54.101 + if (dev2->bid_flags & BLKID_BID_FL_VERIFIED)
54.102 + continue;
54.103 + if (!dev->bid_type || !dev2->bid_type ||
54.104 + strcmp(dev->bid_type, dev2->bid_type))
54.105 + continue;
54.106 + if (dev->bid_label && dev2->bid_label &&
54.107 + strcmp(dev->bid_label, dev2->bid_label))
54.108 + continue;
54.109 + if (dev->bid_uuid && dev2->bid_uuid &&
54.110 + strcmp(dev->bid_uuid, dev2->bid_uuid))
54.111 + continue;
54.112 + if ((dev->bid_label && !dev2->bid_label) ||
54.113 + (!dev->bid_label && dev2->bid_label) ||
54.114 + (dev->bid_uuid && !dev2->bid_uuid) ||
54.115 + (!dev->bid_uuid && dev2->bid_uuid))
54.116 + continue;
54.117 + dev2 = blkid_verify(cache, dev2);
54.118 + if (dev2 && !(dev2->bid_flags & BLKID_BID_FL_VERIFIED))
54.119 + blkid_free_dev(dev2);
54.120 + }
54.121 + }
54.122 + return dev;
54.123 +}
54.124 +
54.125 +/* Directories where we will try to search for device names */
54.126 +static const char *dirlist[] = { "/dev", "/devfs", "/devices", NULL };
54.127 +
54.128 +static int is_dm_leaf(const char *devname)
54.129 +{
54.130 + struct dirent *de, *d_de;
54.131 + DIR *dir, *d_dir;
54.132 + char path[256];
54.133 + int ret = 1;
54.134 +
54.135 + if ((dir = opendir("/sys/block")) == NULL)
54.136 + return 0;
54.137 + while ((de = readdir(dir)) != NULL) {
54.138 + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") ||
54.139 + !strcmp(de->d_name, devname) ||
54.140 + strncmp(de->d_name, "dm-", 3) ||
54.141 + strlen(de->d_name) > sizeof(path)-32)
54.142 + continue;
54.143 + sprintf(path, "/sys/block/%s/slaves", de->d_name);
54.144 + if ((d_dir = opendir(path)) == NULL)
54.145 + continue;
54.146 + while ((d_de = readdir(d_dir)) != NULL) {
54.147 + if (!strcmp(d_de->d_name, devname)) {
54.148 + ret = 0;
54.149 + break;
54.150 + }
54.151 + }
54.152 + closedir(d_dir);
54.153 + if (!ret)
54.154 + break;
54.155 + }
54.156 + closedir(dir);
54.157 + return ret;
54.158 +}
54.159 +
54.160 +/*
54.161 + * Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs
54.162 + * provides the real DM device names in /sys/block/<ptname>/dm/name
54.163 + */
54.164 +static char *get_dm_name(const char *ptname)
54.165 +{
54.166 + FILE *f;
54.167 + size_t sz;
54.168 + char path[256], name[256], *res = NULL;
54.169 +
54.170 + snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptname);
54.171 + if ((f = fopen(path, "r")) == NULL)
54.172 + return NULL;
54.173 +
54.174 + /* read "<name>\n" from sysfs */
54.175 + if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) {
54.176 + name[sz - 1] = '\0';
54.177 + snprintf(path, sizeof(path), "/dev/mapper/%s", name);
54.178 + res = blkid_strdup(path);
54.179 + }
54.180 + fclose(f);
54.181 + return res;
54.182 +}
54.183 +
54.184 +/*
54.185 + * Probe a single block device to add to the device cache.
54.186 + */
54.187 +static void probe_one(blkid_cache cache, const char *ptname,
54.188 + dev_t devno, int pri, int only_if_new)
54.189 +{
54.190 + blkid_dev dev = NULL;
54.191 + struct list_head *p, *pnext;
54.192 + const char **dir;
54.193 + char *devname = NULL;
54.194 +
54.195 + /* See if we already have this device number in the cache. */
54.196 + list_for_each_safe(p, pnext, &cache->bic_devs) {
54.197 + blkid_dev tmp = list_entry(p, struct blkid_struct_dev,
54.198 + bid_devs);
54.199 + if (tmp->bid_devno == devno) {
54.200 + if (only_if_new && !access(tmp->bid_name, F_OK))
54.201 + return;
54.202 + dev = blkid_verify(cache, tmp);
54.203 + if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))
54.204 + break;
54.205 + dev = 0;
54.206 + }
54.207 + }
54.208 + if (dev && dev->bid_devno == devno)
54.209 + goto set_pri;
54.210 +
54.211 + /* Try to translate private device-mapper dm-<N> names
54.212 + * to standard /dev/mapper/<name>.
54.213 + */
54.214 + if (!strncmp(ptname, "dm-", 3) && isdigit(ptname[3])) {
54.215 + devname = get_dm_name(ptname);
54.216 + if (!devname)
54.217 + blkid__scan_dir("/dev/mapper", devno, 0, &devname);
54.218 + if (devname)
54.219 + goto get_dev;
54.220 + }
54.221 +
54.222 + /*
54.223 + * Take a quick look at /dev/ptname for the device number. We check
54.224 + * all of the likely device directories. If we don't find it, or if
54.225 + * the stat information doesn't check out, use blkid_devno_to_devname()
54.226 + * to find it via an exhaustive search for the device major/minor.
54.227 + */
54.228 + for (dir = dirlist; *dir; dir++) {
54.229 + struct stat st;
54.230 + char device[256];
54.231 +
54.232 + sprintf(device, "%s/%s", *dir, ptname);
54.233 + if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) &&
54.234 + dev->bid_devno == devno)
54.235 + goto set_pri;
54.236 +
54.237 + if (stat(device, &st) == 0 &&
54.238 + blkidP_is_disk_device(st.st_mode) &&
54.239 + st.st_rdev == devno) {
54.240 + devname = blkid_strdup(device);
54.241 + goto get_dev;
54.242 + }
54.243 + }
54.244 + /* Do a short-cut scan of /dev/mapper first */
54.245 + if (!devname)
54.246 + devname = get_dm_name(ptname);
54.247 + if (!devname)
54.248 + blkid__scan_dir("/dev/mapper", devno, 0, &devname);
54.249 + if (!devname) {
54.250 + devname = blkid_devno_to_devname(devno);
54.251 + if (!devname)
54.252 + return;
54.253 + }
54.254 +get_dev:
54.255 + dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL);
54.256 + free(devname);
54.257 +set_pri:
54.258 + if (dev) {
54.259 + if (pri)
54.260 + dev->bid_pri = pri;
54.261 + else if (!strncmp(dev->bid_name, "/dev/mapper/", 11)) {
54.262 + dev->bid_pri = BLKID_PRI_DM;
54.263 + if (is_dm_leaf(ptname))
54.264 + dev->bid_pri += 5;
54.265 + } else if (!strncmp(ptname, "md", 2))
54.266 + dev->bid_pri = BLKID_PRI_MD;
54.267 + }
54.268 + return;
54.269 +}
54.270 +
54.271 +#define PROC_PARTITIONS "/proc/partitions"
54.272 +#define VG_DIR "/proc/lvm/VGs"
54.273 +
54.274 +/*
54.275 + * This function initializes the UUID cache with devices from the LVM
54.276 + * proc hierarchy. We currently depend on the names of the LVM
54.277 + * hierarchy giving us the device structure in /dev. (XXX is this a
54.278 + * safe thing to do?)
54.279 + */
54.280 +#ifdef VG_DIR
54.281 +static dev_t lvm_get_devno(const char *lvm_device)
54.282 +{
54.283 + FILE *lvf;
54.284 + char buf[1024];
54.285 + int ma, mi;
54.286 + dev_t ret = 0;
54.287 +
54.288 + DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device));
54.289 + if ((lvf = fopen(lvm_device, "r")) == NULL) {
54.290 + DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno,
54.291 + strerror(errno)));
54.292 + return 0;
54.293 + }
54.294 +
54.295 + while (fgets(buf, sizeof(buf), lvf)) {
54.296 + if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) {
54.297 + ret = makedev(ma, mi);
54.298 + break;
54.299 + }
54.300 + }
54.301 + fclose(lvf);
54.302 +
54.303 + return ret;
54.304 +}
54.305 +
54.306 +static void lvm_probe_all(blkid_cache cache, int only_if_new)
54.307 +{
54.308 + DIR *vg_list;
54.309 + struct dirent *vg_iter;
54.310 + int vg_len = strlen(VG_DIR);
54.311 + dev_t dev;
54.312 +
54.313 + if ((vg_list = opendir(VG_DIR)) == NULL)
54.314 + return;
54.315 +
54.316 + DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR));
54.317 +
54.318 + while ((vg_iter = readdir(vg_list)) != NULL) {
54.319 + DIR *lv_list;
54.320 + char *vdirname;
54.321 + char *vg_name;
54.322 + struct dirent *lv_iter;
54.323 +
54.324 + vg_name = vg_iter->d_name;
54.325 + if (!strcmp(vg_name, ".") || !strcmp(vg_name, ".."))
54.326 + continue;
54.327 + vdirname = malloc(vg_len + strlen(vg_name) + 8);
54.328 + if (!vdirname)
54.329 + goto exit;
54.330 + sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name);
54.331 +
54.332 + lv_list = opendir(vdirname);
54.333 + free(vdirname);
54.334 + if (lv_list == NULL)
54.335 + continue;
54.336 +
54.337 + while ((lv_iter = readdir(lv_list)) != NULL) {
54.338 + char *lv_name, *lvm_device;
54.339 +
54.340 + lv_name = lv_iter->d_name;
54.341 + if (!strcmp(lv_name, ".") || !strcmp(lv_name, ".."))
54.342 + continue;
54.343 +
54.344 + lvm_device = malloc(vg_len + strlen(vg_name) +
54.345 + strlen(lv_name) + 8);
54.346 + if (!lvm_device) {
54.347 + closedir(lv_list);
54.348 + goto exit;
54.349 + }
54.350 + sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name,
54.351 + lv_name);
54.352 + dev = lvm_get_devno(lvm_device);
54.353 + sprintf(lvm_device, "%s/%s", vg_name, lv_name);
54.354 + DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n",
54.355 + lvm_device,
54.356 + (unsigned int) dev));
54.357 + probe_one(cache, lvm_device, dev, BLKID_PRI_LVM,
54.358 + only_if_new);
54.359 + free(lvm_device);
54.360 + }
54.361 + closedir(lv_list);
54.362 + }
54.363 +exit:
54.364 + closedir(vg_list);
54.365 +}
54.366 +#endif
54.367 +
54.368 +#define PROC_EVMS_VOLUMES "/proc/evms/volumes"
54.369 +
54.370 +static int
54.371 +evms_probe_all(blkid_cache cache, int only_if_new)
54.372 +{
54.373 + char line[100];
54.374 + int ma, mi, sz, num = 0;
54.375 + FILE *procpt;
54.376 + char device[110];
54.377 +
54.378 + procpt = fopen(PROC_EVMS_VOLUMES, "r");
54.379 + if (!procpt)
54.380 + return 0;
54.381 + while (fgets(line, sizeof(line), procpt)) {
54.382 + if (sscanf (line, " %d %d %d %*s %*s %[^\n ]",
54.383 + &ma, &mi, &sz, device) != 4)
54.384 + continue;
54.385 +
54.386 + DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n",
54.387 + device, ma, mi));
54.388 +
54.389 + probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS,
54.390 + only_if_new);
54.391 + num++;
54.392 + }
54.393 + fclose(procpt);
54.394 + return num;
54.395 +}
54.396 +
54.397 +/*
54.398 + * Read the device data for all available block devices in the system.
54.399 + */
54.400 +static int probe_all(blkid_cache cache, int only_if_new)
54.401 +{
54.402 + FILE *proc;
54.403 + char line[1024];
54.404 + char ptname0[129], ptname1[129], *ptname = 0;
54.405 + char *ptnames[2];
54.406 + dev_t devs[2];
54.407 + int ma, mi;
54.408 + unsigned long long sz;
54.409 + int lens[2] = { 0, 0 };
54.410 + int which = 0, last = 0;
54.411 + struct list_head *p, *pnext;
54.412 +
54.413 + ptnames[0] = ptname0;
54.414 + ptnames[1] = ptname1;
54.415 +
54.416 + if (!cache)
54.417 + return -BLKID_ERR_PARAM;
54.418 +
54.419 + if (cache->bic_flags & BLKID_BIC_FL_PROBED &&
54.420 + time(0) - cache->bic_time < BLKID_PROBE_INTERVAL)
54.421 + return 0;
54.422 +
54.423 + blkid_read_cache(cache);
54.424 + evms_probe_all(cache, only_if_new);
54.425 +#ifdef VG_DIR
54.426 + lvm_probe_all(cache, only_if_new);
54.427 +#endif
54.428 +
54.429 + proc = fopen(PROC_PARTITIONS, "r");
54.430 + if (!proc)
54.431 + return -BLKID_ERR_PROC;
54.432 +
54.433 + while (fgets(line, sizeof(line), proc)) {
54.434 + last = which;
54.435 + which ^= 1;
54.436 + ptname = ptnames[which];
54.437 +
54.438 + if (sscanf(line, " %d %d %llu %128[^\n ]",
54.439 + &ma, &mi, &sz, ptname) != 4)
54.440 + continue;
54.441 + devs[which] = makedev(ma, mi);
54.442 +
54.443 + DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname));
54.444 +
54.445 + /* Skip whole disk devs unless they have no partitions.
54.446 + * If base name of device has changed, also
54.447 + * check previous dev to see if it didn't have a partn.
54.448 + * heuristic: partition name ends in a digit, & partition
54.449 + * names contain whole device name as substring.
54.450 + *
54.451 + * Skip extended partitions.
54.452 + * heuristic: size is 1
54.453 + *
54.454 + * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
54.455 + */
54.456 +
54.457 + lens[which] = strlen(ptname);
54.458 +
54.459 + /* ends in a digit, clearly a partition, so check */
54.460 + if (isdigit(ptname[lens[which] - 1])) {
54.461 + DBG(DEBUG_DEVNAME,
54.462 + printf("partition dev %s, devno 0x%04X\n",
54.463 + ptname, (unsigned int) devs[which]));
54.464 +
54.465 + if (sz > 1)
54.466 + probe_one(cache, ptname, devs[which], 0,
54.467 + only_if_new);
54.468 + lens[which] = 0; /* mark as checked */
54.469 + }
54.470 +
54.471 + /*
54.472 + * If last was a whole disk and we just found a partition
54.473 + * on it, remove the whole-disk dev from the cache if
54.474 + * it exists.
54.475 + */
54.476 + if (lens[last] && !strncmp(ptnames[last], ptname, lens[last])) {
54.477 + list_for_each_safe(p, pnext, &cache->bic_devs) {
54.478 + blkid_dev tmp;
54.479 +
54.480 + /* find blkid dev for the whole-disk devno */
54.481 + tmp = list_entry(p, struct blkid_struct_dev,
54.482 + bid_devs);
54.483 + if (tmp->bid_devno == devs[last]) {
54.484 + DBG(DEBUG_DEVNAME,
54.485 + printf("freeing %s\n",
54.486 + tmp->bid_name));
54.487 + blkid_free_dev(tmp);
54.488 + cache->bic_flags |= BLKID_BIC_FL_CHANGED;
54.489 + break;
54.490 + }
54.491 + }
54.492 + lens[last] = 0;
54.493 + }
54.494 + /*
54.495 + * If last was not checked because it looked like a whole-disk
54.496 + * dev, and the device's base name has changed,
54.497 + * check last as well.
54.498 + */
54.499 + if (lens[last] && strncmp(ptnames[last], ptname, lens[last])) {
54.500 + DBG(DEBUG_DEVNAME,
54.501 + printf("whole dev %s, devno 0x%04X\n",
54.502 + ptnames[last], (unsigned int) devs[last]));
54.503 + probe_one(cache, ptnames[last], devs[last], 0,
54.504 + only_if_new);
54.505 + lens[last] = 0;
54.506 + }
54.507 + }
54.508 +
54.509 + /* Handle the last device if it wasn't partitioned */
54.510 + if (lens[which])
54.511 + probe_one(cache, ptname, devs[which], 0, only_if_new);
54.512 +
54.513 + fclose(proc);
54.514 + blkid_flush_cache(cache);
54.515 + return 0;
54.516 +}
54.517 +
54.518 +int blkid_probe_all(blkid_cache cache)
54.519 +{
54.520 + int ret;
54.521 +
54.522 + DBG(DEBUG_PROBE, printf("Begin blkid_probe_all()\n"));
54.523 + ret = probe_all(cache, 0);
54.524 + cache->bic_time = time(0);
54.525 + cache->bic_flags |= BLKID_BIC_FL_PROBED;
54.526 + DBG(DEBUG_PROBE, printf("End blkid_probe_all()\n"));
54.527 + return ret;
54.528 +}
54.529 +
54.530 +int blkid_probe_all_new(blkid_cache cache)
54.531 +{
54.532 + int ret;
54.533 +
54.534 + DBG(DEBUG_PROBE, printf("Begin blkid_probe_all_new()\n"));
54.535 + ret = probe_all(cache, 1);
54.536 + DBG(DEBUG_PROBE, printf("End blkid_probe_all_new()\n"));
54.537 + return ret;
54.538 +}
54.539 +
54.540 +
54.541 +#ifdef TEST_PROGRAM
54.542 +int main(int argc, char **argv)
54.543 +{
54.544 + blkid_cache cache = NULL;
54.545 + int ret;
54.546 +
54.547 + blkid_debug_mask = DEBUG_ALL;
54.548 + if (argc != 1) {
54.549 + fprintf(stderr, "Usage: %s\n"
54.550 + "Probe all devices and exit\n", argv[0]);
54.551 + exit(1);
54.552 + }
54.553 + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
54.554 + fprintf(stderr, "%s: error creating cache (%d)\n",
54.555 + argv[0], ret);
54.556 + exit(1);
54.557 + }
54.558 + if (blkid_probe_all(cache) < 0)
54.559 + printf("%s: error probing devices\n", argv[0]);
54.560 +
54.561 + blkid_put_cache(cache);
54.562 + return (0);
54.563 +}
54.564 +#endif
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/libext2fs/lib/libblkid/devno.c Wed Aug 25 01:28:08 2021 +0200
55.3 @@ -0,0 +1,232 @@
55.4 +/*
55.5 + * devno.c - find a particular device by its device number (major/minor)
55.6 + *
55.7 + * Copyright (C) 2000, 2001, 2003 Theodore Ts'o
55.8 + * Copyright (C) 2001 Andreas Dilger
55.9 + *
55.10 + * %Begin-Header%
55.11 + * This file may be redistributed under the terms of the
55.12 + * GNU Lesser General Public License.
55.13 + * %End-Header%
55.14 + */
55.15 +
55.16 +#include "config.h"
55.17 +#include <stdio.h>
55.18 +#include <string.h>
55.19 +#if HAVE_UNISTD_H
55.20 +#include <unistd.h>
55.21 +#endif
55.22 +#include <stdlib.h>
55.23 +#include <string.h>
55.24 +#if HAVE_SYS_TYPES_H
55.25 +#include <sys/types.h>
55.26 +#endif
55.27 +#if HAVE_SYS_STAT_H
55.28 +#include <sys/stat.h>
55.29 +#endif
55.30 +#include <dirent.h>
55.31 +#if HAVE_ERRNO_H
55.32 +#include <errno.h>
55.33 +#endif
55.34 +#if HAVE_SYS_MKDEV_H
55.35 +#include <sys/mkdev.h>
55.36 +#endif
55.37 +#ifdef HAVE_SYS_SYSMACROS_H
55.38 +#include <sys/sysmacros.h>
55.39 +#endif
55.40 +
55.41 +#include "blkidP.h"
55.42 +
55.43 +char *blkid_strndup(const char *s, int length)
55.44 +{
55.45 + char *ret;
55.46 +
55.47 + if (!s)
55.48 + return NULL;
55.49 +
55.50 + if (!length)
55.51 + length = strlen(s);
55.52 +
55.53 + ret = malloc(length + 1);
55.54 + if (ret) {
55.55 + strncpy(ret, s, length);
55.56 + ret[length] = '\0';
55.57 + }
55.58 + return ret;
55.59 +}
55.60 +
55.61 +char *blkid_strdup(const char *s)
55.62 +{
55.63 + return blkid_strndup(s, 0);
55.64 +}
55.65 +
55.66 +/*
55.67 + * This function adds an entry to the directory list
55.68 + */
55.69 +static void add_to_dirlist(const char *name, struct dir_list **list)
55.70 +{
55.71 + struct dir_list *dp;
55.72 +
55.73 + dp = malloc(sizeof(struct dir_list));
55.74 + if (!dp)
55.75 + return;
55.76 + dp->name = blkid_strdup(name);
55.77 + if (!dp->name) {
55.78 + free(dp);
55.79 + return;
55.80 + }
55.81 + dp->next = *list;
55.82 + *list = dp;
55.83 +}
55.84 +
55.85 +/*
55.86 + * This function frees a directory list
55.87 + */
55.88 +static void free_dirlist(struct dir_list **list)
55.89 +{
55.90 + struct dir_list *dp, *next;
55.91 +
55.92 + for (dp = *list; dp; dp = next) {
55.93 + next = dp->next;
55.94 + free(dp->name);
55.95 + free(dp);
55.96 + }
55.97 + *list = NULL;
55.98 +}
55.99 +
55.100 +void blkid__scan_dir(const char *dirname, dev_t devno, struct dir_list **list,
55.101 + char **devname)
55.102 +{
55.103 + DIR *dir;
55.104 + struct dirent *dp;
55.105 + char path[1024];
55.106 + int dirlen;
55.107 + struct stat st;
55.108 +
55.109 + if ((dir = opendir(dirname)) == NULL)
55.110 + return;
55.111 + dirlen = strlen(dirname) + 2;
55.112 + while ((dp = readdir(dir)) != 0) {
55.113 + if (dirlen + strlen(dp->d_name) >= sizeof(path))
55.114 + continue;
55.115 +
55.116 + if (dp->d_name[0] == '.' &&
55.117 + ((dp->d_name[1] == 0) ||
55.118 + ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
55.119 + continue;
55.120 +
55.121 + sprintf(path, "%s/%s", dirname, dp->d_name);
55.122 + if (stat(path, &st) < 0)
55.123 + continue;
55.124 +
55.125 + if (blkidP_is_disk_device(st.st_mode) && st.st_rdev == devno) {
55.126 + *devname = blkid_strdup(path);
55.127 + DBG(DEBUG_DEVNO,
55.128 + printf("found 0x%llx at %s (%p)\n", (long long)devno,
55.129 + path, *devname));
55.130 + break;
55.131 + }
55.132 + if (list && S_ISDIR(st.st_mode) && !lstat(path, &st) &&
55.133 + S_ISDIR(st.st_mode))
55.134 + add_to_dirlist(path, list);
55.135 + }
55.136 + closedir(dir);
55.137 + return;
55.138 +}
55.139 +
55.140 +/* Directories where we will try to search for device numbers */
55.141 +static const char *devdirs[] = { "/devices", "/devfs", "/dev", NULL };
55.142 +
55.143 +/*
55.144 + * This function finds the pathname to a block device with a given
55.145 + * device number. It returns a pointer to allocated memory to the
55.146 + * pathname on success, and NULL on failure.
55.147 + */
55.148 +char *blkid_devno_to_devname(dev_t devno)
55.149 +{
55.150 + struct dir_list *list = NULL, *new_list = NULL;
55.151 + char *devname = NULL;
55.152 + const char **dir;
55.153 +
55.154 + /*
55.155 + * Add the starting directories to search in reverse order of
55.156 + * importance, since we are using a stack...
55.157 + */
55.158 + for (dir = devdirs; *dir; dir++)
55.159 + add_to_dirlist(*dir, &list);
55.160 +
55.161 + while (list) {
55.162 + struct dir_list *current = list;
55.163 +
55.164 + list = list->next;
55.165 + DBG(DEBUG_DEVNO, printf("directory %s\n", current->name));
55.166 + blkid__scan_dir(current->name, devno, &new_list, &devname);
55.167 + free(current->name);
55.168 + free(current);
55.169 + if (devname)
55.170 + break;
55.171 + /*
55.172 + * If we're done checking at this level, descend to
55.173 + * the next level of subdirectories. (breadth-first)
55.174 + */
55.175 + if (list == NULL) {
55.176 + list = new_list;
55.177 + new_list = NULL;
55.178 + }
55.179 + }
55.180 + free_dirlist(&list);
55.181 + free_dirlist(&new_list);
55.182 +
55.183 + if (!devname) {
55.184 + DBG(DEBUG_DEVNO,
55.185 + printf("blkid: couldn't find devno 0x%04lx\n",
55.186 + (unsigned long) devno));
55.187 + } else {
55.188 + DBG(DEBUG_DEVNO,
55.189 + printf("found devno 0x%04llx as %s\n", (long long)devno, devname));
55.190 + }
55.191 +
55.192 +
55.193 + return devname;
55.194 +}
55.195 +
55.196 +#ifdef TEST_PROGRAM
55.197 +int main(int argc, char** argv)
55.198 +{
55.199 + char *devname, *tmp;
55.200 + int major, minor;
55.201 + dev_t devno;
55.202 + const char *errmsg = "Couldn't parse %s: %s\n";
55.203 +
55.204 + blkid_debug_mask = DEBUG_ALL;
55.205 + if ((argc != 2) && (argc != 3)) {
55.206 + fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n"
55.207 + "Resolve a device number to a device name\n",
55.208 + argv[0], argv[0]);
55.209 + exit(1);
55.210 + }
55.211 + if (argc == 2) {
55.212 + devno = strtoul(argv[1], &tmp, 0);
55.213 + if (*tmp) {
55.214 + fprintf(stderr, errmsg, "device number", argv[1]);
55.215 + exit(1);
55.216 + }
55.217 + } else {
55.218 + major = strtoul(argv[1], &tmp, 0);
55.219 + if (*tmp) {
55.220 + fprintf(stderr, errmsg, "major number", argv[1]);
55.221 + exit(1);
55.222 + }
55.223 + minor = strtoul(argv[2], &tmp, 0);
55.224 + if (*tmp) {
55.225 + fprintf(stderr, errmsg, "minor number", argv[2]);
55.226 + exit(1);
55.227 + }
55.228 + devno = makedev(major, minor);
55.229 + }
55.230 + printf("Looking for device 0x%04llx\n", (long long)devno);
55.231 + devname = blkid_devno_to_devname(devno);
55.232 + free(devname);
55.233 + return 0;
55.234 +}
55.235 +#endif
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
56.2 +++ b/libext2fs/lib/libblkid/getsize.c Wed Aug 25 01:28:08 2021 +0200
56.3 @@ -0,0 +1,217 @@
56.4 +/*
56.5 + * getsize.c --- get the size of a partition.
56.6 + *
56.7 + * Copyright (C) 1995, 1995 Theodore Ts'o.
56.8 + *
56.9 + * %Begin-Header%
56.10 + * This file may be redistributed under the terms of the
56.11 + * GNU Lesser General Public License.
56.12 + * %End-Header%
56.13 + */
56.14 +
56.15 +#ifndef _LARGEFILE_SOURCE
56.16 +#define _LARGEFILE_SOURCE
56.17 +#endif
56.18 +#ifndef _LARGEFILE64_SOURCE
56.19 +#define _LARGEFILE64_SOURCE
56.20 +#endif
56.21 +
56.22 +#include "config.h"
56.23 +#include "blkidP.h"
56.24 +
56.25 +#include <stdio.h>
56.26 +#if HAVE_UNISTD_H
56.27 +#include <unistd.h>
56.28 +#endif
56.29 +#if HAVE_ERRNO_H
56.30 +#include <errno.h>
56.31 +#endif
56.32 +#include <fcntl.h>
56.33 +#ifdef HAVE_SYS_IOCTL_H
56.34 +#include <sys/ioctl.h>
56.35 +#endif
56.36 +#ifdef HAVE_LINUX_FD_H
56.37 +#include <linux/fd.h>
56.38 +#endif
56.39 +#ifdef HAVE_SYS_DISKLABEL_H
56.40 +#include <sys/disklabel.h>
56.41 +#endif
56.42 +#ifdef HAVE_SYS_DISK_H
56.43 +#include <sys/disk.h>
56.44 +#endif
56.45 +#ifdef __linux__
56.46 +#include <sys/utsname.h>
56.47 +#endif
56.48 +#if HAVE_SYS_STAT_H
56.49 +#include <sys/stat.h>
56.50 +#endif
56.51 +
56.52 +
56.53 +#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
56.54 +#define BLKGETSIZE _IO(0x12,96) /* return device size */
56.55 +#endif
56.56 +
56.57 +#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
56.58 +#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
56.59 +#endif
56.60 +
56.61 +#ifdef APPLE_DARWIN
56.62 +#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
56.63 +#endif /* APPLE_DARWIN */
56.64 +
56.65 +static int valid_offset(int fd, blkid_loff_t offset)
56.66 +{
56.67 + char ch;
56.68 +
56.69 + if (blkid_llseek(fd, offset, 0) < 0)
56.70 + return 0;
56.71 + if (read(fd, &ch, 1) < 1)
56.72 + return 0;
56.73 + return 1;
56.74 +}
56.75 +
56.76 +/*
56.77 + * Returns the number of bytes in a partition
56.78 + */
56.79 +blkid_loff_t blkid_get_dev_size(int fd)
56.80 +{
56.81 + unsigned long long size64;
56.82 + blkid_loff_t high, low;
56.83 +
56.84 +#if defined DKIOCGETBLOCKCOUNT && defined DKIOCGETBLOCKSIZE /* For Apple Darwin */
56.85 + unsigned int size;
56.86 +
56.87 + if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0 &&
56.88 + ioctl(fd, DKIOCGETBLOCKSIZE, &size) >= 0) {
56.89 + if (sizeof(blkid_loff_t) < sizeof(unsigned long long) &&
56.90 + (size64 * size) > 0xFFFFFFFF)
56.91 + return 0; /* EFBIG */
56.92 + return (blkid_loff_t)size64 * size;
56.93 + }
56.94 +#endif
56.95 +
56.96 +#ifdef BLKGETSIZE64
56.97 + {
56.98 + int valid_blkgetsize64 = 1;
56.99 +#ifdef __linux__
56.100 + struct utsname ut;
56.101 +
56.102 + if ((uname(&ut) == 0) &&
56.103 + ((ut.release[0] == '2') && (ut.release[1] == '.') &&
56.104 + (ut.release[2] < '6') && (ut.release[3] == '.')))
56.105 + valid_blkgetsize64 = 0;
56.106 +#endif
56.107 + if (valid_blkgetsize64 &&
56.108 + ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
56.109 + if (sizeof(blkid_loff_t) < sizeof(unsigned long long) &&
56.110 + (size64 > 0xFFFFFFFF))
56.111 + return 0; /* EFBIG */
56.112 + return size64;
56.113 + }
56.114 + }
56.115 +#endif /* BLKGETSIZE64 */
56.116 +
56.117 +#ifdef BLKGETSIZE
56.118 + {
56.119 + unsigned long size;
56.120 +
56.121 + if (ioctl(fd, BLKGETSIZE, &size) >= 0)
56.122 + return (blkid_loff_t)size << 9;
56.123 + }
56.124 +#endif
56.125 +
56.126 +/* tested on FreeBSD 6.1-RELEASE i386 */
56.127 +#ifdef DIOCGMEDIASIZE
56.128 + if (ioctl(fd, DIOCGMEDIASIZE, &size64) >= 0)
56.129 + return (off_t)size64;
56.130 +#endif /* DIOCGMEDIASIZE */
56.131 +
56.132 +#ifdef FDGETPRM
56.133 + {
56.134 + struct floppy_struct this_floppy;
56.135 +
56.136 + if (ioctl(fd, FDGETPRM, &this_floppy) >= 0)
56.137 + return (blkid_loff_t)this_floppy.size << 9;
56.138 + }
56.139 +#endif
56.140 +#if defined(HAVE_SYS_DISKLABEL_H) && defined(DIOCGDINFO)
56.141 + {
56.142 + int part = -1;
56.143 + struct disklabel lab;
56.144 + struct partition *pp;
56.145 + char ch;
56.146 + struct stat st;
56.147 +
56.148 + /*
56.149 + * This code works for FreeBSD 4.11 i386, except for the full
56.150 + * device (such as /dev/ad0). It doesn't work properly for
56.151 + * newer FreeBSD though. FreeBSD >= 5.0 should be covered by
56.152 + * the DIOCGMEDIASIZE above however.
56.153 + *
56.154 + * Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw,
56.155 + * character) devices, so we need to check for S_ISCHR, too.
56.156 + */
56.157 + if (fstat(fd, &st) >= 0 &&
56.158 + blkidP_is_disk_device(st.st_mode))
56.159 + part = st.st_rdev & 7;
56.160 +
56.161 + if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
56.162 + pp = &lab.d_partitions[part];
56.163 + if (pp->p_size)
56.164 + return pp->p_size << 9;
56.165 + }
56.166 + }
56.167 +#endif /* defined(HAVE_SYS_DISKLABEL_H) && defined(DIOCGDINFO) */
56.168 + {
56.169 +#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
56.170 + struct stat64 st;
56.171 + if (fstat64(fd, &st) == 0)
56.172 +#else
56.173 + struct stat st;
56.174 + if (fstat(fd, &st) == 0)
56.175 +#endif
56.176 + if (S_ISREG(st.st_mode))
56.177 + return st.st_size;
56.178 + }
56.179 +
56.180 + /*
56.181 + * OK, we couldn't figure it out by using a specialized ioctl,
56.182 + * which is generally the best way. So do binary search to
56.183 + * find the size of the partition.
56.184 + */
56.185 + low = 0;
56.186 + for (high = 1024; valid_offset(fd, high); high *= 2)
56.187 + low = high;
56.188 + while (low < high - 1) {
56.189 + const blkid_loff_t mid = (low + high) / 2;
56.190 +
56.191 + if (valid_offset(fd, mid))
56.192 + low = mid;
56.193 + else
56.194 + high = mid;
56.195 + }
56.196 + return low + 1;
56.197 +}
56.198 +
56.199 +#ifdef TEST_PROGRAM
56.200 +int main(int argc, char **argv)
56.201 +{
56.202 + long long bytes;
56.203 + int fd;
56.204 +
56.205 + if (argc < 2) {
56.206 + fprintf(stderr, "Usage: %s device\n"
56.207 + "Determine the size of a device\n", argv[0]);
56.208 + return 1;
56.209 + }
56.210 +
56.211 + if ((fd = open(argv[1], O_RDONLY)) < 0)
56.212 + perror(argv[0]);
56.213 +
56.214 + bytes = blkid_get_dev_size(fd);
56.215 + printf("Device %s has %lld 1k blocks.\n", argv[1],
56.216 + (unsigned long long)bytes >> 10);
56.217 +
56.218 + return 0;
56.219 +}
56.220 +#endif
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
57.2 +++ b/libext2fs/lib/libblkid/llseek.c Wed Aug 25 01:28:08 2021 +0200
57.3 @@ -0,0 +1,147 @@
57.4 +/*
57.5 + * llseek.c -- stub calling the llseek system call
57.6 + *
57.7 + * Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o.
57.8 + *
57.9 + * %Begin-Header%
57.10 + * This file may be redistributed under the terms of the
57.11 + * GNU Lesser General Public License.
57.12 + * %End-Header%
57.13 + */
57.14 +
57.15 +#ifndef _LARGEFILE_SOURCE
57.16 +#define _LARGEFILE_SOURCE
57.17 +#endif
57.18 +#ifndef _LARGEFILE64_SOURCE
57.19 +#define _LARGEFILE64_SOURCE
57.20 +#endif
57.21 +
57.22 +#include "config.h"
57.23 +#if HAVE_SYS_TYPES_H
57.24 +#include <sys/types.h>
57.25 +#endif
57.26 +
57.27 +#if HAVE_ERRNO_H
57.28 +#include <errno.h>
57.29 +#endif
57.30 +#if HAVE_UNISTD_H
57.31 +#include <unistd.h>
57.32 +#endif
57.33 +#ifdef __MSDOS__
57.34 +#include <io.h>
57.35 +#endif
57.36 +
57.37 +#include "blkidP.h"
57.38 +
57.39 +#ifdef __linux__
57.40 +
57.41 +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
57.42 +
57.43 +#define my_llseek lseek64
57.44 +
57.45 +#elif defined(HAVE_LLSEEK)
57.46 +#include <sys/syscall.h>
57.47 +
57.48 +#ifndef HAVE_LLSEEK_PROTOTYPE
57.49 +extern long long llseek(int fd, long long offset, int origin);
57.50 +#endif
57.51 +
57.52 +#define my_llseek llseek
57.53 +
57.54 +#else /* ! HAVE_LLSEEK */
57.55 +
57.56 +#if SIZEOF_LONG == SIZEOF_LONG_LONG
57.57 +
57.58 +#define llseek lseek
57.59 +
57.60 +#else /* SIZEOF_LONG != SIZEOF_LONG_LONG */
57.61 +
57.62 +#include <linux/unistd.h>
57.63 +
57.64 +#ifndef __NR__llseek
57.65 +#define __NR__llseek 140
57.66 +#endif
57.67 +
57.68 +#ifndef __i386__
57.69 +static int _llseek(unsigned int, unsigned long, unsigned long,
57.70 + blkid_loff_t *, unsigned int);
57.71 +
57.72 +static _syscall5(int, _llseek, unsigned int, fd, unsigned long, offset_high,
57.73 + unsigned long, offset_low, blkid_loff_t *, result,
57.74 + unsigned int, origin)
57.75 +#endif
57.76 +
57.77 +static blkid_loff_t my_llseek(int fd, blkid_loff_t offset, int origin)
57.78 +{
57.79 + blkid_loff_t result;
57.80 + int retval;
57.81 +
57.82 +#ifndef __i386__
57.83 + retval = _llseek(fd, ((unsigned long long) offset) >> 32,
57.84 + ((unsigned long long)offset) & 0xffffffff,
57.85 + &result, origin);
57.86 +#else
57.87 + retval = syscall(__NR__llseek, fd, ((unsigned long long) offset) >> 32,
57.88 + ((unsigned long long)offset) & 0xffffffff,
57.89 + &result, origin);
57.90 +#endif
57.91 + return (retval == -1 ? (blkid_loff_t) retval : result);
57.92 +}
57.93 +
57.94 +#endif /* __alpha__ || __ia64__ */
57.95 +
57.96 +#endif /* HAVE_LLSEEK */
57.97 +
57.98 +blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence)
57.99 +{
57.100 + blkid_loff_t result;
57.101 + static int do_compat = 0;
57.102 +
57.103 + if ((sizeof(off_t) >= sizeof(blkid_loff_t)) ||
57.104 + (offset < ((blkid_loff_t) 1 << ((sizeof(off_t)*8) -1))))
57.105 + return lseek(fd, (off_t) offset, whence);
57.106 +
57.107 + if (do_compat) {
57.108 + errno = EOVERFLOW;
57.109 + return -1;
57.110 + }
57.111 +
57.112 + result = my_llseek(fd, offset, whence);
57.113 + if (result == -1 && errno == ENOSYS) {
57.114 + /*
57.115 + * Just in case this code runs on top of an old kernel
57.116 + * which does not support the llseek system call
57.117 + */
57.118 + do_compat++;
57.119 + errno = EOVERFLOW;
57.120 + }
57.121 + return result;
57.122 +}
57.123 +
57.124 +#else /* !linux */
57.125 +
57.126 +#ifndef EOVERFLOW
57.127 +#ifdef EXT2_ET_INVALID_ARGUMENT
57.128 +#define EOVERFLOW EXT2_ET_INVALID_ARGUMENT
57.129 +#else
57.130 +#define EOVERFLOW 112
57.131 +#endif
57.132 +#endif
57.133 +
57.134 +blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int origin)
57.135 +{
57.136 +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
57.137 + return lseek64 (fd, offset, origin);
57.138 +#else
57.139 + if ((sizeof(off_t) < sizeof(blkid_loff_t)) &&
57.140 + (offset >= ((blkid_loff_t) 1 << ((sizeof(off_t)*8) - 1)))) {
57.141 + errno = EOVERFLOW;
57.142 + return -1;
57.143 + }
57.144 + return lseek(fd, (off_t) offset, origin);
57.145 +#endif
57.146 +}
57.147 +
57.148 +#endif /* linux */
57.149 +
57.150 +
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58.2 +++ b/libext2fs/lib/libblkid/probe.c Wed Aug 25 01:28:08 2021 +0200
58.3 @@ -0,0 +1,1840 @@
58.4 +/*
58.5 + * probe.c - identify a block device by its contents, and return a dev
58.6 + * struct with the details
58.7 + *
58.8 + * Copyright (C) 1999 by Andries Brouwer
58.9 + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
58.10 + * Copyright (C) 2001 by Andreas Dilger
58.11 + * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
58.12 + *
58.13 + * %Begin-Header%
58.14 + * This file may be redistributed under the terms of the
58.15 + * GNU Lesser General Public License.
58.16 + * %End-Header%
58.17 + */
58.18 +
58.19 +#include "config.h"
58.20 +#include <stdio.h>
58.21 +#include <string.h>
58.22 +#include <stdlib.h>
58.23 +#include <unistd.h>
58.24 +#include <fcntl.h>
58.25 +#include <ctype.h>
58.26 +#include <sys/types.h>
58.27 +#ifdef HAVE_SYS_STAT_H
58.28 +#include <sys/stat.h>
58.29 +#endif
58.30 +#ifdef HAVE_SYS_MKDEV_H
58.31 +#include <sys/mkdev.h>
58.32 +#endif
58.33 +#ifdef __linux__
58.34 +#include <sys/utsname.h>
58.35 +#endif
58.36 +#ifdef HAVE_ERRNO_H
58.37 +#include <errno.h>
58.38 +#endif
58.39 +#include "blkidP.h"
58.40 +#include "uuid/uuid.h"
58.41 +#include "probe.h"
58.42 +
58.43 +static int figure_label_len(const unsigned char *label, int len)
58.44 +{
58.45 + const unsigned char *end = label + len - 1;
58.46 +
58.47 + while (end >= label && (*end == ' ' || *end == 0))
58.48 + --end;
58.49 + if (end >= label)
58.50 + return end - label + 1;
58.51 + return 0;
58.52 +}
58.53 +
58.54 +static unsigned char *get_buffer(struct blkid_probe *pr,
58.55 + blkid_loff_t off, size_t len)
58.56 +{
58.57 + ssize_t ret_read;
58.58 + unsigned char *newbuf;
58.59 +
58.60 + if (off + len <= SB_BUFFER_SIZE) {
58.61 + if (!pr->sbbuf) {
58.62 + pr->sbbuf = malloc(SB_BUFFER_SIZE);
58.63 + if (!pr->sbbuf)
58.64 + return NULL;
58.65 + if (lseek(pr->fd, 0, SEEK_SET) < 0)
58.66 + return NULL;
58.67 + ret_read = read(pr->fd, pr->sbbuf, SB_BUFFER_SIZE);
58.68 + if (ret_read < 0)
58.69 + ret_read = 0;
58.70 + pr->sb_valid = ret_read;
58.71 + }
58.72 + if (off+len > pr->sb_valid)
58.73 + return NULL;
58.74 + return pr->sbbuf + off;
58.75 + } else {
58.76 + if (len > pr->buf_max) {
58.77 + newbuf = realloc(pr->buf, len);
58.78 + if (newbuf == NULL)
58.79 + return NULL;
58.80 + pr->buf = newbuf;
58.81 + pr->buf_max = len;
58.82 + }
58.83 + if (blkid_llseek(pr->fd, off, SEEK_SET) < 0)
58.84 + return NULL;
58.85 + ret_read = read(pr->fd, pr->buf, len);
58.86 + if (ret_read != (ssize_t) len)
58.87 + return NULL;
58.88 + return pr->buf;
58.89 + }
58.90 +}
58.91 +
58.92 +
58.93 +/*
58.94 + * This is a special case code to check for an MDRAID device. We do
58.95 + * this special since it requires checking for a superblock at the end
58.96 + * of the device.
58.97 + */
58.98 +static int check_mdraid(int fd, unsigned char *ret_uuid)
58.99 +{
58.100 + struct mdp_superblock_s *md;
58.101 + blkid_loff_t offset;
58.102 + char buf[4096];
58.103 +
58.104 + if (fd < 0)
58.105 + return -BLKID_ERR_PARAM;
58.106 +
58.107 + offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536;
58.108 +
58.109 + if (blkid_llseek(fd, offset, 0) < 0 ||
58.110 + read(fd, buf, 4096) != 4096)
58.111 + return -BLKID_ERR_IO;
58.112 + /* Check for magic number */
58.113 + if (memcmp("\251+N\374", buf, 4) && memcmp("\374N+\251", buf, 4))
58.114 + return -BLKID_ERR_PARAM;
58.115 +
58.116 + if (!ret_uuid)
58.117 + return 0;
58.118 + *ret_uuid = 0;
58.119 +
58.120 + /* The MD UUID is not contiguous in the superblock, make it so */
58.121 + md = (struct mdp_superblock_s *)buf;
58.122 + if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) {
58.123 + memcpy(ret_uuid, &md->set_uuid0, 4);
58.124 + memcpy(ret_uuid + 4, &md->set_uuid1, 12);
58.125 + }
58.126 + return 0;
58.127 +}
58.128 +
58.129 +static void set_uuid(blkid_dev dev, uuid_t uuid, const char *tag)
58.130 +{
58.131 + char str[37];
58.132 +
58.133 + if (!uuid_is_null(uuid)) {
58.134 + uuid_unparse(uuid, str);
58.135 + blkid_set_tag(dev, tag ? tag : "UUID", str, sizeof(str));
58.136 + }
58.137 +}
58.138 +
58.139 +static void get_ext2_info(blkid_dev dev, struct blkid_magic *id,
58.140 + unsigned char *buf)
58.141 +{
58.142 + struct ext2_super_block *es = (struct ext2_super_block *) buf;
58.143 + const char *label = 0;
58.144 +
58.145 + DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n",
58.146 + blkid_le32(es->s_feature_compat),
58.147 + blkid_le32(es->s_feature_incompat),
58.148 + blkid_le32(es->s_feature_ro_compat)));
58.149 +
58.150 + if (strlen(es->s_volume_name))
58.151 + label = es->s_volume_name;
58.152 + blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name));
58.153 +
58.154 + set_uuid(dev, es->s_uuid, 0);
58.155 +
58.156 + if ((es->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
58.157 + !uuid_is_null(es->s_journal_uuid))
58.158 + set_uuid(dev, es->s_journal_uuid, "EXT_JOURNAL");
58.159 +
58.160 + if (strcmp(id->bim_type, "ext2") &&
58.161 + ((blkid_le32(es->s_feature_incompat) &
58.162 + EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0))
58.163 + blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2"));
58.164 +}
58.165 +
58.166 +/*
58.167 + * Check to see if a filesystem is in /proc/filesystems.
58.168 + * Returns 1 if found, 0 if not
58.169 + */
58.170 +static int fs_proc_check(const char *fs_name)
58.171 +{
58.172 + FILE *f;
58.173 + char buf[80], *cp, *t;
58.174 +
58.175 + f = fopen("/proc/filesystems", "r");
58.176 + if (!f)
58.177 + return (0);
58.178 + while (!feof(f)) {
58.179 + if (!fgets(buf, sizeof(buf), f))
58.180 + break;
58.181 + cp = buf;
58.182 + if (!isspace(*cp)) {
58.183 + while (*cp && !isspace(*cp))
58.184 + cp++;
58.185 + }
58.186 + while (*cp && isspace(*cp))
58.187 + cp++;
58.188 + if ((t = strchr(cp, '\n')) != NULL)
58.189 + *t = 0;
58.190 + if ((t = strchr(cp, '\t')) != NULL)
58.191 + *t = 0;
58.192 + if ((t = strchr(cp, ' ')) != NULL)
58.193 + *t = 0;
58.194 + if (!strcmp(fs_name, cp)) {
58.195 + fclose(f);
58.196 + return (1);
58.197 + }
58.198 + }
58.199 + fclose(f);
58.200 + return (0);
58.201 +}
58.202 +
58.203 +/*
58.204 + * Check to see if a filesystem is available as a module
58.205 + * Returns 1 if found, 0 if not
58.206 + */
58.207 +static int check_for_modules(const char *fs_name)
58.208 +{
58.209 +#ifdef __linux__
58.210 + struct utsname uts;
58.211 + FILE *f;
58.212 + char buf[1024], *cp;
58.213 + int namesz;
58.214 +
58.215 + if (uname(&uts))
58.216 + return (0);
58.217 + snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release);
58.218 +
58.219 + f = fopen(buf, "r");
58.220 + if (!f)
58.221 + return (0);
58.222 +
58.223 + namesz = strlen(fs_name);
58.224 +
58.225 + while (!feof(f)) {
58.226 + if (!fgets(buf, sizeof(buf), f))
58.227 + break;
58.228 + if ((cp = strchr(buf, ':')) != NULL)
58.229 + *cp = 0;
58.230 + else
58.231 + continue;
58.232 + if ((cp = strrchr(buf, '/')) != NULL)
58.233 + cp++;
58.234 + else
58.235 + cp = buf;
58.236 + if (!strncmp(cp, fs_name, namesz) &&
58.237 + (!strcmp(cp + namesz, ".ko") ||
58.238 + !strcmp(cp + namesz, ".ko.gz"))) {
58.239 + fclose(f);
58.240 + return (1);
58.241 + }
58.242 + }
58.243 + fclose(f);
58.244 +#endif
58.245 + return (0);
58.246 +}
58.247 +
58.248 +static int linux_version_code(void)
58.249 +{
58.250 +#ifdef __linux__
58.251 + struct utsname ut;
58.252 + static int version_code = -1;
58.253 + int major, minor, rev;
58.254 + char *endptr;
58.255 + const char *cp;
58.256 +
58.257 + if (version_code > 0)
58.258 + return version_code;
58.259 +
58.260 + if (uname(&ut))
58.261 + return 0;
58.262 + cp = ut.release;
58.263 +
58.264 + major = strtol(cp, &endptr, 10);
58.265 + if (cp == endptr || *endptr != '.')
58.266 + return 0;
58.267 + cp = endptr + 1;
58.268 + minor = strtol(cp, &endptr, 10);
58.269 + if (cp == endptr || *endptr != '.')
58.270 + return 0;
58.271 + cp = endptr + 1;
58.272 + rev = strtol(cp, &endptr, 10);
58.273 + if (cp == endptr)
58.274 + return 0;
58.275 + version_code = (((major * 256) + minor) * 256) + rev;
58.276 + return version_code;
58.277 +#else
58.278 + return 0;
58.279 +#endif
58.280 +}
58.281 +
58.282 +#define EXT4_SUPPORTS_EXT2 (2 * 65536 + 6*256 + 29)
58.283 +
58.284 +static int system_supports_ext2(void)
58.285 +{
58.286 + static time_t last_check = 0;
58.287 + static int ret = -1;
58.288 + time_t now = time(0);
58.289 +
58.290 + if (ret != -1 || (now - last_check) < 5)
58.291 + return ret;
58.292 + last_check = now;
58.293 + ret = (fs_proc_check("ext2") || check_for_modules("ext2"));
58.294 + return ret;
58.295 +}
58.296 +
58.297 +static int system_supports_ext4(void)
58.298 +{
58.299 + static time_t last_check = 0;
58.300 + static int ret = -1;
58.301 + time_t now = time(0);
58.302 +
58.303 + if (ret != -1 || (now - last_check) < 5)
58.304 + return ret;
58.305 + last_check = now;
58.306 + ret = (fs_proc_check("ext4") || check_for_modules("ext4"));
58.307 + return ret;
58.308 +}
58.309 +
58.310 +static int system_supports_ext4dev(void)
58.311 +{
58.312 + static time_t last_check = 0;
58.313 + static int ret = -1;
58.314 + time_t now = time(0);
58.315 +
58.316 + if (ret != -1 || (now - last_check) < 5)
58.317 + return ret;
58.318 + last_check = now;
58.319 + ret = (fs_proc_check("ext4dev") || check_for_modules("ext4dev"));
58.320 + return ret;
58.321 +}
58.322 +
58.323 +static int probe_ext4dev(struct blkid_probe *probe,
58.324 + struct blkid_magic *id,
58.325 + unsigned char *buf)
58.326 +{
58.327 + struct ext2_super_block *es;
58.328 + es = (struct ext2_super_block *)buf;
58.329 +
58.330 + /* Distinguish from jbd */
58.331 + if (blkid_le32(es->s_feature_incompat) &
58.332 + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
58.333 + return -BLKID_ERR_PARAM;
58.334 +
58.335 + /*
58.336 + * If the filesystem does not have a journal and ext2 and ext4
58.337 + * is not present, then force this to be detected as an
58.338 + * ext4dev filesystem.
58.339 + */
58.340 + if (!(blkid_le32(es->s_feature_compat) &
58.341 + EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
58.342 + !system_supports_ext2() && !system_supports_ext4() &&
58.343 + system_supports_ext4dev() &&
58.344 + linux_version_code() >= EXT4_SUPPORTS_EXT2)
58.345 + goto force_ext4dev;
58.346 +
58.347 + /*
58.348 + * If the filesystem is marked as OK for use by in-development
58.349 + * filesystem code, but ext4dev is not supported, and ext4 is,
58.350 + * then don't call ourselves ext4dev, since we should be
58.351 + * detected as ext4 in that case.
58.352 + *
58.353 + * If the filesystem is marked as in use by production
58.354 + * filesystem, then it can only be used by ext4 and NOT by
58.355 + * ext4dev, so always disclaim we are ext4dev in that case.
58.356 + */
58.357 + if (blkid_le32(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) {
58.358 + if (!system_supports_ext4dev() && system_supports_ext4())
58.359 + return -BLKID_ERR_PARAM;
58.360 + } else
58.361 + return -BLKID_ERR_PARAM;
58.362 +
58.363 +force_ext4dev:
58.364 + get_ext2_info(probe->dev, id, buf);
58.365 + return 0;
58.366 +}
58.367 +
58.368 +static int probe_ext4(struct blkid_probe *probe, struct blkid_magic *id,
58.369 + unsigned char *buf)
58.370 +{
58.371 + struct ext2_super_block *es;
58.372 + es = (struct ext2_super_block *)buf;
58.373 +
58.374 + /* Distinguish from jbd */
58.375 + if (blkid_le32(es->s_feature_incompat) &
58.376 + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
58.377 + return -BLKID_ERR_PARAM;
58.378 +
58.379 + /*
58.380 + * If the filesystem does not have a journal and ext2 is not
58.381 + * present, then force this to be detected as an ext2
58.382 + * filesystem.
58.383 + */
58.384 + if (!(blkid_le32(es->s_feature_compat) &
58.385 + EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
58.386 + !system_supports_ext2() && system_supports_ext4() &&
58.387 + linux_version_code() >= EXT4_SUPPORTS_EXT2)
58.388 + goto force_ext4;
58.389 +
58.390 + /* Ext4 has at least one feature which ext3 doesn't understand */
58.391 + if (!(blkid_le32(es->s_feature_ro_compat) &
58.392 + EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) &&
58.393 + !(blkid_le32(es->s_feature_incompat) &
58.394 + EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
58.395 + return -BLKID_ERR_PARAM;
58.396 +
58.397 +force_ext4:
58.398 + /*
58.399 + * If the filesystem is a OK for use by in-development
58.400 + * filesystem code, and ext4dev is supported or ext4 is not
58.401 + * supported, then don't call ourselves ext4, so we can redo
58.402 + * the detection and mark the filesystem as ext4dev.
58.403 + *
58.404 + * If the filesystem is marked as in use by production
58.405 + * filesystem, then it can only be used by ext4 and NOT by
58.406 + * ext4dev.
58.407 + */
58.408 + if (blkid_le32(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) {
58.409 + if (system_supports_ext4dev() || !system_supports_ext4())
58.410 + return -BLKID_ERR_PARAM;
58.411 + }
58.412 + get_ext2_info(probe->dev, id, buf);
58.413 + return 0;
58.414 +}
58.415 +
58.416 +static int probe_ext3(struct blkid_probe *probe, struct blkid_magic *id,
58.417 + unsigned char *buf)
58.418 +{
58.419 + struct ext2_super_block *es;
58.420 + es = (struct ext2_super_block *)buf;
58.421 +
58.422 + /* ext3 requires journal */
58.423 + if (!(blkid_le32(es->s_feature_compat) &
58.424 + EXT3_FEATURE_COMPAT_HAS_JOURNAL))
58.425 + return -BLKID_ERR_PARAM;
58.426 +
58.427 + /* Any features which ext3 doesn't understand */
58.428 + if ((blkid_le32(es->s_feature_ro_compat) &
58.429 + EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) ||
58.430 + (blkid_le32(es->s_feature_incompat) &
58.431 + EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
58.432 + return -BLKID_ERR_PARAM;
58.433 +
58.434 + get_ext2_info(probe->dev, id, buf);
58.435 + return 0;
58.436 +}
58.437 +
58.438 +static int probe_ext2(struct blkid_probe *probe, struct blkid_magic *id,
58.439 + unsigned char *buf)
58.440 +{
58.441 + struct ext2_super_block *es;
58.442 +
58.443 + es = (struct ext2_super_block *)buf;
58.444 +
58.445 + /* Distinguish between ext3 and ext2 */
58.446 + if ((blkid_le32(es->s_feature_compat) &
58.447 + EXT3_FEATURE_COMPAT_HAS_JOURNAL))
58.448 + return -BLKID_ERR_PARAM;
58.449 +
58.450 + /* Any features which ext2 doesn't understand */
58.451 + if ((blkid_le32(es->s_feature_ro_compat) &
58.452 + EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) ||
58.453 + (blkid_le32(es->s_feature_incompat) &
58.454 + EXT2_FEATURE_INCOMPAT_UNSUPPORTED))
58.455 + return -BLKID_ERR_PARAM;
58.456 +
58.457 + /*
58.458 + * If ext2 is not present, but ext4 or ext4dev are, then
58.459 + * disclaim we are ext2
58.460 + */
58.461 + if (!system_supports_ext2() &&
58.462 + (system_supports_ext4() || system_supports_ext4dev()) &&
58.463 + linux_version_code() >= EXT4_SUPPORTS_EXT2)
58.464 + return -BLKID_ERR_PARAM;
58.465 +
58.466 + get_ext2_info(probe->dev, id, buf);
58.467 + return 0;
58.468 +}
58.469 +
58.470 +static int probe_jbd(struct blkid_probe *probe, struct blkid_magic *id,
58.471 + unsigned char *buf)
58.472 +{
58.473 + struct ext2_super_block *es = (struct ext2_super_block *) buf;
58.474 +
58.475 + if (!(blkid_le32(es->s_feature_incompat) &
58.476 + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
58.477 + return -BLKID_ERR_PARAM;
58.478 +
58.479 + get_ext2_info(probe->dev, id, buf);
58.480 +
58.481 + return 0;
58.482 +}
58.483 +
58.484 +#define FAT_ATTR_VOLUME_ID 0x08
58.485 +#define FAT_ATTR_DIR 0x10
58.486 +#define FAT_ATTR_LONG_NAME 0x0f
58.487 +#define FAT_ATTR_MASK 0x3f
58.488 +#define FAT_ENTRY_FREE 0xe5
58.489 +
58.490 +static const char *no_name = "NO NAME ";
58.491 +
58.492 +static unsigned char *search_fat_label(struct vfat_dir_entry *dir, int count)
58.493 +{
58.494 + int i;
58.495 +
58.496 + for (i = 0; i < count; i++) {
58.497 + if (dir[i].name[0] == 0x00)
58.498 + break;
58.499 +
58.500 + if ((dir[i].name[0] == FAT_ENTRY_FREE) ||
58.501 + (dir[i].cluster_high != 0 || dir[i].cluster_low != 0) ||
58.502 + ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME))
58.503 + continue;
58.504 +
58.505 + if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) ==
58.506 + FAT_ATTR_VOLUME_ID) {
58.507 + return dir[i].name;
58.508 + }
58.509 + }
58.510 + return 0;
58.511 +}
58.512 +
58.513 +/* FAT label extraction from the root directory taken from Kay
58.514 + * Sievers's volume_id library */
58.515 +static int probe_fat(struct blkid_probe *probe,
58.516 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.517 + unsigned char *buf)
58.518 +{
58.519 + struct vfat_super_block *vs = (struct vfat_super_block *) buf;
58.520 + struct msdos_super_block *ms = (struct msdos_super_block *) buf;
58.521 + struct vfat_dir_entry *dir;
58.522 + char serno[10];
58.523 + const unsigned char *label = 0, *vol_label = 0, *tmp;
58.524 + unsigned char *vol_serno;
58.525 + int label_len = 0, maxloop = 100;
58.526 + __u16 sector_size, dir_entries, reserved;
58.527 + __u32 sect_count, fat_size, dir_size, cluster_count, fat_length;
58.528 + __u32 buf_size, start_data_sect, next, root_start, root_dir_entries;
58.529 +
58.530 + /* sector size check */
58.531 + tmp = (unsigned char *)&ms->ms_sector_size;
58.532 + sector_size = tmp[0] + (tmp[1] << 8);
58.533 + if (sector_size != 0x200 && sector_size != 0x400 &&
58.534 + sector_size != 0x800 && sector_size != 0x1000)
58.535 + return 1;
58.536 +
58.537 + tmp = (unsigned char *)&ms->ms_dir_entries;
58.538 + dir_entries = tmp[0] + (tmp[1] << 8);
58.539 + reserved = blkid_le16(ms->ms_reserved);
58.540 + tmp = (unsigned char *)&ms->ms_sectors;
58.541 + sect_count = tmp[0] + (tmp[1] << 8);
58.542 + if (sect_count == 0)
58.543 + sect_count = blkid_le32(ms->ms_total_sect);
58.544 +
58.545 + fat_length = blkid_le16(ms->ms_fat_length);
58.546 + if (fat_length == 0)
58.547 + fat_length = blkid_le32(vs->vs_fat32_length);
58.548 +
58.549 + fat_size = fat_length * ms->ms_fats;
58.550 + dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
58.551 + (sector_size-1)) / sector_size;
58.552 +
58.553 + cluster_count = sect_count - (reserved + fat_size + dir_size);
58.554 + if (ms->ms_cluster_size == 0)
58.555 + return 1;
58.556 + cluster_count /= ms->ms_cluster_size;
58.557 +
58.558 + if (cluster_count > FAT32_MAX)
58.559 + return 1;
58.560 +
58.561 + if (ms->ms_fat_length) {
58.562 + /* the label may be an attribute in the root directory */
58.563 + root_start = (reserved + fat_size) * sector_size;
58.564 + root_dir_entries = vs->vs_dir_entries[0] +
58.565 + (vs->vs_dir_entries[1] << 8);
58.566 +
58.567 + buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
58.568 + dir = (struct vfat_dir_entry *) get_buffer(probe, root_start,
58.569 + buf_size);
58.570 + if (dir)
58.571 + vol_label = search_fat_label(dir, root_dir_entries);
58.572 +
58.573 + if (!vol_label || !memcmp(vol_label, no_name, 11))
58.574 + vol_label = ms->ms_label;
58.575 + vol_serno = ms->ms_serno;
58.576 +
58.577 + blkid_set_tag(probe->dev, "SEC_TYPE", "msdos",
58.578 + sizeof("msdos"));
58.579 + } else {
58.580 + /* Search the FAT32 root dir for the label attribute */
58.581 + buf_size = vs->vs_cluster_size * sector_size;
58.582 + start_data_sect = reserved + fat_size;
58.583 +
58.584 + next = blkid_le32(vs->vs_root_cluster);
58.585 + while (next && --maxloop) {
58.586 + __u32 next_sect_off;
58.587 + __u64 next_off, fat_entry_off;
58.588 + int count;
58.589 +
58.590 + next_sect_off = (next - 2) * vs->vs_cluster_size;
58.591 + next_off = (__u64) (start_data_sect + next_sect_off) *
58.592 + sector_size;
58.593 +
58.594 + dir = (struct vfat_dir_entry *)
58.595 + get_buffer(probe, next_off, buf_size);
58.596 + if (dir == NULL)
58.597 + break;
58.598 +
58.599 + count = buf_size / sizeof(struct vfat_dir_entry);
58.600 +
58.601 + vol_label = search_fat_label(dir, count);
58.602 + if (vol_label)
58.603 + break;
58.604 +
58.605 + /* get FAT entry */
58.606 + fat_entry_off =
58.607 + ((unsigned int) reserved *
58.608 + (unsigned int) sector_size) +
58.609 + (next * sizeof(__u32));
58.610 + buf = get_buffer(probe, fat_entry_off, buf_size);
58.611 + if (buf == NULL)
58.612 + break;
58.613 +
58.614 + /* set next cluster */
58.615 + next = blkid_le32(*((__u32 *) buf) & 0x0fffffff);
58.616 + }
58.617 +
58.618 + if (!vol_label || !memcmp(vol_label, no_name, 11))
58.619 + vol_label = vs->vs_label;
58.620 + vol_serno = vs->vs_serno;
58.621 + }
58.622 +
58.623 + if (vol_label && memcmp(vol_label, no_name, 11)) {
58.624 + if ((label_len = figure_label_len(vol_label, 11)))
58.625 + label = vol_label;
58.626 + }
58.627 +
58.628 + /* We can't just print them as %04X, because they are unaligned */
58.629 + sprintf(serno, "%02X%02X-%02X%02X", vol_serno[3], vol_serno[2],
58.630 + vol_serno[1], vol_serno[0]);
58.631 +
58.632 + blkid_set_tag(probe->dev, "LABEL", (const char *) label, label_len);
58.633 + blkid_set_tag(probe->dev, "UUID", serno, sizeof(serno)-1);
58.634 +
58.635 + return 0;
58.636 +}
58.637 +
58.638 +/*
58.639 + * The FAT filesystem could be without a magic string in superblock
58.640 + * (e.g. old floppies). This heuristic for FAT detection is inspired
58.641 + * by http://vrfy.org/projects/volume_id/ and Linux kernel.
58.642 + * [7-Jul-2005, Karel Zak <kzak@redhat.com>]
58.643 + */
58.644 +static int probe_fat_nomagic(struct blkid_probe *probe,
58.645 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.646 + unsigned char *buf)
58.647 +{
58.648 + struct msdos_super_block *ms;
58.649 +
58.650 + ms = (struct msdos_super_block *)buf;
58.651 +
58.652 + /* heads check */
58.653 + if (ms->ms_heads == 0)
58.654 + return 1;
58.655 +
58.656 + /* cluster size check*/
58.657 + if (ms->ms_cluster_size == 0 ||
58.658 + (ms->ms_cluster_size & (ms->ms_cluster_size-1)))
58.659 + return 1;
58.660 +
58.661 + /* media check */
58.662 + if (ms->ms_media < 0xf8 && ms->ms_media != 0xf0)
58.663 + return 1;
58.664 +
58.665 + /* fat counts(Linux kernel expects at least 1 FAT table) */
58.666 + if (!ms->ms_fats)
58.667 + return 1;
58.668 +
58.669 + /*
58.670 + * OS/2 and apparently DFSee will place a FAT12/16-like
58.671 + * pseudo-superblock in the first 512 bytes of non-FAT
58.672 + * filesystems --- at least JFS and HPFS, and possibly others.
58.673 + * So we explicitly check for those filesystems at the
58.674 + * FAT12/16 filesystem magic field identifier, and if they are
58.675 + * present, we rule this out as a FAT filesystem, despite the
58.676 + * FAT-like pseudo-header.
58.677 + */
58.678 + if ((memcmp(ms->ms_magic, "JFS ", 8) == 0) ||
58.679 + (memcmp(ms->ms_magic, "HPFS ", 8) == 0))
58.680 + return 1;
58.681 +
58.682 + return probe_fat(probe, id, buf);
58.683 +}
58.684 +
58.685 +static int probe_ntfs(struct blkid_probe *probe,
58.686 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.687 + unsigned char *buf)
58.688 +{
58.689 + struct ntfs_super_block *ns;
58.690 + struct master_file_table_record *mft;
58.691 + struct file_attribute *attr;
58.692 + char uuid_str[17], label_str[129], *cp;
58.693 + int bytes_per_sector, sectors_per_cluster;
58.694 + int mft_record_size, attr_off, attr_len;
58.695 + unsigned int i, attr_type, val_len;
58.696 + int val_off;
58.697 + __u64 nr_clusters;
58.698 + blkid_loff_t off;
58.699 + unsigned char *buf_mft, *val;
58.700 +
58.701 + ns = (struct ntfs_super_block *) buf;
58.702 +
58.703 + bytes_per_sector = ns->bios_parameter_block[0] +
58.704 + (ns->bios_parameter_block[1] << 8);
58.705 + sectors_per_cluster = ns->bios_parameter_block[2];
58.706 +
58.707 + if ((bytes_per_sector < 512) || (sectors_per_cluster == 0))
58.708 + return 1;
58.709 +
58.710 + if (ns->cluster_per_mft_record < 0)
58.711 + mft_record_size = 1 << (0-ns->cluster_per_mft_record);
58.712 + else
58.713 + mft_record_size = ns->cluster_per_mft_record *
58.714 + sectors_per_cluster * bytes_per_sector;
58.715 + nr_clusters = blkid_le64(ns->number_of_sectors) / sectors_per_cluster;
58.716 +
58.717 + if ((blkid_le64(ns->mft_cluster_location) > nr_clusters) ||
58.718 + (blkid_le64(ns->mft_mirror_cluster_location) > nr_clusters))
58.719 + return 1;
58.720 +
58.721 + off = blkid_le64(ns->mft_mirror_cluster_location) *
58.722 + bytes_per_sector * sectors_per_cluster;
58.723 +
58.724 + buf_mft = get_buffer(probe, off, mft_record_size);
58.725 + if (!buf_mft)
58.726 + return 1;
58.727 +
58.728 + if (memcmp(buf_mft, "FILE", 4))
58.729 + return 1;
58.730 +
58.731 + off = blkid_le64(ns->mft_cluster_location) * bytes_per_sector *
58.732 + sectors_per_cluster;
58.733 +
58.734 + buf_mft = get_buffer(probe, off, mft_record_size);
58.735 + if (!buf_mft)
58.736 + return 1;
58.737 +
58.738 + if (memcmp(buf_mft, "FILE", 4))
58.739 + return 1;
58.740 +
58.741 + off += MFT_RECORD_VOLUME * mft_record_size;
58.742 +
58.743 + buf_mft = get_buffer(probe, off, mft_record_size);
58.744 + if (!buf_mft)
58.745 + return 1;
58.746 +
58.747 + if (memcmp(buf_mft, "FILE", 4))
58.748 + return 1;
58.749 +
58.750 + mft = (struct master_file_table_record *) buf_mft;
58.751 +
58.752 + attr_off = blkid_le16(mft->attrs_offset);
58.753 + label_str[0] = 0;
58.754 +
58.755 + while (1) {
58.756 + attr = (struct file_attribute *) (buf_mft + attr_off);
58.757 + attr_len = blkid_le16(attr->len);
58.758 + attr_type = blkid_le32(attr->type);
58.759 + val_off = blkid_le16(attr->value_offset);
58.760 + val_len = blkid_le32(attr->value_len);
58.761 +
58.762 + attr_off += attr_len;
58.763 +
58.764 + if ((attr_off > mft_record_size) ||
58.765 + (attr_len == 0))
58.766 + break;
58.767 +
58.768 + if (attr_type == MFT_RECORD_ATTR_END)
58.769 + break;
58.770 +
58.771 + if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
58.772 + if (val_len > sizeof(label_str))
58.773 + val_len = sizeof(label_str)-1;
58.774 +
58.775 + for (i=0, cp=label_str; i < val_len; i+=2,cp++) {
58.776 + val = ((__u8 *) attr) + val_off + i;
58.777 + *cp = val[0];
58.778 + if (val[1])
58.779 + *cp = '?';
58.780 + }
58.781 + *cp = 0;
58.782 + }
58.783 + }
58.784 +
58.785 + sprintf(uuid_str, "%016llX", blkid_le64(ns->volume_serial));
58.786 + blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
58.787 + if (label_str[0])
58.788 + blkid_set_tag(probe->dev, "LABEL", label_str, 0);
58.789 + return 0;
58.790 +}
58.791 +
58.792 +
58.793 +static int probe_xfs(struct blkid_probe *probe,
58.794 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.795 + unsigned char *buf)
58.796 +{
58.797 + struct xfs_super_block *xs;
58.798 + const char *label = 0;
58.799 +
58.800 + xs = (struct xfs_super_block *)buf;
58.801 +
58.802 + if (strlen(xs->xs_fname))
58.803 + label = xs->xs_fname;
58.804 + blkid_set_tag(probe->dev, "LABEL", label, sizeof(xs->xs_fname));
58.805 + set_uuid(probe->dev, xs->xs_uuid, 0);
58.806 + return 0;
58.807 +}
58.808 +
58.809 +static int probe_reiserfs(struct blkid_probe *probe,
58.810 + struct blkid_magic *id, unsigned char *buf)
58.811 +{
58.812 + struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf;
58.813 + unsigned int blocksize;
58.814 + const char *label = 0;
58.815 +
58.816 + blocksize = blkid_le16(rs->rs_blocksize);
58.817 +
58.818 + /* The blocksize must be at least 1k */
58.819 + if ((blocksize >> 10) == 0)
58.820 + return -BLKID_ERR_PARAM;
58.821 +
58.822 + /* If the superblock is inside the journal, we have the wrong one */
58.823 + if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block))
58.824 + return -BLKID_ERR_BIG;
58.825 +
58.826 + /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
58.827 + if (id->bim_magic[6] == '2' || id->bim_magic[6] == '3') {
58.828 + if (strlen(rs->rs_label))
58.829 + label = rs->rs_label;
58.830 + set_uuid(probe->dev, rs->rs_uuid, 0);
58.831 + }
58.832 + blkid_set_tag(probe->dev, "LABEL", label, sizeof(rs->rs_label));
58.833 +
58.834 + return 0;
58.835 +}
58.836 +
58.837 +static int probe_reiserfs4(struct blkid_probe *probe,
58.838 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.839 + unsigned char *buf)
58.840 +{
58.841 + struct reiser4_super_block *rs4 = (struct reiser4_super_block *) buf;
58.842 + const unsigned char *label = 0;
58.843 +
58.844 + if (strlen((char *) rs4->rs4_label))
58.845 + label = rs4->rs4_label;
58.846 + set_uuid(probe->dev, rs4->rs4_uuid, 0);
58.847 + blkid_set_tag(probe->dev, "LABEL", (const char *) label,
58.848 + sizeof(rs4->rs4_label));
58.849 +
58.850 + return 0;
58.851 +}
58.852 +
58.853 +static int probe_jfs(struct blkid_probe *probe,
58.854 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.855 + unsigned char *buf)
58.856 +{
58.857 + struct jfs_super_block *js;
58.858 + const char *label = 0;
58.859 +
58.860 + js = (struct jfs_super_block *)buf;
58.861 +
58.862 + if (blkid_le32(js->js_bsize) != (1U << blkid_le16(js->js_l2bsize)))
58.863 + return 1;
58.864 +
58.865 + if (blkid_le32(js->js_pbsize) != (1U << blkid_le16(js->js_l2pbsize)))
58.866 + return 1;
58.867 +
58.868 + if ((blkid_le16(js->js_l2bsize) - blkid_le16(js->js_l2pbsize)) !=
58.869 + blkid_le16(js->js_l2bfactor))
58.870 + return 1;
58.871 +
58.872 + if (strlen((char *) js->js_label))
58.873 + label = (char *) js->js_label;
58.874 + blkid_set_tag(probe->dev, "LABEL", label, sizeof(js->js_label));
58.875 + set_uuid(probe->dev, js->js_uuid, 0);
58.876 + return 0;
58.877 +}
58.878 +
58.879 +static int probe_zfs(struct blkid_probe *probe __BLKID_ATTR((unused)),
58.880 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.881 + unsigned char *buf __BLKID_ATTR((unused)))
58.882 +{
58.883 +#if 0
58.884 + char *vdev_label;
58.885 + const char *pool_name = 0;
58.886 +
58.887 + /* read nvpair data for pool name, pool GUID (complex) */
58.888 + blkid_set_tag(probe->dev, "LABEL", pool_name, sizeof(pool_name));
58.889 + set_uuid(probe->dev, pool_guid, 0);
58.890 +#endif
58.891 + return 0;
58.892 +}
58.893 +
58.894 +static int probe_luks(struct blkid_probe *probe,
58.895 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.896 + unsigned char *buf)
58.897 +{
58.898 + char uuid[40];
58.899 +
58.900 + /* 168 is the offset to the 40 character uuid:
58.901 + * http://luks.endorphin.org/LUKS-on-disk-format.pdf */
58.902 + strncpy(uuid, (char *) buf+168, 40);
58.903 + blkid_set_tag(probe->dev, "UUID", uuid, sizeof(uuid));
58.904 + return 0;
58.905 +}
58.906 +
58.907 +static int probe_romfs(struct blkid_probe *probe,
58.908 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.909 + unsigned char *buf)
58.910 +{
58.911 + struct romfs_super_block *ros;
58.912 + const char *label = 0;
58.913 +
58.914 + ros = (struct romfs_super_block *)buf;
58.915 +
58.916 + if (strlen((char *) ros->ros_volume))
58.917 + label = (char *) ros->ros_volume;
58.918 + blkid_set_tag(probe->dev, "LABEL", label, 0);
58.919 + return 0;
58.920 +}
58.921 +
58.922 +static int probe_cramfs(struct blkid_probe *probe,
58.923 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.924 + unsigned char *buf)
58.925 +{
58.926 + struct cramfs_super_block *csb;
58.927 + const char *label = 0;
58.928 +
58.929 + csb = (struct cramfs_super_block *)buf;
58.930 +
58.931 + if (strlen((char *) csb->name))
58.932 + label = (char *) csb->name;
58.933 + blkid_set_tag(probe->dev, "LABEL", label, 0);
58.934 + return 0;
58.935 +}
58.936 +
58.937 +static int probe_swap0(struct blkid_probe *probe,
58.938 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.939 + unsigned char *buf __BLKID_ATTR((unused)))
58.940 +{
58.941 + blkid_set_tag(probe->dev, "UUID", 0, 0);
58.942 + blkid_set_tag(probe->dev, "LABEL", 0, 0);
58.943 + return 0;
58.944 +}
58.945 +
58.946 +static int probe_swap1(struct blkid_probe *probe,
58.947 + struct blkid_magic *id,
58.948 + unsigned char *buf __BLKID_ATTR((unused)))
58.949 +{
58.950 + struct swap_id_block *sws;
58.951 +
58.952 + probe_swap0(probe, id, buf);
58.953 + /*
58.954 + * Version 1 swap headers are always located at offset of 1024
58.955 + * bytes, although the swap signature itself is located at the
58.956 + * end of the page (which may vary depending on hardware
58.957 + * pagesize).
58.958 + */
58.959 + sws = (struct swap_id_block *) get_buffer(probe, 1024, 1024);
58.960 + if (!sws)
58.961 + return 1;
58.962 +
58.963 + /* check for wrong version or zeroed pagecount, for sanity */
58.964 + if (!memcmp(id->bim_magic, "SWAPSPACE2", id->bim_len) &&
58.965 + (sws->sws_version != 1 || sws->sws_lastpage == 0))
58.966 + return 1;
58.967 +
58.968 + /* arbitrary sanity check.. is there any garbage down there? */
58.969 + if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) {
58.970 + if (sws->sws_volume[0])
58.971 + blkid_set_tag(probe->dev, "LABEL", sws->sws_volume,
58.972 + sizeof(sws->sws_volume));
58.973 + if (sws->sws_uuid[0])
58.974 + set_uuid(probe->dev, sws->sws_uuid, 0);
58.975 + }
58.976 + return 0;
58.977 +}
58.978 +
58.979 +static int probe_iso9660(struct blkid_probe *probe,
58.980 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.981 + unsigned char *buf)
58.982 +{
58.983 + struct iso_volume_descriptor *iso;
58.984 + const unsigned char *label;
58.985 +
58.986 + iso = (struct iso_volume_descriptor *) buf;
58.987 + label = iso->volume_id;
58.988 +
58.989 + blkid_set_tag(probe->dev, "LABEL", (const char *) label,
58.990 + figure_label_len(label, 32));
58.991 + return 0;
58.992 +}
58.993 +
58.994 +
58.995 +static const char
58.996 +*udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
58.997 + "NSR03", "TEA01", 0 };
58.998 +
58.999 +static int probe_udf(struct blkid_probe *probe,
58.1000 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.1001 + unsigned char *buf __BLKID_ATTR((unused)))
58.1002 +{
58.1003 + int j, bs;
58.1004 + struct iso_volume_descriptor *isosb;
58.1005 + const char ** m;
58.1006 +
58.1007 + /* determine the block size by scanning in 2K increments
58.1008 + (block sizes larger than 2K will be null padded) */
58.1009 + for (bs = 1; bs < 16; bs++) {
58.1010 + isosb = (struct iso_volume_descriptor *)
58.1011 + get_buffer(probe, (blkid_loff_t) bs*2048+32768,
58.1012 + sizeof(*isosb));
58.1013 + if (!isosb)
58.1014 + return 1;
58.1015 + if (isosb->vd_id[0])
58.1016 + break;
58.1017 + }
58.1018 +
58.1019 + /* Scan up to another 64 blocks looking for additional VSD's */
58.1020 + for (j = 1; j < 64; j++) {
58.1021 + if (j > 1) {
58.1022 + isosb = (struct iso_volume_descriptor *)
58.1023 + get_buffer(probe, j*bs*2048+32768,
58.1024 + sizeof(*isosb));
58.1025 + if (!isosb)
58.1026 + return 1;
58.1027 + }
58.1028 + /* If we find NSR0x then call it udf:
58.1029 + NSR01 for UDF 1.00
58.1030 + NSR02 for UDF 1.50
58.1031 + NSR03 for UDF 2.00 */
58.1032 + if (!memcmp(isosb->vd_id, "NSR0", 4))
58.1033 + return probe_iso9660(probe, id, buf);
58.1034 + for (m = udf_magic; *m; m++)
58.1035 + if (!memcmp(*m, isosb->vd_id, 5))
58.1036 + break;
58.1037 + if (*m == 0)
58.1038 + return 1;
58.1039 + }
58.1040 + return 1;
58.1041 +}
58.1042 +
58.1043 +static int probe_ocfs(struct blkid_probe *probe,
58.1044 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.1045 + unsigned char *buf)
58.1046 +{
58.1047 + struct ocfs_volume_header ovh;
58.1048 + struct ocfs_volume_label ovl;
58.1049 + __u32 major;
58.1050 +
58.1051 + memcpy(&ovh, buf, sizeof(ovh));
58.1052 + memcpy(&ovl, buf+512, sizeof(ovl));
58.1053 +
58.1054 + major = ocfsmajor(ovh);
58.1055 + if (major == 1)
58.1056 + blkid_set_tag(probe->dev,"SEC_TYPE","ocfs1",sizeof("ocfs1"));
58.1057 + else if (major >= 9)
58.1058 + blkid_set_tag(probe->dev,"SEC_TYPE","ntocfs",sizeof("ntocfs"));
58.1059 +
58.1060 + blkid_set_tag(probe->dev, "LABEL", ovl.label, ocfslabellen(ovl));
58.1061 + blkid_set_tag(probe->dev, "MOUNT", ovh.mount, ocfsmountlen(ovh));
58.1062 + set_uuid(probe->dev, ovl.vol_id, 0);
58.1063 + return 0;
58.1064 +}
58.1065 +
58.1066 +static int probe_ocfs2(struct blkid_probe *probe,
58.1067 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.1068 + unsigned char *buf)
58.1069 +{
58.1070 + struct ocfs2_super_block *osb;
58.1071 +
58.1072 + osb = (struct ocfs2_super_block *)buf;
58.1073 +
58.1074 + blkid_set_tag(probe->dev, "LABEL", osb->s_label, sizeof(osb->s_label));
58.1075 + set_uuid(probe->dev, osb->s_uuid, 0);
58.1076 + return 0;
58.1077 +}
58.1078 +
58.1079 +static int probe_oracleasm(struct blkid_probe *probe,
58.1080 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.1081 + unsigned char *buf)
58.1082 +{
58.1083 + struct oracle_asm_disk_label *dl;
58.1084 +
58.1085 + dl = (struct oracle_asm_disk_label *)buf;
58.1086 +
58.1087 + blkid_set_tag(probe->dev, "LABEL", dl->dl_id, sizeof(dl->dl_id));
58.1088 + return 0;
58.1089 +}
58.1090 +
58.1091 +static int probe_gfs(struct blkid_probe *probe,
58.1092 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.1093 + unsigned char *buf)
58.1094 +{
58.1095 + struct gfs2_sb *sbd;
58.1096 + const char *label = 0;
58.1097 +
58.1098 + sbd = (struct gfs2_sb *)buf;
58.1099 +
58.1100 + if (blkid_be32(sbd->sb_fs_format) == GFS_FORMAT_FS &&
58.1101 + blkid_be32(sbd->sb_multihost_format) == GFS_FORMAT_MULTI)
58.1102 + {
58.1103 + blkid_set_tag(probe->dev, "UUID", 0, 0);
58.1104 +
58.1105 + if (strlen(sbd->sb_locktable))
58.1106 + label = sbd->sb_locktable;
58.1107 + blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable));
58.1108 + return 0;
58.1109 + }
58.1110 + return 1;
58.1111 +}
58.1112 +
58.1113 +static int probe_gfs2(struct blkid_probe *probe,
58.1114 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.1115 + unsigned char *buf)
58.1116 +{
58.1117 + struct gfs2_sb *sbd;
58.1118 + const char *label = 0;
58.1119 +
58.1120 + sbd = (struct gfs2_sb *)buf;
58.1121 +
58.1122 + if (blkid_be32(sbd->sb_fs_format) == GFS2_FORMAT_FS &&
58.1123 + blkid_be32(sbd->sb_multihost_format) == GFS2_FORMAT_MULTI)
58.1124 + {
58.1125 + blkid_set_tag(probe->dev, "UUID", 0, 0);
58.1126 +
58.1127 + if (strlen(sbd->sb_locktable))
58.1128 + label = sbd->sb_locktable;
58.1129 + blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable));
58.1130 + return 0;
58.1131 + }
58.1132 + return 1;
58.1133 +}
58.1134 +
58.1135 +static void unicode_16be_to_utf8(unsigned char *str, int out_len,
58.1136 + const unsigned char *buf, int in_len)
58.1137 +{
58.1138 + int i, j;
58.1139 + unsigned int c;
58.1140 +
58.1141 + for (i = j = 0; i + 2 <= in_len; i += 2) {
58.1142 + c = (buf[i] << 8) | buf[i+1];
58.1143 + if (c == 0) {
58.1144 + str[j] = '\0';
58.1145 + break;
58.1146 + } else if (c < 0x80) {
58.1147 + if (j+1 >= out_len)
58.1148 + break;
58.1149 + str[j++] = (unsigned char) c;
58.1150 + } else if (c < 0x800) {
58.1151 + if (j+2 >= out_len)
58.1152 + break;
58.1153 + str[j++] = (unsigned char) (0xc0 | (c >> 6));
58.1154 + str[j++] = (unsigned char) (0x80 | (c & 0x3f));
58.1155 + } else {
58.1156 + if (j+3 >= out_len)
58.1157 + break;
58.1158 + str[j++] = (unsigned char) (0xe0 | (c >> 12));
58.1159 + str[j++] = (unsigned char) (0x80 | ((c >> 6) & 0x3f));
58.1160 + str[j++] = (unsigned char) (0x80 | (c & 0x3f));
58.1161 + }
58.1162 + }
58.1163 + str[j] = '\0';
58.1164 +}
58.1165 +
58.1166 +static void unicode_16le_to_utf8(unsigned char *str, int out_len,
58.1167 + const unsigned char *buf, int in_len)
58.1168 +{
58.1169 + int i, j;
58.1170 + unsigned int c;
58.1171 +
58.1172 + for (i = j = 0; i + 2 <= in_len; i += 2) {
58.1173 + c = (buf[i+1] << 8) | buf[i];
58.1174 + if (c == 0) {
58.1175 + str[j] = '\0';
58.1176 + break;
58.1177 + } else if (c < 0x80) {
58.1178 + if (j+1 >= out_len)
58.1179 + break;
58.1180 + str[j++] = (unsigned char) c;
58.1181 + } else if (c < 0x800) {
58.1182 + if (j+2 >= out_len)
58.1183 + break;
58.1184 + str[j++] = (unsigned char) (0xc0 | (c >> 6));
58.1185 + str[j++] = (unsigned char) (0x80 | (c & 0x3f));
58.1186 + } else {
58.1187 + if (j+3 >= out_len)
58.1188 + break;
58.1189 + str[j++] = (unsigned char) (0xe0 | (c >> 12));
58.1190 + str[j++] = (unsigned char) (0x80 | ((c >> 6) & 0x3f));
58.1191 + str[j++] = (unsigned char) (0x80 | (c & 0x3f));
58.1192 + }
58.1193 + }
58.1194 + str[j] = '\0';
58.1195 +}
58.1196 +
58.1197 +static int probe_hfs(struct blkid_probe *probe __BLKID_ATTR((unused)),
58.1198 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.1199 + unsigned char *buf)
58.1200 +{
58.1201 + struct hfs_mdb *hfs = (struct hfs_mdb *)buf;
58.1202 + unsigned long long *uuid_ptr;
58.1203 + char uuid_str[17];
58.1204 + __u64 uuid;
58.1205 +
58.1206 + if ((memcmp(hfs->embed_sig, "H+", 2) == 0) ||
58.1207 + (memcmp(hfs->embed_sig, "HX", 2) == 0))
58.1208 + return 1; /* Not hfs, but an embedded HFS+ */
58.1209 +
58.1210 + uuid_ptr = (unsigned long long *)hfs->finder_info.id;
58.1211 + uuid = blkid_le64(*uuid_ptr);
58.1212 + if (uuid) {
58.1213 + sprintf(uuid_str, "%016llX", uuid);
58.1214 + blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
58.1215 + }
58.1216 + blkid_set_tag(probe->dev, "LABEL", (char *)hfs->label, hfs->label_len);
58.1217 + return 0;
58.1218 +}
58.1219 +
58.1220 +
58.1221 +#define HFSPLUS_SECTOR_SIZE 512
58.1222 +
58.1223 +static int probe_hfsplus(struct blkid_probe *probe,
58.1224 + struct blkid_magic *id,
58.1225 + unsigned char *buf)
58.1226 +{
58.1227 + struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
58.1228 + struct hfsplus_bnode_descriptor *descr;
58.1229 + struct hfsplus_bheader_record *bnode;
58.1230 + struct hfsplus_catalog_key *key;
58.1231 + struct hfsplus_vol_header *hfsplus;
58.1232 + struct hfs_mdb *sbd = (struct hfs_mdb *) buf;
58.1233 + unsigned int alloc_block_size;
58.1234 + unsigned int alloc_first_block;
58.1235 + unsigned int embed_first_block;
58.1236 + unsigned int off = 0;
58.1237 + unsigned int blocksize;
58.1238 + unsigned int cat_block;
58.1239 + unsigned int ext_block_start;
58.1240 + unsigned int ext_block_count;
58.1241 + unsigned int record_count;
58.1242 + unsigned int leaf_node_head;
58.1243 + unsigned int leaf_node_count;
58.1244 + unsigned int leaf_node_size;
58.1245 + unsigned int leaf_block;
58.1246 + unsigned int label_len;
58.1247 + unsigned long long *uuid_ptr;
58.1248 + __u64 leaf_off, uuid;
58.1249 + char uuid_str[17], label[512];
58.1250 + int ext;
58.1251 +
58.1252 + /* Check for a HFS+ volume embedded in a HFS volume */
58.1253 + if (memcmp(sbd->signature, "BD", 2) == 0) {
58.1254 + if ((memcmp(sbd->embed_sig, "H+", 2) != 0) &&
58.1255 + (memcmp(sbd->embed_sig, "HX", 2) != 0))
58.1256 + /* This must be an HFS volume, so fail */
58.1257 + return 1;
58.1258 +
58.1259 + alloc_block_size = blkid_be32(sbd->al_blk_size);
58.1260 + alloc_first_block = blkid_be16(sbd->al_bl_st);
58.1261 + embed_first_block = blkid_be16(sbd->embed_startblock);
58.1262 + off = (alloc_first_block * 512) +
58.1263 + (embed_first_block * alloc_block_size);
58.1264 + buf = get_buffer(probe, off + (id->bim_kboff * 1024),
58.1265 + sizeof(*sbd));
58.1266 + if (!buf)
58.1267 + return 1;
58.1268 +
58.1269 + hfsplus = (struct hfsplus_vol_header *) buf;
58.1270 + }
58.1271 +
58.1272 + hfsplus = (struct hfsplus_vol_header *) buf;
58.1273 +
58.1274 + if ((memcmp(hfsplus->signature, "H+", 2) != 0) &&
58.1275 + (memcmp(hfsplus->signature, "HX", 2) != 0))
58.1276 + return 1;
58.1277 +
58.1278 + uuid_ptr = (unsigned long long *)hfsplus->finder_info.id;
58.1279 + uuid = blkid_le64(*uuid_ptr);
58.1280 + if (uuid) {
58.1281 + sprintf(uuid_str, "%016llX", uuid);
58.1282 + blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
58.1283 + }
58.1284 +
58.1285 + blocksize = blkid_be32(hfsplus->blocksize);
58.1286 + if (blocksize < HFSPLUS_SECTOR_SIZE)
58.1287 + return 1;
58.1288 +
58.1289 + memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
58.1290 + cat_block = blkid_be32(extents[0].start_block);
58.1291 +
58.1292 + buf = get_buffer(probe, off + ((__u64) cat_block * blocksize), 0x2000);
58.1293 + if (!buf)
58.1294 + return 0;
58.1295 +
58.1296 + bnode = (struct hfsplus_bheader_record *)
58.1297 + &buf[sizeof(struct hfsplus_bnode_descriptor)];
58.1298 +
58.1299 + leaf_node_head = blkid_be32(bnode->leaf_head);
58.1300 + leaf_node_size = blkid_be16(bnode->node_size);
58.1301 + leaf_node_count = blkid_be32(bnode->leaf_count);
58.1302 + if (leaf_node_count == 0)
58.1303 + return 0;
58.1304 +
58.1305 + leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
58.1306 +
58.1307 + /* get physical location */
58.1308 + for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
58.1309 + ext_block_start = blkid_be32(extents[ext].start_block);
58.1310 + ext_block_count = blkid_be32(extents[ext].block_count);
58.1311 + if (ext_block_count == 0)
58.1312 + return 0;
58.1313 +
58.1314 + /* this is our extent */
58.1315 + if (leaf_block < ext_block_count)
58.1316 + break;
58.1317 +
58.1318 + leaf_block -= ext_block_count;
58.1319 + }
58.1320 + if (ext == HFSPLUS_EXTENT_COUNT)
58.1321 + return 0;
58.1322 +
58.1323 + leaf_off = (__u64) (ext_block_start + leaf_block) * blocksize;
58.1324 +
58.1325 + buf = get_buffer(probe, off + leaf_off, leaf_node_size);
58.1326 + if (!buf)
58.1327 + return 0;
58.1328 +
58.1329 + descr = (struct hfsplus_bnode_descriptor *) buf;
58.1330 + record_count = blkid_be16(descr->num_recs);
58.1331 + if (record_count == 0)
58.1332 + return 0;
58.1333 +
58.1334 + if (descr->type != HFS_NODE_LEAF)
58.1335 + return 0;
58.1336 +
58.1337 + key = (struct hfsplus_catalog_key *)
58.1338 + &buf[sizeof(struct hfsplus_bnode_descriptor)];
58.1339 +
58.1340 + if (blkid_be32(key->parent_id) != HFSPLUS_POR_CNID)
58.1341 + return 0;
58.1342 +
58.1343 + label_len = blkid_be16(key->unicode_len) * 2;
58.1344 + unicode_16be_to_utf8((unsigned char *)label, sizeof(label),
58.1345 + key->unicode, label_len);
58.1346 + blkid_set_tag(probe->dev, "LABEL", label, 0);
58.1347 + return 0;
58.1348 +}
58.1349 +
58.1350 +#define LVM2_LABEL_SIZE 512
58.1351 +static unsigned int lvm2_calc_crc(const void *buf, unsigned int size)
58.1352 +{
58.1353 + static const unsigned int crctab[] = {
58.1354 + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
58.1355 + 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
58.1356 + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
58.1357 + 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
58.1358 + };
58.1359 + unsigned int i, crc = 0xf597a6cf;
58.1360 + const __u8 *data = (const __u8 *) buf;
58.1361 +
58.1362 + for (i = 0; i < size; i++) {
58.1363 + crc ^= *data++;
58.1364 + crc = (crc >> 4) ^ crctab[crc & 0xf];
58.1365 + crc = (crc >> 4) ^ crctab[crc & 0xf];
58.1366 + }
58.1367 + return crc;
58.1368 +}
58.1369 +
58.1370 +static int probe_lvm2(struct blkid_probe *probe,
58.1371 + struct blkid_magic *id,
58.1372 + unsigned char *buf)
58.1373 +{
58.1374 + int sector = (id->bim_kboff) << 1;
58.1375 + struct lvm2_pv_label_header *label= (struct lvm2_pv_label_header *)buf;
58.1376 + char *p, *q, uuid[40];
58.1377 + unsigned int i, b;
58.1378 +
58.1379 + /* buf is at 0k or 1k offset; find label inside */
58.1380 + if (memcmp(buf, "LABELONE", 8) == 0) {
58.1381 + label = (struct lvm2_pv_label_header *)buf;
58.1382 + } else if (memcmp(buf + 512, "LABELONE", 8) == 0) {
58.1383 + label = (struct lvm2_pv_label_header *)(buf + 512);
58.1384 + sector++;
58.1385 + } else {
58.1386 + return 1;
58.1387 + }
58.1388 +
58.1389 + if (blkid_le64(label->sector_xl) != (unsigned) sector) {
58.1390 + DBG(DEBUG_PROBE,
58.1391 + printf("LVM2: label for sector %llu found at sector %d\n",
58.1392 + blkid_le64(label->sector_xl), sector));
58.1393 + return 1;
58.1394 + }
58.1395 +
58.1396 + if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE -
58.1397 + ((char *)&label->offset_xl - (char *)label)) !=
58.1398 + blkid_le32(label->crc_xl)) {
58.1399 + DBG(DEBUG_PROBE,
58.1400 + printf("LVM2: label checksum incorrect at sector %d\n",
58.1401 + sector));
58.1402 + return 1;
58.1403 + }
58.1404 +
58.1405 + for (i=0, b=1, p=uuid, q= (char *) label->pv_uuid; i < LVM2_ID_LEN;
58.1406 + i++, b <<= 1) {
58.1407 + if (b & 0x4444440)
58.1408 + *p++ = '-';
58.1409 + *p++ = *q++;
58.1410 + }
58.1411 +
58.1412 + blkid_set_tag(probe->dev, "UUID", uuid, LVM2_ID_LEN+6);
58.1413 +
58.1414 + return 0;
58.1415 +}
58.1416 +
58.1417 +static int probe_btrfs(struct blkid_probe *probe,
58.1418 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.1419 + unsigned char *buf)
58.1420 +{
58.1421 + struct btrfs_super_block *bs;
58.1422 + const char *label = 0;
58.1423 +
58.1424 + bs = (struct btrfs_super_block *)buf;
58.1425 +
58.1426 + if (strlen(bs->label))
58.1427 + label = bs->label;
58.1428 + blkid_set_tag(probe->dev, "LABEL", label, sizeof(bs->label));
58.1429 + set_uuid(probe->dev, bs->fsid, 0);
58.1430 + return 0;
58.1431 +}
58.1432 +
58.1433 +static int probe_f2fs(struct blkid_probe *probe,
58.1434 + struct blkid_magic *id __BLKID_ATTR((unused)),
58.1435 + unsigned char *buf)
58.1436 +{
58.1437 + struct f2fs_super_block *bs;
58.1438 +
58.1439 + bs = (struct f2fs_super_block *)buf;
58.1440 + set_uuid(probe->dev, bs->uuid, 0);
58.1441 + return 0;
58.1442 +}
58.1443 +
58.1444 +static uint64_t exfat_block_to_offset(const struct exfat_super_block *sb,
58.1445 + uint64_t block)
58.1446 +{
58.1447 + return block << sb->block_bits;
58.1448 +}
58.1449 +
58.1450 +static uint64_t exfat_cluster_to_block(const struct exfat_super_block *sb,
58.1451 + uint32_t cluster)
58.1452 +{
58.1453 + return sb->cluster_block_start +
58.1454 + ((uint64_t)(cluster - EXFAT_FIRST_DATA_CLUSTER) << sb->bpc_bits);
58.1455 +}
58.1456 +
58.1457 +static uint64_t exfat_cluster_to_offset(const struct exfat_super_block *sb,
58.1458 + uint32_t cluster)
58.1459 +{
58.1460 + return exfat_block_to_offset(sb, exfat_cluster_to_block(sb, cluster));
58.1461 +}
58.1462 +
58.1463 +static uint32_t exfat_next_cluster(struct blkid_probe *probe,
58.1464 + const struct exfat_super_block *sb,
58.1465 + uint32_t cluster)
58.1466 +{
58.1467 + uint32_t *next;
58.1468 + uint64_t offset;
58.1469 +
58.1470 + offset = exfat_block_to_offset(sb, sb->fat_block_start)
58.1471 + + (uint64_t) cluster * sizeof (cluster);
58.1472 + next = (uint32_t *)get_buffer(probe, offset, sizeof (uint32_t));
58.1473 +
58.1474 + return next ? *next : 0;
58.1475 +}
58.1476 +
58.1477 +static struct exfat_entry_label *find_exfat_entry_label(
58.1478 + struct blkid_probe *probe, const struct exfat_super_block *sb)
58.1479 +{
58.1480 + uint32_t cluster = sb->rootdir_cluster;
58.1481 + uint64_t offset = exfat_cluster_to_offset(sb, cluster);
58.1482 + uint8_t *entry;
58.1483 + const size_t max_iter = 10000;
58.1484 + size_t i = 0;
58.1485 +
58.1486 + for (; i < max_iter; ++i) {
58.1487 + entry = (uint8_t *)get_buffer(probe, offset, EXFAT_ENTRY_SIZE);
58.1488 + if (!entry)
58.1489 + return NULL;
58.1490 + if (entry[0] == EXFAT_ENTRY_EOD)
58.1491 + return NULL;
58.1492 + if (entry[0] == EXFAT_ENTRY_LABEL)
58.1493 + return (struct exfat_entry_label*) entry;
58.1494 +
58.1495 + offset += EXFAT_ENTRY_SIZE;
58.1496 + if (offset % CLUSTER_SIZE(sb) == 0) {
58.1497 + cluster = exfat_next_cluster(probe, sb, cluster);
58.1498 + if (cluster < EXFAT_FIRST_DATA_CLUSTER)
58.1499 + return NULL;
58.1500 + if (cluster > EXFAT_LAST_DATA_CLUSTER)
58.1501 + return NULL;
58.1502 + offset = exfat_cluster_to_offset(sb, cluster);
58.1503 + }
58.1504 + }
58.1505 +
58.1506 + return NULL;
58.1507 +}
58.1508 +
58.1509 +static int probe_exfat(struct blkid_probe *probe, struct blkid_magic *id,
58.1510 + unsigned char *buf)
58.1511 +{
58.1512 + struct exfat_super_block *sb;
58.1513 + struct exfat_entry_label *label;
58.1514 + uuid_t uuid;
58.1515 +
58.1516 + sb = (struct exfat_super_block *)buf;
58.1517 + if (!sb || !CLUSTER_SIZE(sb)) {
58.1518 + DBG(DEBUG_PROBE, printf("bad exfat superblock.\n"));
58.1519 + return errno ? - errno : 1;
58.1520 + }
58.1521 +
58.1522 + label = find_exfat_entry_label(probe, sb);
58.1523 + if (label) {
58.1524 + char utf8_label[128];
58.1525 + unicode_16le_to_utf8(utf8_label, sizeof(utf8_label), label->name, label->length * 2);
58.1526 + blkid_set_tag(probe->dev, "LABEL", utf8_label, 0);
58.1527 + } else {
58.1528 + blkid_set_tag(probe->dev, "LABEL", "disk", 4);
58.1529 + }
58.1530 +
58.1531 + memset(uuid, 0, sizeof (uuid));
58.1532 + snprintf(uuid, sizeof (uuid), "%02hhX%02hhX-%02hhX%02hhX",
58.1533 + sb->volume_serial[3], sb->volume_serial[2],
58.1534 + sb->volume_serial[1], sb->volume_serial[0]);
58.1535 + blkid_set_tag(probe->dev, "UUID", uuid, strlen(uuid));
58.1536 +
58.1537 + return 0;
58.1538 +}
58.1539 +
58.1540 +/*
58.1541 + * Various filesystem magics that we can check for. Note that kboff and
58.1542 + * sboff are in kilobytes and bytes respectively. All magics are in
58.1543 + * byte strings so we don't worry about endian issues.
58.1544 + */
58.1545 +static struct blkid_magic type_array[] = {
58.1546 +/* type kboff sboff len magic probe */
58.1547 + { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm },
58.1548 + { "ntfs", 0, 3, 8, "NTFS ", probe_ntfs },
58.1549 + { "jbd", 1, 0x38, 2, "\123\357", probe_jbd },
58.1550 + { "ext4dev", 1, 0x38, 2, "\123\357", probe_ext4dev },
58.1551 + { "ext4", 1, 0x38, 2, "\123\357", probe_ext4 },
58.1552 + { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 },
58.1553 + { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 },
58.1554 + { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs },
58.1555 + { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs },
58.1556 + { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs },
58.1557 + { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs },
58.1558 + { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs },
58.1559 + { "reiser4", 64, 0, 7, "ReIsEr4", probe_reiserfs4 },
58.1560 + { "gfs2", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs2 },
58.1561 + { "gfs", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs },
58.1562 + { "vfat", 0, 0x52, 5, "MSWIN", probe_fat },
58.1563 + { "vfat", 0, 0x52, 8, "FAT32 ", probe_fat },
58.1564 + { "vfat", 0, 0x36, 5, "MSDOS", probe_fat },
58.1565 + { "vfat", 0, 0x36, 8, "FAT16 ", probe_fat },
58.1566 + { "vfat", 0, 0x36, 8, "FAT12 ", probe_fat },
58.1567 + { "vfat", 0, 0, 1, "\353", probe_fat_nomagic },
58.1568 + { "vfat", 0, 0, 1, "\351", probe_fat_nomagic },
58.1569 + { "vfat", 0, 0x1fe, 2, "\125\252", probe_fat_nomagic },
58.1570 + { "minix", 1, 0x10, 2, "\177\023", 0 },
58.1571 + { "minix", 1, 0x10, 2, "\217\023", 0 },
58.1572 + { "minix", 1, 0x10, 2, "\150\044", 0 },
58.1573 + { "minix", 1, 0x10, 2, "\170\044", 0 },
58.1574 + { "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
58.1575 + { "xfs", 0, 0, 4, "XFSB", probe_xfs },
58.1576 + { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs },
58.1577 + { "bfs", 0, 0, 4, "\316\372\173\033", 0 },
58.1578 + { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs },
58.1579 + { "qnx4", 0, 4, 6, "QNX4FS", 0 },
58.1580 + { "udf", 32, 1, 5, "BEA01", probe_udf },
58.1581 + { "udf", 32, 1, 5, "BOOT2", probe_udf },
58.1582 + { "udf", 32, 1, 5, "CD001", probe_udf },
58.1583 + { "udf", 32, 1, 5, "CDW02", probe_udf },
58.1584 + { "udf", 32, 1, 5, "NSR02", probe_udf },
58.1585 + { "udf", 32, 1, 5, "NSR03", probe_udf },
58.1586 + { "udf", 32, 1, 5, "TEA01", probe_udf },
58.1587 + { "iso9660", 32, 1, 5, "CD001", probe_iso9660 },
58.1588 + { "iso9660", 32, 9, 5, "CDROM", probe_iso9660 },
58.1589 + { "jfs", 32, 0, 4, "JFS1", probe_jfs },
58.1590 + /* ZFS has 128 root blocks (#4 is the first used), check only 6 of them */
58.1591 + { "zfs", 128, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs },
58.1592 + { "zfs", 128, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs },
58.1593 + { "zfs", 132, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs },
58.1594 + { "zfs", 132, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs },
58.1595 + { "zfs", 136, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs },
58.1596 + { "zfs", 136, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs },
58.1597 + { "zfs", 384, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs },
58.1598 + { "zfs", 384, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs },
58.1599 + { "zfs", 388, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs },
58.1600 + { "zfs", 388, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs },
58.1601 + { "zfs", 392, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs },
58.1602 + { "zfs", 392, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs },
58.1603 + { "hfsplus", 1, 0, 2, "BD", probe_hfsplus },
58.1604 + { "hfsplus", 1, 0, 2, "H+", probe_hfsplus },
58.1605 + { "hfsplus", 1, 0, 2, "HX", probe_hfsplus },
58.1606 + { "hfs", 1, 0, 2, "BD", probe_hfs },
58.1607 + { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
58.1608 + { "hpfs", 8, 0, 4, "I\350\225\371", 0 },
58.1609 + { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
58.1610 + { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 },
58.1611 + { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 },
58.1612 + { "swsuspend", 0, 0xff6, 9, "S1SUSPEND", probe_swap1 },
58.1613 + { "swsuspend", 0, 0xff6, 9, "S2SUSPEND", probe_swap1 },
58.1614 + { "swsuspend", 0, 0xff6, 9, "ULSUSPEND", probe_swap1 },
58.1615 + { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 },
58.1616 + { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 },
58.1617 + { "swsuspend", 0, 0x1ff6, 9, "S1SUSPEND", probe_swap1 },
58.1618 + { "swsuspend", 0, 0x1ff6, 9, "S2SUSPEND", probe_swap1 },
58.1619 + { "swsuspend", 0, 0x1ff6, 9, "ULSUSPEND", probe_swap1 },
58.1620 + { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 },
58.1621 + { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 },
58.1622 + { "swsuspend", 0, 0x3ff6, 9, "S1SUSPEND", probe_swap1 },
58.1623 + { "swsuspend", 0, 0x3ff6, 9, "S2SUSPEND", probe_swap1 },
58.1624 + { "swsuspend", 0, 0x3ff6, 9, "ULSUSPEND", probe_swap1 },
58.1625 + { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 },
58.1626 + { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 },
58.1627 + { "swsuspend", 0, 0x7ff6, 9, "S1SUSPEND", probe_swap1 },
58.1628 + { "swsuspend", 0, 0x7ff6, 9, "S2SUSPEND", probe_swap1 },
58.1629 + { "swsuspend", 0, 0x7ff6, 9, "ULSUSPEND", probe_swap1 },
58.1630 + { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 },
58.1631 + { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 },
58.1632 + { "swsuspend", 0, 0xfff6, 9, "S1SUSPEND", probe_swap1 },
58.1633 + { "swsuspend", 0, 0xfff6, 9, "S2SUSPEND", probe_swap1 },
58.1634 + { "swsuspend", 0, 0xfff6, 9, "ULSUSPEND", probe_swap1 },
58.1635 + { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs },
58.1636 + { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 },
58.1637 + { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 },
58.1638 + { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 },
58.1639 + { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 },
58.1640 + { "crypt_LUKS", 0, 0, 6, "LUKS\xba\xbe", probe_luks },
58.1641 + { "squashfs", 0, 0, 4, "sqsh", 0 },
58.1642 + { "squashfs", 0, 0, 4, "hsqs", 0 },
58.1643 + { "lvm2pv", 0, 0x218, 8, "LVM2 001", probe_lvm2 },
58.1644 + { "lvm2pv", 0, 0x018, 8, "LVM2 001", probe_lvm2 },
58.1645 + { "lvm2pv", 1, 0x018, 8, "LVM2 001", probe_lvm2 },
58.1646 + { "lvm2pv", 1, 0x218, 8, "LVM2 001", probe_lvm2 },
58.1647 + { "btrfs", 64, 0x40, 8, "_BHRfS_M", probe_btrfs },
58.1648 + { "f2fs", 1, 0, 4, "\x10\x20\xf5\xf2", probe_f2fs },
58.1649 + { "exfat", 0, 3, 8, "EXFAT ", probe_exfat },
58.1650 + { NULL, 0, 0, 0, NULL, NULL }
58.1651 +};
58.1652 +
58.1653 +/*
58.1654 + * Verify that the data in dev is consistent with what is on the actual
58.1655 + * block device (using the devname field only). Normally this will be
58.1656 + * called when finding items in the cache, but for long running processes
58.1657 + * is also desirable to revalidate an item before use.
58.1658 + *
58.1659 + * If we are unable to revalidate the data, we return the old data and
58.1660 + * do not set the BLKID_BID_FL_VERIFIED flag on it.
58.1661 + */
58.1662 +blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
58.1663 +{
58.1664 + struct blkid_magic *id;
58.1665 + struct blkid_probe probe;
58.1666 + blkid_tag_iterate iter;
58.1667 + unsigned char *buf;
58.1668 + const char *type, *value;
58.1669 + struct stat st;
58.1670 + time_t now;
58.1671 + double diff;
58.1672 + int idx;
58.1673 +
58.1674 + if (!dev)
58.1675 + return NULL;
58.1676 +
58.1677 + now = time(0);
58.1678 + diff = difftime(now, dev->bid_time);
58.1679 +
58.1680 + if (stat(dev->bid_name, &st) < 0) {
58.1681 + DBG(DEBUG_PROBE,
58.1682 + printf("blkid_verify: error %s (%d) while "
58.1683 + "trying to stat %s\n", strerror(errno), errno,
58.1684 + dev->bid_name));
58.1685 + open_err:
58.1686 + if ((errno == EPERM) || (errno == EACCES) || (errno == ENOENT)) {
58.1687 + /* We don't have read permission, just return cache data. */
58.1688 + DBG(DEBUG_PROBE, printf("returning unverified data for %s\n",
58.1689 + dev->bid_name));
58.1690 + return dev;
58.1691 + }
58.1692 + blkid_free_dev(dev);
58.1693 + return NULL;
58.1694 + }
58.1695 +
58.1696 + if ((now >= dev->bid_time) &&
58.1697 + (st.st_mtime <= dev->bid_time) &&
58.1698 + ((diff < BLKID_PROBE_MIN) ||
58.1699 + (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
58.1700 + diff < BLKID_PROBE_INTERVAL)))
58.1701 + return dev;
58.1702 +
58.1703 + DBG(DEBUG_PROBE,
58.1704 + printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t"
58.1705 + "time since last check %lu)\n",
58.1706 + dev->bid_name, (unsigned long)dev->bid_time,
58.1707 + (unsigned long)st.st_mtime, (unsigned long)diff));
58.1708 +
58.1709 + if ((probe.fd = open(dev->bid_name, O_RDONLY)) < 0) {
58.1710 + DBG(DEBUG_PROBE, printf("blkid_verify: error %s (%d) while "
58.1711 + "opening %s\n", strerror(errno), errno,
58.1712 + dev->bid_name));
58.1713 + goto open_err;
58.1714 + }
58.1715 +
58.1716 + probe.cache = cache;
58.1717 + probe.dev = dev;
58.1718 + probe.sbbuf = 0;
58.1719 + probe.buf = 0;
58.1720 + probe.buf_max = 0;
58.1721 +
58.1722 + /*
58.1723 + * Iterate over the type array. If we already know the type,
58.1724 + * then try that first. If it doesn't work, then blow away
58.1725 + * the type information, and try again.
58.1726 + *
58.1727 + */
58.1728 +try_again:
58.1729 + type = 0;
58.1730 + if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
58.1731 + uuid_t uuid;
58.1732 +
58.1733 + if (check_mdraid(probe.fd, uuid) == 0) {
58.1734 + set_uuid(dev, uuid, 0);
58.1735 + type = "mdraid";
58.1736 + goto found_type;
58.1737 + }
58.1738 + }
58.1739 + for (id = type_array; id->bim_type; id++) {
58.1740 + if (dev->bid_type &&
58.1741 + strcmp(id->bim_type, dev->bid_type))
58.1742 + continue;
58.1743 +
58.1744 + idx = id->bim_kboff + (id->bim_sboff >> 10);
58.1745 + buf = get_buffer(&probe, (__u64) idx << 10, 1024);
58.1746 + if (!buf)
58.1747 + continue;
58.1748 +
58.1749 + if (memcmp(id->bim_magic, buf + (id->bim_sboff & 0x3ff),
58.1750 + id->bim_len))
58.1751 + continue;
58.1752 +
58.1753 + if ((id->bim_probe == NULL) ||
58.1754 + (id->bim_probe(&probe, id, buf) == 0)) {
58.1755 + type = id->bim_type;
58.1756 + goto found_type;
58.1757 + }
58.1758 + }
58.1759 +
58.1760 + if (!id->bim_type && dev->bid_type) {
58.1761 + /*
58.1762 + * Zap the device filesystem information and try again
58.1763 + */
58.1764 + DBG(DEBUG_PROBE,
58.1765 + printf("previous fs type %s not valid, "
58.1766 + "trying full probe\n", dev->bid_type));
58.1767 + iter = blkid_tag_iterate_begin(dev);
58.1768 + while (blkid_tag_next(iter, &type, &value) == 0)
58.1769 + blkid_set_tag(dev, type, 0, 0);
58.1770 + blkid_tag_iterate_end(iter);
58.1771 + goto try_again;
58.1772 + }
58.1773 +
58.1774 + if (!dev->bid_type) {
58.1775 + blkid_free_dev(dev);
58.1776 + dev = 0;
58.1777 + goto found_type;
58.1778 + }
58.1779 +
58.1780 +found_type:
58.1781 + if (dev && type) {
58.1782 + dev->bid_devno = st.st_rdev;
58.1783 + dev->bid_time = time(0);
58.1784 + dev->bid_flags |= BLKID_BID_FL_VERIFIED;
58.1785 + cache->bic_flags |= BLKID_BIC_FL_CHANGED;
58.1786 +
58.1787 + blkid_set_tag(dev, "TYPE", type, 0);
58.1788 +
58.1789 + DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
58.1790 + dev->bid_name, (long long)st.st_rdev, type));
58.1791 + }
58.1792 +
58.1793 + free(probe.sbbuf);
58.1794 + free(probe.buf);
58.1795 + if (probe.fd >= 0)
58.1796 + close(probe.fd);
58.1797 +
58.1798 + return dev;
58.1799 +}
58.1800 +
58.1801 +int blkid_known_fstype(const char *fstype)
58.1802 +{
58.1803 + struct blkid_magic *id;
58.1804 +
58.1805 + for (id = type_array; id->bim_type; id++) {
58.1806 + if (strcmp(fstype, id->bim_type) == 0)
58.1807 + return 1;
58.1808 + }
58.1809 + return 0;
58.1810 +}
58.1811 +
58.1812 +#ifdef TEST_PROGRAM
58.1813 +int main(int argc, char **argv)
58.1814 +{
58.1815 + blkid_dev dev;
58.1816 + blkid_cache cache;
58.1817 + int ret;
58.1818 +
58.1819 + if (argc != 2) {
58.1820 + fprintf(stderr, "Usage: %s device\n"
58.1821 + "Probe a single device to determine type\n", argv[0]);
58.1822 + exit(1);
58.1823 + }
58.1824 + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
58.1825 + fprintf(stderr, "%s: error creating cache (%d)\n",
58.1826 + argv[0], ret);
58.1827 + exit(1);
58.1828 + }
58.1829 + dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
58.1830 + if (!dev) {
58.1831 + printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
58.1832 + return (1);
58.1833 + }
58.1834 + printf("TYPE='%s'\n", dev->bid_type ? dev->bid_type : "(null)");
58.1835 + if (dev->bid_label)
58.1836 + printf("LABEL='%s'\n", dev->bid_label);
58.1837 + if (dev->bid_uuid)
58.1838 + printf("UUID='%s'\n", dev->bid_uuid);
58.1839 +
58.1840 + blkid_free_dev(dev);
58.1841 + return (0);
58.1842 +}
58.1843 +#endif
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
59.2 +++ b/libext2fs/lib/libblkid/probe.h Wed Aug 25 01:28:08 2021 +0200
59.3 @@ -0,0 +1,895 @@
59.4 +/*
59.5 + * probe.h - constants and on-disk structures for extracting device data
59.6 + *
59.7 + * Copyright (C) 1999 by Andries Brouwer
59.8 + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
59.9 + * Copyright (C) 2001 by Andreas Dilger
59.10 + *
59.11 + * %Begin-Header%
59.12 + * This file may be redistributed under the terms of the
59.13 + * GNU Lesser General Public License.
59.14 + * %End-Header%
59.15 + */
59.16 +
59.17 +#ifndef _BLKID_PROBE_H
59.18 +#define _BLKID_PROBE_H
59.19 +
59.20 +#include <stdint.h>
59.21 +
59.22 +#include <blkid/blkid_types.h>
59.23 +
59.24 +struct blkid_magic;
59.25 +
59.26 +#define SB_BUFFER_SIZE 0x11000
59.27 +
59.28 +struct blkid_probe {
59.29 + int fd;
59.30 + blkid_cache cache;
59.31 + blkid_dev dev;
59.32 + unsigned char *sbbuf;
59.33 + size_t sb_valid;
59.34 + unsigned char *buf;
59.35 + size_t buf_max;
59.36 +};
59.37 +
59.38 +typedef int (*blkid_probe_t)(struct blkid_probe *probe,
59.39 + struct blkid_magic *id, unsigned char *buf);
59.40 +
59.41 +struct blkid_magic {
59.42 + const char *bim_type; /* type name for this magic */
59.43 + long bim_kboff; /* kilobyte offset of superblock */
59.44 + unsigned bim_sboff; /* byte offset within superblock */
59.45 + unsigned bim_len; /* length of magic */
59.46 + const char *bim_magic; /* magic string */
59.47 + blkid_probe_t bim_probe; /* probe function */
59.48 +};
59.49 +
59.50 +/*
59.51 + * Structures for each of the content types we want to extract information
59.52 + * from. We do not necessarily need the magic field here, because we have
59.53 + * already identified the content type before we get this far. It may still
59.54 + * be useful if there are probe functions which handle multiple content types.
59.55 + */
59.56 +struct ext2_super_block {
59.57 + __u32 s_inodes_count;
59.58 + __u32 s_blocks_count;
59.59 + __u32 s_r_blocks_count;
59.60 + __u32 s_free_blocks_count;
59.61 + __u32 s_free_inodes_count;
59.62 + __u32 s_first_data_block;
59.63 + __u32 s_log_block_size;
59.64 + __u32 s_dummy3[7];
59.65 + unsigned char s_magic[2];
59.66 + __u16 s_state;
59.67 + __u32 s_dummy5[8];
59.68 + __u32 s_feature_compat;
59.69 + __u32 s_feature_incompat;
59.70 + __u32 s_feature_ro_compat;
59.71 + unsigned char s_uuid[16];
59.72 + char s_volume_name[16];
59.73 + char s_last_mounted[64];
59.74 + __u32 s_algorithm_usage_bitmap;
59.75 + __u8 s_prealloc_blocks;
59.76 + __u8 s_prealloc_dir_blocks;
59.77 + __u16 s_reserved_gdt_blocks;
59.78 + __u8 s_journal_uuid[16];
59.79 + __u32 s_journal_inum;
59.80 + __u32 s_journal_dev;
59.81 + __u32 s_last_orphan;
59.82 + __u32 s_hash_seed[4];
59.83 + __u8 s_def_hash_version;
59.84 + __u8 s_jnl_backup_type;
59.85 + __u16 s_reserved_word_pad;
59.86 + __u32 s_default_mount_opts;
59.87 + __u32 s_first_meta_bg;
59.88 + __u32 s_mkfs_time;
59.89 + __u32 s_jnl_blocks[17];
59.90 + __u32 s_blocks_count_hi;
59.91 + __u32 s_r_blocks_count_hi;
59.92 + __u32 s_free_blocks_hi;
59.93 + __u16 s_min_extra_isize;
59.94 + __u16 s_want_extra_isize;
59.95 + __u32 s_flags;
59.96 + __u16 s_raid_stride;
59.97 + __u16 s_mmp_interval;
59.98 + __u64 s_mmp_block;
59.99 + __u32 s_raid_stripe_width;
59.100 + __u32 s_reserved[163];
59.101 +};
59.102 +
59.103 +/* for s_flags */
59.104 +#define EXT2_FLAGS_TEST_FILESYS 0x0004
59.105 +
59.106 +/* for s_feature_compat */
59.107 +#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
59.108 +
59.109 +/* for s_feature_ro_compat */
59.110 +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
59.111 +#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
59.112 +#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
59.113 +#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008
59.114 +#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
59.115 +#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
59.116 +#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
59.117 +#define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100
59.118 +#define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400
59.119 +
59.120 +/* for s_feature_incompat */
59.121 +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
59.122 +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004
59.123 +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
59.124 +#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
59.125 +#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
59.126 +#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
59.127 +#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
59.128 +#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
59.129 +
59.130 +#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
59.131 + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
59.132 + EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
59.133 +#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
59.134 + EXT2_FEATURE_INCOMPAT_META_BG)
59.135 +#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED ~EXT2_FEATURE_INCOMPAT_SUPP
59.136 +#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT2_FEATURE_RO_COMPAT_SUPP
59.137 +
59.138 +#define EXT3_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
59.139 + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
59.140 + EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
59.141 +#define EXT3_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
59.142 + EXT3_FEATURE_INCOMPAT_RECOVER| \
59.143 + EXT2_FEATURE_INCOMPAT_META_BG)
59.144 +#define EXT3_FEATURE_INCOMPAT_UNSUPPORTED ~EXT3_FEATURE_INCOMPAT_SUPP
59.145 +#define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT3_FEATURE_RO_COMPAT_SUPP
59.146 +
59.147 +
59.148 +struct xfs_super_block {
59.149 + unsigned char xs_magic[4];
59.150 + __u32 xs_blocksize;
59.151 + __u64 xs_dblocks;
59.152 + __u64 xs_rblocks;
59.153 + __u32 xs_dummy1[2];
59.154 + unsigned char xs_uuid[16];
59.155 + __u32 xs_dummy2[15];
59.156 + char xs_fname[12];
59.157 + __u32 xs_dummy3[2];
59.158 + __u64 xs_icount;
59.159 + __u64 xs_ifree;
59.160 + __u64 xs_fdblocks;
59.161 +};
59.162 +
59.163 +struct reiserfs_super_block {
59.164 + __u32 rs_blocks_count;
59.165 + __u32 rs_free_blocks;
59.166 + __u32 rs_root_block;
59.167 + __u32 rs_journal_block;
59.168 + __u32 rs_journal_dev;
59.169 + __u32 rs_orig_journal_size;
59.170 + __u32 rs_dummy2[5];
59.171 + __u16 rs_blocksize;
59.172 + __u16 rs_dummy3[3];
59.173 + unsigned char rs_magic[12];
59.174 + __u32 rs_dummy4[5];
59.175 + unsigned char rs_uuid[16];
59.176 + char rs_label[16];
59.177 +};
59.178 +
59.179 +struct reiser4_super_block {
59.180 + unsigned char rs4_magic[16];
59.181 + __u16 rs4_dummy[2];
59.182 + unsigned char rs4_uuid[16];
59.183 + unsigned char rs4_label[16];
59.184 + __u64 rs4_dummy2;
59.185 +};
59.186 +
59.187 +struct jfs_super_block {
59.188 + unsigned char js_magic[4];
59.189 + __u32 js_version;
59.190 + __u64 js_size;
59.191 + __u32 js_bsize; /* 4: aggregate block size in bytes */
59.192 + __u16 js_l2bsize; /* 2: log2 of s_bsize */
59.193 + __u16 js_l2bfactor; /* 2: log2(s_bsize/hardware block size) */
59.194 + __u32 js_pbsize; /* 4: hardware/LVM block size in bytes */
59.195 + __u16 js_l2pbsize; /* 2: log2 of s_pbsize */
59.196 + __u16 js_pad; /* 2: padding necessary for alignment */
59.197 + __u32 js_dummy2[26];
59.198 + unsigned char js_uuid[16];
59.199 + unsigned char js_label[16];
59.200 + unsigned char js_loguuid[16];
59.201 +};
59.202 +
59.203 +struct romfs_super_block {
59.204 + unsigned char ros_magic[8];
59.205 + __u32 ros_dummy1[2];
59.206 + unsigned char ros_volume[16];
59.207 +};
59.208 +
59.209 +struct cramfs_super_block {
59.210 + __u8 magic[4];
59.211 + __u32 size;
59.212 + __u32 flags;
59.213 + __u32 future;
59.214 + __u8 signature[16];
59.215 + struct cramfs_info {
59.216 + __u32 crc;
59.217 + __u32 edition;
59.218 + __u32 blocks;
59.219 + __u32 files;
59.220 + } info;
59.221 + __u8 name[16];
59.222 +};
59.223 +
59.224 +struct swap_id_block {
59.225 +/* unsigned char sws_boot[1024]; */
59.226 + __u32 sws_version;
59.227 + __u32 sws_lastpage;
59.228 + __u32 sws_nrbad;
59.229 + unsigned char sws_uuid[16];
59.230 + char sws_volume[16];
59.231 + unsigned char sws_pad[117];
59.232 + __u32 sws_badpg;
59.233 +};
59.234 +
59.235 +/* Yucky misaligned values */
59.236 +struct vfat_super_block {
59.237 +/* 00*/ unsigned char vs_ignored[3];
59.238 +/* 03*/ unsigned char vs_sysid[8];
59.239 +/* 0b*/ unsigned char vs_sector_size[2];
59.240 +/* 0d*/ __u8 vs_cluster_size;
59.241 +/* 0e*/ __u16 vs_reserved;
59.242 +/* 10*/ __u8 vs_fats;
59.243 +/* 11*/ unsigned char vs_dir_entries[2];
59.244 +/* 13*/ unsigned char vs_sectors[2];
59.245 +/* 15*/ unsigned char vs_media;
59.246 +/* 16*/ __u16 vs_fat_length;
59.247 +/* 18*/ __u16 vs_secs_track;
59.248 +/* 1a*/ __u16 vs_heads;
59.249 +/* 1c*/ __u32 vs_hidden;
59.250 +/* 20*/ __u32 vs_total_sect;
59.251 +/* 24*/ __u32 vs_fat32_length;
59.252 +/* 28*/ __u16 vs_flags;
59.253 +/* 2a*/ __u8 vs_version[2];
59.254 +/* 2c*/ __u32 vs_root_cluster;
59.255 +/* 30*/ __u16 vs_insfo_sector;
59.256 +/* 32*/ __u16 vs_backup_boot;
59.257 +/* 34*/ __u16 vs_reserved2[6];
59.258 +/* 40*/ unsigned char vs_unknown[3];
59.259 +/* 43*/ unsigned char vs_serno[4];
59.260 +/* 47*/ unsigned char vs_label[11];
59.261 +/* 52*/ unsigned char vs_magic[8];
59.262 +/* 5a*/ unsigned char vs_dummy2[164];
59.263 +/*1fe*/ unsigned char vs_pmagic[2];
59.264 +};
59.265 +
59.266 +/* Yucky misaligned values */
59.267 +struct msdos_super_block {
59.268 +/* 00*/ unsigned char ms_ignored[3];
59.269 +/* 03*/ unsigned char ms_sysid[8];
59.270 +/* 0b*/ unsigned char ms_sector_size[2];
59.271 +/* 0d*/ __u8 ms_cluster_size;
59.272 +/* 0e*/ __u16 ms_reserved;
59.273 +/* 10*/ __u8 ms_fats;
59.274 +/* 11*/ unsigned char ms_dir_entries[2];
59.275 +/* 13*/ unsigned char ms_sectors[2];
59.276 +/* 15*/ unsigned char ms_media;
59.277 +/* 16*/ __u16 ms_fat_length;
59.278 +/* 18*/ __u16 ms_secs_track;
59.279 +/* 1a*/ __u16 ms_heads;
59.280 +/* 1c*/ __u32 ms_hidden;
59.281 +/* 20*/ __u32 ms_total_sect;
59.282 +/* 24*/ unsigned char ms_unknown[3];
59.283 +/* 27*/ unsigned char ms_serno[4];
59.284 +/* 2b*/ unsigned char ms_label[11];
59.285 +/* 36*/ unsigned char ms_magic[8];
59.286 +/* 3d*/ unsigned char ms_dummy2[192];
59.287 +/*1fe*/ unsigned char ms_pmagic[2];
59.288 +};
59.289 +
59.290 +struct vfat_dir_entry {
59.291 + __u8 name[11];
59.292 + __u8 attr;
59.293 + __u16 time_creat;
59.294 + __u16 date_creat;
59.295 + __u16 time_acc;
59.296 + __u16 date_acc;
59.297 + __u16 cluster_high;
59.298 + __u16 time_write;
59.299 + __u16 date_write;
59.300 + __u16 cluster_low;
59.301 + __u32 size;
59.302 +};
59.303 +
59.304 +/* maximum number of clusters */
59.305 +#define FAT12_MAX 0xFF4
59.306 +#define FAT16_MAX 0xFFF4
59.307 +#define FAT32_MAX 0x0FFFFFF6
59.308 +
59.309 +struct minix_super_block {
59.310 + __u16 ms_ninodes;
59.311 + __u16 ms_nzones;
59.312 + __u16 ms_imap_blocks;
59.313 + __u16 ms_zmap_blocks;
59.314 + __u16 ms_firstdatazone;
59.315 + __u16 ms_log_zone_size;
59.316 + __u32 ms_max_size;
59.317 + unsigned char ms_magic[2];
59.318 + __u16 ms_state;
59.319 + __u32 ms_zones;
59.320 +};
59.321 +
59.322 +struct mdp_superblock_s {
59.323 + __u32 md_magic;
59.324 + __u32 major_version;
59.325 + __u32 minor_version;
59.326 + __u32 patch_version;
59.327 + __u32 gvalid_words;
59.328 + __u32 set_uuid0;
59.329 + __u32 ctime;
59.330 + __u32 level;
59.331 + __u32 size;
59.332 + __u32 nr_disks;
59.333 + __u32 raid_disks;
59.334 + __u32 md_minor;
59.335 + __u32 not_persistent;
59.336 + __u32 set_uuid1;
59.337 + __u32 set_uuid2;
59.338 + __u32 set_uuid3;
59.339 +};
59.340 +
59.341 +struct hfs_super_block {
59.342 + char h_magic[2];
59.343 + char h_dummy[18];
59.344 + __u32 h_blksize;
59.345 +};
59.346 +
59.347 +struct ocfs_volume_header {
59.348 + unsigned char minor_version[4];
59.349 + unsigned char major_version[4];
59.350 + unsigned char signature[128];
59.351 + char mount[128];
59.352 + unsigned char mount_len[2];
59.353 +};
59.354 +
59.355 +struct ocfs_volume_label {
59.356 + unsigned char disk_lock[48];
59.357 + char label[64];
59.358 + unsigned char label_len[2];
59.359 + unsigned char vol_id[16];
59.360 + unsigned char vol_id_len[2];
59.361 +};
59.362 +
59.363 +#define ocfsmajor(o) ((__u32)o.major_version[0] \
59.364 + + (((__u32) o.major_version[1]) << 8) \
59.365 + + (((__u32) o.major_version[2]) << 16) \
59.366 + + (((__u32) o.major_version[3]) << 24))
59.367 +#define ocfslabellen(o) ((__u32)o.label_len[0] + (((__u32) o.label_len[1]) << 8))
59.368 +#define ocfsmountlen(o) ((__u32)o.mount_len[0] + (((__u32) o.mount_len[1])<<8))
59.369 +
59.370 +#define OCFS_MAGIC "OracleCFS"
59.371 +
59.372 +struct ocfs2_super_block {
59.373 + unsigned char signature[8];
59.374 + unsigned char s_dummy1[184];
59.375 + unsigned char s_dummy2[80];
59.376 + char s_label[64];
59.377 + unsigned char s_uuid[16];
59.378 +};
59.379 +
59.380 +#define OCFS2_MIN_BLOCKSIZE 512
59.381 +#define OCFS2_MAX_BLOCKSIZE 4096
59.382 +
59.383 +#define OCFS2_SUPER_BLOCK_BLKNO 2
59.384 +
59.385 +#define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2"
59.386 +
59.387 +struct oracle_asm_disk_label {
59.388 + char dummy[32];
59.389 + char dl_tag[8];
59.390 + char dl_id[24];
59.391 +};
59.392 +
59.393 +#define ORACLE_ASM_DISK_LABEL_MARKED "ORCLDISK"
59.394 +#define ORACLE_ASM_DISK_LABEL_OFFSET 32
59.395 +
59.396 +struct iso_volume_descriptor {
59.397 + unsigned char vd_type;
59.398 + unsigned char vd_id[5];
59.399 + unsigned char vd_version;
59.400 + unsigned char flags;
59.401 + unsigned char system_id[32];
59.402 + unsigned char volume_id[32];
59.403 + unsigned char unused[8];
59.404 + unsigned char space_size[8];
59.405 + unsigned char escape_sequences[8];
59.406 +};
59.407 +
59.408 +/* Common gfs/gfs2 constants: */
59.409 +#define GFS_MAGIC 0x01161970
59.410 +#define GFS_DEFAULT_BSIZE 4096
59.411 +#define GFS_SUPERBLOCK_OFFSET (0x10 * GFS_DEFAULT_BSIZE)
59.412 +#define GFS_METATYPE_SB 1
59.413 +#define GFS_FORMAT_SB 100
59.414 +#define GFS_LOCKNAME_LEN 64
59.415 +
59.416 +/* gfs1 constants: */
59.417 +#define GFS_FORMAT_FS 1309
59.418 +#define GFS_FORMAT_MULTI 1401
59.419 +/* gfs2 constants: */
59.420 +#define GFS2_FORMAT_FS 1801
59.421 +#define GFS2_FORMAT_MULTI 1900
59.422 +
59.423 +struct gfs2_meta_header {
59.424 + __u32 mh_magic;
59.425 + __u32 mh_type;
59.426 + __u64 __pad0; /* Was generation number in gfs1 */
59.427 + __u32 mh_format;
59.428 + __u32 __pad1; /* Was incarnation number in gfs1 */
59.429 +};
59.430 +
59.431 +struct gfs2_inum {
59.432 + __u64 no_formal_ino;
59.433 + __u64 no_addr;
59.434 +};
59.435 +
59.436 +struct gfs2_sb {
59.437 + struct gfs2_meta_header sb_header;
59.438 +
59.439 + __u32 sb_fs_format;
59.440 + __u32 sb_multihost_format;
59.441 + __u32 __pad0; /* Was superblock flags in gfs1 */
59.442 +
59.443 + __u32 sb_bsize;
59.444 + __u32 sb_bsize_shift;
59.445 + __u32 __pad1; /* Was journal segment size in gfs1 */
59.446 +
59.447 + struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */
59.448 + struct gfs2_inum __pad2; /* Was rindex dinode in gfs1 */
59.449 + struct gfs2_inum sb_root_dir;
59.450 +
59.451 + char sb_lockproto[GFS_LOCKNAME_LEN];
59.452 + char sb_locktable[GFS_LOCKNAME_LEN];
59.453 + /* In gfs1, quota and license dinodes followed */
59.454 +};
59.455 +
59.456 +struct ntfs_super_block {
59.457 + __u8 jump[3];
59.458 + __u8 oem_id[8];
59.459 + __u8 bios_parameter_block[25];
59.460 + __u16 unused[2];
59.461 + __u64 number_of_sectors;
59.462 + __u64 mft_cluster_location;
59.463 + __u64 mft_mirror_cluster_location;
59.464 + __s8 cluster_per_mft_record;
59.465 + __u8 reserved1[3];
59.466 + __s8 cluster_per_index_record;
59.467 + __u8 reserved2[3];
59.468 + __u64 volume_serial;
59.469 + __u16 checksum;
59.470 +};
59.471 +
59.472 +struct master_file_table_record {
59.473 + __u32 magic;
59.474 + __u16 usa_ofs;
59.475 + __u16 usa_count;
59.476 + __u64 lsn;
59.477 + __u16 sequence_number;
59.478 + __u16 link_count;
59.479 + __u16 attrs_offset;
59.480 + __u16 flags;
59.481 + __u32 bytes_in_use;
59.482 + __u32 bytes_allocated;
59.483 +} __attribute__((__packed__));
59.484 +
59.485 +struct file_attribute {
59.486 + __u32 type;
59.487 + __u32 len;
59.488 + __u8 non_resident;
59.489 + __u8 name_len;
59.490 + __u16 name_offset;
59.491 + __u16 flags;
59.492 + __u16 instance;
59.493 + __u32 value_len;
59.494 + __u16 value_offset;
59.495 +} __attribute__((__packed__));
59.496 +
59.497 +#define MFT_RECORD_VOLUME 3
59.498 +#define MFT_RECORD_ATTR_VOLUME_NAME 0x60
59.499 +#define MFT_RECORD_ATTR_VOLUME_INFO 0x70
59.500 +#define MFT_RECORD_ATTR_OBJECT_ID 0x40
59.501 +#define MFT_RECORD_ATTR_END 0xffffffffu
59.502 +
59.503 +/* HFS / HFS+ */
59.504 +struct hfs_finder_info {
59.505 + __u32 boot_folder;
59.506 + __u32 start_app;
59.507 + __u32 open_folder;
59.508 + __u32 os9_folder;
59.509 + __u32 reserved;
59.510 + __u32 osx_folder;
59.511 + __u8 id[8];
59.512 +} __attribute__((packed));
59.513 +
59.514 +struct hfs_mdb {
59.515 + __u8 signature[2];
59.516 + __u32 cr_date;
59.517 + __u32 ls_Mod;
59.518 + __u16 atrb;
59.519 + __u16 nm_fls;
59.520 + __u16 vbm_st;
59.521 + __u16 alloc_ptr;
59.522 + __u16 nm_al_blks;
59.523 + __u32 al_blk_size;
59.524 + __u32 clp_size;
59.525 + __u16 al_bl_st;
59.526 + __u32 nxt_cnid;
59.527 + __u16 free_bks;
59.528 + __u8 label_len;
59.529 + __u8 label[27];
59.530 + __u32 vol_bkup;
59.531 + __u16 vol_seq_num;
59.532 + __u32 wr_cnt;
59.533 + __u32 xt_clump_size;
59.534 + __u32 ct_clump_size;
59.535 + __u16 num_root_dirs;
59.536 + __u32 file_count;
59.537 + __u32 dir_count;
59.538 + struct hfs_finder_info finder_info;
59.539 + __u8 embed_sig[2];
59.540 + __u16 embed_startblock;
59.541 + __u16 embed_blockcount;
59.542 +} __attribute__((packed));
59.543 +
59.544 +
59.545 +#define HFS_NODE_LEAF 0xff
59.546 +#define HFSPLUS_POR_CNID 1
59.547 +
59.548 +struct hfsplus_bnode_descriptor {
59.549 + __u32 next;
59.550 + __u32 prev;
59.551 + __u8 type;
59.552 + __u8 height;
59.553 + __u16 num_recs;
59.554 + __u16 reserved;
59.555 +} __attribute__((packed));
59.556 +
59.557 +struct hfsplus_bheader_record {
59.558 + __u16 depth;
59.559 + __u32 root;
59.560 + __u32 leaf_count;
59.561 + __u32 leaf_head;
59.562 + __u32 leaf_tail;
59.563 + __u16 node_size;
59.564 +} __attribute__((packed));
59.565 +
59.566 +struct hfsplus_catalog_key {
59.567 + __u16 key_len;
59.568 + __u32 parent_id;
59.569 + __u16 unicode_len;
59.570 + __u8 unicode[255 * 2];
59.571 +} __attribute__((packed));
59.572 +
59.573 +struct hfsplus_extent {
59.574 + __u32 start_block;
59.575 + __u32 block_count;
59.576 +} __attribute__((packed));
59.577 +
59.578 +#define HFSPLUS_EXTENT_COUNT 8
59.579 +struct hfsplus_fork {
59.580 + __u64 total_size;
59.581 + __u32 clump_size;
59.582 + __u32 total_blocks;
59.583 + struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
59.584 +} __attribute__((packed));
59.585 +
59.586 +struct hfsplus_vol_header {
59.587 + __u8 signature[2];
59.588 + __u16 version;
59.589 + __u32 attributes;
59.590 + __u32 last_mount_vers;
59.591 + __u32 reserved;
59.592 + __u32 create_date;
59.593 + __u32 modify_date;
59.594 + __u32 backup_date;
59.595 + __u32 checked_date;
59.596 + __u32 file_count;
59.597 + __u32 folder_count;
59.598 + __u32 blocksize;
59.599 + __u32 total_blocks;
59.600 + __u32 free_blocks;
59.601 + __u32 next_alloc;
59.602 + __u32 rsrc_clump_sz;
59.603 + __u32 data_clump_sz;
59.604 + __u32 next_cnid;
59.605 + __u32 write_count;
59.606 + __u64 encodings_bmp;
59.607 + struct hfs_finder_info finder_info;
59.608 + struct hfsplus_fork alloc_file;
59.609 + struct hfsplus_fork ext_file;
59.610 + struct hfsplus_fork cat_file;
59.611 + struct hfsplus_fork attr_file;
59.612 + struct hfsplus_fork start_file;
59.613 +} __attribute__((packed));
59.614 +
59.615 +
59.616 +/* this is lvm's label_header & pv_header combined. */
59.617 +
59.618 +#define LVM2_ID_LEN 32
59.619 +
59.620 +struct lvm2_pv_label_header {
59.621 + /* label_header */
59.622 + __u8 id[8]; /* LABELONE */
59.623 + __u64 sector_xl; /* Sector number of this label */
59.624 + __u32 crc_xl; /* From next field to end of sector */
59.625 + __u32 offset_xl; /* Offset from start of struct to contents */
59.626 + __u8 type[8]; /* LVM2 001 */
59.627 + /* pv_header */
59.628 + __u8 pv_uuid[LVM2_ID_LEN];
59.629 +} __attribute__ ((packed));
59.630 +
59.631 +
59.632 +/*
59.633 + * this is a very generous portion of the super block, giving us
59.634 + * room to translate 14 chunks with 3 stripes each.
59.635 + */
59.636 +#define BTRFS_SYSTEM_CHUNK_ARRAY_SIZE 2048
59.637 +#define BTRFS_LABEL_SIZE 256
59.638 +#define BTRFS_UUID_SIZE 16
59.639 +#define BTRFS_FSID_SIZE 16
59.640 +#define BTRFS_CSUM_SIZE 32
59.641 +
59.642 +struct btrfs_dev_item {
59.643 + /* the internal btrfs device id */
59.644 + __u64 devid;
59.645 +
59.646 + /* size of the device */
59.647 + __u64 total_bytes;
59.648 +
59.649 + /* bytes used */
59.650 + __u64 bytes_used;
59.651 +
59.652 + /* optimal io alignment for this device */
59.653 + __u32 io_align;
59.654 +
59.655 + /* optimal io width for this device */
59.656 + __u32 io_width;
59.657 +
59.658 + /* minimal io size for this device */
59.659 + __u32 sector_size;
59.660 +
59.661 + /* type and info about this device */
59.662 + __u64 type;
59.663 +
59.664 + /* expected generation for this device */
59.665 + __u64 generation;
59.666 +
59.667 + /*
59.668 + * starting byte of this partition on the device,
59.669 + * to allow for stripe alignment in the future
59.670 + */
59.671 + __u64 start_offset;
59.672 +
59.673 + /* grouping information for allocation decisions */
59.674 + __u32 dev_group;
59.675 +
59.676 + /* seek speed 0-100 where 100 is fastest */
59.677 + __u8 seek_speed;
59.678 +
59.679 + /* bandwidth 0-100 where 100 is fastest */
59.680 + __u8 bandwidth;
59.681 +
59.682 + /* btrfs generated uuid for this device */
59.683 + __u8 uuid[BTRFS_UUID_SIZE];
59.684 +
59.685 + /* uuid of FS who owns this device */
59.686 + __u8 fsid[BTRFS_UUID_SIZE];
59.687 +} __attribute__ ((__packed__));
59.688 +
59.689 +/*
59.690 + * the super block basically lists the main trees of the FS
59.691 + * it currently lacks any block count etc etc
59.692 + */
59.693 +struct btrfs_super_block {
59.694 + __u8 csum[BTRFS_CSUM_SIZE];
59.695 + /* the first 3 fields must match struct btrfs_header */
59.696 + __u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
59.697 + __u64 bytenr; /* this block number */
59.698 + __u64 flags;
59.699 +
59.700 + /* allowed to be different from the btrfs_header from here own down */
59.701 + __u64 magic;
59.702 + __u64 generation;
59.703 + __u64 root;
59.704 + __u64 chunk_root;
59.705 + __u64 log_root;
59.706 +
59.707 + /* this will help find the new super based on the log root */
59.708 + __u64 log_root_transid;
59.709 + __u64 total_bytes;
59.710 + __u64 bytes_used;
59.711 + __u64 root_dir_objectid;
59.712 + __u64 num_devices;
59.713 + __u32 sectorsize;
59.714 + __u32 nodesize;
59.715 + __u32 leafsize;
59.716 + __u32 stripesize;
59.717 + __u32 sys_chunk_array_size;
59.718 + __u64 chunk_root_generation;
59.719 + __u64 compat_flags;
59.720 + __u64 compat_ro_flags;
59.721 + __u64 incompat_flags;
59.722 + __u16 csum_type;
59.723 + __u8 root_level;
59.724 + __u8 chunk_root_level;
59.725 + __u8 log_root_level;
59.726 + struct btrfs_dev_item dev_item;
59.727 +
59.728 + char label[BTRFS_LABEL_SIZE];
59.729 +
59.730 + /* future expansion */
59.731 + __u64 reserved[32];
59.732 + __u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
59.733 +} __attribute__ ((__packed__));
59.734 +
59.735 +#define F2FS_MAX_EXTENSION 64 /* # of extension entries */
59.736 +
59.737 +struct f2fs_super_block {
59.738 + __u32 magic; /* Magic Number */
59.739 + __u16 major_ver; /* Major Version */
59.740 + __u16 minor_ver; /* Minor Version */
59.741 + __u32 log_sectorsize; /* log2 sector size in bytes */
59.742 + __u32 log_sectors_per_block; /* log2 # of sectors per block */
59.743 + __u32 log_blocksize; /* log2 block size in bytes */
59.744 + __u32 log_blocks_per_seg; /* log2 # of blocks per segment */
59.745 + __u32 segs_per_sec; /* # of segments per section */
59.746 + __u32 secs_per_zone; /* # of sections per zone */
59.747 + __u32 checksum_offset; /* checksum offset inside super block */
59.748 + __u64 block_count; /* total # of user blocks */
59.749 + __u32 section_count; /* total # of sections */
59.750 + __u32 segment_count; /* total # of segments */
59.751 + __u32 segment_count_ckpt; /* # of segments for checkpoint */
59.752 + __u32 segment_count_sit; /* # of segments for SIT */
59.753 + __u32 segment_count_nat; /* # of segments for NAT */
59.754 + __u32 segment_count_ssa; /* # of segments for SSA */
59.755 + __u32 segment_count_main; /* # of segments for main area */
59.756 + __u32 segment0_blkaddr; /* start block address of segment 0 */
59.757 + __u32 cp_blkaddr; /* start block address of checkpoint */
59.758 + __u32 sit_blkaddr; /* start block address of SIT */
59.759 + __u32 nat_blkaddr; /* start block address of NAT */
59.760 + __u32 ssa_blkaddr; /* start block address of SSA */
59.761 + __u32 main_blkaddr; /* start block address of main area */
59.762 + __u32 root_ino; /* root inode number */
59.763 + __u32 node_ino; /* node inode number */
59.764 + __u32 meta_ino; /* meta inode number */
59.765 + __u8 uuid[16]; /* 128-bit uuid for volume */
59.766 + __u16 volume_name[512]; /* volume name */
59.767 + __u32 extension_count; /* # of extensions below */
59.768 + __u8 extension_list[F2FS_MAX_EXTENSION][8]; /* extension array */
59.769 +} __attribute__((__packed__));
59.770 +
59.771 +struct exfat_super_block {
59.772 + uint8_t jump[3];
59.773 + uint8_t oem_name[8];
59.774 + uint8_t __unused1[53];
59.775 + uint64_t block_start;
59.776 + uint64_t block_count;
59.777 + uint32_t fat_block_start;
59.778 + uint32_t fat_block_count;
59.779 + uint32_t cluster_block_start;
59.780 + uint32_t cluster_count;
59.781 + uint32_t rootdir_cluster;
59.782 + uint8_t volume_serial[4];
59.783 + struct {
59.784 + uint8_t vermin;
59.785 + uint8_t vermaj;
59.786 + } version;
59.787 + uint16_t volume_state;
59.788 + uint8_t block_bits;
59.789 + uint8_t bpc_bits;
59.790 + uint8_t fat_count;
59.791 + uint8_t drive_no;
59.792 + uint8_t allocated_percent;
59.793 +} __attribute__((__packed__));
59.794 +
59.795 +struct exfat_entry_label {
59.796 + uint8_t type;
59.797 + uint8_t length;
59.798 + uint8_t name[30];
59.799 +} __attribute__((__packed__));
59.800 +
59.801 +#define BLOCK_SIZE(sb) (1 << (sb)->block_bits)
59.802 +#define CLUSTER_SIZE(sb) (BLOCK_SIZE(sb) << (sb)->bpc_bits)
59.803 +
59.804 +#define EXFAT_FIRST_DATA_CLUSTER 2
59.805 +#define EXFAT_LAST_DATA_CLUSTER 0xffffff6
59.806 +#define EXFAT_ENTRY_SIZE 32
59.807 +
59.808 +#define EXFAT_ENTRY_EOD 0x00
59.809 +#define EXFAT_ENTRY_LABEL 0x83
59.810 +
59.811 +/*
59.812 + * Byte swap functions
59.813 + */
59.814 +#ifdef __GNUC__
59.815 +#define _INLINE_ static __inline__
59.816 +#else /* For Watcom C */
59.817 +#define _INLINE_ static inline
59.818 +#endif
59.819 +
59.820 +static __u16 blkid_swab16(__u16 val);
59.821 +static __u32 blkid_swab32(__u32 val);
59.822 +static __u64 blkid_swab64(__u64 val);
59.823 +
59.824 +#if ((defined __GNUC__) && \
59.825 + (defined(__i386__) || defined(__i486__) || defined(__i586__)))
59.826 +
59.827 +#define _BLKID_HAVE_ASM_BITOPS_
59.828 +
59.829 +_INLINE_ __u32 blkid_swab32(__u32 val)
59.830 +{
59.831 +#ifdef EXT2FS_REQUIRE_486
59.832 + __asm__("bswap %0" : "=r" (val) : "0" (val));
59.833 +#else
59.834 + __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
59.835 + "rorl $16,%0\n\t" /* swap words */
59.836 + "xchgb %b0,%h0" /* swap higher bytes */
59.837 + :"=q" (val)
59.838 + : "0" (val));
59.839 +#endif
59.840 + return val;
59.841 +}
59.842 +
59.843 +_INLINE_ __u16 blkid_swab16(__u16 val)
59.844 +{
59.845 + __asm__("xchgb %b0,%h0" /* swap bytes */ \
59.846 + : "=q" (val) \
59.847 + : "0" (val)); \
59.848 + return val;
59.849 +}
59.850 +
59.851 +_INLINE_ __u64 blkid_swab64(__u64 val)
59.852 +{
59.853 + return (blkid_swab32(val >> 32) |
59.854 + (((__u64) blkid_swab32(val & 0xFFFFFFFFUL)) << 32));
59.855 +}
59.856 +#endif
59.857 +
59.858 +#if !defined(_BLKID_HAVE_ASM_BITOPS_)
59.859 +
59.860 +_INLINE_ __u16 blkid_swab16(__u16 val)
59.861 +{
59.862 + return (val >> 8) | (val << 8);
59.863 +}
59.864 +
59.865 +_INLINE_ __u32 blkid_swab32(__u32 val)
59.866 +{
59.867 + return ((val>>24) | ((val>>8)&0xFF00) |
59.868 + ((val<<8)&0xFF0000) | (val<<24));
59.869 +}
59.870 +
59.871 +_INLINE_ __u64 blkid_swab64(__u64 val)
59.872 +{
59.873 + return (blkid_swab32(val >> 32) |
59.874 + (((__u64) blkid_swab32(val & 0xFFFFFFFFUL)) << 32));
59.875 +}
59.876 +#endif
59.877 +
59.878 +
59.879 +
59.880 +#ifdef WORDS_BIGENDIAN
59.881 +#define blkid_le16(x) blkid_swab16(x)
59.882 +#define blkid_le32(x) blkid_swab32(x)
59.883 +#define blkid_le64(x) blkid_swab64(x)
59.884 +#define blkid_be16(x) (x)
59.885 +#define blkid_be32(x) (x)
59.886 +#define blkid_be64(x) (x)
59.887 +#else
59.888 +#define blkid_le16(x) (x)
59.889 +#define blkid_le32(x) (x)
59.890 +#define blkid_le64(x) (x)
59.891 +#define blkid_be16(x) blkid_swab16(x)
59.892 +#define blkid_be32(x) blkid_swab32(x)
59.893 +#define blkid_be64(x) blkid_swab64(x)
59.894 +#endif
59.895 +
59.896 +#undef _INLINE_
59.897 +
59.898 +#endif /* _BLKID_PROBE_H */
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60.2 +++ b/libext2fs/lib/libblkid/read.c Wed Aug 25 01:28:08 2021 +0200
60.3 @@ -0,0 +1,494 @@
60.4 +/*
60.5 + * read.c - read the blkid cache from disk, to avoid scanning all devices
60.6 + *
60.7 + * Copyright (C) 2001, 2003 Theodore Y. Ts'o
60.8 + * Copyright (C) 2001 Andreas Dilger
60.9 + *
60.10 + * %Begin-Header%
60.11 + * This file may be redistributed under the terms of the
60.12 + * GNU Lesser General Public License.
60.13 + * %End-Header%
60.14 + */
60.15 +
60.16 +#define _XOPEN_SOURCE 600 /* for inclusion of strtoull */
60.17 +
60.18 +#include "config.h"
60.19 +#include <stdio.h>
60.20 +#include <ctype.h>
60.21 +#include <string.h>
60.22 +#include <time.h>
60.23 +#include <sys/types.h>
60.24 +#include <sys/stat.h>
60.25 +#include <fcntl.h>
60.26 +#include <unistd.h>
60.27 +#if HAVE_ERRNO_H
60.28 +#include <errno.h>
60.29 +#endif
60.30 +
60.31 +#include "blkidP.h"
60.32 +#include "uuid/uuid.h"
60.33 +
60.34 +#ifdef HAVE_STRTOULL
60.35 +#define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */
60.36 +#else
60.37 +/* FIXME: need to support real strtoull here */
60.38 +#define STRTOULL strtoul
60.39 +#endif
60.40 +
60.41 +#if HAVE_STDLIB_H
60.42 +#include <stdlib.h>
60.43 +#endif
60.44 +
60.45 +#ifdef TEST_PROGRAM
60.46 +#define blkid_debug_dump_dev(dev) (debug_dump_dev(dev))
60.47 +static void debug_dump_dev(blkid_dev dev);
60.48 +#endif
60.49 +
60.50 +/*
60.51 + * File format:
60.52 + *
60.53 + * <device [<NAME="value"> ...]>device_name</device>
60.54 + *
60.55 + * The following tags are required for each entry:
60.56 + * <ID="id"> unique (within this file) ID number of this device
60.57 + * <TIME="time"> (ascii time_t) time this entry was last read from disk
60.58 + * <TYPE="type"> (detected) type of filesystem/data for this partition
60.59 + *
60.60 + * The following tags may be present, depending on the device contents
60.61 + * <LABEL="label"> (user supplied) label (volume name, etc)
60.62 + * <UUID="uuid"> (generated) universally unique identifier (serial no)
60.63 + */
60.64 +
60.65 +static char *skip_over_blank(char *cp)
60.66 +{
60.67 + while (*cp && isspace(*cp))
60.68 + cp++;
60.69 + return cp;
60.70 +}
60.71 +
60.72 +static char *skip_over_word(char *cp)
60.73 +{
60.74 + char ch;
60.75 +
60.76 + while ((ch = *cp)) {
60.77 + /* If we see a backslash, skip the next character */
60.78 + if (ch == '\\') {
60.79 + cp++;
60.80 + if (*cp == '\0')
60.81 + break;
60.82 + cp++;
60.83 + continue;
60.84 + }
60.85 + if (isspace(ch) || ch == '<' || ch == '>')
60.86 + break;
60.87 + cp++;
60.88 + }
60.89 + return cp;
60.90 +}
60.91 +
60.92 +static char *strip_line(char *line)
60.93 +{
60.94 + char *p;
60.95 +
60.96 + line = skip_over_blank(line);
60.97 +
60.98 + p = line + strlen(line) - 1;
60.99 +
60.100 + while (*line) {
60.101 + if (isspace(*p))
60.102 + *p-- = '\0';
60.103 + else
60.104 + break;
60.105 + }
60.106 +
60.107 + return line;
60.108 +}
60.109 +
60.110 +#if 0
60.111 +static char *parse_word(char **buf)
60.112 +{
60.113 + char *word, *next;
60.114 +
60.115 + word = *buf;
60.116 + if (*word == '\0')
60.117 + return NULL;
60.118 +
60.119 + word = skip_over_blank(word);
60.120 + next = skip_over_word(word);
60.121 + if (*next) {
60.122 + char *end = next - 1;
60.123 + if (*end == '"' || *end == '\'')
60.124 + *end = '\0';
60.125 + *next++ = '\0';
60.126 + }
60.127 + *buf = next;
60.128 +
60.129 + if (*word == '"' || *word == '\'')
60.130 + word++;
60.131 + return word;
60.132 +}
60.133 +#endif
60.134 +
60.135 +/*
60.136 + * Start parsing a new line from the cache.
60.137 + *
60.138 + * line starts with "<device" return 1 -> continue parsing line
60.139 + * line starts with "<foo", empty, or # return 0 -> skip line
60.140 + * line starts with other, return -BLKID_ERR_CACHE -> error
60.141 + */
60.142 +static int parse_start(char **cp)
60.143 +{
60.144 + char *p;
60.145 +
60.146 + p = strip_line(*cp);
60.147 +
60.148 + /* Skip comment or blank lines. We can't just NUL the first '#' char,
60.149 + * in case it is inside quotes, or escaped.
60.150 + */
60.151 + if (*p == '\0' || *p == '#')
60.152 + return 0;
60.153 +
60.154 + if (!strncmp(p, "<device", 7)) {
60.155 + DBG(DEBUG_READ, printf("found device header: %8s\n", p));
60.156 + p += 7;
60.157 +
60.158 + *cp = p;
60.159 + return 1;
60.160 + }
60.161 +
60.162 + if (*p == '<')
60.163 + return 0;
60.164 +
60.165 + return -BLKID_ERR_CACHE;
60.166 +}
60.167 +
60.168 +/* Consume the remaining XML on the line (cosmetic only) */
60.169 +static int parse_end(char **cp)
60.170 +{
60.171 + *cp = skip_over_blank(*cp);
60.172 +
60.173 + if (!strncmp(*cp, "</device>", 9)) {
60.174 + DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp));
60.175 + *cp += 9;
60.176 + return 0;
60.177 + }
60.178 +
60.179 + return -BLKID_ERR_CACHE;
60.180 +}
60.181 +
60.182 +/*
60.183 + * Allocate a new device struct with device name filled in. Will handle
60.184 + * finding the device on lines of the form:
60.185 + * <device foo=bar>devname</device>
60.186 + * <device>devname<foo>bar</foo></device>
60.187 + */
60.188 +static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp)
60.189 +{
60.190 + char *start, *tmp, *end, *name;
60.191 + int ret;
60.192 +
60.193 + if ((ret = parse_start(cp)) <= 0)
60.194 + return ret;
60.195 +
60.196 + start = tmp = strchr(*cp, '>');
60.197 + if (!start) {
60.198 + DBG(DEBUG_READ,
60.199 + printf("blkid: short line parsing dev: %s\n", *cp));
60.200 + return -BLKID_ERR_CACHE;
60.201 + }
60.202 + start = skip_over_blank(start + 1);
60.203 + end = skip_over_word(start);
60.204 +
60.205 + DBG(DEBUG_READ, printf("device should be %.*s\n",
60.206 + (int)(end - start), start));
60.207 +
60.208 + if (**cp == '>')
60.209 + *cp = end;
60.210 + else
60.211 + (*cp)++;
60.212 +
60.213 + *tmp = '\0';
60.214 +
60.215 + if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) {
60.216 + DBG(DEBUG_READ,
60.217 + printf("blkid: missing </device> ending: %s\n", end));
60.218 + } else if (tmp)
60.219 + *tmp = '\0';
60.220 +
60.221 + if (end - start <= 1) {
60.222 + DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp));
60.223 + return -BLKID_ERR_CACHE;
60.224 + }
60.225 +
60.226 + name = blkid_strndup(start, end-start);
60.227 + if (name == NULL)
60.228 + return -BLKID_ERR_MEM;
60.229 +
60.230 + DBG(DEBUG_READ, printf("found dev %s\n", name));
60.231 +
60.232 + if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE))) {
60.233 + free(name);
60.234 + return -BLKID_ERR_MEM;
60.235 + }
60.236 +
60.237 + free(name);
60.238 + return 1;
60.239 +}
60.240 +
60.241 +/*
60.242 + * Extract a tag of the form NAME="value" from the line.
60.243 + */
60.244 +static int parse_token(char **name, char **value, char **cp)
60.245 +{
60.246 + char *end;
60.247 +
60.248 + if (!name || !value || !cp)
60.249 + return -BLKID_ERR_PARAM;
60.250 +
60.251 + if (!(*value = strchr(*cp, '=')))
60.252 + return 0;
60.253 +
60.254 + **value = '\0';
60.255 + *name = strip_line(*cp);
60.256 + *value = skip_over_blank(*value + 1);
60.257 +
60.258 + if (**value == '"') {
60.259 + end = strchr(*value + 1, '"');
60.260 + if (!end) {
60.261 + DBG(DEBUG_READ,
60.262 + printf("unbalanced quotes at: %s\n", *value));
60.263 + *cp = *value;
60.264 + return -BLKID_ERR_CACHE;
60.265 + }
60.266 + (*value)++;
60.267 + *end = '\0';
60.268 + end++;
60.269 + } else {
60.270 + end = skip_over_word(*value);
60.271 + if (*end) {
60.272 + *end = '\0';
60.273 + end++;
60.274 + }
60.275 + }
60.276 + *cp = end;
60.277 +
60.278 + return 1;
60.279 +}
60.280 +
60.281 +/*
60.282 + * Extract a tag of the form <NAME>value</NAME> from the line.
60.283 + */
60.284 +/*
60.285 +static int parse_xml(char **name, char **value, char **cp)
60.286 +{
60.287 + char *end;
60.288 +
60.289 + if (!name || !value || !cp)
60.290 + return -BLKID_ERR_PARAM;
60.291 +
60.292 + *name = strip_line(*cp);
60.293 +
60.294 + if ((*name)[0] != '<' || (*name)[1] == '/')
60.295 + return 0;
60.296 +
60.297 + FIXME: finish this.
60.298 +}
60.299 +*/
60.300 +
60.301 +/*
60.302 + * Extract a tag from the line.
60.303 + *
60.304 + * Return 1 if a valid tag was found.
60.305 + * Return 0 if no tag found.
60.306 + * Return -ve error code.
60.307 + */
60.308 +static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp)
60.309 +{
60.310 + char *name;
60.311 + char *value;
60.312 + int ret;
60.313 +
60.314 + if (!cache || !dev)
60.315 + return -BLKID_ERR_PARAM;
60.316 +
60.317 + if ((ret = parse_token(&name, &value, cp)) <= 0 /* &&
60.318 + (ret = parse_xml(&name, &value, cp)) <= 0 */)
60.319 + return ret;
60.320 +
60.321 + /* Some tags are stored directly in the device struct */
60.322 + if (!strcmp(name, "DEVNO"))
60.323 + dev->bid_devno = STRTOULL(value, 0, 0);
60.324 + else if (!strcmp(name, "PRI"))
60.325 + dev->bid_pri = strtol(value, 0, 0);
60.326 + else if (!strcmp(name, "TIME"))
60.327 + dev->bid_time = STRTOULL(value, 0, 0);
60.328 + else
60.329 + ret = blkid_set_tag(dev, name, value, strlen(value));
60.330 +
60.331 + DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value));
60.332 +
60.333 + return ret < 0 ? ret : 1;
60.334 +}
60.335 +
60.336 +/*
60.337 + * Parse a single line of data, and return a newly allocated dev struct.
60.338 + * Add the new device to the cache struct, if one was read.
60.339 + *
60.340 + * Lines are of the form <device [TAG="value" ...]>/dev/foo</device>
60.341 + *
60.342 + * Returns -ve value on error.
60.343 + * Returns 0 otherwise.
60.344 + * If a valid device was read, *dev_p is non-NULL, otherwise it is NULL
60.345 + * (e.g. comment lines, unknown XML content, etc).
60.346 + */
60.347 +static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp)
60.348 +{
60.349 + blkid_dev dev;
60.350 + int ret;
60.351 +
60.352 + if (!cache || !dev_p)
60.353 + return -BLKID_ERR_PARAM;
60.354 +
60.355 + *dev_p = NULL;
60.356 +
60.357 + DBG(DEBUG_READ, printf("line: %s\n", cp));
60.358 +
60.359 + if ((ret = parse_dev(cache, dev_p, &cp)) <= 0)
60.360 + return ret;
60.361 +
60.362 + dev = *dev_p;
60.363 +
60.364 + while ((ret = parse_tag(cache, dev, &cp)) > 0) {
60.365 + ;
60.366 + }
60.367 +
60.368 + if (dev->bid_type == NULL) {
60.369 + DBG(DEBUG_READ,
60.370 + printf("blkid: device %s has no TYPE\n",dev->bid_name));
60.371 + blkid_free_dev(dev);
60.372 + }
60.373 +
60.374 + DBG(DEBUG_READ, blkid_debug_dump_dev(dev));
60.375 +
60.376 + return ret;
60.377 +}
60.378 +
60.379 +/*
60.380 + * Parse the specified filename, and return the data in the supplied or
60.381 + * a newly allocated cache struct. If the file doesn't exist, return a
60.382 + * new empty cache struct.
60.383 + */
60.384 +void blkid_read_cache(blkid_cache cache)
60.385 +{
60.386 + FILE *file;
60.387 + char buf[4096];
60.388 + int fd, lineno = 0;
60.389 + struct stat st;
60.390 +
60.391 + if (!cache)
60.392 + return;
60.393 +
60.394 + /*
60.395 + * If the file doesn't exist, then we just return an empty
60.396 + * struct so that the cache can be populated.
60.397 + */
60.398 + if ((fd = open(cache->bic_filename, O_RDONLY)) < 0)
60.399 + return;
60.400 + if (fstat(fd, &st) < 0)
60.401 + goto errout;
60.402 + if ((st.st_mtime == cache->bic_ftime) ||
60.403 + (cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
60.404 + DBG(DEBUG_CACHE, printf("skipping re-read of %s\n",
60.405 + cache->bic_filename));
60.406 + goto errout;
60.407 + }
60.408 +
60.409 + DBG(DEBUG_CACHE, printf("reading cache file %s\n",
60.410 + cache->bic_filename));
60.411 +
60.412 + file = fdopen(fd, "r");
60.413 + if (!file)
60.414 + goto errout;
60.415 +
60.416 + while (fgets(buf, sizeof(buf), file)) {
60.417 + blkid_dev dev;
60.418 + unsigned int end;
60.419 +
60.420 + lineno++;
60.421 + if (buf[0] == 0)
60.422 + continue;
60.423 + end = strlen(buf) - 1;
60.424 + /* Continue reading next line if it ends with a backslash */
60.425 + while (buf[end] == '\\' && end < sizeof(buf) - 2 &&
60.426 + fgets(buf + end, sizeof(buf) - end, file)) {
60.427 + end = strlen(buf) - 1;
60.428 + lineno++;
60.429 + }
60.430 +
60.431 + if (blkid_parse_line(cache, &dev, buf) < 0) {
60.432 + DBG(DEBUG_READ,
60.433 + printf("blkid: bad format on line %d\n", lineno));
60.434 + continue;
60.435 + }
60.436 + }
60.437 + fclose(file);
60.438 +
60.439 + /*
60.440 + * Initially we do not need to write out the cache file.
60.441 + */
60.442 + cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
60.443 + cache->bic_ftime = st.st_mtime;
60.444 +
60.445 + return;
60.446 +errout:
60.447 + close(fd);
60.448 + return;
60.449 +}
60.450 +
60.451 +#ifdef TEST_PROGRAM
60.452 +static void debug_dump_dev(blkid_dev dev)
60.453 +{
60.454 + struct list_head *p;
60.455 +
60.456 + if (!dev) {
60.457 + printf(" dev: NULL\n");
60.458 + return;
60.459 + }
60.460 +
60.461 + printf(" dev: name = %s\n", dev->bid_name);
60.462 + printf(" dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno);
60.463 + printf(" dev: TIME=\"%lld\"\n", (long long)dev->bid_time);
60.464 + printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
60.465 + printf(" dev: flags = 0x%08X\n", dev->bid_flags);
60.466 +
60.467 + list_for_each(p, &dev->bid_tags) {
60.468 + blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
60.469 + if (tag)
60.470 + printf(" tag: %s=\"%s\"\n", tag->bit_name,
60.471 + tag->bit_val);
60.472 + else
60.473 + printf(" tag: NULL\n");
60.474 + }
60.475 + printf("\n");
60.476 +}
60.477 +
60.478 +int main(int argc, char**argv)
60.479 +{
60.480 + blkid_cache cache = NULL;
60.481 + int ret;
60.482 +
60.483 + blkid_debug_mask = DEBUG_ALL;
60.484 + if (argc > 2) {
60.485 + fprintf(stderr, "Usage: %s [filename]\n"
60.486 + "Test parsing of the cache (filename)\n", argv[0]);
60.487 + exit(1);
60.488 + }
60.489 + if ((ret = blkid_get_cache(&cache, argv[1])) < 0)
60.490 + fprintf(stderr, "error %d reading cache file %s\n", ret,
60.491 + argv[1] ? argv[1] : BLKID_CACHE_FILE);
60.492 +
60.493 + blkid_put_cache(cache);
60.494 +
60.495 + return ret;
60.496 +}
60.497 +#endif
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
61.2 +++ b/libext2fs/lib/libblkid/resolve.c Wed Aug 25 01:28:08 2021 +0200
61.3 @@ -0,0 +1,140 @@
61.4 +/*
61.5 + * resolve.c - resolve names and tags into specific devices
61.6 + *
61.7 + * Copyright (C) 2001, 2003 Theodore Ts'o.
61.8 + * Copyright (C) 2001 Andreas Dilger
61.9 + *
61.10 + * %Begin-Header%
61.11 + * This file may be redistributed under the terms of the
61.12 + * GNU Lesser General Public License.
61.13 + * %End-Header%
61.14 + */
61.15 +
61.16 +#include "config.h"
61.17 +#include <stdio.h>
61.18 +#if HAVE_UNISTD_H
61.19 +#include <unistd.h>
61.20 +#endif
61.21 +#include <stdlib.h>
61.22 +#include <fcntl.h>
61.23 +#include <string.h>
61.24 +#include <sys/types.h>
61.25 +#include <sys/stat.h>
61.26 +#include "blkidP.h"
61.27 +
61.28 +/*
61.29 + * Find a tagname (e.g. LABEL or UUID) on a specific device.
61.30 + */
61.31 +char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
61.32 + const char *devname)
61.33 +{
61.34 + blkid_tag found;
61.35 + blkid_dev dev;
61.36 + blkid_cache c = cache;
61.37 + char *ret = NULL;
61.38 +
61.39 + DBG(DEBUG_RESOLVE, printf("looking for %s on %s\n", tagname, devname));
61.40 +
61.41 + if (!devname)
61.42 + return NULL;
61.43 +
61.44 + if (!cache) {
61.45 + if (blkid_get_cache(&c, NULL) < 0)
61.46 + return NULL;
61.47 + }
61.48 +
61.49 + if ((dev = blkid_get_dev(c, devname, BLKID_DEV_NORMAL)) &&
61.50 + (found = blkid_find_tag_dev(dev, tagname)))
61.51 + ret = blkid_strdup(found->bit_val);
61.52 +
61.53 + if (!cache)
61.54 + blkid_put_cache(c);
61.55 +
61.56 + return ret;
61.57 +}
61.58 +
61.59 +/*
61.60 + * Locate a device name from a token (NAME=value string), or (name, value)
61.61 + * pair. In the case of a token, value is ignored. If the "token" is not
61.62 + * of the form "NAME=value" and there is no value given, then it is assumed
61.63 + * to be the actual devname and a copy is returned.
61.64 + */
61.65 +char *blkid_get_devname(blkid_cache cache, const char *token,
61.66 + const char *value)
61.67 +{
61.68 + blkid_dev dev;
61.69 + blkid_cache c = cache;
61.70 + char *t = 0, *v = 0;
61.71 + char *ret = NULL;
61.72 +
61.73 + if (!token)
61.74 + return NULL;
61.75 +
61.76 + if (!cache) {
61.77 + if (blkid_get_cache(&c, NULL) < 0)
61.78 + return NULL;
61.79 + }
61.80 +
61.81 + DBG(DEBUG_RESOLVE,
61.82 + printf("looking for %s%s%s %s\n", token, value ? "=" : "",
61.83 + value ? value : "", cache ? "in cache" : "from disk"));
61.84 +
61.85 + if (!value) {
61.86 + if (!strchr(token, '=')) {
61.87 + ret = blkid_strdup(token);
61.88 + goto out;
61.89 + }
61.90 + blkid_parse_tag_string(token, &t, &v);
61.91 + if (!t || !v)
61.92 + goto out;
61.93 + token = t;
61.94 + value = v;
61.95 + }
61.96 +
61.97 + dev = blkid_find_dev_with_tag(c, token, value);
61.98 + if (!dev)
61.99 + goto out;
61.100 +
61.101 + ret = blkid_strdup(blkid_dev_devname(dev));
61.102 +
61.103 +out:
61.104 + free(t);
61.105 + free(v);
61.106 + if (!cache) {
61.107 + blkid_put_cache(c);
61.108 + }
61.109 + return (ret);
61.110 +}
61.111 +
61.112 +#ifdef TEST_PROGRAM
61.113 +int main(int argc, char **argv)
61.114 +{
61.115 + char *value;
61.116 + blkid_cache cache;
61.117 +
61.118 + blkid_debug_mask = DEBUG_ALL;
61.119 + if (argc != 2 && argc != 3) {
61.120 + fprintf(stderr, "Usage:\t%s tagname=value\n"
61.121 + "\t%s tagname devname\n"
61.122 + "Find which device holds a given token or\n"
61.123 + "Find what the value of a tag is in a device\n",
61.124 + argv[0], argv[0]);
61.125 + exit(1);
61.126 + }
61.127 + if (blkid_get_cache(&cache, "/dev/null") < 0) {
61.128 + fprintf(stderr, "Couldn't get blkid cache\n");
61.129 + exit(1);
61.130 + }
61.131 +
61.132 + if (argv[2]) {
61.133 + value = blkid_get_tag_value(cache, argv[1], argv[2]);
61.134 + printf("%s has tag %s=%s\n", argv[2], argv[1],
61.135 + value ? value : "<missing>");
61.136 + } else {
61.137 + value = blkid_get_devname(cache, argv[1], NULL);
61.138 + printf("%s has tag %s\n", value ? value : "<none>", argv[1]);
61.139 + }
61.140 + blkid_put_cache(cache);
61.141 + return value ? 0 : 1;
61.142 +}
61.143 +#endif
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
62.2 +++ b/libext2fs/lib/libblkid/save.c Wed Aug 25 01:28:08 2021 +0200
62.3 @@ -0,0 +1,205 @@
62.4 +/*
62.5 + * save.c - write the cache struct to disk
62.6 + *
62.7 + * Copyright (C) 2001 by Andreas Dilger
62.8 + * Copyright (C) 2003 Theodore Ts'o
62.9 + *
62.10 + * %Begin-Header%
62.11 + * This file may be redistributed under the terms of the
62.12 + * GNU Lesser General Public License.
62.13 + * %End-Header%
62.14 + */
62.15 +
62.16 +#include "config.h"
62.17 +#include <stdio.h>
62.18 +#include <string.h>
62.19 +#include <stdlib.h>
62.20 +#include <unistd.h>
62.21 +#include <sys/types.h>
62.22 +#ifdef HAVE_SYS_STAT_H
62.23 +#include <sys/stat.h>
62.24 +#endif
62.25 +#ifdef HAVE_SYS_MKDEV_H
62.26 +#include <sys/mkdev.h>
62.27 +#endif
62.28 +#ifdef HAVE_ERRNO_H
62.29 +#include <errno.h>
62.30 +#endif
62.31 +#include "blkidP.h"
62.32 +
62.33 +#ifdef _WIN32
62.34 +#include "windows.h"
62.35 +#endif
62.36 +
62.37 +static int save_dev(blkid_dev dev, FILE *file)
62.38 +{
62.39 + struct list_head *p;
62.40 +
62.41 + if (!dev || dev->bid_name[0] != '/')
62.42 + return 0;
62.43 +
62.44 + DBG(DEBUG_SAVE,
62.45 + printf("device %s, type %s\n", dev->bid_name, dev->bid_type ?
62.46 + dev->bid_type : "(null)"));
62.47 +
62.48 + fprintf(file,
62.49 + "<device DEVNO=\"0x%04lx\" TIME=\"%ld\"",
62.50 + (unsigned long) dev->bid_devno, (long) dev->bid_time);
62.51 + if (dev->bid_pri)
62.52 + fprintf(file, " PRI=\"%d\"", dev->bid_pri);
62.53 + list_for_each(p, &dev->bid_tags) {
62.54 + blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
62.55 + fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val);
62.56 + }
62.57 + fprintf(file, ">%s</device>\n", dev->bid_name);
62.58 +
62.59 + return 0;
62.60 +}
62.61 +
62.62 +/*
62.63 + * Write out the cache struct to the cache file on disk.
62.64 + */
62.65 +int blkid_flush_cache(blkid_cache cache)
62.66 +{
62.67 + struct list_head *p;
62.68 + char *tmp = NULL;
62.69 + const char *opened = NULL;
62.70 + const char *filename;
62.71 + FILE *file = NULL;
62.72 + int fd, ret = 0;
62.73 + struct stat st;
62.74 +
62.75 + if (!cache)
62.76 + return -BLKID_ERR_PARAM;
62.77 +
62.78 + if (list_empty(&cache->bic_devs) ||
62.79 + !(cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
62.80 + DBG(DEBUG_SAVE, printf("skipping cache file write\n"));
62.81 + return 0;
62.82 + }
62.83 +
62.84 + filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE;
62.85 +
62.86 + /* If we can't write to the cache file, then don't even try */
62.87 + if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) ||
62.88 + (ret == 0 && access(filename, W_OK) < 0)) {
62.89 + DBG(DEBUG_SAVE,
62.90 + printf("can't write to cache file %s\n", filename));
62.91 + return 0;
62.92 + }
62.93 +
62.94 + /*
62.95 + * Try and create a temporary file in the same directory so
62.96 + * that in case of error we don't overwrite the cache file.
62.97 + * If the cache file doesn't yet exist, it isn't a regular
62.98 + * file (e.g. /dev/null or a socket), or we couldn't create
62.99 + * a temporary file then we open it directly.
62.100 + */
62.101 + if (ret == 0 && S_ISREG(st.st_mode)) {
62.102 + tmp = malloc(strlen(filename) + 8);
62.103 + if (tmp) {
62.104 + mode_t save_umask = umask(022);
62.105 + sprintf(tmp, "%s-XXXXXX", filename);
62.106 + fd = mkstemp(tmp);
62.107 + umask(save_umask);
62.108 + if (fd >= 0) {
62.109 + file = fdopen(fd, "w");
62.110 + opened = tmp;
62.111 + }
62.112 +#ifndef _WIN32
62.113 + fchmod(fd, 0644);
62.114 +#else
62.115 + chmod(tmp, 0644);
62.116 +#endif
62.117 + }
62.118 + }
62.119 +
62.120 + if (!file) {
62.121 + file = fopen(filename, "w");
62.122 + opened = filename;
62.123 + }
62.124 +
62.125 + DBG(DEBUG_SAVE,
62.126 + printf("writing cache file %s (really %s)\n",
62.127 + filename, opened));
62.128 +
62.129 + if (!file) {
62.130 + ret = errno;
62.131 + goto errout;
62.132 + }
62.133 +
62.134 + list_for_each(p, &cache->bic_devs) {
62.135 + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
62.136 + if (!dev->bid_type)
62.137 + continue;
62.138 + if ((ret = save_dev(dev, file)) < 0)
62.139 + break;
62.140 + }
62.141 +
62.142 + if (ret >= 0) {
62.143 + cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
62.144 + ret = 1;
62.145 + }
62.146 +
62.147 + fclose(file);
62.148 + if (opened != filename) {
62.149 + if (ret < 0) {
62.150 + (void) unlink(opened);
62.151 + DBG(DEBUG_SAVE,
62.152 + printf("unlinked temp cache %s\n", opened));
62.153 + } else {
62.154 + char *backup;
62.155 +
62.156 + backup = malloc(strlen(filename) + 5);
62.157 + if (backup) {
62.158 + sprintf(backup, "%s.old", filename);
62.159 + unlink(backup);
62.160 + (void) link(filename, backup);
62.161 + free(backup);
62.162 + }
62.163 + if (rename(opened, filename) < 0)
62.164 + (void) unlink(opened);
62.165 + DBG(DEBUG_SAVE,
62.166 + printf("moved temp cache %s\n", opened));
62.167 + }
62.168 + }
62.169 +
62.170 +errout:
62.171 + free(tmp);
62.172 + return ret;
62.173 +}
62.174 +
62.175 +#ifdef TEST_PROGRAM
62.176 +int main(int argc, char **argv)
62.177 +{
62.178 + blkid_cache cache = NULL;
62.179 + int ret;
62.180 +
62.181 + blkid_debug_mask = DEBUG_ALL;
62.182 + if (argc > 2) {
62.183 + fprintf(stderr, "Usage: %s [filename]\n"
62.184 + "Test loading/saving a cache (filename)\n", argv[0]);
62.185 + exit(1);
62.186 + }
62.187 +
62.188 + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
62.189 + fprintf(stderr, "%s: error creating cache (%d)\n",
62.190 + argv[0], ret);
62.191 + exit(1);
62.192 + }
62.193 + if ((ret = blkid_probe_all(cache)) < 0) {
62.194 + fprintf(stderr, "error (%d) probing devices\n", ret);
62.195 + exit(1);
62.196 + }
62.197 + cache->bic_filename = blkid_strdup(argv[1]);
62.198 +
62.199 + if ((ret = blkid_flush_cache(cache)) < 0) {
62.200 + fprintf(stderr, "error (%d) saving cache\n", ret);
62.201 + exit(1);
62.202 + }
62.203 +
62.204 + blkid_put_cache(cache);
62.205 +
62.206 + return ret;
62.207 +}
62.208 +#endif
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
63.2 +++ b/libext2fs/lib/libblkid/tag.c Wed Aug 25 01:28:08 2021 +0200
63.3 @@ -0,0 +1,471 @@
63.4 +/*
63.5 + * tag.c - allocation/initialization/free routines for tag structs
63.6 + *
63.7 + * Copyright (C) 2001 Andreas Dilger
63.8 + * Copyright (C) 2003 Theodore Ts'o
63.9 + *
63.10 + * %Begin-Header%
63.11 + * This file may be redistributed under the terms of the
63.12 + * GNU Lesser General Public License.
63.13 + * %End-Header%
63.14 + */
63.15 +
63.16 +#include "config.h"
63.17 +#include <unistd.h>
63.18 +#include <stdlib.h>
63.19 +#include <string.h>
63.20 +#include <stdio.h>
63.21 +
63.22 +#include "blkidP.h"
63.23 +
63.24 +static blkid_tag blkid_new_tag(void)
63.25 +{
63.26 + blkid_tag tag;
63.27 +
63.28 + if (!(tag = (blkid_tag) calloc(1, sizeof(struct blkid_struct_tag))))
63.29 + return NULL;
63.30 +
63.31 + INIT_LIST_HEAD(&tag->bit_tags);
63.32 + INIT_LIST_HEAD(&tag->bit_names);
63.33 +
63.34 + return tag;
63.35 +}
63.36 +
63.37 +#ifdef CONFIG_BLKID_DEBUG
63.38 +void blkid_debug_dump_tag(blkid_tag tag)
63.39 +{
63.40 + if (!tag) {
63.41 + printf(" tag: NULL\n");
63.42 + return;
63.43 + }
63.44 +
63.45 + printf(" tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val);
63.46 +}
63.47 +#endif
63.48 +
63.49 +void blkid_free_tag(blkid_tag tag)
63.50 +{
63.51 + if (!tag)
63.52 + return;
63.53 +
63.54 + DBG(DEBUG_TAG, printf(" freeing tag %s=%s\n", tag->bit_name,
63.55 + tag->bit_val ? tag->bit_val : "(NULL)"));
63.56 + DBG(DEBUG_TAG, blkid_debug_dump_tag(tag));
63.57 +
63.58 + list_del(&tag->bit_tags); /* list of tags for this device */
63.59 + list_del(&tag->bit_names); /* list of tags with this type */
63.60 +
63.61 + free(tag->bit_name);
63.62 + free(tag->bit_val);
63.63 +
63.64 + free(tag);
63.65 +}
63.66 +
63.67 +/*
63.68 + * Find the desired tag on a device. If value is NULL, then the
63.69 + * first such tag is returned, otherwise return only exact tag if found.
63.70 + */
63.71 +blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type)
63.72 +{
63.73 + struct list_head *p;
63.74 +
63.75 + if (!dev || !type)
63.76 + return NULL;
63.77 +
63.78 + list_for_each(p, &dev->bid_tags) {
63.79 + blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
63.80 + bit_tags);
63.81 +
63.82 + if (!strcmp(tmp->bit_name, type))
63.83 + return tmp;
63.84 + }
63.85 + return NULL;
63.86 +}
63.87 +
63.88 +extern int blkid_dev_has_tag(blkid_dev dev, const char *type,
63.89 + const char *value)
63.90 +{
63.91 + blkid_tag tag;
63.92 +
63.93 + if (!dev || !type)
63.94 + return -1;
63.95 +
63.96 + tag = blkid_find_tag_dev(dev, type);
63.97 + if (!value)
63.98 + return (tag != NULL);
63.99 + if (!tag || strcmp(tag->bit_val, value))
63.100 + return 0;
63.101 + return 1;
63.102 +}
63.103 +
63.104 +/*
63.105 + * Find the desired tag type in the cache.
63.106 + * We return the head tag for this tag type.
63.107 + */
63.108 +static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type)
63.109 +{
63.110 + blkid_tag head = NULL, tmp;
63.111 + struct list_head *p;
63.112 +
63.113 + if (!cache || !type)
63.114 + return NULL;
63.115 +
63.116 + list_for_each(p, &cache->bic_tags) {
63.117 + tmp = list_entry(p, struct blkid_struct_tag, bit_tags);
63.118 + if (!strcmp(tmp->bit_name, type)) {
63.119 + DBG(DEBUG_TAG,
63.120 + printf(" found cache tag head %s\n", type));
63.121 + head = tmp;
63.122 + break;
63.123 + }
63.124 + }
63.125 + return head;
63.126 +}
63.127 +
63.128 +/*
63.129 + * Set a tag on an existing device.
63.130 + *
63.131 + * If value is NULL, then delete the tagsfrom the device.
63.132 + */
63.133 +int blkid_set_tag(blkid_dev dev, const char *name,
63.134 + const char *value, const int vlength)
63.135 +{
63.136 + blkid_tag t = 0, head = 0;
63.137 + char *val = 0;
63.138 + char **dev_var = 0;
63.139 +
63.140 + if (!dev || !name)
63.141 + return -BLKID_ERR_PARAM;
63.142 +
63.143 + if (!(val = blkid_strndup(value, vlength)) && value)
63.144 + return -BLKID_ERR_MEM;
63.145 +
63.146 + /*
63.147 + * Certain common tags are linked directly to the device struct
63.148 + * We need to know what they are before we do anything else because
63.149 + * the function name parameter might get freed later on.
63.150 + */
63.151 + if (!strcmp(name, "TYPE"))
63.152 + dev_var = &dev->bid_type;
63.153 + else if (!strcmp(name, "LABEL"))
63.154 + dev_var = &dev->bid_label;
63.155 + else if (!strcmp(name, "UUID"))
63.156 + dev_var = &dev->bid_uuid;
63.157 +
63.158 + t = blkid_find_tag_dev(dev, name);
63.159 + if (!value) {
63.160 + if (t)
63.161 + blkid_free_tag(t);
63.162 + } else if (t) {
63.163 + if (!strcmp(t->bit_val, val)) {
63.164 + /* Same thing, exit */
63.165 + free(val);
63.166 + return 0;
63.167 + }
63.168 + free(t->bit_val);
63.169 + t->bit_val = val;
63.170 + } else {
63.171 + /* Existing tag not present, add to device */
63.172 + if (!(t = blkid_new_tag()))
63.173 + goto errout;
63.174 + t->bit_name = blkid_strdup(name);
63.175 + t->bit_val = val;
63.176 + t->bit_dev = dev;
63.177 +
63.178 + list_add_tail(&t->bit_tags, &dev->bid_tags);
63.179 +
63.180 + if (dev->bid_cache) {
63.181 + head = blkid_find_head_cache(dev->bid_cache,
63.182 + t->bit_name);
63.183 + if (!head) {
63.184 + head = blkid_new_tag();
63.185 + if (!head)
63.186 + goto errout;
63.187 +
63.188 + DBG(DEBUG_TAG,
63.189 + printf(" creating new cache tag head %s\n", name));
63.190 + head->bit_name = blkid_strdup(name);
63.191 + if (!head->bit_name)
63.192 + goto errout;
63.193 + list_add_tail(&head->bit_tags,
63.194 + &dev->bid_cache->bic_tags);
63.195 + }
63.196 + list_add_tail(&t->bit_names, &head->bit_names);
63.197 + }
63.198 + }
63.199 +
63.200 + /* Link common tags directly to the device struct */
63.201 + if (dev_var)
63.202 + *dev_var = val;
63.203 +
63.204 + if (dev->bid_cache)
63.205 + dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED;
63.206 + return 0;
63.207 +
63.208 +errout:
63.209 + if (t)
63.210 + blkid_free_tag(t);
63.211 + else free(val);
63.212 + if (head)
63.213 + blkid_free_tag(head);
63.214 + return -BLKID_ERR_MEM;
63.215 +}
63.216 +
63.217 +
63.218 +/*
63.219 + * Parse a "NAME=value" string. This is slightly different than
63.220 + * parse_token, because that will end an unquoted value at a space, while
63.221 + * this will assume that an unquoted value is the rest of the token (e.g.
63.222 + * if we are passed an already quoted string from the command-line we don't
63.223 + * have to both quote and escape quote so that the quotes make it to
63.224 + * us).
63.225 + *
63.226 + * Returns 0 on success, and -1 on failure.
63.227 + */
63.228 +int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val)
63.229 +{
63.230 + char *name, *value, *cp;
63.231 +
63.232 + DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token));
63.233 +
63.234 + if (!token || !(cp = strchr(token, '=')))
63.235 + return -1;
63.236 +
63.237 + name = blkid_strdup(token);
63.238 + if (!name)
63.239 + return -1;
63.240 + value = name + (cp - token);
63.241 + *value++ = '\0';
63.242 + if (*value == '"' || *value == '\'') {
63.243 + char c = *value++;
63.244 + if (!(cp = strrchr(value, c)))
63.245 + goto errout; /* missing closing quote */
63.246 + *cp = '\0';
63.247 + }
63.248 + value = blkid_strdup(value);
63.249 + if (!value)
63.250 + goto errout;
63.251 +
63.252 + *ret_type = name;
63.253 + *ret_val = value;
63.254 +
63.255 + return 0;
63.256 +
63.257 +errout:
63.258 + free(name);
63.259 + return -1;
63.260 +}
63.261 +
63.262 +/*
63.263 + * Tag iteration routines for the public libblkid interface.
63.264 + *
63.265 + * These routines do not expose the list.h implementation, which are a
63.266 + * contamination of the namespace, and which force us to reveal far, far
63.267 + * too much of our internal implementation. I'm not convinced I want
63.268 + * to keep list.h in the long term, anyway. It's fine for kernel
63.269 + * programming, but performance is not the #1 priority for this
63.270 + * library, and I really don't like the tradeoff of type-safety for
63.271 + * performance for this application. [tytso:20030125.2007EST]
63.272 + */
63.273 +
63.274 +/*
63.275 + * This series of functions iterate over all tags in a device
63.276 + */
63.277 +#define TAG_ITERATE_MAGIC 0x01a5284c
63.278 +
63.279 +struct blkid_struct_tag_iterate {
63.280 + int magic;
63.281 + blkid_dev dev;
63.282 + struct list_head *p;
63.283 +};
63.284 +
63.285 +extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev)
63.286 +{
63.287 + blkid_tag_iterate iter;
63.288 +
63.289 + iter = malloc(sizeof(struct blkid_struct_tag_iterate));
63.290 + if (iter) {
63.291 + iter->magic = TAG_ITERATE_MAGIC;
63.292 + iter->dev = dev;
63.293 + iter->p = dev->bid_tags.next;
63.294 + }
63.295 + return (iter);
63.296 +}
63.297 +
63.298 +/*
63.299 + * Return 0 on success, -1 on error
63.300 + */
63.301 +extern int blkid_tag_next(blkid_tag_iterate iter,
63.302 + const char **type, const char **value)
63.303 +{
63.304 + blkid_tag tag;
63.305 +
63.306 + *type = 0;
63.307 + *value = 0;
63.308 + if (!iter || iter->magic != TAG_ITERATE_MAGIC ||
63.309 + iter->p == &iter->dev->bid_tags)
63.310 + return -1;
63.311 + tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags);
63.312 + *type = tag->bit_name;
63.313 + *value = tag->bit_val;
63.314 + iter->p = iter->p->next;
63.315 + return 0;
63.316 +}
63.317 +
63.318 +extern void blkid_tag_iterate_end(blkid_tag_iterate iter)
63.319 +{
63.320 + if (!iter || iter->magic != TAG_ITERATE_MAGIC)
63.321 + return;
63.322 + iter->magic = 0;
63.323 + free(iter);
63.324 +}
63.325 +
63.326 +/*
63.327 + * This function returns a device which matches a particular
63.328 + * type/value pair. If there is more than one device that matches the
63.329 + * search specification, it returns the one with the highest priority
63.330 + * value. This allows us to give preference to EVMS or LVM devices.
63.331 + */
63.332 +extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
63.333 + const char *type,
63.334 + const char *value)
63.335 +{
63.336 + blkid_tag head;
63.337 + blkid_dev dev;
63.338 + int pri;
63.339 + struct list_head *p;
63.340 + int probe_new = 0;
63.341 +
63.342 + if (!cache || !type || !value)
63.343 + return NULL;
63.344 +
63.345 + blkid_read_cache(cache);
63.346 +
63.347 + DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value));
63.348 +
63.349 +try_again:
63.350 + pri = -1;
63.351 + dev = 0;
63.352 + head = blkid_find_head_cache(cache, type);
63.353 +
63.354 + if (head) {
63.355 + list_for_each(p, &head->bit_names) {
63.356 + blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
63.357 + bit_names);
63.358 +
63.359 + if (!strcmp(tmp->bit_val, value) &&
63.360 + (tmp->bit_dev->bid_pri > pri) &&
63.361 + !access(tmp->bit_dev->bid_name, F_OK)) {
63.362 + dev = tmp->bit_dev;
63.363 + pri = dev->bid_pri;
63.364 + }
63.365 + }
63.366 + }
63.367 + if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
63.368 + dev = blkid_verify(cache, dev);
63.369 + if (!dev || (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED)))
63.370 + goto try_again;
63.371 + }
63.372 +
63.373 + if (!dev && !probe_new) {
63.374 + if (blkid_probe_all_new(cache) < 0)
63.375 + return NULL;
63.376 + probe_new++;
63.377 + goto try_again;
63.378 + }
63.379 +
63.380 + if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
63.381 + if (blkid_probe_all(cache) < 0)
63.382 + return NULL;
63.383 + goto try_again;
63.384 + }
63.385 + return dev;
63.386 +}
63.387 +
63.388 +#ifdef TEST_PROGRAM
63.389 +#ifdef HAVE_GETOPT_H
63.390 +#include <getopt.h>
63.391 +#else
63.392 +extern char *optarg;
63.393 +extern int optind;
63.394 +#endif
63.395 +
63.396 +void usage(char *prog)
63.397 +{
63.398 + fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask] device "
63.399 + "[type value]\n",
63.400 + prog);
63.401 + fprintf(stderr, "\tList all tags for a device and exit\n");
63.402 + exit(1);
63.403 +}
63.404 +
63.405 +int main(int argc, char **argv)
63.406 +{
63.407 + blkid_tag_iterate iter;
63.408 + blkid_cache cache = NULL;
63.409 + blkid_dev dev;
63.410 + int c, ret, found;
63.411 + int flags = BLKID_DEV_FIND;
63.412 + char *tmp;
63.413 + char *file = NULL;
63.414 + char *devname = NULL;
63.415 + char *search_type = NULL;
63.416 + char *search_value = NULL;
63.417 + const char *type, *value;
63.418 +
63.419 + while ((c = getopt (argc, argv, "m:f:")) != EOF)
63.420 + switch (c) {
63.421 + case 'f':
63.422 + file = optarg;
63.423 + break;
63.424 + case 'm':
63.425 + blkid_debug_mask = strtoul (optarg, &tmp, 0);
63.426 + if (*tmp) {
63.427 + fprintf(stderr, "Invalid debug mask: %s\n",
63.428 + optarg);
63.429 + exit(1);
63.430 + }
63.431 + break;
63.432 + case '?':
63.433 + usage(argv[0]);
63.434 + }
63.435 + if (argc > optind)
63.436 + devname = argv[optind++];
63.437 + if (argc > optind)
63.438 + search_type = argv[optind++];
63.439 + if (argc > optind)
63.440 + search_value = argv[optind++];
63.441 + if (!devname || (argc != optind))
63.442 + usage(argv[0]);
63.443 +
63.444 + if ((ret = blkid_get_cache(&cache, file)) != 0) {
63.445 + fprintf(stderr, "%s: error creating cache (%d)\n",
63.446 + argv[0], ret);
63.447 + exit(1);
63.448 + }
63.449 +
63.450 + dev = blkid_get_dev(cache, devname, flags);
63.451 + if (!dev) {
63.452 + fprintf(stderr, "%s: Can not find device in blkid cache\n",
63.453 + devname);
63.454 + exit(1);
63.455 + }
63.456 + if (search_type) {
63.457 + found = blkid_dev_has_tag(dev, search_type, search_value);
63.458 + printf("Device %s: (%s, %s) %s\n", blkid_dev_devname(dev),
63.459 + search_type, search_value ? search_value : "NULL",
63.460 + found ? "FOUND" : "NOT FOUND");
63.461 + return(!found);
63.462 + }
63.463 + printf("Device %s...\n", blkid_dev_devname(dev));
63.464 +
63.465 + iter = blkid_tag_iterate_begin(dev);
63.466 + while (blkid_tag_next(iter, &type, &value) == 0) {
63.467 + printf("\tTag %s has value %s\n", type, value);
63.468 + }
63.469 + blkid_tag_iterate_end(iter);
63.470 +
63.471 + blkid_put_cache(cache);
63.472 + return (0);
63.473 +}
63.474 +#endif
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
64.2 +++ b/libext2fs/lib/libblkid/tst_types.c Wed Aug 25 01:28:08 2021 +0200
64.3 @@ -0,0 +1,64 @@
64.4 +/*
64.5 + * This testing program makes sure the blkid_types header file
64.6 + *
64.7 + * Copyright (C) 2006 by Theodore Ts'o.
64.8 + *
64.9 + * %Begin-Header%
64.10 + * This file may be redistributed under the terms of the GNU Public
64.11 + * License.
64.12 + * %End-Header%
64.13 + */
64.14 +
64.15 +#include "config.h"
64.16 +#include <sys/types.h>
64.17 +#include "blkid/blkid_types.h"
64.18 +
64.19 +#include <stdlib.h>
64.20 +#include <stdio.h>
64.21 +
64.22 +int main(int argc, char **argv)
64.23 +{
64.24 + if (sizeof(__u8) != 1) {
64.25 + printf("Sizeof(__u8) is %d should be 1\n",
64.26 + (int)sizeof(__u8));
64.27 + exit(1);
64.28 + }
64.29 + if (sizeof(__s8) != 1) {
64.30 + printf("Sizeof(_s8) is %d should be 1\n",
64.31 + (int)sizeof(__s8));
64.32 + exit(1);
64.33 + }
64.34 + if (sizeof(__u16) != 2) {
64.35 + printf("Sizeof(__u16) is %d should be 2\n",
64.36 + (int)sizeof(__u16));
64.37 + exit(1);
64.38 + }
64.39 + if (sizeof(__s16) != 2) {
64.40 + printf("Sizeof(__s16) is %d should be 2\n",
64.41 + (int)sizeof(__s16));
64.42 + exit(1);
64.43 + }
64.44 + if (sizeof(__u32) != 4) {
64.45 + printf("Sizeof(__u32) is %d should be 4\n",
64.46 + (int)sizeof(__u32));
64.47 + exit(1);
64.48 + }
64.49 + if (sizeof(__s32) != 4) {
64.50 + printf("Sizeof(__s32) is %d should be 4\n",
64.51 + (int)sizeof(__s32));
64.52 + exit(1);
64.53 + }
64.54 + if (sizeof(__u64) != 8) {
64.55 + printf("Sizeof(__u64) is %d should be 8\n",
64.56 + (int)sizeof(__u64));
64.57 + exit(1);
64.58 + }
64.59 + if (sizeof(__s64) != 8) {
64.60 + printf("Sizeof(__s64) is %d should be 8\n",
64.61 + (int)sizeof(__s64));
64.62 + exit(1);
64.63 + }
64.64 + printf("The blkid_types.h types are correct.\n");
64.65 + exit(0);
64.66 +}
64.67 +
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
65.2 +++ b/libext2fs/lib/libblkid/version.c Wed Aug 25 01:28:08 2021 +0200
65.3 @@ -0,0 +1,50 @@
65.4 +/*
65.5 + * version.c --- Return the version of the blkid library
65.6 + *
65.7 + * Copyright (C) 2004 Theodore Ts'o.
65.8 + *
65.9 + * %Begin-Header%
65.10 + * This file may be redistributed under the terms of the
65.11 + * GNU Lesser General Public License.
65.12 + * %End-Header%
65.13 + */
65.14 +
65.15 +#include "config.h"
65.16 +#if HAVE_UNISTD_H
65.17 +#include <unistd.h>
65.18 +#endif
65.19 +#include <string.h>
65.20 +#include <stdio.h>
65.21 +#include <ctype.h>
65.22 +
65.23 +#include <blkid/blkid.h>
65.24 +#include "version.h"
65.25 +
65.26 +static const char *lib_version = E2FSPROGS_VERSION;
65.27 +static const char *lib_date = E2FSPROGS_DATE;
65.28 +
65.29 +int blkid_parse_version_string(const char *ver_string)
65.30 +{
65.31 + const char *cp;
65.32 + int version = 0;
65.33 +
65.34 + for (cp = ver_string; *cp; cp++) {
65.35 + if (*cp == '.')
65.36 + continue;
65.37 + if (!isdigit(*cp))
65.38 + break;
65.39 + version = (version * 10) + (*cp - '0');
65.40 + }
65.41 + return version;
65.42 +}
65.43 +
65.44 +int blkid_get_library_version(const char **ver_string,
65.45 + const char **date_string)
65.46 +{
65.47 + if (ver_string)
65.48 + *ver_string = lib_version;
65.49 + if (date_string)
65.50 + *date_string = lib_date;
65.51 +
65.52 + return blkid_parse_version_string(lib_version);
65.53 +}
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
66.2 +++ b/libext2fs/lib/libe2p/Makefile Wed Aug 25 01:28:08 2021 +0200
66.3 @@ -0,0 +1,26 @@
66.4 +PKGDIR ?= ../..
66.5 +L4DIR ?= $(PKGDIR)/../../..
66.6 +
66.7 +TARGET = libe2p.a libe2p.so
66.8 +PC_FILENAME = libe2p
66.9 +
66.10 +SRC_C = \
66.11 + feature.c fgetflags.c fsetflags.c fgetversion.c fsetversion.c \
66.12 + getflags.c getversion.c hashstr.c iod.c ls.c ljs.c mntopts.c \
66.13 + parse_num.c pe.c pf.c ps.c setflags.c setversion.c uuid.c \
66.14 + ostype.c percent.c crypto_mode.c fgetproject.c fsetproject.c
66.15 +
66.16 +REQUIRES_LIBS = libet libsupport
66.17 +
66.18 +PRIVATE_INCDIR += \
66.19 + $(PKGDIR)/lib \
66.20 + $(PKGDIR)/lib/libext2fs \
66.21 + $(PKGDIR)/lib/libsupport \
66.22 + $(PKGDIR)/include/libet \
66.23 + $(PKGDIR)/include/libe2p $(PKGDIR)/include/libe2p/e2p \
66.24 + $(PKGDIR)/include/libext2fs \
66.25 + $(PKGDIR)/include/libsupport
66.26 +
66.27 +CONTRIB_INCDIR = libe2p
66.28 +
66.29 +include $(L4DIR)/mk/lib.mk
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
67.2 +++ b/libext2fs/lib/libe2p/crypto_mode.c Wed Aug 25 01:28:08 2021 +0200
67.3 @@ -0,0 +1,74 @@
67.4 +/*
67.5 + * crypto_mode.c --- convert between encryption modes and strings
67.6 + *
67.7 + * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
67.8 + *
67.9 + * %Begin-Header%
67.10 + * This file may be redistributed under the terms of the GNU Library
67.11 + * General Public License, version 2.
67.12 + * %End-Header%
67.13 + */
67.14 +
67.15 +#include "config.h"
67.16 +#include <stdio.h>
67.17 +#include <stdlib.h>
67.18 +#include <string.h>
67.19 +#include <strings.h>
67.20 +#include <ctype.h>
67.21 +#include <errno.h>
67.22 +
67.23 +#include "e2p.h"
67.24 +
67.25 +struct mode {
67.26 + int num;
67.27 + const char *string;
67.28 +};
67.29 +
67.30 +static struct mode mode_list[] = {
67.31 + { EXT4_ENCRYPTION_MODE_INVALID, "Invalid"},
67.32 + { EXT4_ENCRYPTION_MODE_AES_256_XTS, "AES-256-XTS"},
67.33 + { EXT4_ENCRYPTION_MODE_AES_256_GCM, "AES-256-GCM"},
67.34 + { EXT4_ENCRYPTION_MODE_AES_256_CBC, "AES-256-CBC"},
67.35 + { 0, 0 },
67.36 +};
67.37 +
67.38 +const char *e2p_encmode2string(int num)
67.39 +{
67.40 + struct mode *p;
67.41 + static char buf[20];
67.42 +
67.43 + for (p = mode_list; p->string; p++) {
67.44 + if (num == p->num)
67.45 + return p->string;
67.46 + }
67.47 + sprintf(buf, "ENC_MODE_%d", num);
67.48 + return buf;
67.49 +}
67.50 +
67.51 +/*
67.52 + * Returns the hash algorithm, or -1 on error
67.53 + */
67.54 +int e2p_string2encmode(char *string)
67.55 +{
67.56 + struct mode *p;
67.57 + char *eptr;
67.58 + int num;
67.59 +
67.60 + for (p = mode_list; p->string; p++) {
67.61 + if (!strcasecmp(string, p->string)) {
67.62 + return p->num;
67.63 + }
67.64 + }
67.65 + if (strncasecmp(string, "ENC_MODE_", 9))
67.66 + return -1;
67.67 +
67.68 + if (string[9] == 0)
67.69 + return -1;
67.70 + num = strtol(string+9, &eptr, 10);
67.71 + if (num > 255 || num < 0)
67.72 + return -1;
67.73 + if (*eptr)
67.74 + return -1;
67.75 + return num;
67.76 +}
67.77 +
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
68.2 +++ b/libext2fs/lib/libe2p/feature.c Wed Aug 25 01:28:08 2021 +0200
68.3 @@ -0,0 +1,427 @@
68.4 +/*
68.5 + * feature.c --- convert between features and strings
68.6 + *
68.7 + * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
68.8 + *
68.9 + * %Begin-Header%
68.10 + * This file may be redistributed under the terms of the GNU Library
68.11 + * General Public License, version 2.
68.12 + * %End-Header%
68.13 + */
68.14 +
68.15 +#include "config.h"
68.16 +#include <stdio.h>
68.17 +#include <stdlib.h>
68.18 +#include <string.h>
68.19 +#include <ctype.h>
68.20 +#include <errno.h>
68.21 +
68.22 +#include "e2p.h"
68.23 +#include <ext2fs/ext2fs.h>
68.24 +#include <ext2fs/kernel-jbd.h>
68.25 +
68.26 +struct feature {
68.27 + int compat;
68.28 + unsigned int mask;
68.29 + const char *string;
68.30 +};
68.31 +
68.32 +static struct feature feature_list[] = {
68.33 + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC,
68.34 + "dir_prealloc" },
68.35 + { E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL,
68.36 + "has_journal" },
68.37 + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES,
68.38 + "imagic_inodes" },
68.39 + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR,
68.40 + "ext_attr" },
68.41 + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX,
68.42 + "dir_index" },
68.43 + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INODE,
68.44 + "resize_inode" },
68.45 + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_LAZY_BG,
68.46 + "lazy_bg" },
68.47 + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP,
68.48 + "snapshot_bitmap" },
68.49 + { E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_SPARSE_SUPER2,
68.50 + "sparse_super2" },
68.51 +
68.52 + { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
68.53 + "sparse_super" },
68.54 + { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE,
68.55 + "large_file" },
68.56 + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_HUGE_FILE,
68.57 + "huge_file" },
68.58 + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM,
68.59 + "uninit_bg" },
68.60 + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM,
68.61 + "uninit_groups" },
68.62 + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_DIR_NLINK,
68.63 + "dir_nlink" },
68.64 + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE,
68.65 + "extra_isize" },
68.66 + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_QUOTA,
68.67 + "quota" },
68.68 + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_BIGALLOC,
68.69 + "bigalloc"},
68.70 + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_METADATA_CSUM,
68.71 + "metadata_csum"},
68.72 + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_REPLICA,
68.73 + "replica" },
68.74 + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_READONLY,
68.75 + "read-only" },
68.76 + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_PROJECT,
68.77 + "project"},
68.78 + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS,
68.79 + "shared_blocks"},
68.80 + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_VERITY,
68.81 + "verity"},
68.82 +
68.83 + { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION,
68.84 + "compression" },
68.85 + { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE,
68.86 + "filetype" },
68.87 + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER,
68.88 + "needs_recovery" },
68.89 + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV,
68.90 + "journal_dev" },
68.91 + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
68.92 + "extent" },
68.93 + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
68.94 + "extents" },
68.95 + { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG,
68.96 + "meta_bg" },
68.97 + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_64BIT,
68.98 + "64bit" },
68.99 + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_MMP,
68.100 + "mmp" },
68.101 + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG,
68.102 + "flex_bg"},
68.103 + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_EA_INODE,
68.104 + "ea_inode"},
68.105 + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_DIRDATA,
68.106 + "dirdata"},
68.107 + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_CSUM_SEED,
68.108 + "metadata_csum_seed"},
68.109 + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_LARGEDIR,
68.110 + "large_dir"},
68.111 + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_INLINE_DATA,
68.112 + "inline_data"},
68.113 + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_ENCRYPT,
68.114 + "encrypt"},
68.115 + { 0, 0, 0 },
68.116 +};
68.117 +
68.118 +static struct feature jrnl_feature_list[] = {
68.119 + { E2P_FEATURE_COMPAT, JFS_FEATURE_COMPAT_CHECKSUM,
68.120 + "journal_checksum" },
68.121 +
68.122 + { E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_REVOKE,
68.123 + "journal_incompat_revoke" },
68.124 + { E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_64BIT,
68.125 + "journal_64bit" },
68.126 + { E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_ASYNC_COMMIT,
68.127 + "journal_async_commit" },
68.128 + { E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_CSUM_V2,
68.129 + "journal_checksum_v2" },
68.130 + { E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_CSUM_V3,
68.131 + "journal_checksum_v3" },
68.132 + { 0, 0, 0 },
68.133 +};
68.134 +
68.135 +const char *e2p_feature2string(int compat, unsigned int mask)
68.136 +{
68.137 + struct feature *f;
68.138 + static char buf[20];
68.139 + char fchar;
68.140 + int fnum;
68.141 +
68.142 + for (f = feature_list; f->string; f++) {
68.143 + if ((compat == f->compat) &&
68.144 + (mask == f->mask))
68.145 + return f->string;
68.146 + }
68.147 + switch (compat) {
68.148 + case E2P_FEATURE_COMPAT:
68.149 + fchar = 'C';
68.150 + break;
68.151 + case E2P_FEATURE_INCOMPAT:
68.152 + fchar = 'I';
68.153 + break;
68.154 + case E2P_FEATURE_RO_INCOMPAT:
68.155 + fchar = 'R';
68.156 + break;
68.157 + default:
68.158 + fchar = '?';
68.159 + break;
68.160 + }
68.161 + for (fnum = 0; mask >>= 1; fnum++);
68.162 + sprintf(buf, "FEATURE_%c%d", fchar, fnum);
68.163 + return buf;
68.164 +}
68.165 +
68.166 +int e2p_string2feature(char *string, int *compat_type, unsigned int *mask)
68.167 +{
68.168 + struct feature *f;
68.169 + char *eptr;
68.170 + int num;
68.171 +
68.172 + for (f = feature_list; f->string; f++) {
68.173 + if (!strcasecmp(string, f->string)) {
68.174 + *compat_type = f->compat;
68.175 + *mask = f->mask;
68.176 + return 0;
68.177 + }
68.178 + }
68.179 + if (strncasecmp(string, "FEATURE_", 8))
68.180 + return 1;
68.181 +
68.182 + switch (string[8]) {
68.183 + case 'c':
68.184 + case 'C':
68.185 + *compat_type = E2P_FEATURE_COMPAT;
68.186 + break;
68.187 + case 'i':
68.188 + case 'I':
68.189 + *compat_type = E2P_FEATURE_INCOMPAT;
68.190 + break;
68.191 + case 'r':
68.192 + case 'R':
68.193 + *compat_type = E2P_FEATURE_RO_INCOMPAT;
68.194 + break;
68.195 + default:
68.196 + return 1;
68.197 + }
68.198 + if (string[9] == 0)
68.199 + return 1;
68.200 + num = strtol(string+9, &eptr, 10);
68.201 + if (num > 31 || num < 0)
68.202 + return 1;
68.203 + if (*eptr)
68.204 + return 1;
68.205 + *mask = 1 << num;
68.206 + return 0;
68.207 +}
68.208 +
68.209 +const char *e2p_jrnl_feature2string(int compat, unsigned int mask)
68.210 +{
68.211 + struct feature *f;
68.212 + static char buf[20];
68.213 + char fchar;
68.214 + int fnum;
68.215 +
68.216 + for (f = jrnl_feature_list; f->string; f++) {
68.217 + if ((compat == f->compat) &&
68.218 + (mask == f->mask))
68.219 + return f->string;
68.220 + }
68.221 + switch (compat) {
68.222 + case E2P_FEATURE_COMPAT:
68.223 + fchar = 'C';
68.224 + break;
68.225 + case E2P_FEATURE_INCOMPAT:
68.226 + fchar = 'I';
68.227 + break;
68.228 + case E2P_FEATURE_RO_INCOMPAT:
68.229 + fchar = 'R';
68.230 + break;
68.231 + default:
68.232 + fchar = '?';
68.233 + break;
68.234 + }
68.235 + for (fnum = 0; mask >>= 1; fnum++);
68.236 + sprintf(buf, "FEATURE_%c%d", fchar, fnum);
68.237 + return buf;
68.238 +}
68.239 +
68.240 +int e2p_jrnl_string2feature(char *string, int *compat_type, unsigned int *mask)
68.241 +{
68.242 + struct feature *f;
68.243 + char *eptr;
68.244 + int num;
68.245 +
68.246 + for (f = jrnl_feature_list; f->string; f++) {
68.247 + if (!strcasecmp(string, f->string)) {
68.248 + *compat_type = f->compat;
68.249 + *mask = f->mask;
68.250 + return 0;
68.251 + }
68.252 + }
68.253 + if (strncasecmp(string, "FEATURE_", 8))
68.254 + return 1;
68.255 +
68.256 + switch (string[8]) {
68.257 + case 'c':
68.258 + case 'C':
68.259 + *compat_type = E2P_FEATURE_COMPAT;
68.260 + break;
68.261 + case 'i':
68.262 + case 'I':
68.263 + *compat_type = E2P_FEATURE_INCOMPAT;
68.264 + break;
68.265 + case 'r':
68.266 + case 'R':
68.267 + *compat_type = E2P_FEATURE_RO_INCOMPAT;
68.268 + break;
68.269 + default:
68.270 + return 1;
68.271 + }
68.272 + if (string[9] == 0)
68.273 + return 1;
68.274 + num = strtol(string+9, &eptr, 10);
68.275 + if (num > 31 || num < 0)
68.276 + return 1;
68.277 + if (*eptr)
68.278 + return 1;
68.279 + *mask = 1 << num;
68.280 + return 0;
68.281 +}
68.282 +static char *skip_over_blanks(char *cp)
68.283 +{
68.284 + while (*cp && isspace(*cp))
68.285 + cp++;
68.286 + return cp;
68.287 +}
68.288 +
68.289 +static char *skip_over_word(char *cp)
68.290 +{
68.291 + while (*cp && !isspace(*cp) && *cp != ',')
68.292 + cp++;
68.293 + return cp;
68.294 +}
68.295 +
68.296 +/*
68.297 + * Edit a feature set array as requested by the user. The ok_array,
68.298 + * if set, allows the application to limit what features the user is
68.299 + * allowed to set or clear using this function. If clear_ok_array is set,
68.300 + * then use it tell whether or not it is OK to clear a filesystem feature.
68.301 + */
68.302 +int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array,
68.303 + __u32 *clear_ok_array, int *type_err,
68.304 + unsigned int *mask_err)
68.305 +{
68.306 + char *cp, *buf, *next;
68.307 + int neg;
68.308 + unsigned int mask;
68.309 + int compat_type;
68.310 + int rc = 0;
68.311 +
68.312 + if (!clear_ok_array)
68.313 + clear_ok_array = ok_array;
68.314 +
68.315 + if (type_err)
68.316 + *type_err = 0;
68.317 + if (mask_err)
68.318 + *mask_err = 0;
68.319 +
68.320 + buf = malloc(strlen(str)+1);
68.321 + if (!buf)
68.322 + return 1;
68.323 + strcpy(buf, str);
68.324 + for (cp = buf; cp && *cp; cp = next ? next+1 : 0) {
68.325 + neg = 0;
68.326 + cp = skip_over_blanks(cp);
68.327 + next = skip_over_word(cp);
68.328 +
68.329 + if (*next == 0)
68.330 + next = 0;
68.331 + else
68.332 + *next = 0;
68.333 +
68.334 + if ((strcasecmp(cp, "none") == 0) ||
68.335 + (strcasecmp(cp, "clear") == 0)) {
68.336 + compat_array[0] = 0;
68.337 + compat_array[1] = 0;
68.338 + compat_array[2] = 0;
68.339 + continue;
68.340 + }
68.341 +
68.342 + switch (*cp) {
68.343 + case '-':
68.344 + case '^':
68.345 + neg++;
68.346 + /* fallthrough */
68.347 + case '+':
68.348 + cp++;
68.349 + break;
68.350 + }
68.351 + if (e2p_string2feature(cp, &compat_type, &mask)) {
68.352 + rc = 1;
68.353 + break;
68.354 + }
68.355 + if (neg) {
68.356 + if (clear_ok_array &&
68.357 + !(clear_ok_array[compat_type] & mask)) {
68.358 + rc = 1;
68.359 + if (type_err)
68.360 + *type_err = (compat_type |
68.361 + E2P_FEATURE_NEGATE_FLAG);
68.362 + if (mask_err)
68.363 + *mask_err = mask;
68.364 + break;
68.365 + }
68.366 + compat_array[compat_type] &= ~mask;
68.367 + } else {
68.368 + if (ok_array && !(ok_array[compat_type] & mask)) {
68.369 + rc = 1;
68.370 + if (type_err)
68.371 + *type_err = compat_type;
68.372 + if (mask_err)
68.373 + *mask_err = mask;
68.374 + break;
68.375 + }
68.376 + compat_array[compat_type] |= mask;
68.377 + }
68.378 + }
68.379 + free(buf);
68.380 + return rc;
68.381 +}
68.382 +
68.383 +int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array)
68.384 +{
68.385 + return e2p_edit_feature2(str, compat_array, ok_array, 0, 0, 0);
68.386 +}
68.387 +
68.388 +#ifdef TEST_PROGRAM
68.389 +int main(int argc, char **argv)
68.390 +{
68.391 + int compat, compat2, i;
68.392 + unsigned int mask, mask2;
68.393 + const char *str;
68.394 + struct feature *f;
68.395 +
68.396 + for (i = 0; i < 2; i++) {
68.397 + if (i == 0) {
68.398 + f = feature_list;
68.399 + printf("Feature list:\n");
68.400 + } else {
68.401 + printf("\nJournal feature list:\n");
68.402 + f = jrnl_feature_list;
68.403 + }
68.404 + for (; f->string; f++) {
68.405 + if (i == 0) {
68.406 + e2p_string2feature((char *)f->string, &compat,
68.407 + &mask);
68.408 + str = e2p_feature2string(compat, mask);
68.409 + } else {
68.410 + e2p_jrnl_string2feature((char *)f->string,
68.411 + &compat, &mask);
68.412 + str = e2p_jrnl_feature2string(compat, mask);
68.413 + }
68.414 +
68.415 + printf("\tCompat = %d, Mask = %u, %s\n",
68.416 + compat, mask, f->string);
68.417 + if (strcmp(f->string, str)) {
68.418 + if (e2p_string2feature((char *) str, &compat2,
68.419 + &mask2) ||
68.420 + (compat2 != compat) ||
68.421 + (mask2 != mask)) {
68.422 + fprintf(stderr, "Failure!\n");
68.423 + exit(1);
68.424 + }
68.425 + }
68.426 + }
68.427 + }
68.428 + exit(0);
68.429 +}
68.430 +#endif
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
69.2 +++ b/libext2fs/lib/libe2p/fgetflags.c Wed Aug 25 01:28:08 2021 +0200
69.3 @@ -0,0 +1,102 @@
69.4 +/*
69.5 + * fgetflags.c - Get a file flags on an ext2 file system
69.6 + *
69.7 + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
69.8 + * Laboratoire MASI, Institut Blaise Pascal
69.9 + * Universite Pierre et Marie Curie (Paris VI)
69.10 + *
69.11 + * %Begin-Header%
69.12 + * This file may be redistributed under the terms of the GNU Library
69.13 + * General Public License, version 2.
69.14 + * %End-Header%
69.15 + */
69.16 +
69.17 +/*
69.18 + * History:
69.19 + * 93/10/30 - Creation
69.20 + */
69.21 +
69.22 +#ifndef _LARGEFILE_SOURCE
69.23 +#define _LARGEFILE_SOURCE
69.24 +#endif
69.25 +#ifndef _LARGEFILE64_SOURCE
69.26 +#define _LARGEFILE64_SOURCE
69.27 +#endif
69.28 +
69.29 +#include "config.h"
69.30 +#if HAVE_ERRNO_H
69.31 +#include <errno.h>
69.32 +#endif
69.33 +#if HAVE_UNISTD_H
69.34 +#include <unistd.h>
69.35 +#endif
69.36 +#include <sys/types.h>
69.37 +#include <sys/stat.h>
69.38 +#if HAVE_EXT2_IOCTLS
69.39 +#include <fcntl.h>
69.40 +#include <sys/ioctl.h>
69.41 +#endif
69.42 +
69.43 +#include "e2p.h"
69.44 +
69.45 +#ifdef O_LARGEFILE
69.46 +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
69.47 +#else
69.48 +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
69.49 +#endif
69.50 +
69.51 +int fgetflags (const char * name, unsigned long * flags)
69.52 +{
69.53 + struct stat buf;
69.54 +#if HAVE_STAT_FLAGS && !(APPLE_DARWIN && HAVE_EXT2_IOCTLS)
69.55 +
69.56 + if (stat (name, &buf) == -1)
69.57 + return -1;
69.58 +
69.59 + *flags = 0;
69.60 +#ifdef UF_IMMUTABLE
69.61 + if (buf.st_flags & UF_IMMUTABLE)
69.62 + *flags |= EXT2_IMMUTABLE_FL;
69.63 +#endif
69.64 +#ifdef UF_APPEND
69.65 + if (buf.st_flags & UF_APPEND)
69.66 + *flags |= EXT2_APPEND_FL;
69.67 +#endif
69.68 +#ifdef UF_NODUMP
69.69 + if (buf.st_flags & UF_NODUMP)
69.70 + *flags |= EXT2_NODUMP_FL;
69.71 +#endif
69.72 +
69.73 + return 0;
69.74 +#else /* !HAVE_STAT_FLAGS || (APPLE_DARWIN && HAVE_EXT2_IOCTLS) */
69.75 +#if HAVE_EXT2_IOCTLS
69.76 + int fd, r, f, save_errno = 0;
69.77 +
69.78 + if (!lstat(name, &buf) &&
69.79 + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
69.80 + goto notsupp;
69.81 + }
69.82 +#if !APPLE_DARWIN
69.83 + fd = open (name, OPEN_FLAGS);
69.84 + if (fd == -1)
69.85 + return -1;
69.86 + r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
69.87 + if (r == -1)
69.88 + save_errno = errno;
69.89 + *flags = f;
69.90 + close (fd);
69.91 + if (save_errno)
69.92 + errno = save_errno;
69.93 + return r;
69.94 +#else /* APPLE_DARWIN */
69.95 + f = -1;
69.96 + save_errno = syscall(SYS_fsctl, name, EXT2_IOC_GETFLAGS, &f, 0);
69.97 + *flags = f;
69.98 + return (save_errno);
69.99 +#endif /* !APPLE_DARWIN */
69.100 +notsupp:
69.101 +#endif /* HAVE_EXT2_IOCTLS */
69.102 +#endif
69.103 + errno = EOPNOTSUPP;
69.104 + return -1;
69.105 +}
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
70.2 +++ b/libext2fs/lib/libe2p/fgetproject.c Wed Aug 25 01:28:08 2021 +0200
70.3 @@ -0,0 +1,63 @@
70.4 +/*
70.5 + * fgetproject.c --- get project id
70.6 + *
70.7 + * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
70.8 + *
70.9 + * %Begin-Header%
70.10 + * This file may be redistributed under the terms of the GNU Library
70.11 + * General Public License, version 2.
70.12 + * %End-Header%
70.13 + */
70.14 +
70.15 +#ifndef _LARGEFILE_SOURCE
70.16 +#define _LARGEFILE_SOURCE
70.17 +#endif
70.18 +#ifndef _LARGEFILE64_SOURCE
70.19 +#define _LARGEFILE64_SOURCE
70.20 +#endif
70.21 +
70.22 +#include "config.h"
70.23 +#if HAVE_ERRNO_H
70.24 +#include <errno.h>
70.25 +#endif
70.26 +#if HAVE_UNISTD_H
70.27 +#include <unistd.h>
70.28 +#endif
70.29 +#include <sys/types.h>
70.30 +#include <sys/stat.h>
70.31 +#if HAVE_EXT2_IOCTLS
70.32 +#include <fcntl.h>
70.33 +#include <sys/ioctl.h>
70.34 +#include "project.h"
70.35 +#endif
70.36 +
70.37 +#include "e2p.h"
70.38 +
70.39 +#ifdef O_LARGEFILE
70.40 +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
70.41 +#else
70.42 +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
70.43 +#endif
70.44 +
70.45 +int fgetproject(const char *name, unsigned long *project)
70.46 +{
70.47 +#ifndef FS_IOC_FSGETXATTR
70.48 + errno = EOPNOTSUPP;
70.49 + return -1;
70.50 +#else
70.51 + int fd, r, save_errno = 0;
70.52 + struct fsxattr fsx;
70.53 +
70.54 + fd = open (name, OPEN_FLAGS);
70.55 + if (fd == -1)
70.56 + return -1;
70.57 + r = ioctl (fd, FS_IOC_FSGETXATTR, &fsx);
70.58 + if (r == 0)
70.59 + *project = fsx.fsx_projid;
70.60 + save_errno = errno;
70.61 + close (fd);
70.62 + if (save_errno)
70.63 + errno = save_errno;
70.64 + return r;
70.65 +#endif
70.66 +}
71.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
71.2 +++ b/libext2fs/lib/libe2p/fgetversion.c Wed Aug 25 01:28:08 2021 +0200
71.3 @@ -0,0 +1,76 @@
71.4 +/*
71.5 + * fgetversion.c - Get a file version on an ext2 file system
71.6 + *
71.7 + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
71.8 + * Laboratoire MASI, Institut Blaise Pascal
71.9 + * Universite Pierre et Marie Curie (Paris VI)
71.10 + *
71.11 + * %Begin-Header%
71.12 + * This file may be redistributed under the terms of the GNU Library
71.13 + * General Public License, version 2.
71.14 + * %End-Header%
71.15 + */
71.16 +
71.17 +/*
71.18 + * History:
71.19 + * 93/10/30 - Creation
71.20 + */
71.21 +
71.22 +#ifndef _LARGEFILE_SOURCE
71.23 +#define _LARGEFILE_SOURCE
71.24 +#endif
71.25 +#ifndef _LARGEFILE64_SOURCE
71.26 +#define _LARGEFILE64_SOURCE
71.27 +#endif
71.28 +
71.29 +#include "config.h"
71.30 +#if HAVE_ERRNO_H
71.31 +#include <errno.h>
71.32 +#endif
71.33 +#if HAVE_UNISTD_H
71.34 +#include <unistd.h>
71.35 +#endif
71.36 +#include <fcntl.h>
71.37 +#if HAVE_SYS_IOCTL_H
71.38 +#include <sys/ioctl.h>
71.39 +#endif
71.40 +
71.41 +#include "e2p.h"
71.42 +
71.43 +#ifdef O_LARGEFILE
71.44 +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
71.45 +#else
71.46 +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
71.47 +#endif
71.48 +
71.49 +int fgetversion(const char *name, unsigned long *version)
71.50 +{
71.51 + unsigned int ver = -1;
71.52 + int rc = -1;
71.53 +#if HAVE_EXT2_IOCTLS
71.54 +# if !APPLE_DARWIN
71.55 + int fd, save_errno = 0;
71.56 +
71.57 + fd = open(name, OPEN_FLAGS);
71.58 + if (fd == -1)
71.59 + return -1;
71.60 +
71.61 + rc = ioctl(fd, EXT2_IOC_GETVERSION, &ver);
71.62 + if (rc == -1)
71.63 + save_errno = errno;
71.64 + close(fd);
71.65 + if (rc == -1)
71.66 + errno = save_errno;
71.67 +# else /* APPLE_DARWIN */
71.68 + rc = syscall(SYS_fsctl, name, EXT2_IOC_GETVERSION, &ver, 0);
71.69 +# endif /* !APPLE_DARWIN */
71.70 +#else /* ! HAVE_EXT2_IOCTLS */
71.71 + extern int errno;
71.72 +
71.73 + errno = EOPNOTSUPP;
71.74 +#endif /* ! HAVE_EXT2_IOCTLS */
71.75 + if (rc == 0)
71.76 + *version = ver;
71.77 +
71.78 + return rc;
71.79 +}
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
72.2 +++ b/libext2fs/lib/libe2p/fsetflags.c Wed Aug 25 01:28:08 2021 +0200
72.3 @@ -0,0 +1,107 @@
72.4 +/*
72.5 + * fsetflags.c - Set a file flags on an ext2 file system
72.6 + *
72.7 + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
72.8 + * Laboratoire MASI, Institut Blaise Pascal
72.9 + * Universite Pierre et Marie Curie (Paris VI)
72.10 + *
72.11 + * %Begin-Header%
72.12 + * This file may be redistributed under the terms of the GNU Library
72.13 + * General Public License, version 2.
72.14 + * %End-Header%
72.15 + */
72.16 +
72.17 +/*
72.18 + * History:
72.19 + * 93/10/30 - Creation
72.20 + */
72.21 +
72.22 +#ifndef _LARGEFILE_SOURCE
72.23 +#define _LARGEFILE_SOURCE
72.24 +#endif
72.25 +#ifndef _LARGEFILE64_SOURCE
72.26 +#define _LARGEFILE64_SOURCE
72.27 +#endif
72.28 +
72.29 +#include "config.h"
72.30 +#if HAVE_ERRNO_H
72.31 +#include <errno.h>
72.32 +#endif
72.33 +#if HAVE_UNISTD_H
72.34 +#include <unistd.h>
72.35 +#endif
72.36 +#include <sys/types.h>
72.37 +#include <sys/stat.h>
72.38 +#if HAVE_EXT2_IOCTLS
72.39 +#include <fcntl.h>
72.40 +#include <sys/ioctl.h>
72.41 +#endif
72.42 +
72.43 +#include "e2p.h"
72.44 +
72.45 +/*
72.46 + * Deal with lame glibc's that define this function without actually
72.47 + * implementing it. Can you say "attractive nuisance", boys and girls?
72.48 + * I knew you could!
72.49 + */
72.50 +#ifdef __linux__
72.51 +#undef HAVE_CHFLAGS
72.52 +#endif
72.53 +
72.54 +#ifdef O_LARGEFILE
72.55 +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
72.56 +#else
72.57 +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
72.58 +#endif
72.59 +
72.60 +int fsetflags (const char * name, unsigned long flags)
72.61 +{
72.62 +#if HAVE_CHFLAGS && !(APPLE_DARWIN && HAVE_EXT2_IOCTLS)
72.63 + unsigned long bsd_flags = 0;
72.64 +
72.65 +#ifdef UF_IMMUTABLE
72.66 + if (flags & EXT2_IMMUTABLE_FL)
72.67 + bsd_flags |= UF_IMMUTABLE;
72.68 +#endif
72.69 +#ifdef UF_APPEND
72.70 + if (flags & EXT2_APPEND_FL)
72.71 + bsd_flags |= UF_APPEND;
72.72 +#endif
72.73 +#ifdef UF_NODUMP
72.74 + if (flags & EXT2_NODUMP_FL)
72.75 + bsd_flags |= UF_NODUMP;
72.76 +#endif
72.77 +
72.78 + return chflags (name, bsd_flags);
72.79 +#else /* !HAVE_CHFLAGS || (APPLE_DARWIN && HAVE_EXT2_IOCTLS) */
72.80 +#if HAVE_EXT2_IOCTLS
72.81 + int fd, r, f, save_errno = 0;
72.82 + struct stat buf;
72.83 +
72.84 + if (!lstat(name, &buf) &&
72.85 + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
72.86 + goto notsupp;
72.87 + }
72.88 +#if !APPLE_DARWIN
72.89 + fd = open (name, OPEN_FLAGS);
72.90 + if (fd == -1)
72.91 + return -1;
72.92 + f = (int) flags;
72.93 + r = ioctl (fd, EXT2_IOC_SETFLAGS, &f);
72.94 + if (r == -1)
72.95 + save_errno = errno;
72.96 + close (fd);
72.97 + if (save_errno)
72.98 + errno = save_errno;
72.99 +#else /* APPLE_DARWIN */
72.100 + f = (int) flags;
72.101 + return syscall(SYS_fsctl, name, EXT2_IOC_SETFLAGS, &f, 0);
72.102 +#endif /* !APPLE_DARWIN */
72.103 + return r;
72.104 +
72.105 +notsupp:
72.106 +#endif /* HAVE_EXT2_IOCTLS */
72.107 +#endif
72.108 + errno = EOPNOTSUPP;
72.109 + return -1;
72.110 +}
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
73.2 +++ b/libext2fs/lib/libe2p/fsetproject.c Wed Aug 25 01:28:08 2021 +0200
73.3 @@ -0,0 +1,69 @@
73.4 +/*
73.5 + * fgetproject.c --- get project id
73.6 + *
73.7 + * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
73.8 + *
73.9 + * %Begin-Header%
73.10 + * This file may be redistributed under the terms of the GNU Library
73.11 + * General Public License, version 2.
73.12 + * %End-Header%
73.13 + */
73.14 +
73.15 +#ifndef _LARGEFILE_SOURCE
73.16 +#define _LARGEFILE_SOURCE
73.17 +#endif
73.18 +#ifndef _LARGEFILE64_SOURCE
73.19 +#define _LARGEFILE64_SOURCE
73.20 +#endif
73.21 +
73.22 +#include "config.h"
73.23 +#if HAVE_ERRNO_H
73.24 +#include <errno.h>
73.25 +#endif
73.26 +#if HAVE_UNISTD_H
73.27 +#include <unistd.h>
73.28 +#endif
73.29 +#include <sys/types.h>
73.30 +#include <sys/stat.h>
73.31 +#if HAVE_EXT2_IOCTLS
73.32 +#include <fcntl.h>
73.33 +#include <sys/ioctl.h>
73.34 +#include "project.h"
73.35 +#endif
73.36 +
73.37 +#include "e2p.h"
73.38 +
73.39 +#ifdef O_LARGEFILE
73.40 +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
73.41 +#else
73.42 +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
73.43 +#endif
73.44 +
73.45 +int fsetproject(const char *name, unsigned long project)
73.46 +{
73.47 +#ifndef FS_IOC_FSGETXATTR
73.48 + errno = EOPNOTSUPP;
73.49 + return -1;
73.50 +#else
73.51 + int fd, r, save_errno = 0;
73.52 + struct fsxattr fsx;
73.53 +
73.54 + fd = open (name, OPEN_FLAGS);
73.55 + if (fd == -1)
73.56 + return -1;
73.57 + r = ioctl (fd, FS_IOC_FSGETXATTR, &fsx);
73.58 + if (r == -1) {
73.59 + save_errno = errno;
73.60 + goto errout;
73.61 + }
73.62 + fsx.fsx_projid = project;
73.63 + r = ioctl (fd, FS_IOC_FSSETXATTR, &fsx);
73.64 + if (r == -1)
73.65 + save_errno = errno;
73.66 +errout:
73.67 + close (fd);
73.68 + if (save_errno)
73.69 + errno = save_errno;
73.70 + return r;
73.71 +#endif
73.72 +}
74.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
74.2 +++ b/libext2fs/lib/libe2p/fsetversion.c Wed Aug 25 01:28:08 2021 +0200
74.3 @@ -0,0 +1,72 @@
74.4 +/*
74.5 + * fsetversion.c - Set a file version on an ext2 file system
74.6 + *
74.7 + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
74.8 + * Laboratoire MASI, Institut Blaise Pascal
74.9 + * Universite Pierre et Marie Curie (Paris VI)
74.10 + *
74.11 + * %Begin-Header%
74.12 + * This file may be redistributed under the terms of the GNU Library
74.13 + * General Public License, version 2.
74.14 + * %End-Header%
74.15 + */
74.16 +
74.17 +/*
74.18 + * History:
74.19 + * 93/10/30 - Creation
74.20 + */
74.21 +
74.22 +#ifndef _LARGEFILE_SOURCE
74.23 +#define _LARGEFILE_SOURCE
74.24 +#endif
74.25 +#ifndef _LARGEFILE64_SOURCE
74.26 +#define _LARGEFILE64_SOURCE
74.27 +#endif
74.28 +
74.29 +#include "config.h"
74.30 +#if HAVE_ERRNO_H
74.31 +#include <errno.h>
74.32 +#endif
74.33 +#if HAVE_UNISTD_H
74.34 +#include <unistd.h>
74.35 +#endif
74.36 +#include <fcntl.h>
74.37 +#if HAVE_SYS_IOCTL_H
74.38 +#include <sys/ioctl.h>
74.39 +#endif
74.40 +
74.41 +#include "e2p.h"
74.42 +
74.43 +#ifdef O_LARGEFILE
74.44 +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
74.45 +#else
74.46 +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
74.47 +#endif
74.48 +
74.49 +int fsetversion (const char * name, unsigned long version)
74.50 +{
74.51 +#if HAVE_EXT2_IOCTLS
74.52 +#if !APPLE_DARWIN
74.53 + int fd, r, ver, save_errno = 0;
74.54 +
74.55 + fd = open (name, OPEN_FLAGS);
74.56 + if (fd == -1)
74.57 + return -1;
74.58 + ver = (int) version;
74.59 + r = ioctl (fd, EXT2_IOC_SETVERSION, &ver);
74.60 + if (r == -1)
74.61 + save_errno = errno;
74.62 + close (fd);
74.63 + if (save_errno)
74.64 + errno = save_errno;
74.65 + return r;
74.66 +#else
74.67 + int ver = (int)version;
74.68 + return syscall(SYS_fsctl, name, EXT2_IOC_SETVERSION, &ver, 0);
74.69 +#endif
74.70 +#else /* ! HAVE_EXT2_IOCTLS */
74.71 + extern int errno;
74.72 + errno = EOPNOTSUPP;
74.73 + return -1;
74.74 +#endif /* ! HAVE_EXT2_IOCTLS */
74.75 +}
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
75.2 +++ b/libext2fs/lib/libe2p/getflags.c Wed Aug 25 01:28:08 2021 +0200
75.3 @@ -0,0 +1,70 @@
75.4 +/*
75.5 + * getflags.c - Get a file flags on an ext2 file system
75.6 + *
75.7 + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
75.8 + * Laboratoire MASI, Institut Blaise Pascal
75.9 + * Universite Pierre et Marie Curie (Paris VI)
75.10 + *
75.11 + * %Begin-Header%
75.12 + * This file may be redistributed under the terms of the GNU Library
75.13 + * General Public License, version 2.
75.14 + * %End-Header%
75.15 + */
75.16 +
75.17 +/*
75.18 + * History:
75.19 + * 93/10/30 - Creation
75.20 + */
75.21 +
75.22 +#include "config.h"
75.23 +#if HAVE_ERRNO_H
75.24 +#include <errno.h>
75.25 +#endif
75.26 +#include <sys/types.h>
75.27 +#include <sys/stat.h>
75.28 +#if HAVE_EXT2_IOCTLS
75.29 +#include <sys/ioctl.h>
75.30 +#endif
75.31 +
75.32 +#include "e2p.h"
75.33 +
75.34 +int getflags (int fd, unsigned long * flags)
75.35 +{
75.36 + struct stat buf;
75.37 +#if HAVE_STAT_FLAGS
75.38 +
75.39 + if (fstat (fd, &buf) == -1)
75.40 + return -1;
75.41 +
75.42 + *flags = 0;
75.43 +#ifdef UF_IMMUTABLE
75.44 + if (buf.st_flags & UF_IMMUTABLE)
75.45 + *flags |= EXT2_IMMUTABLE_FL;
75.46 +#endif
75.47 +#ifdef UF_APPEND
75.48 + if (buf.st_flags & UF_APPEND)
75.49 + *flags |= EXT2_APPEND_FL;
75.50 +#endif
75.51 +#ifdef UF_NODUMP
75.52 + if (buf.st_flags & UF_NODUMP)
75.53 + *flags |= EXT2_NODUMP_FL;
75.54 +#endif
75.55 +
75.56 + return 0;
75.57 +#else
75.58 +#if HAVE_EXT2_IOCTLS
75.59 + int r, f;
75.60 +
75.61 + if (!fstat(fd, &buf) &&
75.62 + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode))
75.63 + goto notsupp;
75.64 + r = ioctl(fd, EXT2_IOC_GETFLAGS, &f);
75.65 + *flags = f;
75.66 +
75.67 + return r;
75.68 +notsupp:
75.69 +#endif /* HAVE_EXT2_IOCTLS */
75.70 +#endif
75.71 + errno = EOPNOTSUPP;
75.72 + return -1;
75.73 +}
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
76.2 +++ b/libext2fs/lib/libe2p/getversion.c Wed Aug 25 01:28:08 2021 +0200
76.3 @@ -0,0 +1,42 @@
76.4 +/*
76.5 + * getversion.c - Get a file version on an ext2 file system
76.6 + *
76.7 + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
76.8 + * Laboratoire MASI, Institut Blaise Pascal
76.9 + * Universite Pierre et Marie Curie (Paris VI)
76.10 + *
76.11 + * %Begin-Header%
76.12 + * This file may be redistributed under the terms of the GNU Library
76.13 + * General Public License, version 2.
76.14 + * %End-Header%
76.15 + */
76.16 +
76.17 +/*
76.18 + * History:
76.19 + * 93/10/30 - Creation
76.20 + */
76.21 +
76.22 +#include "config.h"
76.23 +#if HAVE_ERRNO_H
76.24 +#include <errno.h>
76.25 +#endif
76.26 +#if HAVE_SYS_IOCTL_H
76.27 +#include <sys/ioctl.h>
76.28 +#endif
76.29 +
76.30 +#include "e2p.h"
76.31 +
76.32 +int getversion (int fd, unsigned long * version)
76.33 +{
76.34 +#if HAVE_EXT2_IOCTLS
76.35 + int r, ver;
76.36 +
76.37 + r = ioctl (fd, EXT2_IOC_GETVERSION, &ver);
76.38 + *version = ver;
76.39 + return r;
76.40 +#else /* ! HAVE_EXT2_IOCTLS */
76.41 + extern int errno;
76.42 + errno = EOPNOTSUPP;
76.43 + return -1;
76.44 +#endif /* ! HAVE_EXT2_IOCTLS */
76.45 +}
77.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
77.2 +++ b/libext2fs/lib/libe2p/hashstr.c Wed Aug 25 01:28:08 2021 +0200
77.3 @@ -0,0 +1,72 @@
77.4 +/*
77.5 + * feature.c --- convert between features and strings
77.6 + *
77.7 + * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
77.8 + *
77.9 + * %Begin-Header%
77.10 + * This file may be redistributed under the terms of the GNU Library
77.11 + * General Public License, version 2.
77.12 + * %End-Header%
77.13 + */
77.14 +
77.15 +#include "config.h"
77.16 +#include <stdio.h>
77.17 +#include <stdlib.h>
77.18 +#include <string.h>
77.19 +#include <ctype.h>
77.20 +#include <errno.h>
77.21 +
77.22 +#include "e2p.h"
77.23 +
77.24 +struct hash {
77.25 + int num;
77.26 + const char *string;
77.27 +};
77.28 +
77.29 +static struct hash hash_list[] = {
77.30 + { EXT2_HASH_LEGACY, "legacy" },
77.31 + { EXT2_HASH_HALF_MD4, "half_md4" },
77.32 + { EXT2_HASH_TEA, "tea" },
77.33 + { 0, 0 },
77.34 +};
77.35 +
77.36 +const char *e2p_hash2string(int num)
77.37 +{
77.38 + struct hash *p;
77.39 + static char buf[20];
77.40 +
77.41 + for (p = hash_list; p->string; p++) {
77.42 + if (num == p->num)
77.43 + return p->string;
77.44 + }
77.45 + sprintf(buf, "HASHALG_%d", num);
77.46 + return buf;
77.47 +}
77.48 +
77.49 +/*
77.50 + * Returns the hash algorithm, or -1 on error
77.51 + */
77.52 +int e2p_string2hash(char *string)
77.53 +{
77.54 + struct hash *p;
77.55 + char *eptr;
77.56 + int num;
77.57 +
77.58 + for (p = hash_list; p->string; p++) {
77.59 + if (!strcasecmp(string, p->string)) {
77.60 + return p->num;
77.61 + }
77.62 + }
77.63 + if (strncasecmp(string, "HASHALG_", 8))
77.64 + return -1;
77.65 +
77.66 + if (string[8] == 0)
77.67 + return -1;
77.68 + num = strtol(string+8, &eptr, 10);
77.69 + if (num > 255 || num < 0)
77.70 + return -1;
77.71 + if (*eptr)
77.72 + return -1;
77.73 + return num;
77.74 +}
77.75 +
78.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
78.2 +++ b/libext2fs/lib/libe2p/iod.c Wed Aug 25 01:28:08 2021 +0200
78.3 @@ -0,0 +1,76 @@
78.4 +/*
78.5 + * iod.c - Iterate a function on each entry of a directory
78.6 + *
78.7 + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
78.8 + * Laboratoire MASI, Institut Blaise Pascal
78.9 + * Universite Pierre et Marie Curie (Paris VI)
78.10 + *
78.11 + * %Begin-Header%
78.12 + * This file may be redistributed under the terms of the GNU Library
78.13 + * General Public License, version 2.
78.14 + * %End-Header%
78.15 + */
78.16 +
78.17 +/*
78.18 + * History:
78.19 + * 93/10/30 - Creation
78.20 + */
78.21 +
78.22 +#include "config.h"
78.23 +#include "e2p.h"
78.24 +#if HAVE_UNISTD_H
78.25 +#include <unistd.h>
78.26 +#endif
78.27 +#include <stdlib.h>
78.28 +#include <string.h>
78.29 +
78.30 +int iterate_on_dir (const char * dir_name,
78.31 + int (*func) (const char *, struct dirent *, void *),
78.32 + void * private)
78.33 +{
78.34 + DIR * dir;
78.35 + struct dirent *de, *dep;
78.36 + int max_len = -1, len, ret = 0;
78.37 +
78.38 +#if HAVE_PATHCONF && defined(_PC_NAME_MAX)
78.39 + max_len = pathconf(dir_name, _PC_NAME_MAX);
78.40 +#endif
78.41 + if (max_len == -1) {
78.42 +#ifdef _POSIX_NAME_MAX
78.43 + max_len = _POSIX_NAME_MAX;
78.44 +#else
78.45 +#ifdef NAME_MAX
78.46 + max_len = NAME_MAX;
78.47 +#else
78.48 + max_len = 256;
78.49 +#endif /* NAME_MAX */
78.50 +#endif /* _POSIX_NAME_MAX */
78.51 + }
78.52 + max_len += sizeof(struct dirent);
78.53 +
78.54 + de = malloc(max_len+1);
78.55 + if (!de)
78.56 + return -1;
78.57 + memset(de, 0, max_len+1);
78.58 +
78.59 + dir = opendir (dir_name);
78.60 + if (dir == NULL) {
78.61 + free(de);
78.62 + return -1;
78.63 + }
78.64 + while ((dep = readdir (dir))) {
78.65 +#ifdef HAVE_RECLEN_DIRENT
78.66 + len = dep->d_reclen;
78.67 + if (len > max_len)
78.68 + len = max_len;
78.69 +#else
78.70 + len = sizeof(struct dirent);
78.71 +#endif
78.72 + memcpy(de, dep, len);
78.73 + if ((*func)(dir_name, de, private))
78.74 + ret++;
78.75 + }
78.76 + free(de);
78.77 + closedir(dir);
78.78 + return ret;
78.79 +}
79.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
79.2 +++ b/libext2fs/lib/libe2p/ljs.c Wed Aug 25 01:28:08 2021 +0200
79.3 @@ -0,0 +1,113 @@
79.4 +/*
79.5 + * ljs.c - List the contents of an journal superblock
79.6 + *
79.7 + * Copyright (C) 1995, 1996, 1997 Theodore Ts'o <tytso@mit.edu>
79.8 + *
79.9 + * %Begin-Header%
79.10 + * This file may be redistributed under the terms of the GNU Library
79.11 + * General Public License, version 2.
79.12 + * %End-Header%
79.13 + */
79.14 +
79.15 +
79.16 +#include "config.h"
79.17 +#include <stdio.h>
79.18 +#include <stdlib.h>
79.19 +#include <sys/types.h>
79.20 +#include <string.h>
79.21 +#include <grp.h>
79.22 +#include <pwd.h>
79.23 +#include <time.h>
79.24 +
79.25 +#include "ext2fs/ext2_fs.h"
79.26 +#include "ext2fs/ext2fs.h"
79.27 +#include "e2p.h"
79.28 +#include "ext2fs/kernel-jbd.h"
79.29 +
79.30 +#ifdef WORDS_BIGENDIAN
79.31 +#define e2p_be32(x) (x)
79.32 +#else
79.33 +static __u32 e2p_swab32(__u32 val)
79.34 +{
79.35 + return ((val>>24) | ((val>>8)&0xFF00) |
79.36 + ((val<<8)&0xFF0000) | (val<<24));
79.37 +}
79.38 +
79.39 +#define e2p_be32(x) e2p_swab32(x)
79.40 +#endif
79.41 +
79.42 +static const char *journal_checksum_type_str(__u8 type)
79.43 +{
79.44 + switch (type) {
79.45 + case JBD2_CRC32C_CHKSUM:
79.46 + return "crc32c";
79.47 + default:
79.48 + return "unknown";
79.49 + }
79.50 +}
79.51 +
79.52 +void e2p_list_journal_super(FILE *f, char *journal_sb_buf,
79.53 + int exp_block_size, int flags)
79.54 +{
79.55 + journal_superblock_t *jsb = (journal_superblock_t *) journal_sb_buf;
79.56 + __u32 *mask_ptr, mask, m;
79.57 + unsigned int size;
79.58 + int j, printed = 0;
79.59 + unsigned int i, nr_users;
79.60 +
79.61 + fprintf(f, "%s", "Journal features: ");
79.62 + for (i=0, mask_ptr=&jsb->s_feature_compat; i <3; i++,mask_ptr++) {
79.63 + mask = e2p_be32(*mask_ptr);
79.64 + for (j=0,m=1; j < 32; j++, m<<=1) {
79.65 + if (mask & m) {
79.66 + fprintf(f, " %s", e2p_jrnl_feature2string(i, m));
79.67 + printed++;
79.68 + }
79.69 + }
79.70 + }
79.71 + if (printed == 0)
79.72 + fprintf(f, " (none)");
79.73 + fputc('\n', f);
79.74 + fputs("Journal size: ", f);
79.75 + size = (ntohl(jsb->s_blocksize) / 1024) * ntohl(jsb->s_maxlen);
79.76 + if (size < 8192)
79.77 + fprintf(f, "%uk\n", size);
79.78 + else
79.79 + fprintf(f, "%uM\n", size >> 10);
79.80 + nr_users = (unsigned int) ntohl(jsb->s_nr_users);
79.81 + if (exp_block_size != (int) ntohl(jsb->s_blocksize))
79.82 + fprintf(f, "Journal block size: %u\n",
79.83 + (unsigned int)ntohl(jsb->s_blocksize));
79.84 + fprintf(f, "Journal length: %u\n",
79.85 + (unsigned int)ntohl(jsb->s_maxlen));
79.86 + if (ntohl(jsb->s_first) != 1)
79.87 + fprintf(f, "Journal first block: %u\n",
79.88 + (unsigned int)ntohl(jsb->s_first));
79.89 + fprintf(f, "Journal sequence: 0x%08x\n"
79.90 + "Journal start: %u\n",
79.91 + (unsigned int)ntohl(jsb->s_sequence),
79.92 + (unsigned int)ntohl(jsb->s_start));
79.93 + if (nr_users != 1)
79.94 + fprintf(f, "Journal number of users: %u\n", nr_users);
79.95 + if (jsb->s_feature_compat & e2p_be32(JFS_FEATURE_COMPAT_CHECKSUM))
79.96 + fprintf(f, "%s", "Journal checksum type: crc32\n");
79.97 + if ((jsb->s_feature_incompat &
79.98 + e2p_be32(JFS_FEATURE_INCOMPAT_CSUM_V3)) ||
79.99 + (jsb->s_feature_incompat &
79.100 + e2p_be32(JFS_FEATURE_INCOMPAT_CSUM_V2)))
79.101 + fprintf(f, "Journal checksum type: %s\n"
79.102 + "Journal checksum: 0x%08x\n",
79.103 + journal_checksum_type_str(jsb->s_checksum_type),
79.104 + e2p_be32(jsb->s_checksum));
79.105 + if ((nr_users > 1) ||
79.106 + !e2p_is_null_uuid(&jsb->s_users[0])) {
79.107 + for (i=0; i < nr_users && i < JFS_USERS_MAX; i++) {
79.108 + printf(i ? " %s\n"
79.109 + : "Journal users: %s\n",
79.110 + e2p_uuid2str(&jsb->s_users[i * UUID_SIZE]));
79.111 + }
79.112 + }
79.113 + if (jsb->s_errno != 0)
79.114 + fprintf(f, "Journal errno: %d\n",
79.115 + (int) ntohl(jsb->s_errno));
79.116 +}
80.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
80.2 +++ b/libext2fs/lib/libe2p/ls.c Wed Aug 25 01:28:08 2021 +0200
80.3 @@ -0,0 +1,479 @@
80.4 +/*
80.5 + * ls.c - List the contents of an ext2fs superblock
80.6 + *
80.7 + * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
80.8 + * Laboratoire MASI, Institut Blaise Pascal
80.9 + * Universite Pierre et Marie Curie (Paris VI)
80.10 + *
80.11 + * Copyright (C) 1995, 1996, 1997 Theodore Ts'o <tytso@mit.edu>
80.12 + *
80.13 + * %Begin-Header%
80.14 + * This file may be redistributed under the terms of the GNU Library
80.15 + * General Public License, version 2.
80.16 + * %End-Header%
80.17 + */
80.18 +
80.19 +#include "config.h"
80.20 +#include <stdio.h>
80.21 +#include <stdlib.h>
80.22 +#include <sys/types.h>
80.23 +#include <string.h>
80.24 +#include <grp.h>
80.25 +#include <pwd.h>
80.26 +#include <time.h>
80.27 +
80.28 +#include "e2p.h"
80.29 +#include "support/quotaio.h"
80.30 +
80.31 +static void print_user (unsigned short uid, FILE *f)
80.32 +{
80.33 + struct passwd *pw;
80.34 +
80.35 + fprintf(f, "%u ", uid);
80.36 + pw = getpwuid (uid);
80.37 + if (pw == NULL)
80.38 + fprintf(f, "(user unknown)\n");
80.39 + else
80.40 + fprintf(f, "(user %s)\n", pw->pw_name);
80.41 +}
80.42 +
80.43 +static void print_group (unsigned short gid, FILE *f)
80.44 +{
80.45 + struct group *gr;
80.46 +
80.47 + fprintf(f, "%u ", gid);
80.48 + gr = getgrgid (gid);
80.49 + if (gr == NULL)
80.50 + fprintf(f, "(group unknown)\n");
80.51 + else
80.52 + fprintf(f, "(group %s)\n", gr->gr_name);
80.53 +}
80.54 +
80.55 +#define MONTH_INT (86400 * 30)
80.56 +#define WEEK_INT (86400 * 7)
80.57 +#define DAY_INT (86400)
80.58 +#define HOUR_INT (60 * 60)
80.59 +#define MINUTE_INT (60)
80.60 +
80.61 +static const char *interval_string(unsigned int secs)
80.62 +{
80.63 + static char buf[256], tmp[80];
80.64 + int hr, min, num;
80.65 +
80.66 + buf[0] = 0;
80.67 +
80.68 + if (secs == 0)
80.69 + return "<none>";
80.70 +
80.71 + if (secs >= MONTH_INT) {
80.72 + num = secs / MONTH_INT;
80.73 + secs -= num*MONTH_INT;
80.74 + sprintf(buf, "%d month%s", num, (num>1) ? "s" : "");
80.75 + }
80.76 + if (secs >= WEEK_INT) {
80.77 + num = secs / WEEK_INT;
80.78 + secs -= num*WEEK_INT;
80.79 + sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "",
80.80 + num, (num>1) ? "s" : "");
80.81 + strcat(buf, tmp);
80.82 + }
80.83 + if (secs >= DAY_INT) {
80.84 + num = secs / DAY_INT;
80.85 + secs -= num*DAY_INT;
80.86 + sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "",
80.87 + num, (num>1) ? "s" : "");
80.88 + strcat(buf, tmp);
80.89 + }
80.90 + if (secs > 0) {
80.91 + hr = secs / HOUR_INT;
80.92 + secs -= hr*HOUR_INT;
80.93 + min = secs / MINUTE_INT;
80.94 + secs -= min*MINUTE_INT;
80.95 + sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "",
80.96 + hr, min, secs);
80.97 + strcat(buf, tmp);
80.98 + }
80.99 + return buf;
80.100 +}
80.101 +
80.102 +static void print_features(struct ext2_super_block * s, FILE *f)
80.103 +{
80.104 +#ifdef EXT2_DYNAMIC_REV
80.105 + int i, j, printed=0;
80.106 + __u32 *mask = &s->s_feature_compat, m;
80.107 +
80.108 + fprintf(f, "Filesystem features: ");
80.109 + for (i=0; i <3; i++,mask++) {
80.110 + for (j=0,m=1; j < 32; j++, m<<=1) {
80.111 + if (*mask & m) {
80.112 + fprintf(f, " %s", e2p_feature2string(i, m));
80.113 + printed++;
80.114 + }
80.115 + }
80.116 + }
80.117 + if (printed == 0)
80.118 + fprintf(f, " (none)");
80.119 + fprintf(f, "\n");
80.120 +#endif
80.121 +}
80.122 +
80.123 +static void print_mntopts(struct ext2_super_block * s, FILE *f)
80.124 +{
80.125 +#ifdef EXT2_DYNAMIC_REV
80.126 + int i, printed=0;
80.127 + __u32 mask = s->s_default_mount_opts, m;
80.128 +
80.129 + fprintf(f, "Default mount options: ");
80.130 + if (mask & EXT3_DEFM_JMODE) {
80.131 + fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE));
80.132 + printed++;
80.133 + }
80.134 + for (i=0,m=1; i < 32; i++, m<<=1) {
80.135 + if (m & EXT3_DEFM_JMODE)
80.136 + continue;
80.137 + if (mask & m) {
80.138 + fprintf(f, " %s", e2p_mntopt2string(m));
80.139 + printed++;
80.140 + }
80.141 + }
80.142 + if (printed == 0)
80.143 + fprintf(f, " (none)");
80.144 + fprintf(f, "\n");
80.145 +#endif
80.146 +}
80.147 +
80.148 +static void print_super_flags(struct ext2_super_block * s, FILE *f)
80.149 +{
80.150 + int flags_found = 0;
80.151 +
80.152 + if (s->s_flags == 0)
80.153 + return;
80.154 +
80.155 + fputs("Filesystem flags: ", f);
80.156 + if (s->s_flags & EXT2_FLAGS_SIGNED_HASH) {
80.157 + fputs("signed_directory_hash ", f);
80.158 + flags_found++;
80.159 + }
80.160 + if (s->s_flags & EXT2_FLAGS_UNSIGNED_HASH) {
80.161 + fputs("unsigned_directory_hash ", f);
80.162 + flags_found++;
80.163 + }
80.164 + if (s->s_flags & EXT2_FLAGS_TEST_FILESYS) {
80.165 + fputs("test_filesystem ", f);
80.166 + flags_found++;
80.167 + }
80.168 + if (flags_found)
80.169 + fputs("\n", f);
80.170 + else
80.171 + fputs("(none)\n", f);
80.172 +}
80.173 +
80.174 +static __u64 e2p_blocks_count(struct ext2_super_block *super)
80.175 +{
80.176 + return super->s_blocks_count |
80.177 + (ext2fs_has_feature_64bit(super) ?
80.178 + (__u64) super->s_blocks_count_hi << 32 : 0);
80.179 +}
80.180 +
80.181 +static __u64 e2p_r_blocks_count(struct ext2_super_block *super)
80.182 +{
80.183 + return super->s_r_blocks_count |
80.184 + (ext2fs_has_feature_64bit(super) ?
80.185 + (__u64) super->s_r_blocks_count_hi << 32 : 0);
80.186 +}
80.187 +
80.188 +static __u64 e2p_free_blocks_count(struct ext2_super_block *super)
80.189 +{
80.190 + return super->s_free_blocks_count |
80.191 + (ext2fs_has_feature_64bit(super) ?
80.192 + (__u64) super->s_free_blocks_hi << 32 : 0);
80.193 +}
80.194 +
80.195 +#ifndef EXT2_INODE_SIZE
80.196 +#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode)
80.197 +#endif
80.198 +
80.199 +#ifndef EXT2_GOOD_OLD_REV
80.200 +#define EXT2_GOOD_OLD_REV 0
80.201 +#endif
80.202 +
80.203 +static const char *checksum_type(__u8 type)
80.204 +{
80.205 + switch (type) {
80.206 + case EXT2_CRC32C_CHKSUM:
80.207 + return "crc32c";
80.208 + default:
80.209 + return "unknown";
80.210 + }
80.211 +}
80.212 +
80.213 +static const char *quota_prefix[MAXQUOTAS] = {
80.214 + [USRQUOTA] = "User quota inode:",
80.215 + [GRPQUOTA] = "Group quota inode:",
80.216 + [PRJQUOTA] = "Project quota inode:",
80.217 +};
80.218 +
80.219 +/**
80.220 + * Convert type of quota to written representation
80.221 + */
80.222 +static const char *quota_type2prefix(enum quota_type qtype)
80.223 +{
80.224 + return quota_prefix[qtype];
80.225 +}
80.226 +
80.227 +void list_super2(struct ext2_super_block * sb, FILE *f)
80.228 +{
80.229 + int inode_blocks_per_group;
80.230 + char buf[80], *str;
80.231 + time_t tm;
80.232 + enum quota_type qtype;
80.233 +
80.234 + inode_blocks_per_group = (((sb->s_inodes_per_group *
80.235 + EXT2_INODE_SIZE(sb)) +
80.236 + EXT2_BLOCK_SIZE(sb) - 1) /
80.237 + EXT2_BLOCK_SIZE(sb));
80.238 + if (sb->s_volume_name[0]) {
80.239 + memset(buf, 0, sizeof(buf));
80.240 + strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
80.241 + } else
80.242 + strcpy(buf, "<none>");
80.243 + fprintf(f, "Filesystem volume name: %s\n", buf);
80.244 + if (sb->s_last_mounted[0]) {
80.245 + memset(buf, 0, sizeof(buf));
80.246 + strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted));
80.247 + } else
80.248 + strcpy(buf, "<not available>");
80.249 + fprintf(f, "Last mounted on: %s\n", buf);
80.250 + fprintf(f, "Filesystem UUID: %s\n", e2p_uuid2str(sb->s_uuid));
80.251 + fprintf(f, "Filesystem magic number: 0x%04X\n", sb->s_magic);
80.252 + fprintf(f, "Filesystem revision #: %d", sb->s_rev_level);
80.253 + if (sb->s_rev_level == EXT2_GOOD_OLD_REV) {
80.254 + fprintf(f, " (original)\n");
80.255 +#ifdef EXT2_DYNAMIC_REV
80.256 + } else if (sb->s_rev_level == EXT2_DYNAMIC_REV) {
80.257 + fprintf(f, " (dynamic)\n");
80.258 +#endif
80.259 + } else
80.260 + fprintf(f, " (unknown)\n");
80.261 + print_features(sb, f);
80.262 + print_super_flags(sb, f);
80.263 + print_mntopts(sb, f);
80.264 + if (sb->s_mount_opts[0])
80.265 + fprintf(f, "Mount options: %s\n", sb->s_mount_opts);
80.266 + fprintf(f, "Filesystem state: ");
80.267 + print_fs_state (f, sb->s_state);
80.268 + fprintf(f, "\n");
80.269 + fprintf(f, "Errors behavior: ");
80.270 + print_fs_errors(f, sb->s_errors);
80.271 + fprintf(f, "\n");
80.272 + str = e2p_os2string(sb->s_creator_os);
80.273 + fprintf(f, "Filesystem OS type: %s\n", str);
80.274 + free(str);
80.275 + fprintf(f, "Inode count: %u\n", sb->s_inodes_count);
80.276 + fprintf(f, "Block count: %llu\n", e2p_blocks_count(sb));
80.277 + fprintf(f, "Reserved block count: %llu\n", e2p_r_blocks_count(sb));
80.278 + if (sb->s_overhead_blocks)
80.279 + fprintf(f, "Overhead blocks: %u\n",
80.280 + sb->s_overhead_blocks);
80.281 + fprintf(f, "Free blocks: %llu\n", e2p_free_blocks_count(sb));
80.282 + fprintf(f, "Free inodes: %u\n", sb->s_free_inodes_count);
80.283 + fprintf(f, "First block: %u\n", sb->s_first_data_block);
80.284 + fprintf(f, "Block size: %u\n", EXT2_BLOCK_SIZE(sb));
80.285 + if (ext2fs_has_feature_bigalloc(sb))
80.286 + fprintf(f, "Cluster size: %u\n",
80.287 + EXT2_CLUSTER_SIZE(sb));
80.288 + else
80.289 + fprintf(f, "Fragment size: %u\n",
80.290 + EXT2_CLUSTER_SIZE(sb));
80.291 + if (ext2fs_has_feature_64bit(sb))
80.292 + fprintf(f, "Group descriptor size: %u\n", sb->s_desc_size);
80.293 + if (sb->s_reserved_gdt_blocks)
80.294 + fprintf(f, "Reserved GDT blocks: %u\n",
80.295 + sb->s_reserved_gdt_blocks);
80.296 + fprintf(f, "Blocks per group: %u\n", sb->s_blocks_per_group);
80.297 + if (ext2fs_has_feature_bigalloc(sb))
80.298 + fprintf(f, "Clusters per group: %u\n",
80.299 + sb->s_clusters_per_group);
80.300 + else
80.301 + fprintf(f, "Fragments per group: %u\n",
80.302 + sb->s_clusters_per_group);
80.303 + fprintf(f, "Inodes per group: %u\n", sb->s_inodes_per_group);
80.304 + fprintf(f, "Inode blocks per group: %u\n", inode_blocks_per_group);
80.305 + if (sb->s_raid_stride)
80.306 + fprintf(f, "RAID stride: %u\n",
80.307 + sb->s_raid_stride);
80.308 + if (sb->s_raid_stripe_width)
80.309 + fprintf(f, "RAID stripe width: %u\n",
80.310 + sb->s_raid_stripe_width);
80.311 + if (sb->s_first_meta_bg)
80.312 + fprintf(f, "First meta block group: %u\n",
80.313 + sb->s_first_meta_bg);
80.314 + if (sb->s_log_groups_per_flex)
80.315 + fprintf(f, "Flex block group size: %u\n",
80.316 + 1 << sb->s_log_groups_per_flex);
80.317 + if (sb->s_mkfs_time) {
80.318 + tm = sb->s_mkfs_time;
80.319 + fprintf(f, "Filesystem created: %s", ctime(&tm));
80.320 + }
80.321 + tm = sb->s_mtime;
80.322 + fprintf(f, "Last mount time: %s",
80.323 + sb->s_mtime ? ctime(&tm) : "n/a\n");
80.324 + tm = sb->s_wtime;
80.325 + fprintf(f, "Last write time: %s", ctime(&tm));
80.326 + fprintf(f, "Mount count: %u\n", sb->s_mnt_count);
80.327 + fprintf(f, "Maximum mount count: %d\n", sb->s_max_mnt_count);
80.328 + tm = sb->s_lastcheck;
80.329 + fprintf(f, "Last checked: %s", ctime(&tm));
80.330 + fprintf(f, "Check interval: %u (%s)\n", sb->s_checkinterval,
80.331 + interval_string(sb->s_checkinterval));
80.332 + if (sb->s_checkinterval)
80.333 + {
80.334 + time_t next;
80.335 +
80.336 + next = sb->s_lastcheck + sb->s_checkinterval;
80.337 + fprintf(f, "Next check after: %s", ctime(&next));
80.338 + }
80.339 +#define POW2(x) ((__u64) 1 << (x))
80.340 + if (sb->s_kbytes_written) {
80.341 + fprintf(f, "Lifetime writes: ");
80.342 + if (sb->s_kbytes_written < POW2(13))
80.343 + fprintf(f, "%llu kB\n", sb->s_kbytes_written);
80.344 + else if (sb->s_kbytes_written < POW2(23))
80.345 + fprintf(f, "%llu MB\n",
80.346 + (sb->s_kbytes_written + POW2(9)) >> 10);
80.347 + else if (sb->s_kbytes_written < POW2(33))
80.348 + fprintf(f, "%llu GB\n",
80.349 + (sb->s_kbytes_written + POW2(19)) >> 20);
80.350 + else if (sb->s_kbytes_written < POW2(43))
80.351 + fprintf(f, "%llu TB\n",
80.352 + (sb->s_kbytes_written + POW2(29)) >> 30);
80.353 + else
80.354 + fprintf(f, "%llu PB\n",
80.355 + (sb->s_kbytes_written + POW2(39)) >> 40);
80.356 + }
80.357 + fprintf(f, "Reserved blocks uid: ");
80.358 + print_user(sb->s_def_resuid, f);
80.359 + fprintf(f, "Reserved blocks gid: ");
80.360 + print_group(sb->s_def_resgid, f);
80.361 + if (sb->s_rev_level >= EXT2_DYNAMIC_REV) {
80.362 + fprintf(f, "First inode: %d\n", sb->s_first_ino);
80.363 + fprintf(f, "Inode size: %d\n", sb->s_inode_size);
80.364 + if (sb->s_min_extra_isize)
80.365 + fprintf(f, "Required extra isize: %d\n",
80.366 + sb->s_min_extra_isize);
80.367 + if (sb->s_want_extra_isize)
80.368 + fprintf(f, "Desired extra isize: %d\n",
80.369 + sb->s_want_extra_isize);
80.370 + }
80.371 + if (!e2p_is_null_uuid(sb->s_journal_uuid))
80.372 + fprintf(f, "Journal UUID: %s\n",
80.373 + e2p_uuid2str(sb->s_journal_uuid));
80.374 + if (sb->s_journal_inum)
80.375 + fprintf(f, "Journal inode: %u\n",
80.376 + sb->s_journal_inum);
80.377 + if (sb->s_journal_dev)
80.378 + fprintf(f, "Journal device: 0x%04x\n",
80.379 + sb->s_journal_dev);
80.380 + if (sb->s_last_orphan)
80.381 + fprintf(f, "First orphan inode: %u\n",
80.382 + sb->s_last_orphan);
80.383 + if (ext2fs_has_feature_dir_index(sb) ||
80.384 + sb->s_def_hash_version)
80.385 + fprintf(f, "Default directory hash: %s\n",
80.386 + e2p_hash2string(sb->s_def_hash_version));
80.387 + if (!e2p_is_null_uuid(sb->s_hash_seed))
80.388 + fprintf(f, "Directory Hash Seed: %s\n",
80.389 + e2p_uuid2str(sb->s_hash_seed));
80.390 + if (sb->s_jnl_backup_type) {
80.391 + fprintf(f, "Journal backup: ");
80.392 + switch (sb->s_jnl_backup_type) {
80.393 + case 1:
80.394 + fprintf(f, "inode blocks\n");
80.395 + break;
80.396 + default:
80.397 + fprintf(f, "type %u\n", sb->s_jnl_backup_type);
80.398 + }
80.399 + }
80.400 + if (sb->s_backup_bgs[0] || sb->s_backup_bgs[1]) {
80.401 + fprintf(f, "Backup block groups: ");
80.402 + if (sb->s_backup_bgs[0])
80.403 + fprintf(f, "%u ", sb->s_backup_bgs[0]);
80.404 + if (sb->s_backup_bgs[1])
80.405 + fprintf(f, "%u ", sb->s_backup_bgs[1]);
80.406 + fputc('\n', f);
80.407 + }
80.408 + if (sb->s_snapshot_inum) {
80.409 + fprintf(f, "Snapshot inode: %u\n",
80.410 + sb->s_snapshot_inum);
80.411 + fprintf(f, "Snapshot ID: %u\n",
80.412 + sb->s_snapshot_id);
80.413 + fprintf(f, "Snapshot reserved blocks: %llu\n",
80.414 + sb->s_snapshot_r_blocks_count);
80.415 + }
80.416 + if (sb->s_snapshot_list)
80.417 + fprintf(f, "Snapshot list head: %u\n",
80.418 + sb->s_snapshot_list);
80.419 + if (sb->s_error_count)
80.420 + fprintf(f, "FS Error count: %u\n",
80.421 + sb->s_error_count);
80.422 + if (sb->s_first_error_time) {
80.423 + tm = sb->s_first_error_time;
80.424 + fprintf(f, "First error time: %s", ctime(&tm));
80.425 + memset(buf, 0, sizeof(buf));
80.426 + strncpy(buf, (char *)sb->s_first_error_func,
80.427 + sizeof(sb->s_first_error_func));
80.428 + fprintf(f, "First error function: %s\n", buf);
80.429 + fprintf(f, "First error line #: %u\n",
80.430 + sb->s_first_error_line);
80.431 + fprintf(f, "First error inode #: %u\n",
80.432 + sb->s_first_error_ino);
80.433 + fprintf(f, "First error block #: %llu\n",
80.434 + sb->s_first_error_block);
80.435 + }
80.436 + if (sb->s_last_error_time) {
80.437 + tm = sb->s_last_error_time;
80.438 + fprintf(f, "Last error time: %s", ctime(&tm));
80.439 + memset(buf, 0, sizeof(buf));
80.440 + strncpy(buf, (char *)sb->s_last_error_func,
80.441 + sizeof(sb->s_last_error_func));
80.442 + fprintf(f, "Last error function: %s\n", buf);
80.443 + fprintf(f, "Last error line #: %u\n",
80.444 + sb->s_last_error_line);
80.445 + fprintf(f, "Last error inode #: %u\n",
80.446 + sb->s_last_error_ino);
80.447 + fprintf(f, "Last error block #: %llu\n",
80.448 + sb->s_last_error_block);
80.449 + }
80.450 + if (ext2fs_has_feature_mmp(sb)) {
80.451 + fprintf(f, "MMP block number: %llu\n",
80.452 + (long long)sb->s_mmp_block);
80.453 + fprintf(f, "MMP update interval: %u\n",
80.454 + sb->s_mmp_update_interval);
80.455 + }
80.456 + for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
80.457 + if (*quota_sb_inump(sb, qtype) != 0)
80.458 + fprintf(f, "%-26s%u\n",
80.459 + quota_type2prefix(qtype),
80.460 + *quota_sb_inump(sb, qtype));
80.461 + }
80.462 +
80.463 + if (ext2fs_has_feature_metadata_csum(sb)) {
80.464 + fprintf(f, "Checksum type: %s\n",
80.465 + checksum_type(sb->s_checksum_type));
80.466 + fprintf(f, "Checksum: 0x%08x\n",
80.467 + sb->s_checksum);
80.468 + }
80.469 + if (!e2p_is_null_uuid(sb->s_encrypt_pw_salt))
80.470 + fprintf(f, "Encryption PW Salt: %s\n",
80.471 + e2p_uuid2str(sb->s_encrypt_pw_salt));
80.472 +
80.473 + if (ext2fs_has_feature_csum_seed(sb))
80.474 + fprintf(f, "Checksum seed: 0x%08x\n",
80.475 + sb->s_checksum_seed);
80.476 +}
80.477 +
80.478 +void list_super (struct ext2_super_block * s)
80.479 +{
80.480 + list_super2(s, stdout);
80.481 +}
80.482 +
81.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
81.2 +++ b/libext2fs/lib/libe2p/mntopts.c Wed Aug 25 01:28:08 2021 +0200
81.3 @@ -0,0 +1,150 @@
81.4 +/*
81.5 + * mountopts.c --- convert between default mount options and strings
81.6 + *
81.7 + * Copyright (C) 2002 Theodore Ts'o <tytso@mit.edu>
81.8 + *
81.9 + * %Begin-Header%
81.10 + * This file may be redistributed under the terms of the GNU Library
81.11 + * General Public License, version 2.
81.12 + * %End-Header%
81.13 + */
81.14 +
81.15 +#include "config.h"
81.16 +#include <stdio.h>
81.17 +#include <stdlib.h>
81.18 +#include <string.h>
81.19 +#include <strings.h>
81.20 +#include <ctype.h>
81.21 +#include <errno.h>
81.22 +
81.23 +#include "e2p.h"
81.24 +
81.25 +struct mntopt {
81.26 + unsigned int mask;
81.27 + const char *string;
81.28 +};
81.29 +
81.30 +static struct mntopt mntopt_list[] = {
81.31 + { EXT2_DEFM_DEBUG, "debug" },
81.32 + { EXT2_DEFM_BSDGROUPS, "bsdgroups" },
81.33 + { EXT2_DEFM_XATTR_USER, "user_xattr" },
81.34 + { EXT2_DEFM_ACL, "acl" },
81.35 + { EXT2_DEFM_UID16, "uid16" },
81.36 + { EXT3_DEFM_JMODE_DATA, "journal_data" },
81.37 + { EXT3_DEFM_JMODE_ORDERED, "journal_data_ordered" },
81.38 + { EXT3_DEFM_JMODE_WBACK, "journal_data_writeback" },
81.39 + { EXT4_DEFM_NOBARRIER, "nobarrier" },
81.40 + { EXT4_DEFM_BLOCK_VALIDITY, "block_validity" },
81.41 + { EXT4_DEFM_DISCARD, "discard"},
81.42 + { EXT4_DEFM_NODELALLOC, "nodelalloc"},
81.43 + { 0, 0 },
81.44 +};
81.45 +
81.46 +const char *e2p_mntopt2string(unsigned int mask)
81.47 +{
81.48 + struct mntopt *f;
81.49 + static char buf[20];
81.50 + int fnum;
81.51 +
81.52 + for (f = mntopt_list; f->string; f++) {
81.53 + if (mask == f->mask)
81.54 + return f->string;
81.55 + }
81.56 + for (fnum = 0; mask >>= 1; fnum++);
81.57 + sprintf(buf, "MNTOPT_%d", fnum);
81.58 + return buf;
81.59 +}
81.60 +
81.61 +int e2p_string2mntopt(char *string, unsigned int *mask)
81.62 +{
81.63 + struct mntopt *f;
81.64 + char *eptr;
81.65 + int num;
81.66 +
81.67 + for (f = mntopt_list; f->string; f++) {
81.68 + if (!strcasecmp(string, f->string)) {
81.69 + *mask = f->mask;
81.70 + return 0;
81.71 + }
81.72 + }
81.73 + if (strncasecmp(string, "MNTOPT_", 7))
81.74 + return 1;
81.75 +
81.76 + if (string[8] == 0)
81.77 + return 1;
81.78 + num = strtol(string+8, &eptr, 10);
81.79 + if (num > 31 || num < 0)
81.80 + return 1;
81.81 + if (*eptr)
81.82 + return 1;
81.83 + *mask = 1 << num;
81.84 + return 0;
81.85 +}
81.86 +
81.87 +static char *skip_over_blanks(char *cp)
81.88 +{
81.89 + while (*cp && isspace(*cp))
81.90 + cp++;
81.91 + return cp;
81.92 +}
81.93 +
81.94 +static char *skip_over_word(char *cp)
81.95 +{
81.96 + while (*cp && !isspace(*cp) && *cp != ',')
81.97 + cp++;
81.98 + return cp;
81.99 +}
81.100 +
81.101 +/*
81.102 + * Edit a mntopt set array as requested by the user. The ok
81.103 + * parameter, if non-zero, allows the application to limit what
81.104 + * mntopts the user is allowed to set or clear using this function.
81.105 + */
81.106 +int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok)
81.107 +{
81.108 + char *cp, *buf, *next;
81.109 + int neg;
81.110 + unsigned int mask;
81.111 + int rc = 0;
81.112 +
81.113 + buf = malloc(strlen(str)+1);
81.114 + if (!buf)
81.115 + return 1;
81.116 + strcpy(buf, str);
81.117 + cp = buf;
81.118 + while (cp && *cp) {
81.119 + neg = 0;
81.120 + cp = skip_over_blanks(cp);
81.121 + next = skip_over_word(cp);
81.122 + if (*next == 0)
81.123 + next = 0;
81.124 + else
81.125 + *next = 0;
81.126 + switch (*cp) {
81.127 + case '-':
81.128 + case '^':
81.129 + neg++;
81.130 + /* fallthrough */
81.131 + case '+':
81.132 + cp++;
81.133 + break;
81.134 + }
81.135 + if (e2p_string2mntopt(cp, &mask)) {
81.136 + rc = 1;
81.137 + break;
81.138 + }
81.139 + if (ok && !(ok & mask)) {
81.140 + rc = 1;
81.141 + break;
81.142 + }
81.143 + if (mask & EXT3_DEFM_JMODE)
81.144 + *mntopts &= ~EXT3_DEFM_JMODE;
81.145 + if (neg)
81.146 + *mntopts &= ~mask;
81.147 + else
81.148 + *mntopts |= mask;
81.149 + cp = next ? next+1 : 0;
81.150 + }
81.151 + free(buf);
81.152 + return rc;
81.153 +}
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
82.2 +++ b/libext2fs/lib/libe2p/ostype.c Wed Aug 25 01:28:08 2021 +0200
82.3 @@ -0,0 +1,79 @@
82.4 +/*
82.5 + * getostype.c - Get the Filesystem OS type
82.6 + *
82.7 + * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
82.8 + *
82.9 + * %Begin-Header%
82.10 + * This file may be redistributed under the terms of the GNU Library
82.11 + * General Public License, version 2.
82.12 + * %End-Header%
82.13 + */
82.14 +
82.15 +#include "config.h"
82.16 +#include "e2p.h"
82.17 +#include <string.h>
82.18 +#include <stdlib.h>
82.19 +
82.20 +static const char *os_tab[] =
82.21 + { "Linux",
82.22 + "Hurd",
82.23 + "Masix",
82.24 + "FreeBSD",
82.25 + "Lites",
82.26 + 0 };
82.27 +
82.28 +/*
82.29 + * Convert an os_type to a string
82.30 + */
82.31 +char *e2p_os2string(int os_type)
82.32 +{
82.33 + const char *os;
82.34 + char *ret;
82.35 +
82.36 + if (os_type >= 0 && os_type <= EXT2_OS_LITES)
82.37 + os = os_tab[os_type];
82.38 + else
82.39 + os = "(unknown os)";
82.40 +
82.41 + ret = malloc(strlen(os)+1);
82.42 + if (ret)
82.43 + strcpy(ret, os);
82.44 + return ret;
82.45 +}
82.46 +
82.47 +/*
82.48 + * Convert an os_type to a string
82.49 + */
82.50 +int e2p_string2os(char *str)
82.51 +{
82.52 + const char **cpp;
82.53 + int i = 0;
82.54 +
82.55 + for (cpp = os_tab; *cpp; cpp++, i++) {
82.56 + if (!strcasecmp(str, *cpp))
82.57 + return i;
82.58 + }
82.59 + return -1;
82.60 +}
82.61 +
82.62 +#ifdef TEST_PROGRAM
82.63 +int main(int argc, char **argv)
82.64 +{
82.65 + char *s;
82.66 + int i, os;
82.67 +
82.68 + for (i=0; i <= EXT2_OS_LITES; i++) {
82.69 + s = e2p_os2string(i);
82.70 + os = e2p_string2os(s);
82.71 + printf("%d: %s (%d)\n", i, s, os);
82.72 + free(s);
82.73 + if (i != os) {
82.74 + fprintf(stderr, "Failure!\n");
82.75 + exit(1);
82.76 + }
82.77 + }
82.78 + exit(0);
82.79 +}
82.80 +#endif
82.81 +
82.82 +
83.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
83.2 +++ b/libext2fs/lib/libe2p/parse_num.c Wed Aug 25 01:28:08 2021 +0200
83.3 @@ -0,0 +1,91 @@
83.4 +/*
83.5 + * parse_num.c - Parse the number of blocks
83.6 + *
83.7 + * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
83.8 + *
83.9 + * %Begin-Header%
83.10 + * This file may be redistributed under the terms of the GNU Library
83.11 + * General Public License, version 2.
83.12 + * %End-Header%
83.13 + */
83.14 +
83.15 +#include "config.h"
83.16 +#include "e2p.h"
83.17 +
83.18 +#include <stdlib.h>
83.19 +
83.20 +unsigned long long parse_num_blocks2(const char *arg, int log_block_size)
83.21 +{
83.22 + char *p;
83.23 + unsigned long long num;
83.24 +
83.25 + num = strtoull(arg, &p, 0);
83.26 +
83.27 + if (p[0] && p[1])
83.28 + return 0;
83.29 +
83.30 + switch (*p) { /* Using fall-through logic */
83.31 + case 'T': case 't':
83.32 + num <<= 10;
83.33 + /* fallthrough */
83.34 + case 'G': case 'g':
83.35 + num <<= 10;
83.36 + /* fallthrough */
83.37 + case 'M': case 'm':
83.38 + num <<= 10;
83.39 + /* fallthrough */
83.40 + case 'K': case 'k':
83.41 + if (log_block_size < 0)
83.42 + num <<= 10;
83.43 + else
83.44 + num >>= log_block_size;
83.45 + break;
83.46 + case 's':
83.47 + if (log_block_size < 0)
83.48 + num <<= 9;
83.49 + else
83.50 + num >>= (1+log_block_size);
83.51 + break;
83.52 + case '\0':
83.53 + break;
83.54 + default:
83.55 + return 0;
83.56 + }
83.57 + return num;
83.58 +}
83.59 +
83.60 +unsigned long parse_num_blocks(const char *arg, int log_block_size)
83.61 +{
83.62 + return parse_num_blocks2(arg, log_block_size);
83.63 +}
83.64 +
83.65 +#ifdef DEBUG
83.66 +#include <unistd.h>
83.67 +#include <stdio.h>
83.68 +
83.69 +main(int argc, char **argv)
83.70 +{
83.71 + unsigned long num;
83.72 + int log_block_size = 0;
83.73 +
83.74 + if (argc != 2 && argc != 3) {
83.75 + fprintf(stderr, "Usage: %s arg [log_block_size]\n", argv[0]);
83.76 + exit(1);
83.77 + }
83.78 +
83.79 + if (argc == 3) {
83.80 + char *p;
83.81 +
83.82 + log_block_size = strtol(argv[2], &p, 0);
83.83 + if (*p) {
83.84 + fprintf(stderr, "Bad log_block_size: %s\n", argv[2]);
83.85 + exit(1);
83.86 + }
83.87 + }
83.88 +
83.89 + num = parse_num_blocks(argv[1], log_block_size);
83.90 +
83.91 + printf("Parsed number: %lu\n", num);
83.92 + exit(0);
83.93 +}
83.94 +#endif
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
84.2 +++ b/libext2fs/lib/libe2p/pe.c Wed Aug 25 01:28:08 2021 +0200
84.3 @@ -0,0 +1,40 @@
84.4 +/*
84.5 + * pe.c - Print a second extended filesystem errors behavior
84.6 + *
84.7 + * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
84.8 + * Laboratoire MASI, Institut Blaise Pascal
84.9 + * Universite Pierre et Marie Curie (Paris VI)
84.10 + *
84.11 + * %Begin-Header%
84.12 + * This file may be redistributed under the terms of the GNU Library
84.13 + * General Public License, version 2.
84.14 + * %End-Header%
84.15 + */
84.16 +
84.17 +/*
84.18 + * History:
84.19 + * 94/01/09 - Creation
84.20 + */
84.21 +
84.22 +#include "config.h"
84.23 +#include <stdio.h>
84.24 +
84.25 +#include "e2p.h"
84.26 +
84.27 +void print_fs_errors (FILE * f, unsigned short errors)
84.28 +{
84.29 + switch (errors)
84.30 + {
84.31 + case EXT2_ERRORS_CONTINUE:
84.32 + fprintf (f, "Continue");
84.33 + break;
84.34 + case EXT2_ERRORS_RO:
84.35 + fprintf (f, "Remount read-only");
84.36 + break;
84.37 + case EXT2_ERRORS_PANIC:
84.38 + fprintf (f, "Panic");
84.39 + break;
84.40 + default:
84.41 + fprintf (f, "Unknown (continue)");
84.42 + }
84.43 +}
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
85.2 +++ b/libext2fs/lib/libe2p/percent.c Wed Aug 25 01:28:08 2021 +0200
85.3 @@ -0,0 +1,67 @@
85.4 +/*
85.5 + * percent.c - Take percentage of a number
85.6 + *
85.7 + * Copyright (C) 2006 Theodore Ts'o <tytso@mit.edu>
85.8 + *
85.9 + * %Begin-Header%
85.10 + * This file may be redistributed under the terms of the GNU Library
85.11 + * General Public License, version 2.
85.12 + * %End-Header%
85.13 + */
85.14 +
85.15 +#include "config.h"
85.16 +#include "e2p.h"
85.17 +
85.18 +#include <stdlib.h>
85.19 +
85.20 +/*
85.21 + * We work really hard to calculate this accurately, while avoiding
85.22 + * an overflow. "Is there a hyphen in anal-retentive?" :-)
85.23 + */
85.24 +unsigned int e2p_percent(int percent, unsigned int base)
85.25 +{
85.26 + unsigned int mask = ~((1 << (sizeof(unsigned int) - 1) * 8) - 1);
85.27 +
85.28 + if (!percent)
85.29 + return 0;
85.30 + if (100 % percent == 0)
85.31 + return base / (100 / percent);
85.32 + if (mask & base)
85.33 + return (base / 100) * percent;
85.34 + return base * percent / 100;
85.35 +}
85.36 +
85.37 +#ifdef DEBUG
85.38 +#include <unistd.h>
85.39 +#include <stdio.h>
85.40 +
85.41 +main(int argc, char **argv)
85.42 +{
85.43 + unsigned int base;
85.44 + int percent;
85.45 + char *p;
85.46 + int log_block_size = 0;
85.47 +
85.48 + if (argc != 3) {
85.49 + fprintf(stderr, "Usage: %s percent base\n", argv[0]);
85.50 + exit(1);
85.51 + }
85.52 +
85.53 + percent = strtoul(argv[1], &p, 0);
85.54 + if (p[0] && p[1]) {
85.55 + fprintf(stderr, "Bad percent: %s\n", argv[1]);
85.56 + exit(1);
85.57 + }
85.58 +
85.59 + base = strtoul(argv[2], &p, 0);
85.60 + if (p[0] && p[1]) {
85.61 + fprintf(stderr, "Bad base: %s\n", argv[2]);
85.62 + exit(1);
85.63 + }
85.64 +
85.65 + printf("%d percent of %u is %u.\n", percent, base,
85.66 + e2p_percent(percent, base));
85.67 +
85.68 + exit(0);
85.69 +}
85.70 +#endif
86.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
86.2 +++ b/libext2fs/lib/libe2p/pf.c Wed Aug 25 01:28:08 2021 +0200
86.3 @@ -0,0 +1,77 @@
86.4 +/*
86.5 + * pf.c - Print file attributes on an ext2 file system
86.6 + *
86.7 + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
86.8 + * Laboratoire MASI, Institut Blaise Pascal
86.9 + * Universite Pierre et Marie Curie (Paris VI)
86.10 + *
86.11 + * %Begin-Header%
86.12 + * This file may be redistributed under the terms of the GNU Library
86.13 + * General Public License, version 2.
86.14 + * %End-Header%
86.15 + */
86.16 +
86.17 +/*
86.18 + * History:
86.19 + * 93/10/30 - Creation
86.20 + */
86.21 +
86.22 +#include "config.h"
86.23 +#include <stdio.h>
86.24 +
86.25 +#include "e2p.h"
86.26 +
86.27 +struct flags_name {
86.28 + unsigned long flag;
86.29 + const char *short_name;
86.30 + const char *long_name;
86.31 +};
86.32 +
86.33 +static struct flags_name flags_array[] = {
86.34 + { EXT2_SECRM_FL, "s", "Secure_Deletion" },
86.35 + { EXT2_UNRM_FL, "u" , "Undelete" },
86.36 + { EXT2_SYNC_FL, "S", "Synchronous_Updates" },
86.37 + { EXT2_DIRSYNC_FL, "D", "Synchronous_Directory_Updates" },
86.38 + { EXT2_IMMUTABLE_FL, "i", "Immutable" },
86.39 + { EXT2_APPEND_FL, "a", "Append_Only" },
86.40 + { EXT2_NODUMP_FL, "d", "No_Dump" },
86.41 + { EXT2_NOATIME_FL, "A", "No_Atime" },
86.42 + { EXT2_COMPR_FL, "c", "Compression_Requested" },
86.43 + { EXT4_ENCRYPT_FL, "E", "Encrypted" },
86.44 + { EXT3_JOURNAL_DATA_FL, "j", "Journaled_Data" },
86.45 + { EXT2_INDEX_FL, "I", "Indexed_directory" },
86.46 + { EXT2_NOTAIL_FL, "t", "No_Tailmerging" },
86.47 + { EXT2_TOPDIR_FL, "T", "Top_of_Directory_Hierarchies" },
86.48 + { EXT4_EXTENTS_FL, "e", "Extents" },
86.49 + { FS_NOCOW_FL, "C", "No_COW" },
86.50 + { EXT4_INLINE_DATA_FL, "N", "Inline_Data" },
86.51 + { EXT4_PROJINHERIT_FL, "P", "Project_Hierarchy" },
86.52 + { EXT4_VERITY_FL, "V", "Verity" },
86.53 + { 0, NULL, NULL }
86.54 +};
86.55 +
86.56 +void print_flags (FILE * f, unsigned long flags, unsigned options)
86.57 +{
86.58 + int long_opt = (options & PFOPT_LONG);
86.59 + struct flags_name *fp;
86.60 + int first = 1;
86.61 +
86.62 + for (fp = flags_array; fp->flag != 0; fp++) {
86.63 + if (flags & fp->flag) {
86.64 + if (long_opt) {
86.65 + if (first)
86.66 + first = 0;
86.67 + else
86.68 + fputs(", ", f);
86.69 + fputs(fp->long_name, f);
86.70 + } else
86.71 + fputs(fp->short_name, f);
86.72 + } else {
86.73 + if (!long_opt)
86.74 + fputs("-", f);
86.75 + }
86.76 + }
86.77 + if (long_opt && first)
86.78 + fputs("---", f);
86.79 +}
86.80 +
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
87.2 +++ b/libext2fs/lib/libe2p/project.h Wed Aug 25 01:28:08 2021 +0200
87.3 @@ -0,0 +1,27 @@
87.4 +/*
87.5 + * project.h
87.6 + *
87.7 + * %Begin-Header%
87.8 + * This file may be redistributed under the terms of the GNU Library
87.9 + * General Public License, version 2.
87.10 + * %End-Header%
87.11 + */
87.12 +
87.13 +#include <ext2fs/ext2_fs.h>
87.14 +
87.15 +#if defined(__linux__) && !defined(FS_IOC_FSGETXATTR)
87.16 +#define FS_IOC_FSGETXATTR _IOR('X', 31, struct fsxattr)
87.17 +#define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr)
87.18 +
87.19 +/*
87.20 + * Structure for FS_IOC_FSGETXATTR and FS_IOC_FSSETXATTR.
87.21 + */
87.22 +struct fsxattr {
87.23 + __u32 fsx_xflags; /* xflags field value (get/set) */
87.24 + __u32 fsx_extsize; /* extsize field value (get/set)*/
87.25 + __u32 fsx_nextents; /* nextents field value (get) */
87.26 + __u32 fsx_projid; /* project identifier (get/set) */
87.27 + unsigned char fsx_pad[12];
87.28 +};
87.29 +#endif
87.30 +
88.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
88.2 +++ b/libext2fs/lib/libe2p/ps.c Wed Aug 25 01:28:08 2021 +0200
88.3 @@ -0,0 +1,32 @@
88.4 +/*
88.5 + * ps.c - Print filesystem state
88.6 + *
88.7 + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
88.8 + * Laboratoire MASI, Institut Blaise Pascal
88.9 + * Universite Pierre et Marie Curie (Paris VI)
88.10 + *
88.11 + * %Begin-Header%
88.12 + * This file may be redistributed under the terms of the GNU Library
88.13 + * General Public License, version 2.
88.14 + * %End-Header%
88.15 + */
88.16 +
88.17 +/*
88.18 + * History:
88.19 + * 93/12/22 - Creation
88.20 + */
88.21 +
88.22 +#include "config.h"
88.23 +#include <stdio.h>
88.24 +
88.25 +#include "e2p.h"
88.26 +
88.27 +void print_fs_state (FILE * f, unsigned short state)
88.28 +{
88.29 + if (state & EXT2_VALID_FS)
88.30 + fprintf (f, " clean");
88.31 + else
88.32 + fprintf (f, " not clean");
88.33 + if (state & EXT2_ERROR_FS)
88.34 + fprintf (f, " with errors");
88.35 +}
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
89.2 +++ b/libext2fs/lib/libe2p/setflags.c Wed Aug 25 01:28:08 2021 +0200
89.3 @@ -0,0 +1,77 @@
89.4 +/*
89.5 + * setflags.c - Set a file flags on an ext2 file system
89.6 + *
89.7 + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
89.8 + * Laboratoire MASI, Institut Blaise Pascal
89.9 + * Universite Pierre et Marie Curie (Paris VI)
89.10 + *
89.11 + * %Begin-Header%
89.12 + * This file may be redistributed under the terms of the GNU Library
89.13 + * General Public License, version 2.
89.14 + * %End-Header%
89.15 + */
89.16 +
89.17 +/*
89.18 + * History:
89.19 + * 93/10/30 - Creation
89.20 + */
89.21 +
89.22 +#include "config.h"
89.23 +#if HAVE_ERRNO_H
89.24 +#include <errno.h>
89.25 +#endif
89.26 +#include <sys/types.h>
89.27 +#include <sys/stat.h>
89.28 +#if HAVE_EXT2_IOCTLS
89.29 +#include <sys/ioctl.h>
89.30 +#endif
89.31 +
89.32 +#include "e2p.h"
89.33 +
89.34 +/*
89.35 + * Deal with lame glibc's that define this function without actually
89.36 + * implementing it. Can you say "attractive nuisance", boys and girls?
89.37 + * I knew you could!
89.38 + */
89.39 +#ifdef __linux__
89.40 +#undef HAVE_CHFLAGS
89.41 +#endif
89.42 +
89.43 +int setflags (int fd, unsigned long flags)
89.44 +{
89.45 +#if HAVE_CHFLAGS
89.46 + unsigned long bsd_flags = 0;
89.47 +
89.48 +#ifdef UF_IMMUTABLE
89.49 + if (flags & EXT2_IMMUTABLE_FL)
89.50 + bsd_flags |= UF_IMMUTABLE;
89.51 +#endif
89.52 +#ifdef UF_APPEND
89.53 + if (flags & EXT2_APPEND_FL)
89.54 + bsd_flags |= UF_APPEND;
89.55 +#endif
89.56 +#ifdef UF_NODUMP
89.57 + if (flags & EXT2_NODUMP_FL)
89.58 + bsd_flags |= UF_NODUMP;
89.59 +#endif
89.60 +
89.61 + return fchflags (fd, bsd_flags);
89.62 +#else /* ! HAVE_CHFLAGS */
89.63 +#if HAVE_EXT2_IOCTLS
89.64 + struct stat buf;
89.65 + int f;
89.66 +
89.67 + if (!fstat(fd, &buf) &&
89.68 + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
89.69 + errno = EOPNOTSUPP;
89.70 + return -1;
89.71 + }
89.72 + f = (int) flags;
89.73 +
89.74 + return ioctl(fd, EXT2_IOC_SETFLAGS, &f);
89.75 +#else
89.76 + errno = EOPNOTSUPP;
89.77 + return -1;
89.78 +#endif /* HAVE_EXT2_IOCTLS */
89.79 +#endif /* HAVE_CHFLAGS */
89.80 +}
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
90.2 +++ b/libext2fs/lib/libe2p/setversion.c Wed Aug 25 01:28:08 2021 +0200
90.3 @@ -0,0 +1,41 @@
90.4 +/*
90.5 + * setversion.c - Set a file version on an ext2 file system
90.6 + *
90.7 + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
90.8 + * Laboratoire MASI, Institut Blaise Pascal
90.9 + * Universite Pierre et Marie Curie (Paris VI)
90.10 + *
90.11 + * %Begin-Header%
90.12 + * This file may be redistributed under the terms of the GNU Library
90.13 + * General Public License, version 2.
90.14 + * %End-Header%
90.15 + */
90.16 +
90.17 +/*
90.18 + * History:
90.19 + * 93/10/30 - Creation
90.20 + */
90.21 +
90.22 +#include "config.h"
90.23 +#if HAVE_ERRNO_H
90.24 +#include <errno.h>
90.25 +#endif
90.26 +#if HAVE_SYS_IOCTL_H
90.27 +#include <sys/ioctl.h>
90.28 +#endif
90.29 +
90.30 +#include "e2p.h"
90.31 +
90.32 +int setversion (int fd, unsigned long version)
90.33 +{
90.34 +#if HAVE_EXT2_IOCTLS
90.35 + int ver;
90.36 +
90.37 + ver = (int) version;
90.38 + return ioctl (fd, EXT2_IOC_SETVERSION, &ver);
90.39 +#else /* ! HAVE_EXT2_IOCTLS */
90.40 + extern int errno;
90.41 + errno = EOPNOTSUPP;
90.42 + return -1;
90.43 +#endif /* ! HAVE_EXT2_IOCTLS */
90.44 +}
91.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
91.2 +++ b/libext2fs/lib/libe2p/uuid.c Wed Aug 25 01:28:08 2021 +0200
91.3 @@ -0,0 +1,85 @@
91.4 +/*
91.5 + * uuid.c -- utility routines for manipulating UUID's.
91.6 + *
91.7 + * %Begin-Header%
91.8 + * This file may be redistributed under the terms of the GNU Library
91.9 + * General Public License, version 2.
91.10 + * %End-Header%
91.11 + */
91.12 +
91.13 +#include "config.h"
91.14 +#include <stdio.h>
91.15 +#include <string.h>
91.16 +#include <ext2fs/ext2_types.h>
91.17 +
91.18 +#include "e2p.h"
91.19 +
91.20 +struct uuid {
91.21 + __u32 time_low;
91.22 + __u16 time_mid;
91.23 + __u16 time_hi_and_version;
91.24 + __u16 clock_seq;
91.25 + __u8 node[6];
91.26 +};
91.27 +
91.28 +/* Returns 1 if the uuid is the NULL uuid */
91.29 +int e2p_is_null_uuid(void *uu)
91.30 +{
91.31 + __u8 *cp;
91.32 + int i;
91.33 +
91.34 + for (i=0, cp = uu; i < 16; i++)
91.35 + if (*cp++)
91.36 + return 0;
91.37 + return 1;
91.38 +}
91.39 +
91.40 +static void e2p_unpack_uuid(void *in, struct uuid *uu)
91.41 +{
91.42 + __u8 *ptr = in;
91.43 + __u32 tmp;
91.44 +
91.45 + tmp = *ptr++;
91.46 + tmp = (tmp << 8) | *ptr++;
91.47 + tmp = (tmp << 8) | *ptr++;
91.48 + tmp = (tmp << 8) | *ptr++;
91.49 + uu->time_low = tmp;
91.50 +
91.51 + tmp = *ptr++;
91.52 + tmp = (tmp << 8) | *ptr++;
91.53 + uu->time_mid = tmp;
91.54 +
91.55 + tmp = *ptr++;
91.56 + tmp = (tmp << 8) | *ptr++;
91.57 + uu->time_hi_and_version = tmp;
91.58 +
91.59 + tmp = *ptr++;
91.60 + tmp = (tmp << 8) | *ptr++;
91.61 + uu->clock_seq = tmp;
91.62 +
91.63 + memcpy(uu->node, ptr, 6);
91.64 +}
91.65 +
91.66 +void e2p_uuid_to_str(void *uu, char *out)
91.67 +{
91.68 + struct uuid uuid;
91.69 +
91.70 + e2p_unpack_uuid(uu, &uuid);
91.71 + sprintf(out,
91.72 + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
91.73 + uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
91.74 + uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
91.75 + uuid.node[0], uuid.node[1], uuid.node[2],
91.76 + uuid.node[3], uuid.node[4], uuid.node[5]);
91.77 +}
91.78 +
91.79 +const char *e2p_uuid2str(void *uu)
91.80 +{
91.81 + static char buf[80];
91.82 +
91.83 + if (e2p_is_null_uuid(uu))
91.84 + return "<none>";
91.85 + e2p_uuid_to_str(uu, buf);
91.86 + return buf;
91.87 +}
91.88 +
92.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
92.2 +++ b/libext2fs/lib/libet/Makefile Wed Aug 25 01:28:08 2021 +0200
92.3 @@ -0,0 +1,13 @@
92.4 +PKGDIR ?= ../..
92.5 +L4DIR ?= $(PKGDIR)/../../..
92.6 +
92.7 +TARGET = libet.a libet.so
92.8 +PC_FILENAME = libet
92.9 +SRC_C = error_message.c et_name.c init_et.c com_err.c com_right.c
92.10 +
92.11 +PRIVATE_INCDIR += $(PKGDIR)/lib $(PKGDIR)/include/libet $(PKGDIR)/include/libet/et
92.12 +CONTRIB_INCDIR = libet
92.13 +
92.14 +REQUIRES_LIBS = libc_support_misc
92.15 +
92.16 +include $(L4DIR)/mk/lib.mk
93.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
93.2 +++ b/libext2fs/lib/libet/com_err.c Wed Aug 25 01:28:08 2021 +0200
93.3 @@ -0,0 +1,104 @@
93.4 +/*
93.5 + * Copyright 1987, 1988 by MIT Student Information Processing Board.
93.6 + *
93.7 + * Permission to use, copy, modify, and distribute this software and
93.8 + * its documentation for any purpose is hereby granted, provided that
93.9 + * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
93.10 + * advertising or publicity pertaining to distribution of the software
93.11 + * without specific, written prior permission. M.I.T. and the
93.12 + * M.I.T. S.I.P.B. make no representations about the suitability of
93.13 + * this software for any purpose. It is provided "as is" without
93.14 + * express or implied warranty.
93.15 + */
93.16 +
93.17 +#include "config.h"
93.18 +#include <stdio.h>
93.19 +#ifdef HAVE_TERMIOS_H
93.20 +#include <termios.h>
93.21 +#endif
93.22 +#ifdef HAVE_UNISTD_H
93.23 +#include <unistd.h>
93.24 +#endif
93.25 +#include "com_err.h"
93.26 +#include "error_table.h"
93.27 +#include "internal.h"
93.28 +
93.29 +static void
93.30 +default_com_err_proc (const char *whoami, errcode_t code, const
93.31 + char *fmt, va_list args)
93.32 + COM_ERR_ATTR((format(printf, 3, 0)));
93.33 +
93.34 +static void
93.35 +default_com_err_proc (const char *whoami, errcode_t code, const
93.36 + char *fmt, va_list args)
93.37 +{
93.38 + int do_cr = 1, fd = fileno(stderr);
93.39 +
93.40 + if (whoami) {
93.41 + fputs(whoami, stderr);
93.42 + fputs(": ", stderr);
93.43 + }
93.44 + if (code) {
93.45 + fputs(error_message(code), stderr);
93.46 + fputs(" ", stderr);
93.47 + }
93.48 + if (fmt) {
93.49 + vfprintf (stderr, fmt, args);
93.50 + }
93.51 + if (!isatty(fd))
93.52 + do_cr = 0;
93.53 +#ifdef HAVE_TERMIOS_H
93.54 + else {
93.55 + struct termios t;
93.56 +
93.57 + if ((tcgetattr(fd, &t)) == 0 &&
93.58 + (t.c_oflag & OPOST) && (t.c_oflag & ONLCR))
93.59 + do_cr = 0;
93.60 + }
93.61 +#endif
93.62 + if (do_cr)
93.63 + fputc('\r', stderr);
93.64 + fputc('\n', stderr);
93.65 + fflush(stderr);
93.66 +}
93.67 +
93.68 +typedef void (*errf) (const char *, errcode_t, const char *, va_list);
93.69 +
93.70 +errf com_err_hook = default_com_err_proc;
93.71 +
93.72 +void com_err_va (const char *whoami, errcode_t code, const char *fmt,
93.73 + va_list args)
93.74 +{
93.75 + (*com_err_hook) (whoami, code, fmt, args);
93.76 +}
93.77 +
93.78 +void com_err (const char *whoami,
93.79 + errcode_t code,
93.80 + const char *fmt, ...)
93.81 +{
93.82 + va_list pvar;
93.83 +
93.84 + if (!com_err_hook)
93.85 + com_err_hook = default_com_err_proc;
93.86 + va_start(pvar, fmt);
93.87 + com_err_va (whoami, code, fmt, pvar);
93.88 + va_end(pvar);
93.89 +}
93.90 +
93.91 +errf set_com_err_hook(errf new_proc)
93.92 +{
93.93 + errf x = com_err_hook;
93.94 +
93.95 + if (new_proc)
93.96 + com_err_hook = new_proc;
93.97 + else
93.98 + com_err_hook = default_com_err_proc;
93.99 +
93.100 + return x;
93.101 +}
93.102 +
93.103 +errf reset_com_err_hook(void) {
93.104 + errf x = com_err_hook;
93.105 + com_err_hook = default_com_err_proc;
93.106 + return x;
93.107 +}
94.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
94.2 +++ b/libext2fs/lib/libet/com_right.c Wed Aug 25 01:28:08 2021 +0200
94.3 @@ -0,0 +1,120 @@
94.4 +/*
94.5 + * com_right.c -- provide Heimdall / Kerberos4kth com_err interfaces
94.6 + * for backwards compatibility
94.7 + *
94.8 + * Copyright (c) 2003 by Theodore Ts'o
94.9 + *
94.10 + * Taken from lib/com_err/error.c from Kerberos4kth distribution.
94.11 + *
94.12 + * Copyright (c) 1997, 1998, 2001 Kungliga Tekniska Högskolan
94.13 + * (Royal Institute of Technology, Stockholm, Sweden).
94.14 + * All rights reserved.
94.15 + *
94.16 + * Redistribution and use in source and binary forms, with or without
94.17 + * modification, are permitted provided that the following conditions
94.18 + * are met:
94.19 + *
94.20 + * 1. Redistributions of source code must retain the above copyright
94.21 + * notice, this list of conditions and the following disclaimer.
94.22 + *
94.23 + * 2. Redistributions in binary form must reproduce the above copyright
94.24 + * notice, this list of conditions and the following disclaimer in the
94.25 + * documentation and/or other materials provided with the distribution.
94.26 + *
94.27 + * 3. Neither the name of the Institute nor the names of its contributors
94.28 + * may be used to endorse or promote products derived from this software
94.29 + * without specific prior written permission.
94.30 + *
94.31 + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
94.32 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94.33 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
94.34 + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
94.35 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
94.36 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
94.37 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
94.38 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
94.39 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
94.40 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
94.41 + * SUCH DAMAGE.
94.42 + */
94.43 +
94.44 +#include "config.h"
94.45 +#include <stdio.h>
94.46 +#include <stdlib.h>
94.47 +#include <string.h>
94.48 +#include "com_err.h"
94.49 +#include "error_table.h"
94.50 +
94.51 +const char *
94.52 +com_right(struct et_list *list, long code)
94.53 +{
94.54 + struct et_list *p;
94.55 + for (p = list; p; p = p->next) {
94.56 + if (code >= p->table->base && code < p->table->base + p->table->n_msgs)
94.57 + return p->table->msgs[code - p->table->base];
94.58 + }
94.59 + return NULL;
94.60 +}
94.61 +
94.62 +const char *
94.63 +com_right_r(struct et_list *list, long code, char *str, size_t len)
94.64 +{
94.65 + struct et_list *p;
94.66 + for (p = list; p; p = p->next) {
94.67 + if ((code >= p->table->base) &&
94.68 + (code < p->table->base + p->table->n_msgs)) {
94.69 + strncpy(str, p->table->msgs[code - p->table->base], len);
94.70 + str[len-1] = '\0';
94.71 + return str;
94.72 + }
94.73 + }
94.74 + return NULL;
94.75 +}
94.76 +
94.77 +struct foobar {
94.78 + struct et_list etl;
94.79 + struct error_table tab;
94.80 +};
94.81 +
94.82 +/*
94.83 + * We provide this routine for compatibility with Heimdall generated
94.84 + * foo_err.c files, but we don't use this ourselves for foo_err.c
94.85 + * files generated by our compile_et. This is so our foo_err.c
94.86 + * files can be used with older com_err libraries without running
94.87 + * afoul of dependencies.
94.88 + */
94.89 +void
94.90 +initialize_error_table_r(struct et_list **list,
94.91 + const char **messages,
94.92 + int num_errors,
94.93 + long base)
94.94 +{
94.95 + struct et_list *et, **end;
94.96 + struct error_table *tab;
94.97 + struct foobar *f;
94.98 +
94.99 + for (end = list, et = *list; et; end = &et->next, et = et->next)
94.100 + if (et->table->msgs == messages)
94.101 + return;
94.102 + f = malloc(sizeof(*f));
94.103 + if (f == NULL)
94.104 + return;
94.105 + et = &f->etl;
94.106 + et->table = tab = &f->tab;
94.107 + tab->msgs = messages;
94.108 + tab->n_msgs = num_errors;
94.109 + tab->base = base;
94.110 + et->next = NULL;
94.111 + *end = et;
94.112 +}
94.113 +
94.114 +
94.115 +void
94.116 +free_error_table(struct et_list *et)
94.117 +{
94.118 + while(et){
94.119 + struct et_list *p = et;
94.120 + et = et->next;
94.121 + free(p);
94.122 + }
94.123 +}
95.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
95.2 +++ b/libext2fs/lib/libet/error_message.c Wed Aug 25 01:28:08 2021 +0200
95.3 @@ -0,0 +1,350 @@
95.4 +/*
95.5 + * $Header$
95.6 + * $Source$
95.7 + * $Locker$
95.8 + *
95.9 + * Copyright 1987 by the Student Information Processing Board
95.10 + * of the Massachusetts Institute of Technology
95.11 + *
95.12 + * Permission to use, copy, modify, and distribute this software and
95.13 + * its documentation for any purpose is hereby granted, provided that
95.14 + * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
95.15 + * advertising or publicity pertaining to distribution of the software
95.16 + * without specific, written prior permission. M.I.T. and the
95.17 + * M.I.T. S.I.P.B. make no representations about the suitability of
95.18 + * this software for any purpose. It is provided "as is" without
95.19 + * express or implied warranty.
95.20 + */
95.21 +
95.22 +#include "config.h"
95.23 +#include <stdio.h>
95.24 +#include <stdlib.h>
95.25 +#include <string.h>
95.26 +#include <errno.h>
95.27 +#ifdef HAVE_SYS_PRCTL_H
95.28 +#include <sys/prctl.h>
95.29 +#else
95.30 +#define PR_GET_DUMPABLE 3
95.31 +#endif
95.32 +#if (!defined(HAVE_PRCTL) && defined(linux))
95.33 +#include <sys/syscall.h>
95.34 +#endif
95.35 +#ifdef HAVE_SEMAPHORE_H
95.36 +#include <semaphore.h>
95.37 +#endif
95.38 +#if HAVE_UNISTD_H
95.39 +#include <unistd.h>
95.40 +#endif
95.41 +#if HAVE_FCNTL
95.42 +#include <fcntl.h>
95.43 +#endif
95.44 +#if HAVE_SYS_TYPES_H
95.45 +#include <sys/types.h>
95.46 +#endif
95.47 +#include "com_err.h"
95.48 +#include "error_table.h"
95.49 +#include "internal.h"
95.50 +
95.51 +#ifdef TLS
95.52 +#define THREAD_LOCAL static TLS
95.53 +#else
95.54 +#define THREAD_LOCAL static
95.55 +#endif
95.56 +
95.57 +THREAD_LOCAL char buffer[25];
95.58 +
95.59 +struct et_list * _et_list = (struct et_list *) NULL;
95.60 +struct et_list * _et_dynamic_list = (struct et_list *) NULL;
95.61 +
95.62 +#ifdef __GNUC__
95.63 +#define COMERR_ATTR(x) __attribute__(x)
95.64 +#else
95.65 +#define COMERR_ATTR(x)
95.66 +#endif
95.67 +
95.68 +#ifdef HAVE_SEM_INIT
95.69 +static sem_t _et_lock;
95.70 +static int _et_lock_initialized;
95.71 +
95.72 +static void COMERR_ATTR((constructor)) setup_et_lock(void)
95.73 +{
95.74 + sem_init(&_et_lock, 0, 1);
95.75 + _et_lock_initialized = 1;
95.76 +}
95.77 +
95.78 +static void COMERR_ATTR((destructor)) fini_et_lock(void)
95.79 +{
95.80 + sem_destroy(&_et_lock);
95.81 + _et_lock_initialized = 0;
95.82 +}
95.83 +#endif
95.84 +
95.85 +
95.86 +int et_list_lock(void)
95.87 +{
95.88 +#ifdef HAVE_SEM_INIT
95.89 + if (!_et_lock_initialized)
95.90 + setup_et_lock();
95.91 + return sem_wait(&_et_lock);
95.92 +#else
95.93 + return 0;
95.94 +#endif
95.95 +}
95.96 +
95.97 +int et_list_unlock(void)
95.98 +{
95.99 +#ifdef HAVE_SEM_INIT
95.100 + if (_et_lock_initialized)
95.101 + return sem_post(&_et_lock);
95.102 +#endif
95.103 + return 0;
95.104 +}
95.105 +
95.106 +typedef char *(*gettextf) (const char *);
95.107 +
95.108 +static gettextf com_err_gettext = NULL;
95.109 +
95.110 +gettextf set_com_err_gettext(gettextf new_proc)
95.111 +{
95.112 + gettextf x = com_err_gettext;
95.113 +
95.114 + com_err_gettext = new_proc;
95.115 +
95.116 + return x;
95.117 +}
95.118 +
95.119 +
95.120 +const char * error_message (errcode_t code)
95.121 +{
95.122 + int offset;
95.123 + struct et_list *et;
95.124 + errcode_t table_num;
95.125 + int started = 0;
95.126 + char *cp;
95.127 +
95.128 + offset = (int) (code & ((1<<ERRCODE_RANGE)-1));
95.129 + table_num = code - offset;
95.130 + if (!table_num) {
95.131 +#ifdef HAS_SYS_ERRLIST
95.132 + if (offset < sys_nerr)
95.133 + return(sys_errlist[offset]);
95.134 + else
95.135 + goto oops;
95.136 +#else
95.137 + cp = strerror(offset);
95.138 + if (cp)
95.139 + return(cp);
95.140 + else
95.141 + goto oops;
95.142 +#endif
95.143 + }
95.144 + et_list_lock();
95.145 + for (et = _et_list; et; et = et->next) {
95.146 + if ((et->table->base & 0xffffffL) == (table_num & 0xffffffL)) {
95.147 + /* This is the right table */
95.148 + if (et->table->n_msgs <= offset) {
95.149 + break;
95.150 + } else {
95.151 + const char *msg = et->table->msgs[offset];
95.152 + et_list_unlock();
95.153 + if (com_err_gettext)
95.154 + return (*com_err_gettext)(msg);
95.155 + else
95.156 + return msg;
95.157 + }
95.158 + }
95.159 + }
95.160 + for (et = _et_dynamic_list; et; et = et->next) {
95.161 + if ((et->table->base & 0xffffffL) == (table_num & 0xffffffL)) {
95.162 + /* This is the right table */
95.163 + if (et->table->n_msgs <= offset) {
95.164 + break;
95.165 + } else {
95.166 + const char *msg = et->table->msgs[offset];
95.167 + et_list_unlock();
95.168 + if (com_err_gettext)
95.169 + return (*com_err_gettext)(msg);
95.170 + else
95.171 + return msg;
95.172 + }
95.173 + }
95.174 + }
95.175 + et_list_unlock();
95.176 +oops:
95.177 + strcpy (buffer, "Unknown code ");
95.178 + if (table_num) {
95.179 + strcat (buffer, error_table_name (table_num));
95.180 + strcat (buffer, " ");
95.181 + }
95.182 + for (cp = buffer; *cp; cp++)
95.183 + ;
95.184 + if (offset >= 100) {
95.185 + *cp++ = '0' + offset / 100;
95.186 + offset %= 100;
95.187 + started++;
95.188 + }
95.189 + if (started || offset >= 10) {
95.190 + *cp++ = '0' + offset / 10;
95.191 + offset %= 10;
95.192 + }
95.193 + *cp++ = '0' + offset;
95.194 + *cp = '\0';
95.195 + return(buffer);
95.196 +}
95.197 +
95.198 +/*
95.199 + * This routine will only return a value if the we are not running as
95.200 + * a privileged process.
95.201 + */
95.202 +static char *safe_getenv(const char *arg)
95.203 +{
95.204 +#if !defined(_WIN32)
95.205 + if ((getuid() != geteuid()) || (getgid() != getegid()))
95.206 + return NULL;
95.207 +#endif
95.208 +#if HAVE_PRCTL
95.209 + if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
95.210 + return NULL;
95.211 +#else
95.212 +#if (defined(linux) && defined(SYS_prctl))
95.213 + if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
95.214 + return NULL;
95.215 +#endif
95.216 +#endif
95.217 +
95.218 +#if defined(HAVE_SECURE_GETENV)
95.219 + return secure_getenv(arg);
95.220 +#elif defined(HAVE___SECURE_GETENV)
95.221 + return __secure_getenv(arg);
95.222 +#else
95.223 + return getenv(arg);
95.224 +#endif
95.225 +}
95.226 +
95.227 +#define DEBUG_INIT 0x8000
95.228 +#define DEBUG_ADDREMOVE 0x0001
95.229 +
95.230 +static int debug_mask = 0;
95.231 +static FILE *debug_f = 0;
95.232 +
95.233 +static void init_debug(void)
95.234 +{
95.235 + char *dstr, *fn, *tmp;
95.236 + int fd, flags;
95.237 +
95.238 + if (debug_mask & DEBUG_INIT)
95.239 + return;
95.240 +
95.241 + dstr = getenv("COMERR_DEBUG");
95.242 + if (dstr) {
95.243 + debug_mask = strtoul(dstr, &tmp, 0);
95.244 + if (*tmp || errno)
95.245 + debug_mask = 0;
95.246 + }
95.247 +
95.248 + debug_mask |= DEBUG_INIT;
95.249 + if (debug_mask == DEBUG_INIT)
95.250 + return;
95.251 +
95.252 + fn = safe_getenv("COMERR_DEBUG_FILE");
95.253 + if (fn)
95.254 + debug_f = fopen(fn, "a");
95.255 + if (!debug_f)
95.256 + debug_f = fopen("/dev/tty", "a");
95.257 + if (debug_f) {
95.258 + fd = fileno(debug_f);
95.259 +#if defined(HAVE_FCNTL)
95.260 + if (fd >= 0) {
95.261 + flags = fcntl(fd, F_GETFD);
95.262 + if (flags >= 0)
95.263 + flags = fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
95.264 + if (flags < 0) {
95.265 + fprintf(debug_f, "Couldn't set FD_CLOEXEC "
95.266 + "on debug FILE: %s\n", strerror(errno));
95.267 + fclose(debug_f);
95.268 + debug_f = NULL;
95.269 + debug_mask = DEBUG_INIT;
95.270 + }
95.271 + }
95.272 +#endif
95.273 + } else
95.274 + debug_mask = DEBUG_INIT;
95.275 +
95.276 +}
95.277 +
95.278 +/*
95.279 + * New interface provided by krb5's com_err library
95.280 + */
95.281 +errcode_t add_error_table(const struct error_table * et)
95.282 +{
95.283 + struct et_list *el;
95.284 +
95.285 + if (!(el = (struct et_list *) malloc(sizeof(struct et_list))))
95.286 + return ENOMEM;
95.287 +
95.288 + if (et_list_lock() != 0) {
95.289 + free(el);
95.290 + return errno;
95.291 + }
95.292 +
95.293 + el->table = et;
95.294 + el->next = _et_dynamic_list;
95.295 + _et_dynamic_list = el;
95.296 +
95.297 + init_debug();
95.298 + if (debug_mask & DEBUG_ADDREMOVE)
95.299 + fprintf(debug_f, "add_error_table: %s (0x%p)\n",
95.300 + error_table_name(et->base),
95.301 + (const void *) et);
95.302 +
95.303 + et_list_unlock();
95.304 + return 0;
95.305 +}
95.306 +
95.307 +/*
95.308 + * New interface provided by krb5's com_err library
95.309 + */
95.310 +errcode_t remove_error_table(const struct error_table * et)
95.311 +{
95.312 + struct et_list *el;
95.313 + struct et_list *el2 = 0;
95.314 +
95.315 + if (et_list_lock() != 0)
95.316 + return ENOENT;
95.317 +
95.318 + el = _et_dynamic_list;
95.319 + init_debug();
95.320 + while (el) {
95.321 + if (el->table->base == et->base) {
95.322 + if (el2) /* Not the beginning of the list */
95.323 + el2->next = el->next;
95.324 + else
95.325 + _et_dynamic_list = el->next;
95.326 + (void) free(el);
95.327 + if (debug_mask & DEBUG_ADDREMOVE)
95.328 + fprintf(debug_f,
95.329 + "remove_error_table: %s (0x%p)\n",
95.330 + error_table_name(et->base),
95.331 + (const void *) et);
95.332 + et_list_unlock();
95.333 + return 0;
95.334 + }
95.335 + el2 = el;
95.336 + el = el->next;
95.337 + }
95.338 + if (debug_mask & DEBUG_ADDREMOVE)
95.339 + fprintf(debug_f, "remove_error_table FAILED: %s (0x%p)\n",
95.340 + error_table_name(et->base),
95.341 + (const void *) et);
95.342 + et_list_unlock();
95.343 + return ENOENT;
95.344 +}
95.345 +
95.346 +/*
95.347 + * Variant of the interface provided by Heimdal's com_err library
95.348 + */
95.349 +void
95.350 +add_to_error_table(struct et_list *new_table)
95.351 +{
95.352 + add_error_table(new_table->table);
95.353 +}
96.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
96.2 +++ b/libext2fs/lib/libet/error_table.h Wed Aug 25 01:28:08 2021 +0200
96.3 @@ -0,0 +1,29 @@
96.4 +/*
96.5 + * Copyright 1988 by the Student Information Processing Board of the
96.6 + * Massachusetts Institute of Technology.
96.7 + *
96.8 + * Permission to use, copy, modify, and distribute this software and
96.9 + * its documentation for any purpose is hereby granted, provided that
96.10 + * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
96.11 + * advertising or publicity pertaining to distribution of the software
96.12 + * without specific, written prior permission. M.I.T. and the
96.13 + * M.I.T. S.I.P.B. make no representations about the suitability of
96.14 + * this software for any purpose. It is provided "as is" without
96.15 + * express or implied warranty.
96.16 + */
96.17 +
96.18 +#ifndef _ET_H
96.19 +
96.20 +struct et_list {
96.21 + struct et_list *next;
96.22 + const struct error_table *table;
96.23 +};
96.24 +extern struct et_list *_et_list, *_et_dynamic_list;
96.25 +
96.26 +#define ERRCODE_RANGE 8 /* # of bits to shift table number */
96.27 +#define BITS_PER_CHAR 6 /* # bits to shift per character in name */
96.28 +
96.29 +extern const char *error_table_name(errcode_t num);
96.30 +
96.31 +#define _ET_H
96.32 +#endif
97.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
97.2 +++ b/libext2fs/lib/libet/et_name.c Wed Aug 25 01:28:08 2021 +0200
97.3 @@ -0,0 +1,43 @@
97.4 +/*
97.5 + * Copyright 1987 by MIT Student Information Processing Board
97.6 + *
97.7 + * Permission to use, copy, modify, and distribute this software and
97.8 + * its documentation for any purpose is hereby granted, provided that
97.9 + * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
97.10 + * advertising or publicity pertaining to distribution of the software
97.11 + * without specific, written prior permission. M.I.T. and the
97.12 + * M.I.T. S.I.P.B. make no representations about the suitability of
97.13 + * this software for any purpose. It is provided "as is" without
97.14 + * express or implied warranty.
97.15 + */
97.16 +
97.17 +#include "config.h"
97.18 +#include "com_err.h"
97.19 +#include "error_table.h"
97.20 +#include "internal.h"
97.21 +
97.22 +static const char char_set[] =
97.23 + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
97.24 +
97.25 +static char buf[6];
97.26 +
97.27 +const char * error_table_name(errcode_t num)
97.28 +{
97.29 + int ch;
97.30 + int i;
97.31 + char *p;
97.32 +
97.33 + /* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
97.34 + p = buf;
97.35 + num >>= ERRCODE_RANGE;
97.36 + /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
97.37 + num &= 077777777L;
97.38 + /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
97.39 + for (i = 4; i >= 0; i--) {
97.40 + ch = (int)((num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1));
97.41 + if (ch != 0)
97.42 + *p++ = char_set[ch-1];
97.43 + }
97.44 + *p = '\0';
97.45 + return(buf);
97.46 +}
98.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
98.2 +++ b/libext2fs/lib/libet/init_et.c Wed Aug 25 01:28:08 2021 +0200
98.3 @@ -0,0 +1,53 @@
98.4 +/*
98.5 + * $Header$
98.6 + * $Source$
98.7 + * $Locker$
98.8 + *
98.9 + * Copyright 1986, 1987, 1988 by MIT Information Systems and
98.10 + * the MIT Student Information Processing Board.
98.11 + *
98.12 + * Permission to use, copy, modify, and distribute this software and
98.13 + * its documentation for any purpose is hereby granted, provided that
98.14 + * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
98.15 + * advertising or publicity pertaining to distribution of the software
98.16 + * without specific, written prior permission. M.I.T. and the
98.17 + * M.I.T. S.I.P.B. make no representations about the suitability of
98.18 + * this software for any purpose. It is provided "as is" without
98.19 + * express or implied warranty.
98.20 + */
98.21 +
98.22 +#include "config.h"
98.23 +#include <stdio.h>
98.24 +#include <errno.h>
98.25 +#ifdef HAVE_STDLIB_H
98.26 +#include <stdlib.h>
98.27 +#endif
98.28 +#include "com_err.h"
98.29 +#include "error_table.h"
98.30 +
98.31 +struct foobar {
98.32 + struct et_list etl;
98.33 + struct error_table et;
98.34 +};
98.35 +
98.36 +extern struct et_list * _et_dynamic_list;
98.37 +
98.38 +int init_error_table(const char * const *msgs, long base, int count)
98.39 +{
98.40 + struct foobar * new_et;
98.41 +
98.42 + if (!base || !count || !msgs)
98.43 + return 0;
98.44 +
98.45 + new_et = (struct foobar *) malloc(sizeof(struct foobar));
98.46 + if (!new_et)
98.47 + return ENOMEM; /* oops */
98.48 + new_et->etl.table = &new_et->et;
98.49 + new_et->et.msgs = msgs;
98.50 + new_et->et.base = base;
98.51 + new_et->et.n_msgs= count;
98.52 +
98.53 + new_et->etl.next = _et_dynamic_list;
98.54 + _et_dynamic_list = &new_et->etl;
98.55 + return 0;
98.56 +}
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
99.2 +++ b/libext2fs/lib/libet/internal.h Wed Aug 25 01:28:08 2021 +0200
99.3 @@ -0,0 +1,19 @@
99.4 +/*
99.5 + * internal include file for com_err package
99.6 + *
99.7 + * Permission to use, copy, modify, and distribute this software and
99.8 + * its documentation for any purpose is hereby granted, provided that
99.9 + * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
99.10 + * advertising or publicity pertaining to distribution of the software
99.11 + * without specific, written prior permission. M.I.T. and the
99.12 + * M.I.T. S.I.P.B. make no representations about the suitability of
99.13 + * this software for any purpose. It is provided "as is" without
99.14 + * express or implied warranty.
99.15 + */
99.16 +
99.17 +#include <errno.h>
99.18 +
99.19 +#ifdef NEED_SYS_ERRLIST
99.20 +extern char const * const sys_errlist[];
99.21 +extern const int sys_nerr;
99.22 +#endif
100.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
100.2 +++ b/libext2fs/lib/libet/vfprintf.c Wed Aug 25 01:28:08 2021 +0200
100.3 @@ -0,0 +1,50 @@
100.4 +/*
100.5 + * Copyright (c) 1988 Regents of the University of California.
100.6 + * All rights reserved.
100.7 + *
100.8 + * Redistribution and use in source and binary forms are permitted
100.9 + * provided that the above copyright notice and this paragraph are
100.10 + * duplicated in all such forms and that any documentation,
100.11 + * advertising materials, and other materials related to such
100.12 + * distribution and use acknowledge that the software was developed
100.13 + * by the University of California, Berkeley. The name of the
100.14 + * University may not be used to endorse or promote products derived
100.15 + * from this software without specific prior written permission.
100.16 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
100.17 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
100.18 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
100.19 + */
100.20 +
100.21 +#if defined(LIBC_SCCS) && !defined(lint)
100.22 +static char sccsid[] = "@(#)vfprintf.c 5.2 (Berkeley) 6/27/88";
100.23 +#endif /* LIBC_SCCS and not lint */
100.24 +
100.25 +#include "config.h"
100.26 +#if !HAVE_VPRINTF && HAVE_DOPRNT
100.27 +#include <stdio.h>
100.28 +#include <varargs.h>
100.29 +
100.30 +int
100.31 +vfprintf(iop, fmt, ap)
100.32 + FILE *iop;
100.33 + char *fmt;
100.34 + va_list ap;
100.35 +{
100.36 + int len;
100.37 + char localbuf[BUFSIZ];
100.38 +
100.39 + if (iop->_flag & _IONBF) {
100.40 + iop->_flag &= ~_IONBF;
100.41 + iop->_ptr = iop->_base = localbuf;
100.42 + len = _doprnt(fmt, ap, iop);
100.43 + (void) fflush(iop);
100.44 + iop->_flag |= _IONBF;
100.45 + iop->_base = NULL;
100.46 + iop->_bufsiz = 0;
100.47 + iop->_cnt = 0;
100.48 + } else
100.49 + len = _doprnt(fmt, ap, iop);
100.50 +
100.51 + return (ferror(iop) ? EOF : len);
100.52 +}
100.53 +#endif /* !HAVE_VPRINTF */
102.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
102.2 +++ b/libext2fs/lib/libext2fs/alloc.c Wed Aug 25 01:28:08 2021 +0200
102.3 @@ -0,0 +1,554 @@
102.4 +/*
102.5 + * alloc.c --- allocate new inodes, blocks for ext2fs
102.6 + *
102.7 + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
102.8 + *
102.9 + * %Begin-Header%
102.10 + * This file may be redistributed under the terms of the GNU Library
102.11 + * General Public License, version 2.
102.12 + * %End-Header%
102.13 + */
102.14 +
102.15 +#include "config.h"
102.16 +#include <stdio.h>
102.17 +#if HAVE_UNISTD_H
102.18 +#include <unistd.h>
102.19 +#endif
102.20 +#include <time.h>
102.21 +#include <string.h>
102.22 +#if HAVE_SYS_STAT_H
102.23 +#include <sys/stat.h>
102.24 +#endif
102.25 +#if HAVE_SYS_TYPES_H
102.26 +#include <sys/types.h>
102.27 +#endif
102.28 +
102.29 +#include "ext2_fs.h"
102.30 +#include "ext2fs.h"
102.31 +
102.32 +#define min(a, b) ((a) < (b) ? (a) : (b))
102.33 +
102.34 +#undef DEBUG
102.35 +
102.36 +#ifdef DEBUG
102.37 +# define dbg_printf(f, a...) do {printf(f, ## a); fflush(stdout); } while (0)
102.38 +#else
102.39 +# define dbg_printf(f, a...)
102.40 +#endif
102.41 +
102.42 +/*
102.43 + * Clear the uninit block bitmap flag if necessary
102.44 + */
102.45 +void ext2fs_clear_block_uninit(ext2_filsys fs, dgrp_t group)
102.46 +{
102.47 + if (group >= fs->group_desc_count ||
102.48 + !ext2fs_has_group_desc_csum(fs) ||
102.49 + !(ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
102.50 + return;
102.51 +
102.52 + /* uninit block bitmaps are now initialized in read_bitmaps() */
102.53 +
102.54 + ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
102.55 + ext2fs_group_desc_csum_set(fs, group);
102.56 + ext2fs_mark_super_dirty(fs);
102.57 + ext2fs_mark_bb_dirty(fs);
102.58 +}
102.59 +
102.60 +/*
102.61 + * Check for uninit inode bitmaps and deal with them appropriately
102.62 + */
102.63 +static void check_inode_uninit(ext2_filsys fs, ext2fs_inode_bitmap map,
102.64 + dgrp_t group)
102.65 +{
102.66 + ext2_ino_t i, ino;
102.67 +
102.68 + if (group >= fs->group_desc_count ||
102.69 + !ext2fs_has_group_desc_csum(fs) ||
102.70 + !(ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)))
102.71 + return;
102.72 +
102.73 + ino = (group * fs->super->s_inodes_per_group) + 1;
102.74 + for (i=0; i < fs->super->s_inodes_per_group; i++, ino++)
102.75 + ext2fs_fast_unmark_inode_bitmap2(map, ino);
102.76 +
102.77 + ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
102.78 + /* Mimics what the kernel does */
102.79 + ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
102.80 + ext2fs_group_desc_csum_set(fs, group);
102.81 + ext2fs_mark_ib_dirty(fs);
102.82 + ext2fs_mark_super_dirty(fs);
102.83 +}
102.84 +
102.85 +/*
102.86 + * Right now, just search forward from the parent directory's block
102.87 + * group to find the next free inode.
102.88 + *
102.89 + * Should have a special policy for directories.
102.90 + */
102.91 +errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
102.92 + int mode EXT2FS_ATTR((unused)),
102.93 + ext2fs_inode_bitmap map, ext2_ino_t *ret)
102.94 +{
102.95 + ext2_ino_t start_inode = 0;
102.96 + ext2_ino_t i, ino_in_group, upto, first_zero;
102.97 + errcode_t retval;
102.98 + dgrp_t group;
102.99 +
102.100 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
102.101 +
102.102 + if (!map)
102.103 + map = fs->inode_map;
102.104 + if (!map)
102.105 + return EXT2_ET_NO_INODE_BITMAP;
102.106 +
102.107 + if (dir > 0) {
102.108 + group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super);
102.109 + start_inode = (group * EXT2_INODES_PER_GROUP(fs->super)) + 1;
102.110 + }
102.111 + if (start_inode < EXT2_FIRST_INODE(fs->super))
102.112 + start_inode = EXT2_FIRST_INODE(fs->super);
102.113 + if (start_inode > fs->super->s_inodes_count)
102.114 + return EXT2_ET_INODE_ALLOC_FAIL;
102.115 + i = start_inode;
102.116 + do {
102.117 + ino_in_group = (i - 1) % EXT2_INODES_PER_GROUP(fs->super);
102.118 + group = (i - 1) / EXT2_INODES_PER_GROUP(fs->super);
102.119 +
102.120 + check_inode_uninit(fs, map, group);
102.121 + upto = i + (EXT2_INODES_PER_GROUP(fs->super) - ino_in_group);
102.122 + if (i < start_inode && upto >= start_inode)
102.123 + upto = start_inode - 1;
102.124 + if (upto > fs->super->s_inodes_count)
102.125 + upto = fs->super->s_inodes_count;
102.126 +
102.127 + retval = ext2fs_find_first_zero_inode_bitmap2(map, i, upto,
102.128 + &first_zero);
102.129 + if (retval == 0) {
102.130 + i = first_zero;
102.131 + break;
102.132 + }
102.133 + if (retval != ENOENT)
102.134 + return EXT2_ET_INODE_ALLOC_FAIL;
102.135 + i = upto + 1;
102.136 + if (i > fs->super->s_inodes_count)
102.137 + i = EXT2_FIRST_INODE(fs->super);
102.138 + } while (i != start_inode);
102.139 +
102.140 + if (ext2fs_test_inode_bitmap2(map, i))
102.141 + return EXT2_ET_INODE_ALLOC_FAIL;
102.142 + *ret = i;
102.143 + return 0;
102.144 +}
102.145 +
102.146 +/*
102.147 + * Stupid algorithm --- we now just search forward starting from the
102.148 + * goal. Should put in a smarter one someday....
102.149 + */
102.150 +errcode_t ext2fs_new_block3(ext2_filsys fs, blk64_t goal,
102.151 + ext2fs_block_bitmap map, blk64_t *ret,
102.152 + struct blk_alloc_ctx *ctx)
102.153 +{
102.154 + errcode_t retval;
102.155 + blk64_t b = 0;
102.156 + errcode_t (*gab)(ext2_filsys fs, blk64_t goal, blk64_t *ret);
102.157 + errcode_t (*gab2)(ext2_filsys, blk64_t, blk64_t *,
102.158 + struct blk_alloc_ctx *);
102.159 +
102.160 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
102.161 +
102.162 + if (!map) {
102.163 + /*
102.164 + * In case there are clients out there whose get_alloc_block
102.165 + * handlers call ext2fs_new_block2 with a NULL block map,
102.166 + * temporarily swap out the function pointer so that we don't
102.167 + * end up in an infinite loop.
102.168 + */
102.169 + if (fs->get_alloc_block2) {
102.170 + gab2 = fs->get_alloc_block2;
102.171 + fs->get_alloc_block2 = NULL;
102.172 + retval = gab2(fs, goal, &b, ctx);
102.173 + fs->get_alloc_block2 = gab2;
102.174 + goto allocated;
102.175 + } else if (fs->get_alloc_block) {
102.176 + gab = fs->get_alloc_block;
102.177 + fs->get_alloc_block = NULL;
102.178 + retval = gab(fs, goal, &b);
102.179 + fs->get_alloc_block = gab;
102.180 + goto allocated;
102.181 + }
102.182 + }
102.183 + if (!map)
102.184 + map = fs->block_map;
102.185 + if (!map)
102.186 + return EXT2_ET_NO_BLOCK_BITMAP;
102.187 + if (!goal || (goal >= ext2fs_blocks_count(fs->super)))
102.188 + goal = fs->super->s_first_data_block;
102.189 + goal &= ~EXT2FS_CLUSTER_MASK(fs);
102.190 +
102.191 + retval = ext2fs_find_first_zero_block_bitmap2(map,
102.192 + goal, ext2fs_blocks_count(fs->super) - 1, &b);
102.193 + if ((retval == ENOENT) && (goal != fs->super->s_first_data_block))
102.194 + retval = ext2fs_find_first_zero_block_bitmap2(map,
102.195 + fs->super->s_first_data_block, goal - 1, &b);
102.196 +allocated:
102.197 + if (retval == ENOENT)
102.198 + return EXT2_ET_BLOCK_ALLOC_FAIL;
102.199 + if (retval)
102.200 + return retval;
102.201 +
102.202 + ext2fs_clear_block_uninit(fs, ext2fs_group_of_blk2(fs, b));
102.203 + *ret = b;
102.204 + return 0;
102.205 +}
102.206 +
102.207 +errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal,
102.208 + ext2fs_block_bitmap map, blk64_t *ret)
102.209 +{
102.210 + return ext2fs_new_block3(fs, goal, map, ret, NULL);
102.211 +}
102.212 +
102.213 +errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
102.214 + ext2fs_block_bitmap map, blk_t *ret)
102.215 +{
102.216 + errcode_t retval;
102.217 + blk64_t val;
102.218 + retval = ext2fs_new_block2(fs, goal, map, &val);
102.219 + if (!retval)
102.220 + *ret = (blk_t) val;
102.221 + return retval;
102.222 +}
102.223 +
102.224 +/*
102.225 + * This function zeros out the allocated block, and updates all of the
102.226 + * appropriate filesystem records.
102.227 + */
102.228 +errcode_t ext2fs_alloc_block3(ext2_filsys fs, blk64_t goal, char *block_buf,
102.229 + blk64_t *ret, struct blk_alloc_ctx *ctx)
102.230 +{
102.231 + errcode_t retval;
102.232 + blk64_t block;
102.233 +
102.234 + if (fs->get_alloc_block2) {
102.235 + retval = (fs->get_alloc_block2)(fs, goal, &block, ctx);
102.236 + if (retval)
102.237 + goto fail;
102.238 + } else if (fs->get_alloc_block) {
102.239 + retval = (fs->get_alloc_block)(fs, goal, &block);
102.240 + if (retval)
102.241 + goto fail;
102.242 + } else {
102.243 + if (!fs->block_map) {
102.244 + retval = ext2fs_read_block_bitmap(fs);
102.245 + if (retval)
102.246 + goto fail;
102.247 + }
102.248 +
102.249 + retval = ext2fs_new_block3(fs, goal, 0, &block, ctx);
102.250 + if (retval)
102.251 + goto fail;
102.252 + }
102.253 +
102.254 + if (block_buf) {
102.255 + memset(block_buf, 0, fs->blocksize);
102.256 + retval = io_channel_write_blk64(fs->io, block, 1, block_buf);
102.257 + } else
102.258 + retval = ext2fs_zero_blocks2(fs, block, 1, NULL, NULL);
102.259 + if (retval)
102.260 + goto fail;
102.261 +
102.262 + ext2fs_block_alloc_stats2(fs, block, +1);
102.263 + *ret = block;
102.264 +
102.265 +fail:
102.266 + return retval;
102.267 +}
102.268 +
102.269 +errcode_t ext2fs_alloc_block2(ext2_filsys fs, blk64_t goal,
102.270 + char *block_buf, blk64_t *ret)
102.271 +{
102.272 + return ext2fs_alloc_block3(fs, goal, block_buf, ret, NULL);
102.273 +}
102.274 +
102.275 +errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
102.276 + char *block_buf, blk_t *ret)
102.277 +{
102.278 + errcode_t retval;
102.279 + blk64_t ret64, goal64 = goal;
102.280 + retval = ext2fs_alloc_block3(fs, goal64, block_buf, &ret64, NULL);
102.281 + if (!retval)
102.282 + *ret = (blk_t)ret64;
102.283 + return retval;
102.284 +}
102.285 +
102.286 +errcode_t ext2fs_get_free_blocks2(ext2_filsys fs, blk64_t start, blk64_t finish,
102.287 + int num, ext2fs_block_bitmap map, blk64_t *ret)
102.288 +{
102.289 + blk64_t b = start;
102.290 + int c_ratio;
102.291 +
102.292 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
102.293 +
102.294 + if (!map)
102.295 + map = fs->block_map;
102.296 + if (!map)
102.297 + return EXT2_ET_NO_BLOCK_BITMAP;
102.298 + if (!b)
102.299 + b = fs->super->s_first_data_block;
102.300 + if (!finish)
102.301 + finish = start;
102.302 + if (!num)
102.303 + num = 1;
102.304 + c_ratio = 1 << ext2fs_get_bitmap_granularity(map);
102.305 + b &= ~(c_ratio - 1);
102.306 + finish &= ~(c_ratio -1);
102.307 + do {
102.308 + if (b + num - 1 >= ext2fs_blocks_count(fs->super)) {
102.309 + if (finish > start)
102.310 + return EXT2_ET_BLOCK_ALLOC_FAIL;
102.311 + b = fs->super->s_first_data_block;
102.312 + }
102.313 + if (ext2fs_fast_test_block_bitmap_range2(map, b, num)) {
102.314 + *ret = b;
102.315 + return 0;
102.316 + }
102.317 + b += c_ratio;
102.318 + } while (b != finish);
102.319 + return EXT2_ET_BLOCK_ALLOC_FAIL;
102.320 +}
102.321 +
102.322 +errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
102.323 + int num, ext2fs_block_bitmap map, blk_t *ret)
102.324 +{
102.325 + errcode_t retval;
102.326 + blk64_t val;
102.327 + retval = ext2fs_get_free_blocks2(fs, start, finish, num, map, &val);
102.328 + if(!retval)
102.329 + *ret = (blk_t) val;
102.330 + return retval;
102.331 +}
102.332 +
102.333 +void ext2fs_set_alloc_block_callback(ext2_filsys fs,
102.334 + errcode_t (*func)(ext2_filsys fs,
102.335 + blk64_t goal,
102.336 + blk64_t *ret),
102.337 + errcode_t (**old)(ext2_filsys fs,
102.338 + blk64_t goal,
102.339 + blk64_t *ret))
102.340 +{
102.341 + if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
102.342 + return;
102.343 +
102.344 + if (old)
102.345 + *old = fs->get_alloc_block;
102.346 +
102.347 + fs->get_alloc_block = func;
102.348 +}
102.349 +
102.350 +blk64_t ext2fs_find_inode_goal(ext2_filsys fs, ext2_ino_t ino,
102.351 + struct ext2_inode *inode, blk64_t lblk)
102.352 +{
102.353 + dgrp_t group;
102.354 + __u8 log_flex;
102.355 + struct ext2fs_extent extent;
102.356 + ext2_extent_handle_t handle = NULL;
102.357 + errcode_t err;
102.358 +
102.359 + /* Make sure data stored in inode->i_block is neither fast symlink nor
102.360 + * inline data.
102.361 + */
102.362 + if (inode == NULL || ext2fs_is_fast_symlink(inode) ||
102.363 + inode->i_flags & EXT4_INLINE_DATA_FL)
102.364 + goto no_blocks;
102.365 +
102.366 + if (inode->i_flags & EXT4_EXTENTS_FL) {
102.367 + err = ext2fs_extent_open2(fs, ino, inode, &handle);
102.368 + if (err)
102.369 + goto no_blocks;
102.370 + err = ext2fs_extent_goto2(handle, 0, lblk);
102.371 + if (err)
102.372 + goto no_blocks;
102.373 + err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
102.374 + if (err)
102.375 + goto no_blocks;
102.376 + ext2fs_extent_free(handle);
102.377 + return extent.e_pblk + (lblk - extent.e_lblk);
102.378 + }
102.379 +
102.380 + /* block mapped file; see if block zero is mapped? */
102.381 + if (inode->i_block[0])
102.382 + return inode->i_block[0];
102.383 +
102.384 +no_blocks:
102.385 + ext2fs_extent_free(handle);
102.386 + log_flex = fs->super->s_log_groups_per_flex;
102.387 + group = ext2fs_group_of_ino(fs, ino);
102.388 + if (log_flex)
102.389 + group = group & ~((1 << (log_flex)) - 1);
102.390 + return ext2fs_group_first_block2(fs, group);
102.391 +}
102.392 +
102.393 +/*
102.394 + * Starting at _goal_, scan around the filesystem to find a run of free blocks
102.395 + * that's at least _len_ blocks long. Possible flags:
102.396 + * - EXT2_NEWRANGE_EXACT_GOAL: The range of blocks must start at _goal_.
102.397 + * - EXT2_NEWRANGE_MIN_LENGTH: do not return a allocation shorter than _len_.
102.398 + * - EXT2_NEWRANGE_ZERO_BLOCKS: Zero blocks pblk to pblk+plen before returning.
102.399 + *
102.400 + * The starting block is returned in _pblk_ and the length is returned via
102.401 + * _plen_. The blocks are not marked in the bitmap; the caller must mark
102.402 + * however much of the returned run they actually use, hopefully via
102.403 + * ext2fs_block_alloc_stats_range().
102.404 + *
102.405 + * This function can return a range that is longer than what was requested.
102.406 + */
102.407 +errcode_t ext2fs_new_range(ext2_filsys fs, int flags, blk64_t goal,
102.408 + blk64_t len, ext2fs_block_bitmap map, blk64_t *pblk,
102.409 + blk64_t *plen)
102.410 +{
102.411 + errcode_t retval;
102.412 + blk64_t start, end, b;
102.413 + int looped = 0;
102.414 + blk64_t max_blocks = ext2fs_blocks_count(fs->super);
102.415 + errcode_t (*nrf)(ext2_filsys fs, int flags, blk64_t goal,
102.416 + blk64_t len, blk64_t *pblk, blk64_t *plen);
102.417 +
102.418 + dbg_printf("%s: flags=0x%x goal=%llu len=%llu\n", __func__, flags,
102.419 + goal, len);
102.420 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
102.421 + if (len == 0 || (flags & ~EXT2_NEWRANGE_ALL_FLAGS))
102.422 + return EXT2_ET_INVALID_ARGUMENT;
102.423 +
102.424 + if (!map && fs->new_range) {
102.425 + /*
102.426 + * In case there are clients out there whose new_range
102.427 + * handlers call ext2fs_new_range with a NULL block map,
102.428 + * temporarily swap out the function pointer so that we don't
102.429 + * end up in an infinite loop.
102.430 + */
102.431 + nrf = fs->new_range;
102.432 + fs->new_range = NULL;
102.433 + retval = nrf(fs, flags, goal, len, pblk, plen);
102.434 + fs->new_range = nrf;
102.435 + if (retval)
102.436 + return retval;
102.437 + start = *pblk;
102.438 + end = *pblk + *plen;
102.439 + goto allocated;
102.440 + }
102.441 + if (!map)
102.442 + map = fs->block_map;
102.443 + if (!map)
102.444 + return EXT2_ET_NO_BLOCK_BITMAP;
102.445 + if (!goal || goal >= ext2fs_blocks_count(fs->super))
102.446 + goal = fs->super->s_first_data_block;
102.447 +
102.448 + start = goal;
102.449 + while (!looped || start <= goal) {
102.450 + retval = ext2fs_find_first_zero_block_bitmap2(map, start,
102.451 + max_blocks - 1,
102.452 + &start);
102.453 + if (retval == ENOENT) {
102.454 + /*
102.455 + * If there are no free blocks beyond the starting
102.456 + * point, try scanning the whole filesystem, unless the
102.457 + * user told us only to allocate from _goal_, or if
102.458 + * we're already scanning the whole filesystem.
102.459 + */
102.460 + if (flags & EXT2_NEWRANGE_FIXED_GOAL ||
102.461 + start == fs->super->s_first_data_block)
102.462 + goto fail;
102.463 + start = fs->super->s_first_data_block;
102.464 + continue;
102.465 + } else if (retval)
102.466 + goto errout;
102.467 +
102.468 + if (flags & EXT2_NEWRANGE_FIXED_GOAL && start != goal)
102.469 + goto fail;
102.470 +
102.471 + b = min(start + len - 1, max_blocks - 1);
102.472 + retval = ext2fs_find_first_set_block_bitmap2(map, start, b,
102.473 + &end);
102.474 + if (retval == ENOENT)
102.475 + end = b + 1;
102.476 + else if (retval)
102.477 + goto errout;
102.478 +
102.479 + if (!(flags & EXT2_NEWRANGE_MIN_LENGTH) ||
102.480 + (end - start) >= len) {
102.481 + /* Success! */
102.482 + *pblk = start;
102.483 + *plen = end - start;
102.484 + dbg_printf("%s: new_range goal=%llu--%llu "
102.485 + "blk=%llu--%llu %llu\n",
102.486 + __func__, goal, goal + len - 1,
102.487 + *pblk, *pblk + *plen - 1, *plen);
102.488 +allocated:
102.489 + for (b = start; b < end;
102.490 + b += fs->super->s_blocks_per_group)
102.491 + ext2fs_clear_block_uninit(fs,
102.492 + ext2fs_group_of_blk2(fs, b));
102.493 + return 0;
102.494 + }
102.495 +
102.496 + if (flags & EXT2_NEWRANGE_FIXED_GOAL)
102.497 + goto fail;
102.498 + start = end;
102.499 + if (start >= max_blocks) {
102.500 + if (looped)
102.501 + goto fail;
102.502 + looped = 1;
102.503 + start = fs->super->s_first_data_block;
102.504 + }
102.505 + }
102.506 +
102.507 +fail:
102.508 + retval = EXT2_ET_BLOCK_ALLOC_FAIL;
102.509 +errout:
102.510 + return retval;
102.511 +}
102.512 +
102.513 +void ext2fs_set_new_range_callback(ext2_filsys fs,
102.514 + errcode_t (*func)(ext2_filsys fs, int flags, blk64_t goal,
102.515 + blk64_t len, blk64_t *pblk, blk64_t *plen),
102.516 + errcode_t (**old)(ext2_filsys fs, int flags, blk64_t goal,
102.517 + blk64_t len, blk64_t *pblk, blk64_t *plen))
102.518 +{
102.519 + if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
102.520 + return;
102.521 +
102.522 + if (old)
102.523 + *old = fs->new_range;
102.524 +
102.525 + fs->new_range = func;
102.526 +}
102.527 +
102.528 +errcode_t ext2fs_alloc_range(ext2_filsys fs, int flags, blk64_t goal,
102.529 + blk_t len, blk64_t *ret)
102.530 +{
102.531 + int newr_flags = EXT2_NEWRANGE_MIN_LENGTH;
102.532 + errcode_t retval;
102.533 + blk64_t plen;
102.534 +
102.535 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
102.536 + if (len == 0 || (flags & ~EXT2_ALLOCRANGE_ALL_FLAGS))
102.537 + return EXT2_ET_INVALID_ARGUMENT;
102.538 +
102.539 + if (flags & EXT2_ALLOCRANGE_FIXED_GOAL)
102.540 + newr_flags |= EXT2_NEWRANGE_FIXED_GOAL;
102.541 +
102.542 + retval = ext2fs_new_range(fs, newr_flags, goal, len, NULL, ret, &plen);
102.543 + if (retval)
102.544 + return retval;
102.545 +
102.546 + if (plen < len)
102.547 + return EXT2_ET_BLOCK_ALLOC_FAIL;
102.548 +
102.549 + if (flags & EXT2_ALLOCRANGE_ZERO_BLOCKS) {
102.550 + retval = ext2fs_zero_blocks2(fs, *ret, len, NULL, NULL);
102.551 + if (retval)
102.552 + return retval;
102.553 + }
102.554 +
102.555 + ext2fs_block_alloc_stats_range(fs, *ret, len, +1);
102.556 + return retval;
102.557 +}
103.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
103.2 +++ b/libext2fs/lib/libext2fs/alloc_sb.c Wed Aug 25 01:28:08 2021 +0200
103.3 @@ -0,0 +1,81 @@
103.4 +/*
103.5 + * alloc_sb.c --- Allocate the superblock and block group descriptors for a
103.6 + * newly initialized filesystem. Used by mke2fs when initializing a filesystem
103.7 + *
103.8 + * Copyright (C) 1994, 1995, 1996, 2003 Theodore Ts'o.
103.9 + *
103.10 + * %Begin-Header%
103.11 + * This file may be redistributed under the terms of the GNU Library
103.12 + * General Public License, version 2.
103.13 + * %End-Header%
103.14 + */
103.15 +
103.16 +#include "config.h"
103.17 +#include <stdio.h>
103.18 +#include <string.h>
103.19 +#if HAVE_UNISTD_H
103.20 +#include <unistd.h>
103.21 +#endif
103.22 +#include <fcntl.h>
103.23 +#include <time.h>
103.24 +#if HAVE_SYS_STAT_H
103.25 +#include <sys/stat.h>
103.26 +#endif
103.27 +#if HAVE_SYS_TYPES_H
103.28 +#include <sys/types.h>
103.29 +#endif
103.30 +
103.31 +#include "ext2_fs.h"
103.32 +#include "ext2fs.h"
103.33 +
103.34 +/*
103.35 + * This function reserves the superblock and block group descriptors
103.36 + * for a given block group. It currently returns the number of free
103.37 + * blocks assuming that inode table and allocation bitmaps will be in
103.38 + * the group. This is not necessarily the case when the flex_bg
103.39 + * feature is enabled, so callers should take care! It was only
103.40 + * really intended for use by mke2fs, and even there it's not that
103.41 + * useful. In the future, when we redo this function for 64-bit block
103.42 + * numbers, we should probably return the number of blocks used by the
103.43 + * super block and group descriptors instead.
103.44 + *
103.45 + * See also the comment for ext2fs_super_and_bgd_loc()
103.46 + */
103.47 +int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
103.48 + dgrp_t group,
103.49 + ext2fs_block_bitmap bmap)
103.50 +{
103.51 + blk64_t super_blk, old_desc_blk, new_desc_blk;
103.52 + blk_t used_blks;
103.53 + int old_desc_blocks, num_blocks;
103.54 +
103.55 + ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
103.56 + &old_desc_blk, &new_desc_blk, &used_blks);
103.57 +
103.58 + if (ext2fs_has_feature_meta_bg(fs->super))
103.59 + old_desc_blocks = fs->super->s_first_meta_bg;
103.60 + else
103.61 + old_desc_blocks =
103.62 + fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
103.63 +
103.64 + if (super_blk || (group == 0))
103.65 + ext2fs_mark_block_bitmap2(bmap, super_blk);
103.66 + if ((group == 0) && (fs->blocksize == 1024) &&
103.67 + EXT2FS_CLUSTER_RATIO(fs) > 1)
103.68 + ext2fs_mark_block_bitmap2(bmap, 0);
103.69 +
103.70 + if (old_desc_blk) {
103.71 + num_blocks = old_desc_blocks;
103.72 + if (old_desc_blk + num_blocks >= ext2fs_blocks_count(fs->super))
103.73 + num_blocks = ext2fs_blocks_count(fs->super) -
103.74 + old_desc_blk;
103.75 + ext2fs_mark_block_bitmap_range2(bmap, old_desc_blk, num_blocks);
103.76 + }
103.77 + if (new_desc_blk)
103.78 + ext2fs_mark_block_bitmap2(bmap, new_desc_blk);
103.79 +
103.80 + num_blocks = ext2fs_group_blocks_count(fs, group);
103.81 + num_blocks -= 2 + fs->inode_blocks_per_group + used_blks;
103.82 +
103.83 + return num_blocks ;
103.84 +}
104.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
104.2 +++ b/libext2fs/lib/libext2fs/alloc_stats.c Wed Aug 25 01:28:08 2021 +0200
104.3 @@ -0,0 +1,164 @@
104.4 +/*
104.5 + * alloc_stats.c --- Update allocation statistics for ext2fs
104.6 + *
104.7 + * Copyright (C) 2001 Theodore Ts'o.
104.8 + *
104.9 + * %Begin-Header%
104.10 + * This file may be redistributed under the terms of the GNU Library
104.11 + * General Public License, version 2.
104.12 + * %End-Header%
104.13 + */
104.14 +
104.15 +#include "config.h"
104.16 +#include <stdio.h>
104.17 +
104.18 +#include "ext2_fs.h"
104.19 +#include "ext2fs.h"
104.20 +
104.21 +void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
104.22 + int inuse, int isdir)
104.23 +{
104.24 + int group = ext2fs_group_of_ino(fs, ino);
104.25 +
104.26 + if (ino > fs->super->s_inodes_count) {
104.27 +#ifndef OMIT_COM_ERR
104.28 + com_err("ext2fs_inode_alloc_stats2", 0,
104.29 + "Illegal inode number: %lu", (unsigned long) ino);
104.30 +#endif
104.31 + return;
104.32 + }
104.33 + if (inuse > 0)
104.34 + ext2fs_mark_inode_bitmap2(fs->inode_map, ino);
104.35 + else
104.36 + ext2fs_unmark_inode_bitmap2(fs->inode_map, ino);
104.37 + ext2fs_bg_free_inodes_count_set(fs, group, ext2fs_bg_free_inodes_count(fs, group) - inuse);
104.38 + if (isdir)
104.39 + ext2fs_bg_used_dirs_count_set(fs, group, ext2fs_bg_used_dirs_count(fs, group) + inuse);
104.40 +
104.41 + /* We don't strictly need to be clearing the uninit flag if inuse < 0
104.42 + * (i.e. freeing inodes) but it also means something is bad. */
104.43 + ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
104.44 + if (ext2fs_has_group_desc_csum(fs)) {
104.45 + ext2_ino_t first_unused_inode = fs->super->s_inodes_per_group -
104.46 + ext2fs_bg_itable_unused(fs, group) +
104.47 + group * fs->super->s_inodes_per_group + 1;
104.48 +
104.49 + if (ino >= first_unused_inode)
104.50 + ext2fs_bg_itable_unused_set(fs, group, group * fs->super->s_inodes_per_group + fs->super->s_inodes_per_group - ino);
104.51 + ext2fs_group_desc_csum_set(fs, group);
104.52 + }
104.53 +
104.54 + fs->super->s_free_inodes_count -= inuse;
104.55 + ext2fs_mark_super_dirty(fs);
104.56 + ext2fs_mark_ib_dirty(fs);
104.57 +}
104.58 +
104.59 +void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse)
104.60 +{
104.61 + ext2fs_inode_alloc_stats2(fs, ino, inuse, 0);
104.62 +}
104.63 +
104.64 +void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse)
104.65 +{
104.66 + int group = ext2fs_group_of_blk2(fs, blk);
104.67 +
104.68 + if (blk >= ext2fs_blocks_count(fs->super)) {
104.69 +#ifndef OMIT_COM_ERR
104.70 + com_err("ext2fs_block_alloc_stats", 0,
104.71 + "Illegal block number: %lu", (unsigned long) blk);
104.72 +#endif
104.73 + return;
104.74 + }
104.75 + if (inuse > 0)
104.76 + ext2fs_mark_block_bitmap2(fs->block_map, blk);
104.77 + else
104.78 + ext2fs_unmark_block_bitmap2(fs->block_map, blk);
104.79 + ext2fs_bg_free_blocks_count_set(fs, group, ext2fs_bg_free_blocks_count(fs, group) - inuse);
104.80 + ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
104.81 + ext2fs_group_desc_csum_set(fs, group);
104.82 +
104.83 + ext2fs_free_blocks_count_add(fs->super,
104.84 + -inuse * (blk64_t) EXT2FS_CLUSTER_RATIO(fs));
104.85 + ext2fs_mark_super_dirty(fs);
104.86 + ext2fs_mark_bb_dirty(fs);
104.87 + if (fs->block_alloc_stats)
104.88 + (fs->block_alloc_stats)(fs, (blk64_t) blk, inuse);
104.89 +}
104.90 +
104.91 +void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse)
104.92 +{
104.93 + ext2fs_block_alloc_stats2(fs, blk, inuse);
104.94 +}
104.95 +
104.96 +void ext2fs_set_block_alloc_stats_callback(ext2_filsys fs,
104.97 + void (*func)(ext2_filsys fs,
104.98 + blk64_t blk,
104.99 + int inuse),
104.100 + void (**old)(ext2_filsys fs,
104.101 + blk64_t blk,
104.102 + int inuse))
104.103 +{
104.104 + if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
104.105 + return;
104.106 + if (old)
104.107 + *old = fs->block_alloc_stats;
104.108 +
104.109 + fs->block_alloc_stats = func;
104.110 +}
104.111 +
104.112 +void ext2fs_block_alloc_stats_range(ext2_filsys fs, blk64_t blk,
104.113 + blk_t num, int inuse)
104.114 +{
104.115 +#ifndef OMIT_COM_ERR
104.116 + if (blk + num > ext2fs_blocks_count(fs->super)) {
104.117 + com_err("ext2fs_block_alloc_stats_range", 0,
104.118 + "Illegal block range: %llu (%u) ",
104.119 + (unsigned long long) blk, num);
104.120 + return;
104.121 + }
104.122 +#endif
104.123 + if (inuse == 0)
104.124 + return;
104.125 + if (inuse > 0) {
104.126 + ext2fs_mark_block_bitmap_range2(fs->block_map, blk, num);
104.127 + inuse = 1;
104.128 + } else {
104.129 + ext2fs_unmark_block_bitmap_range2(fs->block_map, blk, num);
104.130 + inuse = -1;
104.131 + }
104.132 + while (num) {
104.133 + int group = ext2fs_group_of_blk2(fs, blk);
104.134 + blk64_t last_blk = ext2fs_group_last_block2(fs, group);
104.135 + blk64_t n = num;
104.136 +
104.137 + if (blk + num > last_blk)
104.138 + n = last_blk - blk + 1;
104.139 +
104.140 + ext2fs_bg_free_blocks_count_set(fs, group,
104.141 + ext2fs_bg_free_blocks_count(fs, group) -
104.142 + inuse*n/EXT2FS_CLUSTER_RATIO(fs));
104.143 + ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
104.144 + ext2fs_group_desc_csum_set(fs, group);
104.145 + ext2fs_free_blocks_count_add(fs->super, -inuse * (blk64_t) n);
104.146 + blk += n;
104.147 + num -= n;
104.148 + }
104.149 + ext2fs_mark_super_dirty(fs);
104.150 + ext2fs_mark_bb_dirty(fs);
104.151 + if (fs->block_alloc_stats_range)
104.152 + (fs->block_alloc_stats_range)(fs, blk, num, inuse);
104.153 +}
104.154 +
104.155 +void ext2fs_set_block_alloc_stats_range_callback(ext2_filsys fs,
104.156 + void (*func)(ext2_filsys fs, blk64_t blk,
104.157 + blk_t num, int inuse),
104.158 + void (**old)(ext2_filsys fs, blk64_t blk,
104.159 + blk_t num, int inuse))
104.160 +{
104.161 + if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
104.162 + return;
104.163 + if (old)
104.164 + *old = fs->block_alloc_stats_range;
104.165 +
104.166 + fs->block_alloc_stats_range = func;
104.167 +}
105.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
105.2 +++ b/libext2fs/lib/libext2fs/alloc_tables.c Wed Aug 25 01:28:08 2021 +0200
105.3 @@ -0,0 +1,278 @@
105.4 +/*
105.5 + * alloc_tables.c --- Allocate tables for a newly initialized
105.6 + * filesystem. Used by mke2fs when initializing a filesystem
105.7 + *
105.8 + * Copyright (C) 1996 Theodore Ts'o.
105.9 + *
105.10 + * %Begin-Header%
105.11 + * This file may be redistributed under the terms of the GNU Library
105.12 + * General Public License, version 2.
105.13 + * %End-Header%
105.14 + */
105.15 +
105.16 +#include "config.h"
105.17 +#include <stdio.h>
105.18 +#include <string.h>
105.19 +#if HAVE_UNISTD_H
105.20 +#include <unistd.h>
105.21 +#endif
105.22 +#include <fcntl.h>
105.23 +#include <time.h>
105.24 +#if HAVE_SYS_STAT_H
105.25 +#include <sys/stat.h>
105.26 +#endif
105.27 +#if HAVE_SYS_TYPES_H
105.28 +#include <sys/types.h>
105.29 +#endif
105.30 +
105.31 +#include "ext2_fs.h"
105.32 +#include "ext2fs.h"
105.33 +#include "ext2fsP.h"
105.34 +
105.35 +/*
105.36 + * This routine searches for free blocks that can allocate a full
105.37 + * group of bitmaps or inode tables for a flexbg group. Returns the
105.38 + * block number with a correct offset were the bitmaps and inode
105.39 + * tables can be allocated continuously and in order.
105.40 + */
105.41 +static blk64_t flexbg_offset(ext2_filsys fs, dgrp_t group, blk64_t start_blk,
105.42 + ext2fs_block_bitmap bmap, int rem_grp,
105.43 + int elem_size)
105.44 +{
105.45 + int flexbg, flexbg_size, size;
105.46 + blk64_t last_blk, first_free = 0;
105.47 + dgrp_t last_grp;
105.48 +
105.49 + flexbg_size = 1 << fs->super->s_log_groups_per_flex;
105.50 + flexbg = group / flexbg_size;
105.51 + size = rem_grp * elem_size;
105.52 +
105.53 + if (size > (int) (fs->super->s_blocks_per_group / 4))
105.54 + size = (int) fs->super->s_blocks_per_group / 4;
105.55 +
105.56 + /*
105.57 + * Don't do a long search if the previous block search is still valid,
105.58 + * but skip minor obstructions such as group descriptor backups.
105.59 + */
105.60 + if (start_blk && start_blk < ext2fs_blocks_count(fs->super) &&
105.61 + ext2fs_get_free_blocks2(fs, start_blk, start_blk + size, elem_size,
105.62 + bmap, &first_free) == 0)
105.63 + return first_free;
105.64 +
105.65 + start_blk = ext2fs_group_first_block2(fs, flexbg_size * flexbg);
105.66 + last_grp = group | (flexbg_size - 1);
105.67 + if (last_grp > fs->group_desc_count-1)
105.68 + last_grp = fs->group_desc_count-1;
105.69 + last_blk = ext2fs_group_last_block2(fs, last_grp);
105.70 +
105.71 + /* Find the first available block */
105.72 + if (ext2fs_get_free_blocks2(fs, start_blk, last_blk, size,
105.73 + bmap, &first_free) == 0)
105.74 + return first_free;
105.75 +
105.76 + if (ext2fs_get_free_blocks2(fs, start_blk, last_blk, elem_size,
105.77 + bmap, &first_free) == 0)
105.78 + return first_free;
105.79 +
105.80 + if (ext2fs_get_free_blocks2(fs, 0, last_blk, elem_size, bmap,
105.81 + &first_free) == 0)
105.82 + return first_free;
105.83 +
105.84 + return first_free;
105.85 +}
105.86 +
105.87 +errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
105.88 + ext2fs_block_bitmap bmap)
105.89 +{
105.90 + errcode_t retval;
105.91 + blk64_t group_blk, start_blk, last_blk, new_blk;
105.92 + dgrp_t last_grp = 0;
105.93 + int rem_grps = 0, flexbg_size = 0, table_offset = 0;
105.94 +
105.95 + group_blk = ext2fs_group_first_block2(fs, group);
105.96 + last_blk = ext2fs_group_last_block2(fs, group);
105.97 +
105.98 + if (!bmap)
105.99 + bmap = fs->block_map;
105.100 +
105.101 + if (ext2fs_has_feature_flex_bg(fs->super) &&
105.102 + fs->super->s_log_groups_per_flex) {
105.103 + flexbg_size = 1 << fs->super->s_log_groups_per_flex;
105.104 + last_grp = group | (flexbg_size - 1);
105.105 + if (last_grp > fs->group_desc_count-1)
105.106 + last_grp = fs->group_desc_count-1;
105.107 + rem_grps = last_grp - group + 1;
105.108 + }
105.109 +
105.110 + /*
105.111 + * Allocate the block and inode bitmaps, if necessary
105.112 + */
105.113 + if (fs->stride && !flexbg_size) {
105.114 + retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk,
105.115 + 1, bmap, &start_blk);
105.116 + if (retval)
105.117 + return retval;
105.118 + start_blk += fs->inode_blocks_per_group;
105.119 + start_blk += ((fs->stride * group) %
105.120 + (last_blk - start_blk + 1));
105.121 + if (start_blk >= last_blk)
105.122 + start_blk = group_blk;
105.123 + } else
105.124 + start_blk = group_blk;
105.125 +
105.126 + if (flexbg_size) {
105.127 + blk64_t prev_block = 0;
105.128 +
105.129 + table_offset = flexbg_size;
105.130 + if (group % flexbg_size)
105.131 + prev_block = ext2fs_block_bitmap_loc(fs, group - 1) + 1;
105.132 + else if (last_grp == fs->group_desc_count-1) {
105.133 + /*
105.134 + * If we are allocating for the last flex_bg
105.135 + * keep the metadata tables contiguous
105.136 + */
105.137 + table_offset = last_grp & (flexbg_size - 1);
105.138 + if (table_offset == 0)
105.139 + table_offset = flexbg_size;
105.140 + else
105.141 + table_offset++;
105.142 + }
105.143 + /* FIXME: Take backup group descriptor blocks into account
105.144 + * if the flexbg allocations will grow to overlap them... */
105.145 + start_blk = flexbg_offset(fs, group, prev_block, bmap,
105.146 + rem_grps, 1);
105.147 + last_blk = ext2fs_group_last_block2(fs, last_grp);
105.148 + }
105.149 +
105.150 + if (!ext2fs_block_bitmap_loc(fs, group)) {
105.151 + retval = ext2fs_get_free_blocks2(fs, start_blk, last_blk,
105.152 + 1, bmap, &new_blk);
105.153 + if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
105.154 + retval = ext2fs_get_free_blocks2(fs, group_blk,
105.155 + last_blk, 1, bmap, &new_blk);
105.156 + if (retval)
105.157 + return retval;
105.158 + ext2fs_mark_block_bitmap2(bmap, new_blk);
105.159 + ext2fs_block_bitmap_loc_set(fs, group, new_blk);
105.160 + if (flexbg_size) {
105.161 + dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk);
105.162 + ext2fs_bg_free_blocks_count_set(fs, gr, ext2fs_bg_free_blocks_count(fs, gr) - 1);
105.163 + ext2fs_free_blocks_count_add(fs->super, -1);
105.164 + ext2fs_bg_flags_clear(fs, gr, EXT2_BG_BLOCK_UNINIT);
105.165 + ext2fs_group_desc_csum_set(fs, gr);
105.166 + }
105.167 + }
105.168 +
105.169 + if (flexbg_size) {
105.170 + blk64_t prev_block = 0;
105.171 + if (group % flexbg_size)
105.172 + prev_block = ext2fs_inode_bitmap_loc(fs, group - 1) + 1;
105.173 + else
105.174 + prev_block = ext2fs_block_bitmap_loc(fs, group) +
105.175 + table_offset;
105.176 + /* FIXME: Take backup group descriptor blocks into account
105.177 + * if the flexbg allocations will grow to overlap them... */
105.178 + start_blk = flexbg_offset(fs, group, prev_block, bmap,
105.179 + rem_grps, 1);
105.180 + last_blk = ext2fs_group_last_block2(fs, last_grp);
105.181 + }
105.182 +
105.183 + if (!ext2fs_inode_bitmap_loc(fs, group)) {
105.184 + retval = ext2fs_get_free_blocks2(fs, start_blk, last_blk,
105.185 + 1, bmap, &new_blk);
105.186 + if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
105.187 + retval = ext2fs_get_free_blocks2(fs, group_blk,
105.188 + last_blk, 1, bmap, &new_blk);
105.189 + if (retval)
105.190 + return retval;
105.191 + ext2fs_mark_block_bitmap2(bmap, new_blk);
105.192 + ext2fs_inode_bitmap_loc_set(fs, group, new_blk);
105.193 + if (flexbg_size) {
105.194 + dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk);
105.195 + ext2fs_bg_free_blocks_count_set(fs, gr, ext2fs_bg_free_blocks_count(fs, gr) - 1);
105.196 + ext2fs_free_blocks_count_add(fs->super, -1);
105.197 + ext2fs_bg_flags_clear(fs, gr, EXT2_BG_BLOCK_UNINIT);
105.198 + ext2fs_group_desc_csum_set(fs, gr);
105.199 + }
105.200 + }
105.201 +
105.202 + /*
105.203 + * Allocate the inode table
105.204 + */
105.205 + if (flexbg_size) {
105.206 + blk64_t prev_block = 0;
105.207 +
105.208 + if (group % flexbg_size)
105.209 + prev_block = ext2fs_inode_table_loc(fs, group - 1) +
105.210 + fs->inode_blocks_per_group;
105.211 + else
105.212 + prev_block = ext2fs_inode_bitmap_loc(fs, group) +
105.213 + table_offset;
105.214 +
105.215 + /* FIXME: Take backup group descriptor blocks into account
105.216 + * if the flexbg allocations will grow to overlap them... */
105.217 + group_blk = flexbg_offset(fs, group, prev_block, bmap,
105.218 + rem_grps, fs->inode_blocks_per_group);
105.219 + last_blk = ext2fs_group_last_block2(fs, last_grp);
105.220 + }
105.221 +
105.222 + if (!ext2fs_inode_table_loc(fs, group)) {
105.223 + retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk,
105.224 + fs->inode_blocks_per_group,
105.225 + bmap, &new_blk);
105.226 + if (retval)
105.227 + return retval;
105.228 +
105.229 + ext2fs_mark_block_bitmap_range2(bmap,
105.230 + new_blk, fs->inode_blocks_per_group);
105.231 + if (flexbg_size) {
105.232 + blk64_t num, blk;
105.233 + num = fs->inode_blocks_per_group;
105.234 + blk = new_blk;
105.235 + while (num) {
105.236 + int gr = ext2fs_group_of_blk2(fs, blk);
105.237 + last_blk = ext2fs_group_last_block2(fs, gr);
105.238 + blk64_t n = num;
105.239 +
105.240 + if (blk + num > last_blk)
105.241 + n = last_blk - blk + 1;
105.242 +
105.243 + ext2fs_bg_free_blocks_count_set(fs, gr,
105.244 + ext2fs_bg_free_blocks_count(fs, gr) -
105.245 + n/EXT2FS_CLUSTER_RATIO(fs));
105.246 + ext2fs_bg_flags_clear(fs, gr,
105.247 + EXT2_BG_BLOCK_UNINIT);
105.248 + ext2fs_group_desc_csum_set(fs, gr);
105.249 + ext2fs_free_blocks_count_add(fs->super, -n);
105.250 + blk += n;
105.251 + num -= n;
105.252 + }
105.253 + }
105.254 + ext2fs_inode_table_loc_set(fs, group, new_blk);
105.255 + }
105.256 + ext2fs_group_desc_csum_set(fs, group);
105.257 + return 0;
105.258 +}
105.259 +
105.260 +errcode_t ext2fs_allocate_tables(ext2_filsys fs)
105.261 +{
105.262 + errcode_t retval;
105.263 + dgrp_t i;
105.264 + struct ext2fs_numeric_progress_struct progress;
105.265 +
105.266 + if (fs->progress_ops && fs->progress_ops->init)
105.267 + (fs->progress_ops->init)(fs, &progress, NULL,
105.268 + fs->group_desc_count);
105.269 +
105.270 + for (i = 0; i < fs->group_desc_count; i++) {
105.271 + if (fs->progress_ops && fs->progress_ops->update)
105.272 + (fs->progress_ops->update)(fs, &progress, i);
105.273 + retval = ext2fs_allocate_group_table(fs, i, fs->block_map);
105.274 + if (retval)
105.275 + return retval;
105.276 + }
105.277 + if (fs->progress_ops && fs->progress_ops->close)
105.278 + (fs->progress_ops->close)(fs, &progress, NULL);
105.279 + return 0;
105.280 +}
105.281 +
106.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
106.2 +++ b/libext2fs/lib/libext2fs/atexit.c Wed Aug 25 01:28:08 2021 +0200
106.3 @@ -0,0 +1,116 @@
106.4 +/*
106.5 + * atexit.c --- Clean things up when we exit normally.
106.6 + *
106.7 + * Copyright Oracle, 2014
106.8 + * Author Darrick J. Wong <darrick.wong@oracle.com>
106.9 + *
106.10 + * %Begin-Header%
106.11 + * This file may be redistributed under the terms of the GNU Library
106.12 + * General Public License, version 2.
106.13 + * %End-Header%
106.14 + */
106.15 +
106.16 +#ifndef _LARGEFILE_SOURCE
106.17 +#define _LARGEFILE_SOURCE
106.18 +#endif
106.19 +#ifndef _LARGEFILE64_SOURCE
106.20 +#define _LARGEFILE64_SOURCE
106.21 +#endif
106.22 +
106.23 +#include "config.h"
106.24 +#include <stdlib.h>
106.25 +
106.26 +#include "ext2_fs.h"
106.27 +#include "ext2fs.h"
106.28 +#include "ext2fsP.h"
106.29 +
106.30 +struct exit_data {
106.31 + ext2_exit_fn func;
106.32 + void *data;
106.33 +};
106.34 +
106.35 +static struct exit_data *items;
106.36 +static size_t nr_items;
106.37 +
106.38 +static void handle_exit(void)
106.39 +{
106.40 + struct exit_data *ed;
106.41 +
106.42 + for (ed = items + nr_items - 1; ed >= items; ed--) {
106.43 + if (ed->func == NULL)
106.44 + continue;
106.45 + ed->func(ed->data);
106.46 + }
106.47 +
106.48 + ext2fs_free_mem(&items);
106.49 + nr_items = 0;
106.50 +}
106.51 +
106.52 +/*
106.53 + * Schedule a function to be called at (normal) program termination.
106.54 + * If you want this to be called during a signal exit, you must capture
106.55 + * the signal and call exit() yourself!
106.56 + */
106.57 +errcode_t ext2fs_add_exit_fn(ext2_exit_fn func, void *data)
106.58 +{
106.59 + struct exit_data *ed, *free_ed = NULL;
106.60 + size_t x;
106.61 + errcode_t ret;
106.62 +
106.63 + if (func == NULL)
106.64 + return EXT2_ET_INVALID_ARGUMENT;
106.65 +
106.66 + for (x = 0, ed = items; x < nr_items; x++, ed++) {
106.67 + if (ed->func == func && ed->data == data)
106.68 + return EXT2_ET_FILE_EXISTS;
106.69 + if (ed->func == NULL)
106.70 + free_ed = ed;
106.71 + }
106.72 +
106.73 + if (free_ed) {
106.74 + free_ed->func = func;
106.75 + free_ed->data = data;
106.76 + return 0;
106.77 + }
106.78 +
106.79 + if (nr_items == 0) {
106.80 + ret = atexit(handle_exit);
106.81 + if (ret)
106.82 + return ret;
106.83 + }
106.84 +
106.85 + ret = ext2fs_resize_mem(0, (nr_items + 1) * sizeof(struct exit_data),
106.86 + &items);
106.87 + if (ret)
106.88 + return ret;
106.89 +
106.90 + items[nr_items].func = func;
106.91 + items[nr_items].data = data;
106.92 + nr_items++;
106.93 +
106.94 + return 0;
106.95 +}
106.96 +
106.97 +/* Remove a function from the exit cleanup list. */
106.98 +errcode_t ext2fs_remove_exit_fn(ext2_exit_fn func, void *data)
106.99 +{
106.100 + struct exit_data *ed;
106.101 + size_t x;
106.102 +
106.103 + if (func == NULL)
106.104 + return EXT2_ET_INVALID_ARGUMENT;
106.105 +
106.106 + for (x = 0, ed = items; x < nr_items; x++, ed++) {
106.107 + if (ed->func == NULL)
106.108 + return 0;
106.109 + if (ed->func == func && ed->data == data) {
106.110 + size_t sz = (nr_items - (x + 1)) *
106.111 + sizeof(struct exit_data);
106.112 + memmove(ed, ed + 1, sz);
106.113 + memset(items + nr_items - 1, 0,
106.114 + sizeof(struct exit_data));
106.115 + }
106.116 + }
106.117 +
106.118 + return 0;
106.119 +}
107.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
107.2 +++ b/libext2fs/lib/libext2fs/badblocks.c Wed Aug 25 01:28:08 2021 +0200
107.3 @@ -0,0 +1,328 @@
107.4 +/*
107.5 + * badblocks.c --- routines to manipulate the bad block structure
107.6 + *
107.7 + * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
107.8 + *
107.9 + * %Begin-Header%
107.10 + * This file may be redistributed under the terms of the GNU Library
107.11 + * General Public License, version 2.
107.12 + * %End-Header%
107.13 + */
107.14 +
107.15 +#include "config.h"
107.16 +#include <stdio.h>
107.17 +#include <string.h>
107.18 +#if HAVE_UNISTD_H
107.19 +#include <unistd.h>
107.20 +#endif
107.21 +#include <fcntl.h>
107.22 +#include <time.h>
107.23 +#if HAVE_SYS_STAT_H
107.24 +#include <sys/stat.h>
107.25 +#endif
107.26 +#if HAVE_SYS_TYPES_H
107.27 +#include <sys/types.h>
107.28 +#endif
107.29 +
107.30 +#include "ext2_fs.h"
107.31 +#include "ext2fsP.h"
107.32 +
107.33 +/*
107.34 + * Helper function for making a badblocks list
107.35 + */
107.36 +static errcode_t make_u32_list(int size, int num, __u32 *list,
107.37 + ext2_u32_list *ret)
107.38 +{
107.39 + ext2_u32_list bb;
107.40 + errcode_t retval;
107.41 +
107.42 + retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb);
107.43 + if (retval)
107.44 + return retval;
107.45 + memset(bb, 0, sizeof(struct ext2_struct_u32_list));
107.46 + bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
107.47 + bb->size = size ? size : 10;
107.48 + bb->num = num;
107.49 + retval = ext2fs_get_array(bb->size, sizeof(blk_t), &bb->list);
107.50 + if (retval) {
107.51 + ext2fs_free_mem(&bb);
107.52 + return retval;
107.53 + }
107.54 + if (list)
107.55 + memcpy(bb->list, list, bb->size * sizeof(blk_t));
107.56 + else
107.57 + memset(bb->list, 0, bb->size * sizeof(blk_t));
107.58 + *ret = bb;
107.59 + return 0;
107.60 +}
107.61 +
107.62 +
107.63 +/*
107.64 + * This procedure creates an empty u32 list.
107.65 + */
107.66 +errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size)
107.67 +{
107.68 + return make_u32_list(size, 0, 0, ret);
107.69 +}
107.70 +
107.71 +/*
107.72 + * This procedure creates an empty badblocks list.
107.73 + */
107.74 +errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
107.75 +{
107.76 + return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret);
107.77 +}
107.78 +
107.79 +
107.80 +/*
107.81 + * This procedure copies a badblocks list
107.82 + */
107.83 +errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest)
107.84 +{
107.85 + errcode_t retval;
107.86 +
107.87 + retval = make_u32_list(src->size, src->num, src->list, dest);
107.88 + if (retval)
107.89 + return retval;
107.90 + (*dest)->badblocks_flags = src->badblocks_flags;
107.91 + return 0;
107.92 +}
107.93 +
107.94 +errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
107.95 + ext2_badblocks_list *dest)
107.96 +{
107.97 + return ext2fs_u32_copy((ext2_u32_list) src,
107.98 + (ext2_u32_list *) dest);
107.99 +}
107.100 +
107.101 +/*
107.102 + * This procedure frees a badblocks list.
107.103 + *
107.104 + * (note: moved to closefs.c)
107.105 + */
107.106 +
107.107 +
107.108 +/*
107.109 + * This procedure adds a block to a badblocks list.
107.110 + */
107.111 +errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk)
107.112 +{
107.113 + errcode_t retval;
107.114 + int i, j;
107.115 + unsigned long old_size;
107.116 +
107.117 + EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
107.118 +
107.119 + if (bb->num >= bb->size) {
107.120 + old_size = bb->size * sizeof(__u32);
107.121 + bb->size += 100;
107.122 + retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32),
107.123 + &bb->list);
107.124 + if (retval) {
107.125 + bb->size -= 100;
107.126 + return retval;
107.127 + }
107.128 + }
107.129 +
107.130 + /*
107.131 + * Add special case code for appending to the end of the list
107.132 + */
107.133 + i = bb->num-1;
107.134 + if ((bb->num != 0) && (bb->list[i] == blk))
107.135 + return 0;
107.136 + if ((bb->num == 0) || (bb->list[i] < blk)) {
107.137 + bb->list[bb->num++] = blk;
107.138 + return 0;
107.139 + }
107.140 +
107.141 + j = bb->num;
107.142 + for (i=0; i < bb->num; i++) {
107.143 + if (bb->list[i] == blk)
107.144 + return 0;
107.145 + if (bb->list[i] > blk) {
107.146 + j = i;
107.147 + break;
107.148 + }
107.149 + }
107.150 + for (i=bb->num; i > j; i--)
107.151 + bb->list[i] = bb->list[i-1];
107.152 + bb->list[j] = blk;
107.153 + bb->num++;
107.154 + return 0;
107.155 +}
107.156 +
107.157 +errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
107.158 +{
107.159 + return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk);
107.160 +}
107.161 +
107.162 +/*
107.163 + * This procedure finds a particular block is on a badblocks
107.164 + * list.
107.165 + */
107.166 +int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk)
107.167 +{
107.168 + int low, high, mid;
107.169 +
107.170 + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
107.171 + return -1;
107.172 +
107.173 + if (bb->num == 0)
107.174 + return -1;
107.175 +
107.176 + low = 0;
107.177 + high = bb->num-1;
107.178 + if (blk == bb->list[low])
107.179 + return low;
107.180 + if (blk == bb->list[high])
107.181 + return high;
107.182 +
107.183 + while (low < high) {
107.184 + mid = ((unsigned)low + (unsigned)high)/2;
107.185 + if (mid == low || mid == high)
107.186 + break;
107.187 + if (blk == bb->list[mid])
107.188 + return mid;
107.189 + if (blk < bb->list[mid])
107.190 + high = mid;
107.191 + else
107.192 + low = mid;
107.193 + }
107.194 + return -1;
107.195 +}
107.196 +
107.197 +/*
107.198 + * This procedure tests to see if a particular block is on a badblocks
107.199 + * list.
107.200 + */
107.201 +int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk)
107.202 +{
107.203 + if (ext2fs_u32_list_find(bb, blk) < 0)
107.204 + return 0;
107.205 + else
107.206 + return 1;
107.207 +}
107.208 +
107.209 +int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
107.210 +{
107.211 + return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk);
107.212 +}
107.213 +
107.214 +
107.215 +/*
107.216 + * Remove a block from the badblock list
107.217 + */
107.218 +int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk)
107.219 +{
107.220 + int remloc, i;
107.221 +
107.222 + if (bb->num == 0)
107.223 + return -1;
107.224 +
107.225 + remloc = ext2fs_u32_list_find(bb, blk);
107.226 + if (remloc < 0)
107.227 + return -1;
107.228 +
107.229 + for (i = remloc ; i < bb->num-1; i++)
107.230 + bb->list[i] = bb->list[i+1];
107.231 + bb->num--;
107.232 + return 0;
107.233 +}
107.234 +
107.235 +void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk)
107.236 +{
107.237 + ext2fs_u32_list_del(bb, blk);
107.238 +}
107.239 +
107.240 +errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
107.241 + ext2_u32_iterate *ret)
107.242 +{
107.243 + ext2_u32_iterate iter;
107.244 + errcode_t retval;
107.245 +
107.246 + EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
107.247 +
107.248 + retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter);
107.249 + if (retval)
107.250 + return retval;
107.251 +
107.252 + iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
107.253 + iter->bb = bb;
107.254 + iter->ptr = 0;
107.255 + *ret = iter;
107.256 + return 0;
107.257 +}
107.258 +
107.259 +errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
107.260 + ext2_badblocks_iterate *ret)
107.261 +{
107.262 + return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb,
107.263 + (ext2_u32_iterate *) ret);
107.264 +}
107.265 +
107.266 +
107.267 +int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk)
107.268 +{
107.269 + ext2_u32_list bb;
107.270 +
107.271 + if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
107.272 + return 0;
107.273 +
107.274 + bb = iter->bb;
107.275 +
107.276 + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
107.277 + return 0;
107.278 +
107.279 + if (iter->ptr < bb->num) {
107.280 + *blk = bb->list[iter->ptr++];
107.281 + return 1;
107.282 + }
107.283 + *blk = 0;
107.284 + return 0;
107.285 +}
107.286 +
107.287 +int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
107.288 +{
107.289 + return ext2fs_u32_list_iterate((ext2_u32_iterate) iter,
107.290 + (__u32 *) blk);
107.291 +}
107.292 +
107.293 +
107.294 +void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter)
107.295 +{
107.296 + if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
107.297 + return;
107.298 +
107.299 + iter->bb = 0;
107.300 + ext2fs_free_mem(&iter);
107.301 +}
107.302 +
107.303 +void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
107.304 +{
107.305 + ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter);
107.306 +}
107.307 +
107.308 +
107.309 +int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2)
107.310 +{
107.311 + EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST);
107.312 + EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST);
107.313 +
107.314 + if (bb1->num != bb2->num)
107.315 + return 0;
107.316 +
107.317 + if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0)
107.318 + return 0;
107.319 + return 1;
107.320 +}
107.321 +
107.322 +int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2)
107.323 +{
107.324 + return ext2fs_u32_list_equal((ext2_u32_list) bb1,
107.325 + (ext2_u32_list) bb2);
107.326 +}
107.327 +
107.328 +int ext2fs_u32_list_count(ext2_u32_list bb)
107.329 +{
107.330 + return bb->num;
107.331 +}
108.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
108.2 +++ b/libext2fs/lib/libext2fs/bb_compat.c Wed Aug 25 01:28:08 2021 +0200
108.3 @@ -0,0 +1,64 @@
108.4 +/*
108.5 + * bb_compat.c --- compatibility badblocks routines
108.6 + *
108.7 + * Copyright (C) 1997 Theodore Ts'o.
108.8 + *
108.9 + * %Begin-Header%
108.10 + * This file may be redistributed under the terms of the GNU Library
108.11 + * General Public License, version 2.
108.12 + * %End-Header%
108.13 + */
108.14 +
108.15 +#include "config.h"
108.16 +#include <stdio.h>
108.17 +#include <string.h>
108.18 +#if HAVE_UNISTD_H
108.19 +#include <unistd.h>
108.20 +#endif
108.21 +#include <fcntl.h>
108.22 +#include <time.h>
108.23 +#if HAVE_SYS_STAT_H
108.24 +#include <sys/stat.h>
108.25 +#endif
108.26 +#if HAVE_SYS_TYPES_H
108.27 +#include <sys/types.h>
108.28 +#endif
108.29 +
108.30 +#include "ext2_fs.h"
108.31 +#include "ext2fsP.h"
108.32 +
108.33 +errcode_t badblocks_list_create(badblocks_list *ret, int size)
108.34 +{
108.35 + return ext2fs_badblocks_list_create(ret, size);
108.36 +}
108.37 +
108.38 +void badblocks_list_free(badblocks_list bb)
108.39 +{
108.40 + ext2fs_badblocks_list_free(bb);
108.41 +}
108.42 +
108.43 +errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
108.44 +{
108.45 + return ext2fs_badblocks_list_add(bb, blk);
108.46 +}
108.47 +
108.48 +int badblocks_list_test(badblocks_list bb, blk_t blk)
108.49 +{
108.50 + return ext2fs_badblocks_list_test(bb, blk);
108.51 +}
108.52 +
108.53 +errcode_t badblocks_list_iterate_begin(badblocks_list bb,
108.54 + badblocks_iterate *ret)
108.55 +{
108.56 + return ext2fs_badblocks_list_iterate_begin(bb, ret);
108.57 +}
108.58 +
108.59 +int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
108.60 +{
108.61 + return ext2fs_badblocks_list_iterate(iter, blk);
108.62 +}
108.63 +
108.64 +void badblocks_list_iterate_end(badblocks_iterate iter)
108.65 +{
108.66 + ext2fs_badblocks_list_iterate_end(iter);
108.67 +}
109.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
109.2 +++ b/libext2fs/lib/libext2fs/bb_inode.c Wed Aug 25 01:28:08 2021 +0200
109.3 @@ -0,0 +1,270 @@
109.4 +/*
109.5 + * bb_inode.c --- routines to update the bad block inode.
109.6 + *
109.7 + * WARNING: This routine modifies a lot of state in the filesystem; if
109.8 + * this routine returns an error, the bad block inode may be in an
109.9 + * inconsistent state.
109.10 + *
109.11 + * Copyright (C) 1994, 1995 Theodore Ts'o.
109.12 + *
109.13 + * %Begin-Header%
109.14 + * This file may be redistributed under the terms of the GNU Library
109.15 + * General Public License, version 2.
109.16 + * %End-Header%
109.17 + */
109.18 +
109.19 +#include "config.h"
109.20 +#include <stdio.h>
109.21 +#include <string.h>
109.22 +#if HAVE_UNISTD_H
109.23 +#include <unistd.h>
109.24 +#endif
109.25 +#include <fcntl.h>
109.26 +#include <time.h>
109.27 +#if HAVE_SYS_STAT_H
109.28 +#include <sys/stat.h>
109.29 +#endif
109.30 +#if HAVE_SYS_TYPES_H
109.31 +#include <sys/types.h>
109.32 +#endif
109.33 +
109.34 +#include "ext2_fs.h"
109.35 +#include "ext2fs.h"
109.36 +
109.37 +struct set_badblock_record {
109.38 + ext2_badblocks_iterate bb_iter;
109.39 + int bad_block_count;
109.40 + blk_t *ind_blocks;
109.41 + int max_ind_blocks;
109.42 + int ind_blocks_size;
109.43 + int ind_blocks_ptr;
109.44 + char *block_buf;
109.45 + errcode_t err;
109.46 +};
109.47 +
109.48 +static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
109.49 + e2_blkcnt_t blockcnt,
109.50 + blk_t ref_block, int ref_offset,
109.51 + void *priv_data);
109.52 +static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
109.53 + e2_blkcnt_t blockcnt,
109.54 + blk_t ref_block, int ref_offset,
109.55 + void *priv_data);
109.56 +
109.57 +/*
109.58 + * Given a bad blocks bitmap, update the bad blocks inode to reflect
109.59 + * the map.
109.60 + */
109.61 +errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
109.62 +{
109.63 + errcode_t retval;
109.64 + struct set_badblock_record rec;
109.65 + struct ext2_inode inode;
109.66 +
109.67 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
109.68 +
109.69 + if (!fs->block_map)
109.70 + return EXT2_ET_NO_BLOCK_BITMAP;
109.71 +
109.72 + memset(&rec, 0, sizeof(rec));
109.73 + rec.max_ind_blocks = 10;
109.74 + retval = ext2fs_get_array(rec.max_ind_blocks, sizeof(blk_t),
109.75 + &rec.ind_blocks);
109.76 + if (retval)
109.77 + return retval;
109.78 + memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
109.79 + retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf);
109.80 + if (retval)
109.81 + goto cleanup;
109.82 + memset(rec.block_buf, 0, fs->blocksize);
109.83 + rec.err = 0;
109.84 +
109.85 + /*
109.86 + * First clear the old bad blocks (while saving the indirect blocks)
109.87 + */
109.88 + retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
109.89 + BLOCK_FLAG_DEPTH_TRAVERSE, 0,
109.90 + clear_bad_block_proc, &rec);
109.91 + if (retval)
109.92 + goto cleanup;
109.93 + if (rec.err) {
109.94 + retval = rec.err;
109.95 + goto cleanup;
109.96 + }
109.97 +
109.98 + /*
109.99 + * Now set the bad blocks!
109.100 + *
109.101 + * First, mark the bad blocks as used. This prevents a bad
109.102 + * block from being used as an indirect block for the bad
109.103 + * block inode (!).
109.104 + */
109.105 + if (bb_list) {
109.106 + retval = ext2fs_badblocks_list_iterate_begin(bb_list,
109.107 + &rec.bb_iter);
109.108 + if (retval)
109.109 + goto cleanup;
109.110 + retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
109.111 + BLOCK_FLAG_APPEND, 0,
109.112 + set_bad_block_proc, &rec);
109.113 + ext2fs_badblocks_list_iterate_end(rec.bb_iter);
109.114 + if (retval)
109.115 + goto cleanup;
109.116 + if (rec.err) {
109.117 + retval = rec.err;
109.118 + goto cleanup;
109.119 + }
109.120 + }
109.121 +
109.122 + /*
109.123 + * Update the bad block inode's mod time and block count
109.124 + * field.
109.125 + */
109.126 + retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
109.127 + if (retval)
109.128 + goto cleanup;
109.129 +
109.130 + inode.i_atime = inode.i_mtime = fs->now ? fs->now : time(0);
109.131 + if (!inode.i_ctime)
109.132 + inode.i_ctime = fs->now ? fs->now : time(0);
109.133 + ext2fs_iblk_set(fs, &inode, rec.bad_block_count);
109.134 + retval = ext2fs_inode_size_set(fs, &inode,
109.135 + rec.bad_block_count * fs->blocksize);
109.136 + if (retval)
109.137 + goto cleanup;
109.138 +
109.139 + retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode);
109.140 + if (retval)
109.141 + goto cleanup;
109.142 +
109.143 +cleanup:
109.144 + ext2fs_free_mem(&rec.ind_blocks);
109.145 + ext2fs_free_mem(&rec.block_buf);
109.146 + return retval;
109.147 +}
109.148 +
109.149 +/*
109.150 + * Helper function for update_bb_inode()
109.151 + *
109.152 + * Clear the bad blocks in the bad block inode, while saving the
109.153 + * indirect blocks.
109.154 + */
109.155 +#ifdef __TURBOC__
109.156 + #pragma argsused
109.157 +#endif
109.158 +static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
109.159 + e2_blkcnt_t blockcnt,
109.160 + blk_t ref_block EXT2FS_ATTR((unused)),
109.161 + int ref_offset EXT2FS_ATTR((unused)),
109.162 + void *priv_data)
109.163 +{
109.164 + struct set_badblock_record *rec = (struct set_badblock_record *)
109.165 + priv_data;
109.166 + errcode_t retval;
109.167 + unsigned long old_size;
109.168 +
109.169 + if (!*block_nr)
109.170 + return 0;
109.171 +
109.172 + /*
109.173 + * If the block number is outrageous, clear it and ignore it.
109.174 + */
109.175 + if (*block_nr >= ext2fs_blocks_count(fs->super) ||
109.176 + *block_nr < fs->super->s_first_data_block) {
109.177 + *block_nr = 0;
109.178 + return BLOCK_CHANGED;
109.179 + }
109.180 +
109.181 + if (blockcnt < 0) {
109.182 + if (rec->ind_blocks_size >= rec->max_ind_blocks) {
109.183 + old_size = rec->max_ind_blocks * sizeof(blk_t);
109.184 + rec->max_ind_blocks += 10;
109.185 + retval = ext2fs_resize_mem(old_size,
109.186 + rec->max_ind_blocks * sizeof(blk_t),
109.187 + &rec->ind_blocks);
109.188 + if (retval) {
109.189 + rec->max_ind_blocks -= 10;
109.190 + rec->err = retval;
109.191 + return BLOCK_ABORT;
109.192 + }
109.193 + }
109.194 + rec->ind_blocks[rec->ind_blocks_size++] = *block_nr;
109.195 + }
109.196 +
109.197 + /*
109.198 + * Mark the block as unused, and update accounting information
109.199 + */
109.200 + ext2fs_block_alloc_stats2(fs, *block_nr, -1);
109.201 +
109.202 + *block_nr = 0;
109.203 + return BLOCK_CHANGED;
109.204 +}
109.205 +
109.206 +
109.207 +/*
109.208 + * Helper function for update_bb_inode()
109.209 + *
109.210 + * Set the block list in the bad block inode, using the supplied bitmap.
109.211 + */
109.212 +#ifdef __TURBOC__
109.213 + #pragma argsused
109.214 +#endif
109.215 +static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
109.216 + e2_blkcnt_t blockcnt,
109.217 + blk_t ref_block EXT2FS_ATTR((unused)),
109.218 + int ref_offset EXT2FS_ATTR((unused)),
109.219 + void *priv_data)
109.220 +{
109.221 + struct set_badblock_record *rec = (struct set_badblock_record *)
109.222 + priv_data;
109.223 + errcode_t retval;
109.224 + blk_t blk;
109.225 +
109.226 + if (blockcnt >= 0) {
109.227 + /*
109.228 + * Get the next bad block.
109.229 + */
109.230 + if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
109.231 + return BLOCK_ABORT;
109.232 + rec->bad_block_count++;
109.233 + } else {
109.234 + /*
109.235 + * An indirect block; fetch a block from the
109.236 + * previously used indirect block list. The block
109.237 + * most be not marked as used; if so, get another one.
109.238 + * If we run out of reserved indirect blocks, allocate
109.239 + * a new one.
109.240 + */
109.241 + retry:
109.242 + if (rec->ind_blocks_ptr < rec->ind_blocks_size) {
109.243 + blk = rec->ind_blocks[rec->ind_blocks_ptr++];
109.244 + if (ext2fs_test_block_bitmap2(fs->block_map, blk))
109.245 + goto retry;
109.246 + } else {
109.247 + retval = ext2fs_new_block(fs, 0, 0, &blk);
109.248 + if (retval) {
109.249 + rec->err = retval;
109.250 + return BLOCK_ABORT;
109.251 + }
109.252 + }
109.253 + retval = io_channel_write_blk64(fs->io, blk, 1, rec->block_buf);
109.254 + if (retval) {
109.255 + rec->err = retval;
109.256 + return BLOCK_ABORT;
109.257 + }
109.258 + }
109.259 +
109.260 + /*
109.261 + * Update block counts
109.262 + */
109.263 + ext2fs_block_alloc_stats2(fs, blk, +1);
109.264 +
109.265 + *block_nr = blk;
109.266 + return BLOCK_CHANGED;
109.267 +}
109.268 +
109.269 +
109.270 +
109.271 +
109.272 +
109.273 +
110.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
110.2 +++ b/libext2fs/lib/libext2fs/bitmaps.c Wed Aug 25 01:28:08 2021 +0200
110.3 @@ -0,0 +1,308 @@
110.4 +/*
110.5 + * bitmaps.c --- routines to read, write, and manipulate the inode and
110.6 + * block bitmaps.
110.7 + *
110.8 + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
110.9 + *
110.10 + * %Begin-Header%
110.11 + * This file may be redistributed under the terms of the GNU Library
110.12 + * General Public License, version 2.
110.13 + * %End-Header%
110.14 + */
110.15 +
110.16 +#include "config.h"
110.17 +#include <stdio.h>
110.18 +#include <string.h>
110.19 +#if HAVE_UNISTD_H
110.20 +#include <unistd.h>
110.21 +#endif
110.22 +#include <fcntl.h>
110.23 +#include <time.h>
110.24 +#if HAVE_SYS_STAT_H
110.25 +#include <sys/stat.h>
110.26 +#endif
110.27 +#if HAVE_SYS_TYPES_H
110.28 +#include <sys/types.h>
110.29 +#endif
110.30 +
110.31 +#include "ext2_fs.h"
110.32 +#include "ext2fs.h"
110.33 +#include "ext2fsP.h"
110.34 +#include "bmap64.h"
110.35 +
110.36 +void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap)
110.37 +{
110.38 + ext2fs_free_generic_bmap(bitmap);
110.39 +}
110.40 +
110.41 +void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap)
110.42 +{
110.43 + ext2fs_free_generic_bmap(bitmap);
110.44 +}
110.45 +
110.46 +errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
110.47 + ext2fs_generic_bitmap *dest)
110.48 +{
110.49 + return (ext2fs_copy_generic_bmap(src, dest));
110.50 +}
110.51 +void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map)
110.52 +{
110.53 + ext2fs_set_generic_bmap_padding(map);
110.54 +}
110.55 +
110.56 +errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
110.57 + const char *descr,
110.58 + ext2fs_inode_bitmap *ret)
110.59 +{
110.60 + __u64 start, end, real_end;
110.61 +
110.62 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
110.63 +
110.64 + fs->write_bitmaps = ext2fs_write_bitmaps;
110.65 +
110.66 + start = 1;
110.67 + end = fs->super->s_inodes_count;
110.68 + real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count);
110.69 +
110.70 + /* Are we permitted to use new-style bitmaps? */
110.71 + if (fs->flags & EXT2_FLAG_64BITS)
110.72 + return (ext2fs_alloc_generic_bmap(fs,
110.73 + EXT2_ET_MAGIC_INODE_BITMAP64,
110.74 + fs->default_bitmap_type,
110.75 + start, end, real_end, descr, ret));
110.76 +
110.77 + /* Otherwise, check to see if the file system is small enough
110.78 + * to use old-style 32-bit bitmaps */
110.79 + if ((end > ~0U) || (real_end > ~0U))
110.80 + return EXT2_ET_CANT_USE_LEGACY_BITMAPS;
110.81 +
110.82 + return (ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_INODE_BITMAP, fs,
110.83 + start, end, real_end,
110.84 + descr, 0,
110.85 + (ext2fs_generic_bitmap *) ret));
110.86 +}
110.87 +
110.88 +errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
110.89 + const char *descr,
110.90 + ext2fs_block_bitmap *ret)
110.91 +{
110.92 + __u64 start, end, real_end;
110.93 +
110.94 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
110.95 +
110.96 + fs->write_bitmaps = ext2fs_write_bitmaps;
110.97 +
110.98 + start = EXT2FS_B2C(fs, fs->super->s_first_data_block);
110.99 + end = EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1);
110.100 + real_end = ((__u64) EXT2_CLUSTERS_PER_GROUP(fs->super)
110.101 + * (__u64) fs->group_desc_count)-1 + start;
110.102 +
110.103 + if (fs->flags & EXT2_FLAG_64BITS)
110.104 + return (ext2fs_alloc_generic_bmap(fs,
110.105 + EXT2_ET_MAGIC_BLOCK_BITMAP64,
110.106 + fs->default_bitmap_type,
110.107 + start, end, real_end, descr, ret));
110.108 +
110.109 + if ((end > ~0U) || (real_end > ~0U))
110.110 + return EXT2_ET_CANT_USE_LEGACY_BITMAPS;
110.111 +
110.112 + return (ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, fs,
110.113 + start, end, real_end,
110.114 + descr, 0,
110.115 + (ext2fs_generic_bitmap *) ret));
110.116 +}
110.117 +
110.118 +/*
110.119 + * ext2fs_allocate_block_bitmap() really allocates a per-cluster
110.120 + * bitmap for backwards compatibility. This function allocates a
110.121 + * block bitmap which is truly per-block, even if clusters/bigalloc
110.122 + * are enabled. mke2fs and e2fsck need this for tracking the
110.123 + * allocation of the file system metadata blocks.
110.124 + */
110.125 +errcode_t ext2fs_allocate_subcluster_bitmap(ext2_filsys fs,
110.126 + const char *descr,
110.127 + ext2fs_block_bitmap *ret)
110.128 +{
110.129 + __u64 start, end, real_end;
110.130 + ext2fs_generic_bitmap bmap;
110.131 + errcode_t retval;
110.132 +
110.133 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
110.134 +
110.135 + fs->write_bitmaps = ext2fs_write_bitmaps;
110.136 +
110.137 + if (!fs->cluster_ratio_bits)
110.138 + return ext2fs_allocate_block_bitmap(fs, descr, ret);
110.139 +
110.140 + if ((fs->flags & EXT2_FLAG_64BITS) == 0)
110.141 + return EXT2_ET_CANT_USE_LEGACY_BITMAPS;
110.142 +
110.143 + start = fs->super->s_first_data_block;
110.144 + end = ext2fs_blocks_count(fs->super)-1;
110.145 + real_end = ((__u64) EXT2_BLOCKS_PER_GROUP(fs->super)
110.146 + * (__u64) fs->group_desc_count)-1 + start;
110.147 +
110.148 + retval = ext2fs_alloc_generic_bmap(fs, EXT2_ET_MAGIC_BLOCK_BITMAP64,
110.149 + fs->default_bitmap_type, start,
110.150 + end, real_end, descr, &bmap);
110.151 + if (retval)
110.152 + return retval;
110.153 + bmap->cluster_bits = 0;
110.154 + *ret = bmap;
110.155 + return 0;
110.156 +}
110.157 +
110.158 +int ext2fs_get_bitmap_granularity(ext2fs_block_bitmap bitmap)
110.159 +{
110.160 + ext2fs_generic_bitmap bmap = bitmap;
110.161 +
110.162 + if (!EXT2FS_IS_64_BITMAP(bmap))
110.163 + return 0;
110.164 +
110.165 + return bmap->cluster_bits;
110.166 +}
110.167 +
110.168 +errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
110.169 + ext2_ino_t end, ext2_ino_t *oend)
110.170 +{
110.171 + __u64 tmp_oend;
110.172 + int retval;
110.173 +
110.174 + retval = ext2fs_fudge_generic_bmap_end((ext2fs_generic_bitmap) bitmap,
110.175 + EXT2_ET_FUDGE_INODE_BITMAP_END,
110.176 + end, &tmp_oend);
110.177 + if (oend)
110.178 + *oend = tmp_oend;
110.179 + return retval;
110.180 +}
110.181 +
110.182 +errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
110.183 + blk_t end, blk_t *oend)
110.184 +{
110.185 + return (ext2fs_fudge_generic_bitmap_end(bitmap,
110.186 + EXT2_ET_MAGIC_BLOCK_BITMAP,
110.187 + EXT2_ET_FUDGE_BLOCK_BITMAP_END,
110.188 + end, oend));
110.189 +}
110.190 +
110.191 +errcode_t ext2fs_fudge_block_bitmap_end2(ext2fs_block_bitmap bitmap,
110.192 + blk64_t end, blk64_t *oend)
110.193 +{
110.194 + return (ext2fs_fudge_generic_bmap_end(bitmap,
110.195 + EXT2_ET_FUDGE_BLOCK_BITMAP_END,
110.196 + end, oend));
110.197 +}
110.198 +
110.199 +void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap)
110.200 +{
110.201 + ext2fs_clear_generic_bmap(bitmap);
110.202 +}
110.203 +
110.204 +void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
110.205 +{
110.206 + ext2fs_clear_generic_bmap(bitmap);
110.207 +}
110.208 +
110.209 +errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
110.210 + ext2fs_inode_bitmap bmap)
110.211 +{
110.212 + return (ext2fs_resize_generic_bitmap(EXT2_ET_MAGIC_INODE_BITMAP,
110.213 + new_end, new_real_end, bmap));
110.214 +}
110.215 +
110.216 +errcode_t ext2fs_resize_inode_bitmap2(__u64 new_end, __u64 new_real_end,
110.217 + ext2fs_inode_bitmap bmap)
110.218 +{
110.219 + return (ext2fs_resize_generic_bmap(bmap, new_end, new_real_end));
110.220 +}
110.221 +
110.222 +errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
110.223 + ext2fs_block_bitmap bmap)
110.224 +{
110.225 + return (ext2fs_resize_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP,
110.226 + new_end, new_real_end, bmap));
110.227 +}
110.228 +
110.229 +errcode_t ext2fs_resize_block_bitmap2(__u64 new_end, __u64 new_real_end,
110.230 + ext2fs_block_bitmap bmap)
110.231 +{
110.232 + return (ext2fs_resize_generic_bmap(bmap, new_end, new_real_end));
110.233 +}
110.234 +
110.235 +errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
110.236 + ext2fs_block_bitmap bm2)
110.237 +{
110.238 + return (ext2fs_compare_generic_bmap(EXT2_ET_NEQ_BLOCK_BITMAP,
110.239 + bm1, bm2));
110.240 +}
110.241 +
110.242 +errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
110.243 + ext2fs_inode_bitmap bm2)
110.244 +{
110.245 + return (ext2fs_compare_generic_bmap(EXT2_ET_NEQ_INODE_BITMAP,
110.246 + bm1, bm2));
110.247 +}
110.248 +
110.249 +errcode_t ext2fs_set_inode_bitmap_range(ext2fs_inode_bitmap bmap,
110.250 + ext2_ino_t start, unsigned int num,
110.251 + void *in)
110.252 +{
110.253 + return (ext2fs_set_generic_bitmap_range(bmap,
110.254 + EXT2_ET_MAGIC_INODE_BITMAP,
110.255 + start, num, in));
110.256 +}
110.257 +
110.258 +errcode_t ext2fs_set_inode_bitmap_range2(ext2fs_inode_bitmap bmap,
110.259 + __u64 start, size_t num,
110.260 + void *in)
110.261 +{
110.262 + return (ext2fs_set_generic_bmap_range(bmap, start, num, in));
110.263 +}
110.264 +
110.265 +errcode_t ext2fs_get_inode_bitmap_range(ext2fs_inode_bitmap bmap,
110.266 + ext2_ino_t start, unsigned int num,
110.267 + void *out)
110.268 +{
110.269 + return (ext2fs_get_generic_bitmap_range(bmap,
110.270 + EXT2_ET_MAGIC_INODE_BITMAP,
110.271 + start, num, out));
110.272 +}
110.273 +
110.274 +errcode_t ext2fs_get_inode_bitmap_range2(ext2fs_inode_bitmap bmap,
110.275 + __u64 start, size_t num,
110.276 + void *out)
110.277 +{
110.278 + return (ext2fs_get_generic_bmap_range(bmap, start, num, out));
110.279 +}
110.280 +
110.281 +errcode_t ext2fs_set_block_bitmap_range(ext2fs_block_bitmap bmap,
110.282 + blk_t start, unsigned int num,
110.283 + void *in)
110.284 +{
110.285 + return (ext2fs_set_generic_bitmap_range(bmap,
110.286 + EXT2_ET_MAGIC_BLOCK_BITMAP,
110.287 + start, num, in));
110.288 +}
110.289 +
110.290 +errcode_t ext2fs_set_block_bitmap_range2(ext2fs_block_bitmap bmap,
110.291 + blk64_t start, size_t num,
110.292 + void *in)
110.293 +{
110.294 + return (ext2fs_set_generic_bmap_range(bmap, start, num, in));
110.295 +}
110.296 +
110.297 +errcode_t ext2fs_get_block_bitmap_range(ext2fs_block_bitmap bmap,
110.298 + blk_t start, unsigned int num,
110.299 + void *out)
110.300 +{
110.301 + return (ext2fs_get_generic_bitmap_range(bmap,
110.302 + EXT2_ET_MAGIC_BLOCK_BITMAP,
110.303 + start, num, out));
110.304 +}
110.305 +
110.306 +errcode_t ext2fs_get_block_bitmap_range2(ext2fs_block_bitmap bmap,
110.307 + blk64_t start, size_t num,
110.308 + void *out)
110.309 +{
110.310 + return (ext2fs_get_generic_bmap_range(bmap, start, num, out));
110.311 +}
111.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
111.2 +++ b/libext2fs/lib/libext2fs/bitops.c Wed Aug 25 01:28:08 2021 +0200
111.3 @@ -0,0 +1,158 @@
111.4 +/*
111.5 + * bitops.c --- Bitmap frobbing code. See bitops.h for the inlined
111.6 + * routines.
111.7 + *
111.8 + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
111.9 + *
111.10 + * %Begin-Header%
111.11 + * This file may be redistributed under the terms of the GNU Library
111.12 + * General Public License, version 2.
111.13 + * %End-Header%
111.14 + */
111.15 +
111.16 +#include "config.h"
111.17 +#include <stdio.h>
111.18 +#if HAVE_SYS_TYPES_H
111.19 +#include <sys/types.h>
111.20 +#endif
111.21 +
111.22 +#include "ext2_fs.h"
111.23 +#include "ext2fs.h"
111.24 +
111.25 +#ifndef _EXT2_HAVE_ASM_BITOPS_
111.26 +
111.27 +/*
111.28 + * For the benefit of those who are trying to port Linux to another
111.29 + * architecture, here are some C-language equivalents. You should
111.30 + * recode these in the native assembly language, if at all possible.
111.31 + *
111.32 + * C language equivalents written by Theodore Ts'o, 9/26/92.
111.33 + * Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian
111.34 + * systems, as well as non-32 bit systems.
111.35 + */
111.36 +
111.37 +int ext2fs_set_bit(unsigned int nr,void * addr)
111.38 +{
111.39 + int mask, retval;
111.40 + unsigned char *ADDR = (unsigned char *) addr;
111.41 +
111.42 + ADDR += nr >> 3;
111.43 + mask = 1 << (nr & 0x07);
111.44 + retval = mask & *ADDR;
111.45 + *ADDR |= mask;
111.46 + return retval;
111.47 +}
111.48 +
111.49 +int ext2fs_clear_bit(unsigned int nr, void * addr)
111.50 +{
111.51 + int mask, retval;
111.52 + unsigned char *ADDR = (unsigned char *) addr;
111.53 +
111.54 + ADDR += nr >> 3;
111.55 + mask = 1 << (nr & 0x07);
111.56 + retval = mask & *ADDR;
111.57 + *ADDR &= ~mask;
111.58 + return retval;
111.59 +}
111.60 +
111.61 +int ext2fs_test_bit(unsigned int nr, const void * addr)
111.62 +{
111.63 + int mask;
111.64 + const unsigned char *ADDR = (const unsigned char *) addr;
111.65 +
111.66 + ADDR += nr >> 3;
111.67 + mask = 1 << (nr & 0x07);
111.68 + return (mask & *ADDR);
111.69 +}
111.70 +
111.71 +#endif /* !_EXT2_HAVE_ASM_BITOPS_ */
111.72 +
111.73 +void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
111.74 + const char *description)
111.75 +{
111.76 +#ifndef OMIT_COM_ERR
111.77 + if (description)
111.78 + com_err(0, errcode, "#%lu for %s", arg, description);
111.79 + else
111.80 + com_err(0, errcode, "#%lu", arg);
111.81 +#endif
111.82 +}
111.83 +
111.84 +/*
111.85 + * C-only 64 bit ops.
111.86 + */
111.87 +
111.88 +int ext2fs_set_bit64(__u64 nr, void * addr)
111.89 +{
111.90 + int mask, retval;
111.91 + unsigned char *ADDR = (unsigned char *) addr;
111.92 +
111.93 + ADDR += nr >> 3;
111.94 + mask = 1 << (nr & 0x07);
111.95 + retval = mask & *ADDR;
111.96 + *ADDR |= mask;
111.97 + return retval;
111.98 +}
111.99 +
111.100 +int ext2fs_clear_bit64(__u64 nr, void * addr)
111.101 +{
111.102 + int mask, retval;
111.103 + unsigned char *ADDR = (unsigned char *) addr;
111.104 +
111.105 + ADDR += nr >> 3;
111.106 + mask = 1 << (nr & 0x07);
111.107 + retval = mask & *ADDR;
111.108 + *ADDR &= ~mask;
111.109 + return retval;
111.110 +}
111.111 +
111.112 +int ext2fs_test_bit64(__u64 nr, const void * addr)
111.113 +{
111.114 + int mask;
111.115 + const unsigned char *ADDR = (const unsigned char *) addr;
111.116 +
111.117 + ADDR += nr >> 3;
111.118 + mask = 1 << (nr & 0x07);
111.119 + return (mask & *ADDR);
111.120 +}
111.121 +
111.122 +static unsigned int popcount8(unsigned int w)
111.123 +{
111.124 + unsigned int res = w - ((w >> 1) & 0x55);
111.125 + res = (res & 0x33) + ((res >> 2) & 0x33);
111.126 + return (res + (res >> 4)) & 0x0F;
111.127 +}
111.128 +
111.129 +static unsigned int popcount32(unsigned int w)
111.130 +{
111.131 + unsigned int res = w - ((w >> 1) & 0x55555555);
111.132 + res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
111.133 + res = (res + (res >> 4)) & 0x0F0F0F0F;
111.134 + res = res + (res >> 8);
111.135 + return (res + (res >> 16)) & 0x000000FF;
111.136 +}
111.137 +
111.138 +unsigned int ext2fs_bitcount(const void *addr, unsigned int nbytes)
111.139 +{
111.140 + const unsigned char *cp = addr;
111.141 + const __u32 *p;
111.142 + unsigned int res = 0;
111.143 +
111.144 + while (((((uintptr_t) cp) & 3) != 0) && (nbytes > 0)) {
111.145 + res += popcount8(*cp++);
111.146 + nbytes--;
111.147 + }
111.148 + p = (const __u32 *) cp;
111.149 +
111.150 + while (nbytes > 4) {
111.151 + res += popcount32(*p++);
111.152 + nbytes -= 4;
111.153 + }
111.154 + cp = (const unsigned char *) p;
111.155 +
111.156 + while (nbytes > 0) {
111.157 + res += popcount8(*cp++);
111.158 + nbytes--;
111.159 + }
111.160 + return res;
111.161 +}
112.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
112.2 +++ b/libext2fs/lib/libext2fs/blkmap64_ba.c Wed Aug 25 01:28:08 2021 +0200
112.3 @@ -0,0 +1,492 @@
112.4 +/*
112.5 + * blkmap64_ba.c --- Simple bitarray implementation for bitmaps
112.6 + *
112.7 + * Copyright (C) 2008 Theodore Ts'o.
112.8 + *
112.9 + * %Begin-Header%
112.10 + * This file may be redistributed under the terms of the GNU Public
112.11 + * License.
112.12 + * %End-Header%
112.13 + */
112.14 +
112.15 +#include "config.h"
112.16 +#include <stdio.h>
112.17 +#include <string.h>
112.18 +#if HAVE_UNISTD_H
112.19 +#include <unistd.h>
112.20 +#endif
112.21 +#include <fcntl.h>
112.22 +#include <time.h>
112.23 +#if HAVE_SYS_STAT_H
112.24 +#include <sys/stat.h>
112.25 +#endif
112.26 +#if HAVE_SYS_TYPES_H
112.27 +#include <sys/types.h>
112.28 +#endif
112.29 +
112.30 +#include "ext2_fs.h"
112.31 +#include "ext2fsP.h"
112.32 +#include "bmap64.h"
112.33 +
112.34 +/*
112.35 + * Private data for bit array implementation of bitmap ops.
112.36 + * Currently, this is just a pointer to our big flat hunk of memory,
112.37 + * exactly equivalent to the old-skool char * bitmap member.
112.38 + */
112.39 +
112.40 +struct ext2fs_ba_private_struct {
112.41 + char *bitarray;
112.42 +};
112.43 +
112.44 +typedef struct ext2fs_ba_private_struct *ext2fs_ba_private;
112.45 +
112.46 +static errcode_t ba_alloc_private_data (ext2fs_generic_bitmap bitmap)
112.47 +{
112.48 + ext2fs_ba_private bp;
112.49 + errcode_t retval;
112.50 + size_t size;
112.51 +
112.52 + /*
112.53 + * Since we only have the one pointer, we could just shove our
112.54 + * private data in the void *private field itself, but then
112.55 + * we'd have to do a fair bit of rewriting if we ever added a
112.56 + * field. I'm agnostic.
112.57 + */
112.58 + retval = ext2fs_get_mem(sizeof (ext2fs_ba_private), &bp);
112.59 + if (retval)
112.60 + return retval;
112.61 +
112.62 + size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
112.63 +
112.64 + retval = ext2fs_get_mem(size, &bp->bitarray);
112.65 + if (retval) {
112.66 + ext2fs_free_mem(&bp);
112.67 + bp = 0;
112.68 + return retval;
112.69 + }
112.70 + bitmap->private = (void *) bp;
112.71 + return 0;
112.72 +}
112.73 +
112.74 +static errcode_t ba_new_bmap(ext2_filsys fs EXT2FS_ATTR((unused)),
112.75 + ext2fs_generic_bitmap bitmap)
112.76 +{
112.77 + ext2fs_ba_private bp;
112.78 + errcode_t retval;
112.79 + size_t size;
112.80 +
112.81 + retval = ba_alloc_private_data (bitmap);
112.82 + if (retval)
112.83 + return retval;
112.84 +
112.85 + bp = (ext2fs_ba_private) bitmap->private;
112.86 + size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
112.87 + memset(bp->bitarray, 0, size);
112.88 +
112.89 + return 0;
112.90 +}
112.91 +
112.92 +static void ba_free_bmap(ext2fs_generic_bitmap bitmap)
112.93 +{
112.94 + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
112.95 +
112.96 + if (!bp)
112.97 + return;
112.98 +
112.99 + if (bp->bitarray) {
112.100 + ext2fs_free_mem (&bp->bitarray);
112.101 + bp->bitarray = 0;
112.102 + }
112.103 + ext2fs_free_mem (&bp);
112.104 + bp = 0;
112.105 +}
112.106 +
112.107 +static errcode_t ba_copy_bmap(ext2fs_generic_bitmap src,
112.108 + ext2fs_generic_bitmap dest)
112.109 +{
112.110 + ext2fs_ba_private src_bp = (ext2fs_ba_private) src->private;
112.111 + ext2fs_ba_private dest_bp;
112.112 + errcode_t retval;
112.113 + size_t size;
112.114 +
112.115 + retval = ba_alloc_private_data (dest);
112.116 + if (retval)
112.117 + return retval;
112.118 +
112.119 + dest_bp = (ext2fs_ba_private) dest->private;
112.120 +
112.121 + size = (size_t) (((src->real_end - src->start) / 8) + 1);
112.122 + memcpy (dest_bp->bitarray, src_bp->bitarray, size);
112.123 +
112.124 + return 0;
112.125 +}
112.126 +
112.127 +static errcode_t ba_resize_bmap(ext2fs_generic_bitmap bmap,
112.128 + __u64 new_end, __u64 new_real_end)
112.129 +{
112.130 + ext2fs_ba_private bp = (ext2fs_ba_private) bmap->private;
112.131 + errcode_t retval;
112.132 + size_t size, new_size;
112.133 + __u64 bitno;
112.134 +
112.135 + /*
112.136 + * If we're expanding the bitmap, make sure all of the new
112.137 + * parts of the bitmap are zero.
112.138 + */
112.139 + if (new_end > bmap->end) {
112.140 + bitno = bmap->real_end;
112.141 + if (bitno > new_end)
112.142 + bitno = new_end;
112.143 + for (; bitno > bmap->end; bitno--)
112.144 + ext2fs_clear_bit64(bitno - bmap->start, bp->bitarray);
112.145 + }
112.146 + if (new_real_end == bmap->real_end) {
112.147 + bmap->end = new_end;
112.148 + return 0;
112.149 + }
112.150 +
112.151 + size = ((bmap->real_end - bmap->start) / 8) + 1;
112.152 + new_size = ((new_real_end - bmap->start) / 8) + 1;
112.153 +
112.154 + if (size != new_size) {
112.155 + retval = ext2fs_resize_mem(size, new_size, &bp->bitarray);
112.156 + if (retval)
112.157 + return retval;
112.158 + }
112.159 + if (new_size > size)
112.160 + memset(bp->bitarray + size, 0, new_size - size);
112.161 +
112.162 + bmap->end = new_end;
112.163 + bmap->real_end = new_real_end;
112.164 + return 0;
112.165 +
112.166 +}
112.167 +
112.168 +static int ba_mark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
112.169 +{
112.170 + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
112.171 + blk64_t bitno = (blk64_t) arg;
112.172 +
112.173 + return ext2fs_set_bit64(bitno - bitmap->start, bp->bitarray);
112.174 +}
112.175 +
112.176 +static int ba_unmark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
112.177 +{
112.178 + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
112.179 + blk64_t bitno = (blk64_t) arg;
112.180 +
112.181 + return ext2fs_clear_bit64(bitno - bitmap->start, bp->bitarray);
112.182 +}
112.183 +
112.184 +static int ba_test_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
112.185 +{
112.186 + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
112.187 + blk64_t bitno = (blk64_t) arg;
112.188 +
112.189 + return ext2fs_test_bit64(bitno - bitmap->start, bp->bitarray);
112.190 +}
112.191 +
112.192 +static void ba_mark_bmap_extent(ext2fs_generic_bitmap bitmap, __u64 arg,
112.193 + unsigned int num)
112.194 +{
112.195 + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
112.196 + blk64_t bitno = (blk64_t) arg;
112.197 + unsigned int i;
112.198 +
112.199 + for (i = 0; i < num; i++)
112.200 + ext2fs_fast_set_bit64(bitno + i - bitmap->start, bp->bitarray);
112.201 +}
112.202 +
112.203 +static void ba_unmark_bmap_extent(ext2fs_generic_bitmap bitmap, __u64 arg,
112.204 + unsigned int num)
112.205 +{
112.206 + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
112.207 + blk64_t bitno = (blk64_t) arg;
112.208 + unsigned int i;
112.209 +
112.210 + for (i = 0; i < num; i++)
112.211 + ext2fs_fast_clear_bit64(bitno + i - bitmap->start, bp->bitarray);
112.212 +}
112.213 +
112.214 +static int ba_test_clear_bmap_extent(ext2fs_generic_bitmap bitmap,
112.215 + __u64 start, unsigned int len)
112.216 +{
112.217 + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
112.218 + __u64 start_byte, len_byte = len >> 3;
112.219 + unsigned int start_bit, len_bit = len % 8;
112.220 + unsigned int first_bit = 0;
112.221 + unsigned int last_bit = 0;
112.222 + int mark_count = 0;
112.223 + int mark_bit = 0;
112.224 + int i;
112.225 + const char *ADDR;
112.226 +
112.227 + ADDR = bp->bitarray;
112.228 + start -= bitmap->start;
112.229 + start_byte = start >> 3;
112.230 + start_bit = start % 8;
112.231 +
112.232 + if (start_bit != 0) {
112.233 + /*
112.234 + * The compared start block number or start inode number
112.235 + * is not the first bit in a byte.
112.236 + */
112.237 + mark_count = 8 - start_bit;
112.238 + if (len < 8 - start_bit) {
112.239 + mark_count = (int)len;
112.240 + mark_bit = len + start_bit - 1;
112.241 + } else
112.242 + mark_bit = 7;
112.243 +
112.244 + for (i = mark_count; i > 0; i--, mark_bit--)
112.245 + first_bit |= 1 << mark_bit;
112.246 +
112.247 + /*
112.248 + * Compare blocks or inodes in the first byte.
112.249 + * If there is any marked bit, this function returns 0.
112.250 + */
112.251 + if (first_bit & ADDR[start_byte])
112.252 + return 0;
112.253 + else if (len <= 8 - start_bit)
112.254 + return 1;
112.255 +
112.256 + start_byte++;
112.257 + len_bit = (len - mark_count) % 8;
112.258 + len_byte = (len - mark_count) >> 3;
112.259 + }
112.260 +
112.261 + /*
112.262 + * The compared start block number or start inode number is
112.263 + * the first bit in a byte.
112.264 + */
112.265 + if (len_bit != 0) {
112.266 + /*
112.267 + * The compared end block number or end inode number is
112.268 + * not the last bit in a byte.
112.269 + */
112.270 + for (mark_bit = len_bit - 1; mark_bit >= 0; mark_bit--)
112.271 + last_bit |= 1 << mark_bit;
112.272 +
112.273 + /*
112.274 + * Compare blocks or inodes in the last byte.
112.275 + * If there is any marked bit, this function returns 0.
112.276 + */
112.277 + if (last_bit & ADDR[start_byte + len_byte])
112.278 + return 0;
112.279 + else if (len_byte == 0)
112.280 + return 1;
112.281 + }
112.282 +
112.283 + /* Check whether all bytes are 0 */
112.284 + return ext2fs_mem_is_zero(ADDR + start_byte, len_byte);
112.285 +}
112.286 +
112.287 +
112.288 +static errcode_t ba_set_bmap_range(ext2fs_generic_bitmap bitmap,
112.289 + __u64 start, size_t num, void *in)
112.290 +{
112.291 + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
112.292 +
112.293 + memcpy (bp->bitarray + (start >> 3), in, (num + 7) >> 3);
112.294 +
112.295 + return 0;
112.296 +}
112.297 +
112.298 +static errcode_t ba_get_bmap_range(ext2fs_generic_bitmap bitmap,
112.299 + __u64 start, size_t num, void *out)
112.300 +{
112.301 + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
112.302 +
112.303 + memcpy (out, bp->bitarray + (start >> 3), (num + 7) >> 3);
112.304 +
112.305 + return 0;
112.306 +}
112.307 +
112.308 +static void ba_clear_bmap(ext2fs_generic_bitmap bitmap)
112.309 +{
112.310 + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
112.311 +
112.312 + memset(bp->bitarray, 0,
112.313 + (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
112.314 +}
112.315 +
112.316 +#ifdef ENABLE_BMAP_STATS
112.317 +static void ba_print_stats(ext2fs_generic_bitmap bitmap)
112.318 +{
112.319 + fprintf(stderr, "%16llu Bytes used by bitarray\n",
112.320 + ((bitmap->real_end - bitmap->start) >> 3) + 1 +
112.321 + sizeof(struct ext2fs_ba_private_struct));
112.322 +}
112.323 +#else
112.324 +static void ba_print_stats(ext2fs_generic_bitmap bitmap EXT2FS_ATTR((unused)))
112.325 +{
112.326 +}
112.327 +#endif
112.328 +
112.329 +/* Find the first zero bit between start and end, inclusive. */
112.330 +static errcode_t ba_find_first_zero(ext2fs_generic_bitmap bitmap,
112.331 + __u64 start, __u64 end, __u64 *out)
112.332 +{
112.333 + ext2fs_ba_private bp = (ext2fs_ba_private)bitmap->private;
112.334 + unsigned long bitpos = start - bitmap->start;
112.335 + unsigned long count = end - start + 1;
112.336 + int byte_found = 0; /* whether a != 0xff byte has been found */
112.337 + const unsigned char *pos;
112.338 + unsigned long max_loop_count, i;
112.339 +
112.340 + /* scan bits until we hit a byte boundary */
112.341 + while ((bitpos & 0x7) != 0 && count > 0) {
112.342 + if (!ext2fs_test_bit64(bitpos, bp->bitarray)) {
112.343 + *out = bitpos + bitmap->start;
112.344 + return 0;
112.345 + }
112.346 + bitpos++;
112.347 + count--;
112.348 + }
112.349 +
112.350 + if (!count)
112.351 + return ENOENT;
112.352 +
112.353 + pos = ((unsigned char *)bp->bitarray) + (bitpos >> 3);
112.354 + /* scan bytes until 8-byte (64-bit) aligned */
112.355 + while (count >= 8 && (((uintptr_t)pos) & 0x07)) {
112.356 + if (*pos != 0xff) {
112.357 + byte_found = 1;
112.358 + break;
112.359 + }
112.360 + pos++;
112.361 + count -= 8;
112.362 + bitpos += 8;
112.363 + }
112.364 +
112.365 + if (!byte_found) {
112.366 + max_loop_count = count >> 6; /* 8-byte blocks */
112.367 + i = max_loop_count;
112.368 + while (i) {
112.369 + if (*((const __u64 *)pos) != ((__u64)-1))
112.370 + break;
112.371 + pos += 8;
112.372 + i--;
112.373 + }
112.374 + count -= 64 * (max_loop_count - i);
112.375 + bitpos += 64 * (max_loop_count - i);
112.376 +
112.377 + max_loop_count = count >> 3;
112.378 + i = max_loop_count;
112.379 + while (i) {
112.380 + if (*pos != 0xff) {
112.381 + byte_found = 1;
112.382 + break;
112.383 + }
112.384 + pos++;
112.385 + i--;
112.386 + }
112.387 + count -= 8 * (max_loop_count - i);
112.388 + bitpos += 8 * (max_loop_count - i);
112.389 + }
112.390 +
112.391 + /* Here either count < 8 or byte_found == 1. */
112.392 + while (count-- > 0) {
112.393 + if (!ext2fs_test_bit64(bitpos, bp->bitarray)) {
112.394 + *out = bitpos + bitmap->start;
112.395 + return 0;
112.396 + }
112.397 + bitpos++;
112.398 + }
112.399 +
112.400 + return ENOENT;
112.401 +}
112.402 +
112.403 +/* Find the first one bit between start and end, inclusive. */
112.404 +static errcode_t ba_find_first_set(ext2fs_generic_bitmap bitmap,
112.405 + __u64 start, __u64 end, __u64 *out)
112.406 +{
112.407 + ext2fs_ba_private bp = (ext2fs_ba_private)bitmap->private;
112.408 + unsigned long bitpos = start - bitmap->start;
112.409 + unsigned long count = end - start + 1;
112.410 + int byte_found = 0; /* whether a != 0xff byte has been found */
112.411 + const unsigned char *pos;
112.412 + unsigned long max_loop_count, i;
112.413 +
112.414 + /* scan bits until we hit a byte boundary */
112.415 + while ((bitpos & 0x7) != 0 && count > 0) {
112.416 + if (ext2fs_test_bit64(bitpos, bp->bitarray)) {
112.417 + *out = bitpos + bitmap->start;
112.418 + return 0;
112.419 + }
112.420 + bitpos++;
112.421 + count--;
112.422 + }
112.423 +
112.424 + if (!count)
112.425 + return ENOENT;
112.426 +
112.427 + pos = ((unsigned char *)bp->bitarray) + (bitpos >> 3);
112.428 + /* scan bytes until 8-byte (64-bit) aligned */
112.429 + while (count >= 8 && (((uintptr_t)pos) & 0x07)) {
112.430 + if (*pos != 0) {
112.431 + byte_found = 1;
112.432 + break;
112.433 + }
112.434 + pos++;
112.435 + count -= 8;
112.436 + bitpos += 8;
112.437 + }
112.438 +
112.439 + if (!byte_found) {
112.440 + max_loop_count = count >> 6; /* 8-byte blocks */
112.441 + i = max_loop_count;
112.442 + while (i) {
112.443 + if (*((const __u64 *)pos) != 0)
112.444 + break;
112.445 + pos += 8;
112.446 + i--;
112.447 + }
112.448 + count -= 64 * (max_loop_count - i);
112.449 + bitpos += 64 * (max_loop_count - i);
112.450 +
112.451 + max_loop_count = count >> 3;
112.452 + i = max_loop_count;
112.453 + while (i) {
112.454 + if (*pos != 0) {
112.455 + byte_found = 1;
112.456 + break;
112.457 + }
112.458 + pos++;
112.459 + i--;
112.460 + }
112.461 + count -= 8 * (max_loop_count - i);
112.462 + bitpos += 8 * (max_loop_count - i);
112.463 + }
112.464 +
112.465 + /* Here either count < 8 or byte_found == 1. */
112.466 + while (count-- > 0) {
112.467 + if (ext2fs_test_bit64(bitpos, bp->bitarray)) {
112.468 + *out = bitpos + bitmap->start;
112.469 + return 0;
112.470 + }
112.471 + bitpos++;
112.472 + }
112.473 +
112.474 + return ENOENT;
112.475 +}
112.476 +
112.477 +struct ext2_bitmap_ops ext2fs_blkmap64_bitarray = {
112.478 + .type = EXT2FS_BMAP64_BITARRAY,
112.479 + .new_bmap = ba_new_bmap,
112.480 + .free_bmap = ba_free_bmap,
112.481 + .copy_bmap = ba_copy_bmap,
112.482 + .resize_bmap = ba_resize_bmap,
112.483 + .mark_bmap = ba_mark_bmap,
112.484 + .unmark_bmap = ba_unmark_bmap,
112.485 + .test_bmap = ba_test_bmap,
112.486 + .test_clear_bmap_extent = ba_test_clear_bmap_extent,
112.487 + .mark_bmap_extent = ba_mark_bmap_extent,
112.488 + .unmark_bmap_extent = ba_unmark_bmap_extent,
112.489 + .set_bmap_range = ba_set_bmap_range,
112.490 + .get_bmap_range = ba_get_bmap_range,
112.491 + .clear_bmap = ba_clear_bmap,
112.492 + .print_stats = ba_print_stats,
112.493 + .find_first_zero = ba_find_first_zero,
112.494 + .find_first_set = ba_find_first_set
112.495 +};
113.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
113.2 +++ b/libext2fs/lib/libext2fs/blkmap64_rb.c Wed Aug 25 01:28:08 2021 +0200
113.3 @@ -0,0 +1,989 @@
113.4 +/*
113.5 + * blkmap64_rb.c --- Simple rb-tree implementation for bitmaps
113.6 + *
113.7 + * (C)2010 Red Hat, Inc., Lukas Czerner <lczerner@redhat.com>
113.8 + *
113.9 + * %Begin-Header%
113.10 + * This file may be redistributed under the terms of the GNU Public
113.11 + * License.
113.12 + * %End-Header%
113.13 + */
113.14 +
113.15 +#include "config.h"
113.16 +#include <stdio.h>
113.17 +#include <string.h>
113.18 +#if HAVE_UNISTD_H
113.19 +#include <unistd.h>
113.20 +#endif
113.21 +#include <fcntl.h>
113.22 +#include <time.h>
113.23 +#if HAVE_SYS_STAT_H
113.24 +#include <sys/stat.h>
113.25 +#endif
113.26 +#if HAVE_SYS_TYPES_H
113.27 +#include <sys/types.h>
113.28 +#endif
113.29 +#if HAVE_LINUX_TYPES_H
113.30 +#include <linux/types.h>
113.31 +#endif
113.32 +
113.33 +#include "ext2_fs.h"
113.34 +#include "ext2fsP.h"
113.35 +#include "bmap64.h"
113.36 +#include "rbtree.h"
113.37 +
113.38 +#include <limits.h>
113.39 +
113.40 +struct bmap_rb_extent {
113.41 + struct rb_node node;
113.42 + __u64 start;
113.43 + __u64 count;
113.44 +};
113.45 +
113.46 +struct ext2fs_rb_private {
113.47 + struct rb_root root;
113.48 + struct bmap_rb_extent *wcursor;
113.49 + struct bmap_rb_extent *rcursor;
113.50 + struct bmap_rb_extent *rcursor_next;
113.51 +#ifdef ENABLE_BMAP_STATS_OPS
113.52 + __u64 mark_hit;
113.53 + __u64 test_hit;
113.54 +#endif
113.55 +};
113.56 +
113.57 +inline static struct bmap_rb_extent *node_to_extent(struct rb_node *node)
113.58 +{
113.59 + /*
113.60 + * This depends on the fact the struct rb_node is at the
113.61 + * beginning of the bmap_rb_extent structure. We use this
113.62 + * instead of the ext2fs_rb_entry macro because it causes gcc
113.63 + * -Wall to generate a huge amount of noise.
113.64 + */
113.65 + return (struct bmap_rb_extent *) node;
113.66 +}
113.67 +
113.68 +static int rb_insert_extent(__u64 start, __u64 count,
113.69 + struct ext2fs_rb_private *);
113.70 +static void rb_get_new_extent(struct bmap_rb_extent **, __u64, __u64);
113.71 +
113.72 +/* #define DEBUG_RB */
113.73 +
113.74 +#ifdef DEBUG_RB
113.75 +static void print_tree(struct rb_root *root)
113.76 +{
113.77 + struct rb_node *node = NULL;
113.78 + struct bmap_rb_extent *ext;
113.79 +
113.80 + fprintf(stderr, "\t\t\t=================================\n");
113.81 + node = ext2fs_rb_first(root);
113.82 + for (node = ext2fs_rb_first(root); node != NULL;
113.83 + node = ext2fs_rb_next(node)) {
113.84 + ext = node_to_extent(node);
113.85 + fprintf(stderr, "\t\t\t--> (%llu -> %llu)\n",
113.86 + ext->start, ext->start + ext->count);
113.87 + }
113.88 + fprintf(stderr, "\t\t\t=================================\n");
113.89 +}
113.90 +
113.91 +static void check_tree(struct rb_root *root, const char *msg)
113.92 +{
113.93 + struct rb_node *node;
113.94 + struct bmap_rb_extent *ext, *old = NULL;
113.95 +
113.96 + for (node = ext2fs_rb_first(root); node;
113.97 + node = ext2fs_rb_next(node)) {
113.98 + ext = node_to_extent(node);
113.99 + if (ext->count == 0) {
113.100 + fprintf(stderr, "Tree Error: count is zero\n");
113.101 + fprintf(stderr, "extent: %llu -> %llu (%llu)\n",
113.102 + ext->start, ext->start + ext->count,
113.103 + ext->count);
113.104 + goto err_out;
113.105 + }
113.106 + if (ext->start + ext->count < ext->start) {
113.107 + fprintf(stderr,
113.108 + "Tree Error: start or count is crazy\n");
113.109 + fprintf(stderr, "extent: %llu -> %llu (%llu)\n",
113.110 + ext->start, ext->start + ext->count,
113.111 + ext->count);
113.112 + goto err_out;
113.113 + }
113.114 +
113.115 + if (old) {
113.116 + if (old->start > ext->start) {
113.117 + fprintf(stderr, "Tree Error: start is crazy\n");
113.118 + fprintf(stderr, "extent: %llu -> %llu (%llu)\n",
113.119 + old->start, old->start + old->count,
113.120 + old->count);
113.121 + fprintf(stderr,
113.122 + "extent next: %llu -> %llu (%llu)\n",
113.123 + ext->start, ext->start + ext->count,
113.124 + ext->count);
113.125 + goto err_out;
113.126 + }
113.127 + if ((old->start + old->count) >= ext->start) {
113.128 + fprintf(stderr,
113.129 + "Tree Error: extent is crazy\n");
113.130 + fprintf(stderr, "extent: %llu -> %llu (%llu)\n",
113.131 + old->start, old->start + old->count,
113.132 + old->count);
113.133 + fprintf(stderr,
113.134 + "extent next: %llu -> %llu (%llu)\n",
113.135 + ext->start, ext->start + ext->count,
113.136 + ext->count);
113.137 + goto err_out;
113.138 + }
113.139 + }
113.140 + old = ext;
113.141 + }
113.142 + return;
113.143 +
113.144 +err_out:
113.145 + fprintf(stderr, "%s\n", msg);
113.146 + print_tree(root);
113.147 + exit(1);
113.148 +}
113.149 +#else
113.150 +#define check_tree(root, msg) do {} while (0)
113.151 +#define print_tree(root) do {} while (0)
113.152 +#endif
113.153 +
113.154 +static void rb_get_new_extent(struct bmap_rb_extent **ext, __u64 start,
113.155 + __u64 count)
113.156 +{
113.157 + struct bmap_rb_extent *new_ext;
113.158 + int retval;
113.159 +
113.160 + retval = ext2fs_get_mem(sizeof (struct bmap_rb_extent),
113.161 + &new_ext);
113.162 + if (retval)
113.163 + abort();
113.164 +
113.165 + new_ext->start = start;
113.166 + new_ext->count = count;
113.167 + *ext = new_ext;
113.168 +}
113.169 +
113.170 +inline
113.171 +static void rb_free_extent(struct ext2fs_rb_private *bp,
113.172 + struct bmap_rb_extent *ext)
113.173 +{
113.174 + if (bp->wcursor == ext)
113.175 + bp->wcursor = NULL;
113.176 + if (bp->rcursor == ext)
113.177 + bp->rcursor = NULL;
113.178 + if (bp->rcursor_next == ext)
113.179 + bp->rcursor_next = NULL;
113.180 + ext2fs_free_mem(&ext);
113.181 +}
113.182 +
113.183 +static errcode_t rb_alloc_private_data (ext2fs_generic_bitmap bitmap)
113.184 +{
113.185 + struct ext2fs_rb_private *bp;
113.186 + errcode_t retval;
113.187 +
113.188 + retval = ext2fs_get_mem(sizeof (struct ext2fs_rb_private), &bp);
113.189 + if (retval)
113.190 + return retval;
113.191 +
113.192 + bp->root = RB_ROOT;
113.193 + bp->rcursor = NULL;
113.194 + bp->rcursor_next = NULL;
113.195 + bp->wcursor = NULL;
113.196 +
113.197 +#ifdef ENABLE_BMAP_STATS_OPS
113.198 + bp->test_hit = 0;
113.199 + bp->mark_hit = 0;
113.200 +#endif
113.201 +
113.202 + bitmap->private = (void *) bp;
113.203 + return 0;
113.204 +}
113.205 +
113.206 +static errcode_t rb_new_bmap(ext2_filsys fs EXT2FS_ATTR((unused)),
113.207 + ext2fs_generic_bitmap bitmap)
113.208 +{
113.209 + errcode_t retval;
113.210 +
113.211 + retval = rb_alloc_private_data (bitmap);
113.212 + if (retval)
113.213 + return retval;
113.214 +
113.215 + return 0;
113.216 +}
113.217 +
113.218 +static void rb_free_tree(struct rb_root *root)
113.219 +{
113.220 + struct bmap_rb_extent *ext;
113.221 + struct rb_node *node, *next;
113.222 +
113.223 + for (node = ext2fs_rb_first(root); node; node = next) {
113.224 + next = ext2fs_rb_next(node);
113.225 + ext = node_to_extent(node);
113.226 + ext2fs_rb_erase(node, root);
113.227 + ext2fs_free_mem(&ext);
113.228 + }
113.229 +}
113.230 +
113.231 +static void rb_free_bmap(ext2fs_generic_bitmap bitmap)
113.232 +{
113.233 + struct ext2fs_rb_private *bp;
113.234 +
113.235 + bp = (struct ext2fs_rb_private *) bitmap->private;
113.236 +
113.237 + rb_free_tree(&bp->root);
113.238 + ext2fs_free_mem(&bp);
113.239 + bp = 0;
113.240 +}
113.241 +
113.242 +static errcode_t rb_copy_bmap(ext2fs_generic_bitmap src,
113.243 + ext2fs_generic_bitmap dest)
113.244 +{
113.245 + struct ext2fs_rb_private *src_bp, *dest_bp;
113.246 + struct bmap_rb_extent *src_ext, *dest_ext;
113.247 + struct rb_node *dest_node, *src_node, *dest_last, **n;
113.248 + errcode_t retval = 0;
113.249 +
113.250 + retval = rb_alloc_private_data (dest);
113.251 + if (retval)
113.252 + return retval;
113.253 +
113.254 + src_bp = (struct ext2fs_rb_private *) src->private;
113.255 + dest_bp = (struct ext2fs_rb_private *) dest->private;
113.256 + src_bp->rcursor = NULL;
113.257 + dest_bp->rcursor = NULL;
113.258 +
113.259 + src_node = ext2fs_rb_first(&src_bp->root);
113.260 + while (src_node) {
113.261 + src_ext = node_to_extent(src_node);
113.262 + retval = ext2fs_get_mem(sizeof (struct bmap_rb_extent),
113.263 + &dest_ext);
113.264 + if (retval)
113.265 + break;
113.266 +
113.267 + memcpy(dest_ext, src_ext, sizeof(struct bmap_rb_extent));
113.268 +
113.269 + dest_node = &dest_ext->node;
113.270 + n = &dest_bp->root.rb_node;
113.271 +
113.272 + dest_last = NULL;
113.273 + if (*n) {
113.274 + dest_last = ext2fs_rb_last(&dest_bp->root);
113.275 + n = &(dest_last)->rb_right;
113.276 + }
113.277 +
113.278 + ext2fs_rb_link_node(dest_node, dest_last, n);
113.279 + ext2fs_rb_insert_color(dest_node, &dest_bp->root);
113.280 +
113.281 + src_node = ext2fs_rb_next(src_node);
113.282 + }
113.283 +
113.284 + return retval;
113.285 +}
113.286 +
113.287 +static void rb_truncate(__u64 new_max, struct rb_root *root)
113.288 +{
113.289 + struct bmap_rb_extent *ext;
113.290 + struct rb_node *node;
113.291 +
113.292 + node = ext2fs_rb_last(root);
113.293 + while (node) {
113.294 + ext = node_to_extent(node);
113.295 +
113.296 + if ((ext->start + ext->count - 1) <= new_max)
113.297 + break;
113.298 + else if (ext->start > new_max) {
113.299 + ext2fs_rb_erase(node, root);
113.300 + ext2fs_free_mem(&ext);
113.301 + node = ext2fs_rb_last(root);
113.302 + continue;
113.303 + } else
113.304 + ext->count = new_max - ext->start + 1;
113.305 + }
113.306 +}
113.307 +
113.308 +static errcode_t rb_resize_bmap(ext2fs_generic_bitmap bmap,
113.309 + __u64 new_end, __u64 new_real_end)
113.310 +{
113.311 + struct ext2fs_rb_private *bp;
113.312 +
113.313 + bp = (struct ext2fs_rb_private *) bmap->private;
113.314 + bp->rcursor = NULL;
113.315 + bp->wcursor = NULL;
113.316 +
113.317 + rb_truncate(((new_end < bmap->end) ? new_end : bmap->end) - bmap->start,
113.318 + &bp->root);
113.319 +
113.320 + bmap->end = new_end;
113.321 + bmap->real_end = new_real_end;
113.322 +
113.323 + if (bmap->end < bmap->real_end)
113.324 + rb_insert_extent(bmap->end + 1 - bmap->start,
113.325 + bmap->real_end - bmap->end, bp);
113.326 + return 0;
113.327 +
113.328 +}
113.329 +
113.330 +inline static int
113.331 +rb_test_bit(struct ext2fs_rb_private *bp, __u64 bit)
113.332 +{
113.333 + struct bmap_rb_extent *rcursor, *next_ext = NULL;
113.334 + struct rb_node *parent = NULL, *next;
113.335 + struct rb_node **n = &bp->root.rb_node;
113.336 + struct bmap_rb_extent *ext;
113.337 +
113.338 + rcursor = bp->rcursor;
113.339 + if (!rcursor)
113.340 + goto search_tree;
113.341 +
113.342 + if (bit >= rcursor->start && bit < rcursor->start + rcursor->count) {
113.343 +#ifdef ENABLE_BMAP_STATS_OPS
113.344 + bp->test_hit++;
113.345 +#endif
113.346 + return 1;
113.347 + }
113.348 +
113.349 + next_ext = bp->rcursor_next;
113.350 + if (!next_ext) {
113.351 + next = ext2fs_rb_next(&rcursor->node);
113.352 + if (next)
113.353 + next_ext = node_to_extent(next);
113.354 + bp->rcursor_next = next_ext;
113.355 + }
113.356 + if (next_ext) {
113.357 + if ((bit >= rcursor->start + rcursor->count) &&
113.358 + (bit < next_ext->start)) {
113.359 +#ifdef BMAP_STATS_OPS
113.360 + bp->test_hit++;
113.361 +#endif
113.362 + return 0;
113.363 + }
113.364 + }
113.365 + bp->rcursor = NULL;
113.366 + bp->rcursor_next = NULL;
113.367 +
113.368 + rcursor = bp->wcursor;
113.369 + if (!rcursor)
113.370 + goto search_tree;
113.371 +
113.372 + if (bit >= rcursor->start && bit < rcursor->start + rcursor->count)
113.373 + return 1;
113.374 +
113.375 +search_tree:
113.376 +
113.377 + while (*n) {
113.378 + parent = *n;
113.379 + ext = node_to_extent(parent);
113.380 + if (bit < ext->start)
113.381 + n = &(*n)->rb_left;
113.382 + else if (bit >= (ext->start + ext->count))
113.383 + n = &(*n)->rb_right;
113.384 + else {
113.385 + bp->rcursor = ext;
113.386 + bp->rcursor_next = NULL;
113.387 + return 1;
113.388 + }
113.389 + }
113.390 + return 0;
113.391 +}
113.392 +
113.393 +static int rb_insert_extent(__u64 start, __u64 count,
113.394 + struct ext2fs_rb_private *bp)
113.395 +{
113.396 + struct rb_root *root = &bp->root;
113.397 + struct rb_node *parent = NULL, **n = &root->rb_node;
113.398 + struct rb_node *new_node, *node, *next;
113.399 + struct bmap_rb_extent *new_ext;
113.400 + struct bmap_rb_extent *ext;
113.401 + int retval = 0;
113.402 +
113.403 + if (count == 0)
113.404 + return 0;
113.405 +
113.406 + bp->rcursor_next = NULL;
113.407 + ext = bp->wcursor;
113.408 + if (ext) {
113.409 + if (start >= ext->start &&
113.410 + start <= (ext->start + ext->count)) {
113.411 +#ifdef ENABLE_BMAP_STATS_OPS
113.412 + bp->mark_hit++;
113.413 +#endif
113.414 + goto got_extent;
113.415 + }
113.416 + }
113.417 +
113.418 + while (*n) {
113.419 + parent = *n;
113.420 + ext = node_to_extent(parent);
113.421 +
113.422 + if (start < ext->start) {
113.423 + n = &(*n)->rb_left;
113.424 + } else if (start > (ext->start + ext->count)) {
113.425 + n = &(*n)->rb_right;
113.426 + } else {
113.427 +got_extent:
113.428 + if ((start + count) <= (ext->start + ext->count))
113.429 + return 1;
113.430 +
113.431 + if ((ext->start + ext->count) == start)
113.432 + retval = 0;
113.433 + else
113.434 + retval = 1;
113.435 +
113.436 + count += (start - ext->start);
113.437 + start = ext->start;
113.438 + new_ext = ext;
113.439 + new_node = &ext->node;
113.440 +
113.441 + goto skip_insert;
113.442 + }
113.443 + }
113.444 +
113.445 + rb_get_new_extent(&new_ext, start, count);
113.446 +
113.447 + new_node = &new_ext->node;
113.448 + ext2fs_rb_link_node(new_node, parent, n);
113.449 + ext2fs_rb_insert_color(new_node, root);
113.450 + bp->wcursor = new_ext;
113.451 +
113.452 + node = ext2fs_rb_prev(new_node);
113.453 + if (node) {
113.454 + ext = node_to_extent(node);
113.455 + if ((ext->start + ext->count) == start) {
113.456 + start = ext->start;
113.457 + count += ext->count;
113.458 + ext2fs_rb_erase(node, root);
113.459 + rb_free_extent(bp, ext);
113.460 + }
113.461 + }
113.462 +
113.463 +skip_insert:
113.464 + /* See if we can merge extent to the right */
113.465 + for (node = ext2fs_rb_next(new_node); node != NULL; node = next) {
113.466 + next = ext2fs_rb_next(node);
113.467 + ext = node_to_extent(node);
113.468 +
113.469 + if ((ext->start + ext->count) <= start)
113.470 + continue;
113.471 +
113.472 + /* No more merging */
113.473 + if ((start + count) < ext->start)
113.474 + break;
113.475 +
113.476 + /* ext is embedded in new_ext interval */
113.477 + if ((start + count) >= (ext->start + ext->count)) {
113.478 + ext2fs_rb_erase(node, root);
113.479 + rb_free_extent(bp, ext);
113.480 + continue;
113.481 + } else {
113.482 + /* merge ext with new_ext */
113.483 + count += ((ext->start + ext->count) -
113.484 + (start + count));
113.485 + ext2fs_rb_erase(node, root);
113.486 + rb_free_extent(bp, ext);
113.487 + break;
113.488 + }
113.489 + }
113.490 +
113.491 + new_ext->start = start;
113.492 + new_ext->count = count;
113.493 +
113.494 + return retval;
113.495 +}
113.496 +
113.497 +static int rb_remove_extent(__u64 start, __u64 count,
113.498 + struct ext2fs_rb_private *bp)
113.499 +{
113.500 + struct rb_root *root = &bp->root;
113.501 + struct rb_node *parent = NULL, **n = &root->rb_node;
113.502 + struct rb_node *node;
113.503 + struct bmap_rb_extent *ext;
113.504 + __u64 new_start, new_count;
113.505 + int retval = 0;
113.506 +
113.507 + if (ext2fs_rb_empty_root(root))
113.508 + return 0;
113.509 +
113.510 + while (*n) {
113.511 + parent = *n;
113.512 + ext = node_to_extent(parent);
113.513 + if (start < ext->start) {
113.514 + n = &(*n)->rb_left;
113.515 + continue;
113.516 + } else if (start >= (ext->start + ext->count)) {
113.517 + n = &(*n)->rb_right;
113.518 + continue;
113.519 + }
113.520 +
113.521 + if ((start > ext->start) &&
113.522 + (start + count) < (ext->start + ext->count)) {
113.523 + /* We have to split extent into two */
113.524 + new_start = start + count;
113.525 + new_count = (ext->start + ext->count) - new_start;
113.526 +
113.527 + ext->count = start - ext->start;
113.528 +
113.529 + rb_insert_extent(new_start, new_count, bp);
113.530 + return 1;
113.531 + }
113.532 +
113.533 + if ((start + count) >= (ext->start + ext->count)) {
113.534 + ext->count = start - ext->start;
113.535 + retval = 1;
113.536 + }
113.537 +
113.538 + if (0 == ext->count) {
113.539 + parent = ext2fs_rb_next(&ext->node);
113.540 + ext2fs_rb_erase(&ext->node, root);
113.541 + rb_free_extent(bp, ext);
113.542 + break;
113.543 + }
113.544 +
113.545 + if (start == ext->start) {
113.546 + ext->start += count;
113.547 + ext->count -= count;
113.548 + return 1;
113.549 + }
113.550 + }
113.551 +
113.552 + /* See if we should delete or truncate extent on the right */
113.553 + for (; parent != NULL; parent = node) {
113.554 + node = ext2fs_rb_next(parent);
113.555 + ext = node_to_extent(parent);
113.556 + if ((ext->start + ext->count) <= start)
113.557 + continue;
113.558 +
113.559 + /* No more extents to be removed/truncated */
113.560 + if ((start + count) < ext->start)
113.561 + break;
113.562 +
113.563 + /* The entire extent is within the region to be removed */
113.564 + if ((start + count) >= (ext->start + ext->count)) {
113.565 + ext2fs_rb_erase(parent, root);
113.566 + rb_free_extent(bp, ext);
113.567 + retval = 1;
113.568 + continue;
113.569 + } else {
113.570 + /* modify the last extent in region to be removed */
113.571 + ext->count -= ((start + count) - ext->start);
113.572 + ext->start = start + count;
113.573 + retval = 1;
113.574 + break;
113.575 + }
113.576 + }
113.577 +
113.578 + return retval;
113.579 +}
113.580 +
113.581 +static int rb_mark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
113.582 +{
113.583 + struct ext2fs_rb_private *bp;
113.584 + int retval;
113.585 +
113.586 + bp = (struct ext2fs_rb_private *) bitmap->private;
113.587 + arg -= bitmap->start;
113.588 +
113.589 + retval = rb_insert_extent(arg, 1, bp);
113.590 + check_tree(&bp->root, __func__);
113.591 + return retval;
113.592 +}
113.593 +
113.594 +static int rb_unmark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
113.595 +{
113.596 + struct ext2fs_rb_private *bp;
113.597 + int retval;
113.598 +
113.599 + bp = (struct ext2fs_rb_private *) bitmap->private;
113.600 + arg -= bitmap->start;
113.601 +
113.602 + retval = rb_remove_extent(arg, 1, bp);
113.603 + check_tree(&bp->root, __func__);
113.604 +
113.605 + return retval;
113.606 +}
113.607 +
113.608 +inline
113.609 +static int rb_test_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
113.610 +{
113.611 + struct ext2fs_rb_private *bp;
113.612 +
113.613 + bp = (struct ext2fs_rb_private *) bitmap->private;
113.614 + arg -= bitmap->start;
113.615 +
113.616 + return rb_test_bit(bp, arg);
113.617 +}
113.618 +
113.619 +static void rb_mark_bmap_extent(ext2fs_generic_bitmap bitmap, __u64 arg,
113.620 + unsigned int num)
113.621 +{
113.622 + struct ext2fs_rb_private *bp;
113.623 +
113.624 + bp = (struct ext2fs_rb_private *) bitmap->private;
113.625 + arg -= bitmap->start;
113.626 +
113.627 + rb_insert_extent(arg, num, bp);
113.628 + check_tree(&bp->root, __func__);
113.629 +}
113.630 +
113.631 +static void rb_unmark_bmap_extent(ext2fs_generic_bitmap bitmap, __u64 arg,
113.632 + unsigned int num)
113.633 +{
113.634 + struct ext2fs_rb_private *bp;
113.635 +
113.636 + bp = (struct ext2fs_rb_private *) bitmap->private;
113.637 + arg -= bitmap->start;
113.638 +
113.639 + rb_remove_extent(arg, num, bp);
113.640 + check_tree(&bp->root, __func__);
113.641 +}
113.642 +
113.643 +static int rb_test_clear_bmap_extent(ext2fs_generic_bitmap bitmap,
113.644 + __u64 start, unsigned int len)
113.645 +{
113.646 + struct rb_node *parent = NULL, **n;
113.647 + struct rb_node *node, *next;
113.648 + struct ext2fs_rb_private *bp;
113.649 + struct bmap_rb_extent *ext;
113.650 + int retval = 1;
113.651 +
113.652 + bp = (struct ext2fs_rb_private *) bitmap->private;
113.653 + n = &bp->root.rb_node;
113.654 + start -= bitmap->start;
113.655 +
113.656 + if (len == 0 || ext2fs_rb_empty_root(&bp->root))
113.657 + return 1;
113.658 +
113.659 + /*
113.660 + * If we find nothing, we should examine whole extent, but
113.661 + * when we find match, the extent is not clean, thus be return
113.662 + * false.
113.663 + */
113.664 + while (*n) {
113.665 + parent = *n;
113.666 + ext = node_to_extent(parent);
113.667 + if (start < ext->start) {
113.668 + n = &(*n)->rb_left;
113.669 + } else if (start >= (ext->start + ext->count)) {
113.670 + n = &(*n)->rb_right;
113.671 + } else {
113.672 + /*
113.673 + * We found extent int the tree -> extent is not
113.674 + * clean
113.675 + */
113.676 + return 0;
113.677 + }
113.678 + }
113.679 +
113.680 + node = parent;
113.681 + while (node) {
113.682 + next = ext2fs_rb_next(node);
113.683 + ext = node_to_extent(node);
113.684 + node = next;
113.685 +
113.686 + if ((ext->start + ext->count) <= start)
113.687 + continue;
113.688 +
113.689 + /* No more merging */
113.690 + if ((start + len) <= ext->start)
113.691 + break;
113.692 +
113.693 + retval = 0;
113.694 + break;
113.695 + }
113.696 + return retval;
113.697 +}
113.698 +
113.699 +static errcode_t rb_set_bmap_range(ext2fs_generic_bitmap bitmap,
113.700 + __u64 start, size_t num, void *in)
113.701 +{
113.702 + struct ext2fs_rb_private *bp;
113.703 + unsigned char *cp = in;
113.704 + size_t i;
113.705 + int first_set = -1;
113.706 +
113.707 + bp = (struct ext2fs_rb_private *) bitmap->private;
113.708 +
113.709 + for (i = 0; i < num; i++) {
113.710 + if ((i & 7) == 0) {
113.711 + unsigned char c = cp[i/8];
113.712 + if (c == 0xFF) {
113.713 + if (first_set == -1)
113.714 + first_set = i;
113.715 + i += 7;
113.716 + continue;
113.717 + }
113.718 + if ((c == 0x00) && (first_set == -1)) {
113.719 + i += 7;
113.720 + continue;
113.721 + }
113.722 + }
113.723 + if (ext2fs_test_bit(i, in)) {
113.724 + if (first_set == -1)
113.725 + first_set = i;
113.726 + continue;
113.727 + }
113.728 + if (first_set == -1)
113.729 + continue;
113.730 +
113.731 + rb_insert_extent(start + first_set - bitmap->start,
113.732 + i - first_set, bp);
113.733 + check_tree(&bp->root, __func__);
113.734 + first_set = -1;
113.735 + }
113.736 + if (first_set != -1) {
113.737 + rb_insert_extent(start + first_set - bitmap->start,
113.738 + num - first_set, bp);
113.739 + check_tree(&bp->root, __func__);
113.740 + }
113.741 +
113.742 + return 0;
113.743 +}
113.744 +
113.745 +static errcode_t rb_get_bmap_range(ext2fs_generic_bitmap bitmap,
113.746 + __u64 start, size_t num, void *out)
113.747 +{
113.748 +
113.749 + struct rb_node *parent = NULL, *next, **n;
113.750 + struct ext2fs_rb_private *bp;
113.751 + struct bmap_rb_extent *ext;
113.752 + __u64 count, pos;
113.753 +
113.754 + bp = (struct ext2fs_rb_private *) bitmap->private;
113.755 + n = &bp->root.rb_node;
113.756 + start -= bitmap->start;
113.757 +
113.758 + if (ext2fs_rb_empty_root(&bp->root))
113.759 + return 0;
113.760 +
113.761 + while (*n) {
113.762 + parent = *n;
113.763 + ext = node_to_extent(parent);
113.764 + if (start < ext->start) {
113.765 + n = &(*n)->rb_left;
113.766 + } else if (start >= (ext->start + ext->count)) {
113.767 + n = &(*n)->rb_right;
113.768 + } else
113.769 + break;
113.770 + }
113.771 +
113.772 + memset(out, 0, (num + 7) >> 3);
113.773 +
113.774 + for (; parent != NULL; parent = next) {
113.775 + next = ext2fs_rb_next(parent);
113.776 + ext = node_to_extent(parent);
113.777 +
113.778 + pos = ext->start;
113.779 + count = ext->count;
113.780 + if (pos >= start + num)
113.781 + break;
113.782 + if (pos < start) {
113.783 + if (pos + count < start)
113.784 + continue;
113.785 + count -= start - pos;
113.786 + pos = start;
113.787 + }
113.788 + if (pos + count > start + num)
113.789 + count = start + num - pos;
113.790 +
113.791 + while (count > 0) {
113.792 + if ((count >= 8) &&
113.793 + ((pos - start) % 8) == 0) {
113.794 + int nbytes = count >> 3;
113.795 + int offset = (pos - start) >> 3;
113.796 +
113.797 + memset(((char *) out) + offset, 0xFF, nbytes);
113.798 + pos += nbytes << 3;
113.799 + count -= nbytes << 3;
113.800 + continue;
113.801 + }
113.802 + ext2fs_fast_set_bit64((pos - start), out);
113.803 + pos++;
113.804 + count--;
113.805 + }
113.806 + }
113.807 + return 0;
113.808 +}
113.809 +
113.810 +static void rb_clear_bmap(ext2fs_generic_bitmap bitmap)
113.811 +{
113.812 + struct ext2fs_rb_private *bp;
113.813 +
113.814 + bp = (struct ext2fs_rb_private *) bitmap->private;
113.815 +
113.816 + rb_free_tree(&bp->root);
113.817 + bp->rcursor = NULL;
113.818 + bp->rcursor_next = NULL;
113.819 + bp->wcursor = NULL;
113.820 + check_tree(&bp->root, __func__);
113.821 +}
113.822 +
113.823 +static errcode_t rb_find_first_zero(ext2fs_generic_bitmap bitmap,
113.824 + __u64 start, __u64 end, __u64 *out)
113.825 +{
113.826 + struct rb_node *parent = NULL, **n;
113.827 + struct ext2fs_rb_private *bp;
113.828 + struct bmap_rb_extent *ext;
113.829 +
113.830 + bp = (struct ext2fs_rb_private *) bitmap->private;
113.831 + n = &bp->root.rb_node;
113.832 + start -= bitmap->start;
113.833 + end -= bitmap->start;
113.834 +
113.835 + if (start > end)
113.836 + return EINVAL;
113.837 +
113.838 + if (ext2fs_rb_empty_root(&bp->root))
113.839 + return ENOENT;
113.840 +
113.841 + while (*n) {
113.842 + parent = *n;
113.843 + ext = node_to_extent(parent);
113.844 + if (start < ext->start) {
113.845 + n = &(*n)->rb_left;
113.846 + } else if (start >= (ext->start + ext->count)) {
113.847 + n = &(*n)->rb_right;
113.848 + } else if (ext->start + ext->count <= end) {
113.849 + *out = ext->start + ext->count + bitmap->start;
113.850 + return 0;
113.851 + } else
113.852 + return ENOENT;
113.853 + }
113.854 +
113.855 + *out = start + bitmap->start;
113.856 + return 0;
113.857 +}
113.858 +
113.859 +static errcode_t rb_find_first_set(ext2fs_generic_bitmap bitmap,
113.860 + __u64 start, __u64 end, __u64 *out)
113.861 +{
113.862 + struct rb_node *parent = NULL, **n;
113.863 + struct rb_node *node;
113.864 + struct ext2fs_rb_private *bp;
113.865 + struct bmap_rb_extent *ext;
113.866 +
113.867 + bp = (struct ext2fs_rb_private *) bitmap->private;
113.868 + n = &bp->root.rb_node;
113.869 + start -= bitmap->start;
113.870 + end -= bitmap->start;
113.871 +
113.872 + if (start > end)
113.873 + return EINVAL;
113.874 +
113.875 + if (ext2fs_rb_empty_root(&bp->root))
113.876 + return ENOENT;
113.877 +
113.878 + while (*n) {
113.879 + parent = *n;
113.880 + ext = node_to_extent(parent);
113.881 + if (start < ext->start) {
113.882 + n = &(*n)->rb_left;
113.883 + } else if (start >= (ext->start + ext->count)) {
113.884 + n = &(*n)->rb_right;
113.885 + } else {
113.886 + /* The start bit is set */
113.887 + *out = start + bitmap->start;
113.888 + return 0;
113.889 + }
113.890 + }
113.891 +
113.892 + node = parent;
113.893 + ext = node_to_extent(node);
113.894 + if (ext->start < start) {
113.895 + node = ext2fs_rb_next(node);
113.896 + if (node == NULL)
113.897 + return ENOENT;
113.898 + ext = node_to_extent(node);
113.899 + }
113.900 + if (ext->start <= end) {
113.901 + *out = ext->start + bitmap->start;
113.902 + return 0;
113.903 + }
113.904 + return ENOENT;
113.905 +}
113.906 +
113.907 +#ifdef ENABLE_BMAP_STATS
113.908 +static void rb_print_stats(ext2fs_generic_bitmap bitmap)
113.909 +{
113.910 + struct ext2fs_rb_private *bp;
113.911 + struct rb_node *node = NULL;
113.912 + struct bmap_rb_extent *ext;
113.913 + __u64 count = 0;
113.914 + __u64 max_size = 0;
113.915 + __u64 min_size = ULONG_MAX;
113.916 + __u64 size = 0, avg_size = 0;
113.917 + double eff;
113.918 +#ifdef ENABLE_BMAP_STATS_OPS
113.919 + __u64 mark_all, test_all;
113.920 + double m_hit = 0.0, t_hit = 0.0;
113.921 +#endif
113.922 +
113.923 + bp = (struct ext2fs_rb_private *) bitmap->private;
113.924 +
113.925 + for (node = ext2fs_rb_first(&bp->root); node != NULL;
113.926 + node = ext2fs_rb_next(node)) {
113.927 + ext = node_to_extent(node);
113.928 + count++;
113.929 + if (ext->count > max_size)
113.930 + max_size = ext->count;
113.931 + if (ext->count < min_size)
113.932 + min_size = ext->count;
113.933 + size += ext->count;
113.934 + }
113.935 +
113.936 + if (count)
113.937 + avg_size = size / count;
113.938 + if (min_size == ULONG_MAX)
113.939 + min_size = 0;
113.940 + eff = (double)((count * sizeof(struct bmap_rb_extent)) << 3) /
113.941 + (bitmap->real_end - bitmap->start);
113.942 +#ifdef ENABLE_BMAP_STATS_OPS
113.943 + mark_all = bitmap->stats.mark_count + bitmap->stats.mark_ext_count;
113.944 + test_all = bitmap->stats.test_count + bitmap->stats.test_ext_count;
113.945 + if (mark_all)
113.946 + m_hit = ((double)bp->mark_hit / mark_all) * 100;
113.947 + if (test_all)
113.948 + t_hit = ((double)bp->test_hit / test_all) * 100;
113.949 +
113.950 + fprintf(stderr, "%16llu cache hits on test (%.2f%%)\n"
113.951 + "%16llu cache hits on mark (%.2f%%)\n",
113.952 + bp->test_hit, t_hit, bp->mark_hit, m_hit);
113.953 +#endif
113.954 + fprintf(stderr, "%16llu extents (%llu bytes)\n",
113.955 + count, ((count * sizeof(struct bmap_rb_extent)) +
113.956 + sizeof(struct ext2fs_rb_private)));
113.957 + fprintf(stderr, "%16llu bits minimum size\n",
113.958 + min_size);
113.959 + fprintf(stderr, "%16llu bits maximum size\n"
113.960 + "%16llu bits average size\n",
113.961 + max_size, avg_size);
113.962 + fprintf(stderr, "%16llu bits set in bitmap (out of %llu)\n", size,
113.963 + bitmap->real_end - bitmap->start);
113.964 + fprintf(stderr,
113.965 + "%16.4lf memory / bitmap bit memory ratio (bitarray = 1)\n",
113.966 + eff);
113.967 +}
113.968 +#else
113.969 +static void rb_print_stats(ext2fs_generic_bitmap bitmap EXT2FS_ATTR((unused)))
113.970 +{
113.971 +}
113.972 +#endif
113.973 +
113.974 +struct ext2_bitmap_ops ext2fs_blkmap64_rbtree = {
113.975 + .type = EXT2FS_BMAP64_RBTREE,
113.976 + .new_bmap = rb_new_bmap,
113.977 + .free_bmap = rb_free_bmap,
113.978 + .copy_bmap = rb_copy_bmap,
113.979 + .resize_bmap = rb_resize_bmap,
113.980 + .mark_bmap = rb_mark_bmap,
113.981 + .unmark_bmap = rb_unmark_bmap,
113.982 + .test_bmap = rb_test_bmap,
113.983 + .test_clear_bmap_extent = rb_test_clear_bmap_extent,
113.984 + .mark_bmap_extent = rb_mark_bmap_extent,
113.985 + .unmark_bmap_extent = rb_unmark_bmap_extent,
113.986 + .set_bmap_range = rb_set_bmap_range,
113.987 + .get_bmap_range = rb_get_bmap_range,
113.988 + .clear_bmap = rb_clear_bmap,
113.989 + .print_stats = rb_print_stats,
113.990 + .find_first_zero = rb_find_first_zero,
113.991 + .find_first_set = rb_find_first_set,
113.992 +};
114.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
114.2 +++ b/libext2fs/lib/libext2fs/blknum.c Wed Aug 25 01:28:08 2021 +0200
114.3 @@ -0,0 +1,543 @@
114.4 +/*
114.5 + * blknum.c --- Functions to handle blk64_t and high/low 64-bit block
114.6 + * number.
114.7 + *
114.8 + * Copyright IBM Corporation, 2007
114.9 + * Author Jose R. Santos <jrs@us.ibm.com>
114.10 + *
114.11 + * %Begin-Header%
114.12 + * This file may be redistributed under the terms of the GNU Public
114.13 + * License.
114.14 + * %End-Header%
114.15 + */
114.16 +
114.17 +#include "config.h"
114.18 +#include "ext2fs.h"
114.19 +
114.20 +/*
114.21 + * Return the group # of a block
114.22 + */
114.23 +dgrp_t ext2fs_group_of_blk2(ext2_filsys fs, blk64_t blk)
114.24 +{
114.25 + return (blk - fs->super->s_first_data_block) /
114.26 + fs->super->s_blocks_per_group;
114.27 +}
114.28 +
114.29 +/*
114.30 + * Return the first block (inclusive) in a group
114.31 + */
114.32 +blk64_t ext2fs_group_first_block2(ext2_filsys fs, dgrp_t group)
114.33 +{
114.34 + return fs->super->s_first_data_block +
114.35 + EXT2_GROUPS_TO_BLOCKS(fs->super, group);
114.36 +}
114.37 +
114.38 +/*
114.39 + * Return the last block (inclusive) in a group
114.40 + */
114.41 +blk64_t ext2fs_group_last_block2(ext2_filsys fs, dgrp_t group)
114.42 +{
114.43 + return (group == fs->group_desc_count - 1 ?
114.44 + ext2fs_blocks_count(fs->super) - 1 :
114.45 + ext2fs_group_first_block2(fs, group) +
114.46 + (fs->super->s_blocks_per_group - 1));
114.47 +}
114.48 +
114.49 +/*
114.50 + * Return the number of blocks in a group
114.51 + */
114.52 +int ext2fs_group_blocks_count(ext2_filsys fs, dgrp_t group)
114.53 +{
114.54 + int num_blocks;
114.55 +
114.56 + if (group == fs->group_desc_count - 1) {
114.57 + num_blocks = (ext2fs_blocks_count(fs->super) -
114.58 + fs->super->s_first_data_block) %
114.59 + fs->super->s_blocks_per_group;
114.60 + if (!num_blocks)
114.61 + num_blocks = fs->super->s_blocks_per_group;
114.62 + } else
114.63 + num_blocks = fs->super->s_blocks_per_group;
114.64 +
114.65 + return num_blocks;
114.66 +}
114.67 +
114.68 +/*
114.69 + * Return the inode data block count
114.70 + */
114.71 +blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs,
114.72 + struct ext2_inode *inode)
114.73 +{
114.74 + return (inode->i_blocks |
114.75 + (ext2fs_has_feature_huge_file(fs->super) ?
114.76 + (__u64) inode->osd2.linux2.l_i_blocks_hi << 32 : 0)) -
114.77 + (inode->i_file_acl ? EXT2_CLUSTER_SIZE(fs->super) >> 9 : 0);
114.78 +}
114.79 +
114.80 +/*
114.81 + * Return the inode i_blocks count
114.82 + */
114.83 +blk64_t ext2fs_inode_i_blocks(ext2_filsys fs,
114.84 + struct ext2_inode *inode)
114.85 +{
114.86 + return (inode->i_blocks |
114.87 + (ext2fs_has_feature_huge_file(fs->super) ?
114.88 + (__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0));
114.89 +}
114.90 +
114.91 +/*
114.92 + * Return the fs block count
114.93 + */
114.94 +blk64_t ext2fs_blocks_count(struct ext2_super_block *super)
114.95 +{
114.96 + return super->s_blocks_count |
114.97 + (ext2fs_has_feature_64bit(super) ?
114.98 + (__u64) super->s_blocks_count_hi << 32 : 0);
114.99 +}
114.100 +
114.101 +/*
114.102 + * Set the fs block count
114.103 + */
114.104 +void ext2fs_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
114.105 +{
114.106 + super->s_blocks_count = blk;
114.107 + if (ext2fs_has_feature_64bit(super))
114.108 + super->s_blocks_count_hi = (__u64) blk >> 32;
114.109 +}
114.110 +
114.111 +/*
114.112 + * Add to the current fs block count
114.113 + */
114.114 +void ext2fs_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
114.115 +{
114.116 + blk64_t tmp;
114.117 + tmp = ext2fs_blocks_count(super) + blk;
114.118 + ext2fs_blocks_count_set(super, tmp);
114.119 +}
114.120 +
114.121 +/*
114.122 + * Return the fs reserved block count
114.123 + */
114.124 +blk64_t ext2fs_r_blocks_count(struct ext2_super_block *super)
114.125 +{
114.126 + return super->s_r_blocks_count |
114.127 + (ext2fs_has_feature_64bit(super) ?
114.128 + (__u64) super->s_r_blocks_count_hi << 32 : 0);
114.129 +}
114.130 +
114.131 +/*
114.132 + * Set the fs reserved block count
114.133 + */
114.134 +void ext2fs_r_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
114.135 +{
114.136 + super->s_r_blocks_count = blk;
114.137 + if (ext2fs_has_feature_64bit(super))
114.138 + super->s_r_blocks_count_hi = (__u64) blk >> 32;
114.139 +}
114.140 +
114.141 +/*
114.142 + * Add to the current reserved fs block count
114.143 + */
114.144 +void ext2fs_r_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
114.145 +{
114.146 + blk64_t tmp;
114.147 + tmp = ext2fs_r_blocks_count(super) + blk;
114.148 + ext2fs_r_blocks_count_set(super, tmp);
114.149 +}
114.150 +
114.151 +/*
114.152 + * Return the fs free block count
114.153 + */
114.154 +blk64_t ext2fs_free_blocks_count(struct ext2_super_block *super)
114.155 +{
114.156 + return super->s_free_blocks_count |
114.157 + (ext2fs_has_feature_64bit(super) ?
114.158 + (__u64) super->s_free_blocks_hi << 32 : 0);
114.159 +}
114.160 +
114.161 +/*
114.162 + * Set the fs free block count
114.163 + */
114.164 +void ext2fs_free_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
114.165 +{
114.166 + super->s_free_blocks_count = blk;
114.167 + if (ext2fs_has_feature_64bit(super))
114.168 + super->s_free_blocks_hi = (__u64) blk >> 32;
114.169 +}
114.170 +
114.171 +/*
114.172 + * Add to the current free fs block count
114.173 + */
114.174 +void ext2fs_free_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
114.175 +{
114.176 + blk64_t tmp;
114.177 + tmp = ext2fs_free_blocks_count(super) + blk;
114.178 + ext2fs_free_blocks_count_set(super, tmp);
114.179 +}
114.180 +
114.181 +/*
114.182 + * Get a pointer to a block group descriptor. We need the explicit
114.183 + * pointer to the group desc for code that swaps block group
114.184 + * descriptors before writing them out, as it wants to make a copy and
114.185 + * do the swap there.
114.186 + */
114.187 +struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs,
114.188 + struct opaque_ext2_group_desc *gdp,
114.189 + dgrp_t group)
114.190 +{
114.191 + int desc_size = EXT2_DESC_SIZE(fs->super) & ~7;
114.192 +
114.193 + return (struct ext2_group_desc *)((char *)gdp + group * desc_size);
114.194 +}
114.195 +
114.196 +/* Do the same but as an ext4 group desc for internal use here */
114.197 +static struct ext4_group_desc *ext4fs_group_desc(ext2_filsys fs,
114.198 + struct opaque_ext2_group_desc *gdp,
114.199 + dgrp_t group)
114.200 +{
114.201 + return (struct ext4_group_desc *)ext2fs_group_desc(fs, gdp, group);
114.202 +}
114.203 +
114.204 +/*
114.205 + * Return the block bitmap checksum of a group
114.206 + */
114.207 +__u32 ext2fs_block_bitmap_checksum(ext2_filsys fs, dgrp_t group)
114.208 +{
114.209 + struct ext4_group_desc *gdp;
114.210 + __u32 csum;
114.211 +
114.212 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.213 + csum = gdp->bg_block_bitmap_csum_lo;
114.214 + if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
114.215 + csum |= ((__u32)gdp->bg_block_bitmap_csum_hi << 16);
114.216 + return csum;
114.217 +}
114.218 +
114.219 +/*
114.220 + * Return the block bitmap block of a group
114.221 + */
114.222 +blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group)
114.223 +{
114.224 + struct ext4_group_desc *gdp;
114.225 +
114.226 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.227 + return gdp->bg_block_bitmap |
114.228 + (ext2fs_has_feature_64bit(fs->super) ?
114.229 + (__u64)gdp->bg_block_bitmap_hi << 32 : 0);
114.230 +}
114.231 +
114.232 +/*
114.233 + * Set the block bitmap block of a group
114.234 + */
114.235 +void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
114.236 +{
114.237 + struct ext4_group_desc *gdp;
114.238 +
114.239 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.240 + gdp->bg_block_bitmap = blk;
114.241 + if (ext2fs_has_feature_64bit(fs->super))
114.242 + gdp->bg_block_bitmap_hi = (__u64) blk >> 32;
114.243 +}
114.244 +
114.245 +/*
114.246 + * Return the inode bitmap checksum of a group
114.247 + */
114.248 +__u32 ext2fs_inode_bitmap_checksum(ext2_filsys fs, dgrp_t group)
114.249 +{
114.250 + struct ext4_group_desc *gdp;
114.251 + __u32 csum;
114.252 +
114.253 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.254 + csum = gdp->bg_inode_bitmap_csum_lo;
114.255 + if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
114.256 + csum |= ((__u32)gdp->bg_inode_bitmap_csum_hi << 16);
114.257 + return csum;
114.258 +}
114.259 +
114.260 +/*
114.261 + * Return the inode bitmap block of a group
114.262 + */
114.263 +blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group)
114.264 +{
114.265 + struct ext4_group_desc *gdp;
114.266 +
114.267 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.268 + return gdp->bg_inode_bitmap |
114.269 + (ext2fs_has_feature_64bit(fs->super) ?
114.270 + (__u64) gdp->bg_inode_bitmap_hi << 32 : 0);
114.271 +}
114.272 +
114.273 +/*
114.274 + * Set the inode bitmap block of a group
114.275 + */
114.276 +void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
114.277 +{
114.278 + struct ext4_group_desc *gdp;
114.279 +
114.280 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.281 + gdp->bg_inode_bitmap = blk;
114.282 + if (ext2fs_has_feature_64bit(fs->super))
114.283 + gdp->bg_inode_bitmap_hi = (__u64) blk >> 32;
114.284 +}
114.285 +
114.286 +/*
114.287 + * Return the inode table block of a group
114.288 + */
114.289 +blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group)
114.290 +{
114.291 + struct ext4_group_desc *gdp;
114.292 +
114.293 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.294 + return gdp->bg_inode_table |
114.295 + (ext2fs_has_feature_64bit(fs->super) ?
114.296 + (__u64) gdp->bg_inode_table_hi << 32 : 0);
114.297 +}
114.298 +
114.299 +/*
114.300 + * Set the inode table block of a group
114.301 + */
114.302 +void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
114.303 +{
114.304 + struct ext4_group_desc *gdp;
114.305 +
114.306 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.307 + gdp->bg_inode_table = blk;
114.308 + if (ext2fs_has_feature_64bit(fs->super))
114.309 + gdp->bg_inode_table_hi = (__u64) blk >> 32;
114.310 +}
114.311 +
114.312 +/*
114.313 + * Return the free blocks count of a group
114.314 + */
114.315 +__u32 ext2fs_bg_free_blocks_count(ext2_filsys fs, dgrp_t group)
114.316 +{
114.317 + struct ext4_group_desc *gdp;
114.318 +
114.319 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.320 + return gdp->bg_free_blocks_count |
114.321 + (ext2fs_has_feature_64bit(fs->super) ?
114.322 + (__u32) gdp->bg_free_blocks_count_hi << 16 : 0);
114.323 +}
114.324 +
114.325 +/*
114.326 + * Set the free blocks count of a group
114.327 + */
114.328 +void ext2fs_bg_free_blocks_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
114.329 +{
114.330 + struct ext4_group_desc *gdp;
114.331 +
114.332 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.333 + gdp->bg_free_blocks_count = n;
114.334 +
114.335 + if (ext2fs_has_feature_64bit(fs->super))
114.336 + gdp->bg_free_blocks_count_hi = (__u32) n >> 16;
114.337 +}
114.338 +
114.339 +/*
114.340 + * Return the free inodes count of a group
114.341 + */
114.342 +__u32 ext2fs_bg_free_inodes_count(ext2_filsys fs, dgrp_t group)
114.343 +{
114.344 + struct ext4_group_desc *gdp;
114.345 +
114.346 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.347 + return gdp->bg_free_inodes_count |
114.348 + (ext2fs_has_feature_64bit(fs->super) ?
114.349 + (__u32) gdp->bg_free_inodes_count_hi << 16 : 0);
114.350 +}
114.351 +
114.352 +/*
114.353 + * Set the free inodes count of a group
114.354 + */
114.355 +void ext2fs_bg_free_inodes_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
114.356 +{
114.357 + struct ext4_group_desc *gdp;
114.358 +
114.359 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.360 + gdp->bg_free_inodes_count = n;
114.361 + if (ext2fs_has_feature_64bit(fs->super))
114.362 + gdp->bg_free_inodes_count_hi = (__u32) n >> 16;
114.363 +}
114.364 +
114.365 +/*
114.366 + * Return the used dirs count of a group
114.367 + */
114.368 +__u32 ext2fs_bg_used_dirs_count(ext2_filsys fs, dgrp_t group)
114.369 +{
114.370 + struct ext4_group_desc *gdp;
114.371 +
114.372 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.373 + return gdp->bg_used_dirs_count |
114.374 + (ext2fs_has_feature_64bit(fs->super) ?
114.375 + (__u32) gdp->bg_used_dirs_count_hi << 16 : 0);
114.376 +}
114.377 +
114.378 +/*
114.379 + * Set the used dirs count of a group
114.380 + */
114.381 +void ext2fs_bg_used_dirs_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
114.382 +{
114.383 + struct ext4_group_desc *gdp;
114.384 +
114.385 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.386 + gdp->bg_used_dirs_count = n;
114.387 + if (ext2fs_has_feature_64bit(fs->super))
114.388 + gdp->bg_used_dirs_count_hi = (__u32) n >> 16;
114.389 +}
114.390 +
114.391 +/*
114.392 + * Return the unused inodes count of a group
114.393 + */
114.394 +__u32 ext2fs_bg_itable_unused(ext2_filsys fs, dgrp_t group)
114.395 +{
114.396 + struct ext4_group_desc *gdp;
114.397 +
114.398 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.399 + return gdp->bg_itable_unused |
114.400 + (ext2fs_has_feature_64bit(fs->super) ?
114.401 + (__u32) gdp->bg_itable_unused_hi << 16 : 0);
114.402 +}
114.403 +
114.404 +/*
114.405 + * Set the unused inodes count of a group
114.406 + */
114.407 +void ext2fs_bg_itable_unused_set(ext2_filsys fs, dgrp_t group, __u32 n)
114.408 +{
114.409 + struct ext4_group_desc *gdp;
114.410 +
114.411 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.412 + gdp->bg_itable_unused = n;
114.413 + if (ext2fs_has_feature_64bit(fs->super))
114.414 + gdp->bg_itable_unused_hi = (__u32) n >> 16;
114.415 +}
114.416 +
114.417 +/*
114.418 + * Get the flags for this block group
114.419 + */
114.420 +__u16 ext2fs_bg_flags(ext2_filsys fs, dgrp_t group)
114.421 +{
114.422 + struct ext4_group_desc *gdp;
114.423 +
114.424 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.425 + return gdp->bg_flags;
114.426 +}
114.427 +
114.428 +/*
114.429 + * Zero out the flags for this block group
114.430 + */
114.431 +void ext2fs_bg_flags_zap(ext2_filsys fs, dgrp_t group)
114.432 +{
114.433 + struct ext4_group_desc *gdp;
114.434 +
114.435 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.436 + gdp->bg_flags = 0;
114.437 + return;
114.438 +}
114.439 +
114.440 +/*
114.441 + * Get the value of a particular flag for this block group
114.442 + */
114.443 +int ext2fs_bg_flags_test(ext2_filsys fs, dgrp_t group, __u16 bg_flag)
114.444 +{
114.445 + struct ext4_group_desc *gdp;
114.446 +
114.447 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.448 + return gdp->bg_flags & bg_flag;
114.449 +}
114.450 +
114.451 +/*
114.452 + * Set a flag or set of flags for this block group
114.453 + */
114.454 +void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags)
114.455 +{
114.456 + struct ext4_group_desc *gdp;
114.457 +
114.458 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.459 + gdp->bg_flags |= bg_flags;
114.460 + return;
114.461 +}
114.462 +
114.463 +/*
114.464 + * Clear a flag or set of flags for this block group
114.465 + */
114.466 +void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags)
114.467 +{
114.468 + struct ext4_group_desc *gdp;
114.469 +
114.470 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.471 + gdp->bg_flags &= ~bg_flags;
114.472 + return;
114.473 +}
114.474 +
114.475 +/*
114.476 + * Get the checksum for this block group
114.477 + */
114.478 +__u16 ext2fs_bg_checksum(ext2_filsys fs, dgrp_t group)
114.479 +{
114.480 + struct ext4_group_desc *gdp;
114.481 +
114.482 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.483 + return gdp->bg_checksum;
114.484 +}
114.485 +
114.486 +/*
114.487 + * Set the checksum for this block group to a previously calculated value
114.488 + */
114.489 +void ext2fs_bg_checksum_set(ext2_filsys fs, dgrp_t group, __u16 checksum)
114.490 +{
114.491 + struct ext4_group_desc *gdp;
114.492 +
114.493 + gdp = ext4fs_group_desc(fs, fs->group_desc, group);
114.494 + gdp->bg_checksum = checksum;
114.495 + return;
114.496 +}
114.497 +
114.498 +/*
114.499 + * Get the acl block of a file
114.500 + */
114.501 +blk64_t ext2fs_file_acl_block(ext2_filsys fs, const struct ext2_inode *inode)
114.502 +{
114.503 + blk64_t blk = inode->i_file_acl;
114.504 +
114.505 + if (fs && ext2fs_has_feature_64bit(fs->super))
114.506 + blk |= ((__u64) inode->osd2.linux2.l_i_file_acl_high) << 32;
114.507 + return blk;
114.508 +}
114.509 +
114.510 +/*
114.511 + * Set the acl block of a file
114.512 + */
114.513 +void ext2fs_file_acl_block_set(ext2_filsys fs, struct ext2_inode *inode,
114.514 + blk64_t blk)
114.515 +{
114.516 + inode->i_file_acl = blk;
114.517 + if (fs && ext2fs_has_feature_64bit(fs->super))
114.518 + inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32;
114.519 +}
114.520 +
114.521 +/*
114.522 + * Set the size of the inode
114.523 + */
114.524 +errcode_t ext2fs_inode_size_set(ext2_filsys fs, struct ext2_inode *inode,
114.525 + ext2_off64_t size)
114.526 +{
114.527 + /* Only regular files get to be larger than 4GB */
114.528 + if (!LINUX_S_ISREG(inode->i_mode) && (size >> 32))
114.529 + return EXT2_ET_FILE_TOO_BIG;
114.530 +
114.531 + /* If we're writing a large file, set the large_file flag */
114.532 + if (LINUX_S_ISREG(inode->i_mode) &&
114.533 + ext2fs_needs_large_file_feature(size) &&
114.534 + (!ext2fs_has_feature_large_file(fs->super) ||
114.535 + fs->super->s_rev_level == EXT2_GOOD_OLD_REV)) {
114.536 + ext2fs_set_feature_large_file(fs->super);
114.537 + ext2fs_update_dynamic_rev(fs);
114.538 + ext2fs_mark_super_dirty(fs);
114.539 + }
114.540 +
114.541 + inode->i_size = size & 0xffffffff;
114.542 + inode->i_size_high = (size >> 32);
114.543 +
114.544 + return 0;
114.545 +}
114.546 +
115.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
115.2 +++ b/libext2fs/lib/libext2fs/block.c Wed Aug 25 01:28:08 2021 +0200
115.3 @@ -0,0 +1,659 @@
115.4 +/*
115.5 + * block.c --- iterate over all blocks in an inode
115.6 + *
115.7 + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
115.8 + *
115.9 + * %Begin-Header%
115.10 + * This file may be redistributed under the terms of the GNU Library
115.11 + * General Public License, version 2.
115.12 + * %End-Header%
115.13 + */
115.14 +
115.15 +#include "config.h"
115.16 +#include <stdio.h>
115.17 +#include <string.h>
115.18 +#if HAVE_UNISTD_H
115.19 +#include <unistd.h>
115.20 +#endif
115.21 +
115.22 +#include "ext2_fs.h"
115.23 +#include "ext2fs.h"
115.24 +
115.25 +struct block_context {
115.26 + ext2_filsys fs;
115.27 + int (*func)(ext2_filsys fs,
115.28 + blk64_t *blocknr,
115.29 + e2_blkcnt_t bcount,
115.30 + blk64_t ref_blk,
115.31 + int ref_offset,
115.32 + void *priv_data);
115.33 + e2_blkcnt_t bcount;
115.34 + int bsize;
115.35 + int flags;
115.36 + errcode_t errcode;
115.37 + char *ind_buf;
115.38 + char *dind_buf;
115.39 + char *tind_buf;
115.40 + void *priv_data;
115.41 +};
115.42 +
115.43 +#define check_for_ro_violation_return(ctx, ret) \
115.44 + do { \
115.45 + if (((ctx)->flags & BLOCK_FLAG_READ_ONLY) && \
115.46 + ((ret) & BLOCK_CHANGED)) { \
115.47 + (ctx)->errcode = EXT2_ET_RO_BLOCK_ITERATE; \
115.48 + ret |= BLOCK_ABORT | BLOCK_ERROR; \
115.49 + return ret; \
115.50 + } \
115.51 + } while (0)
115.52 +
115.53 +#define check_for_ro_violation_goto(ctx, ret, label) \
115.54 + do { \
115.55 + if (((ctx)->flags & BLOCK_FLAG_READ_ONLY) && \
115.56 + ((ret) & BLOCK_CHANGED)) { \
115.57 + (ctx)->errcode = EXT2_ET_RO_BLOCK_ITERATE; \
115.58 + ret |= BLOCK_ABORT | BLOCK_ERROR; \
115.59 + goto label; \
115.60 + } \
115.61 + } while (0)
115.62 +
115.63 +static int block_iterate_ind(blk_t *ind_block, blk_t ref_block,
115.64 + int ref_offset, struct block_context *ctx)
115.65 +{
115.66 + int ret = 0, changed = 0;
115.67 + int i, flags, limit, offset;
115.68 + blk_t *block_nr;
115.69 + blk64_t blk64;
115.70 +
115.71 + limit = ctx->fs->blocksize >> 2;
115.72 + if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
115.73 + !(ctx->flags & BLOCK_FLAG_DATA_ONLY)) {
115.74 + blk64 = *ind_block;
115.75 + ret = (*ctx->func)(ctx->fs, &blk64,
115.76 + BLOCK_COUNT_IND, ref_block,
115.77 + ref_offset, ctx->priv_data);
115.78 + *ind_block = blk64;
115.79 + }
115.80 + check_for_ro_violation_return(ctx, ret);
115.81 + if (!*ind_block || (ret & BLOCK_ABORT)) {
115.82 + ctx->bcount += limit;
115.83 + return ret;
115.84 + }
115.85 + if (*ind_block >= ext2fs_blocks_count(ctx->fs->super) ||
115.86 + *ind_block < ctx->fs->super->s_first_data_block) {
115.87 + ctx->errcode = EXT2_ET_BAD_IND_BLOCK;
115.88 + ret |= BLOCK_ERROR;
115.89 + return ret;
115.90 + }
115.91 + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block,
115.92 + ctx->ind_buf);
115.93 + if (ctx->errcode) {
115.94 + ret |= BLOCK_ERROR;
115.95 + return ret;
115.96 + }
115.97 +
115.98 + block_nr = (blk_t *) ctx->ind_buf;
115.99 + offset = 0;
115.100 + if (ctx->flags & BLOCK_FLAG_APPEND) {
115.101 + for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
115.102 + blk64 = *block_nr;
115.103 + flags = (*ctx->func)(ctx->fs, &blk64, ctx->bcount,
115.104 + *ind_block, offset,
115.105 + ctx->priv_data);
115.106 + *block_nr = blk64;
115.107 + changed |= flags;
115.108 + if (flags & BLOCK_ABORT) {
115.109 + ret |= BLOCK_ABORT;
115.110 + break;
115.111 + }
115.112 + offset += sizeof(blk_t);
115.113 + }
115.114 + } else {
115.115 + for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
115.116 + if (*block_nr == 0)
115.117 + goto skip_sparse;
115.118 + blk64 = *block_nr;
115.119 + flags = (*ctx->func)(ctx->fs, &blk64, ctx->bcount,
115.120 + *ind_block, offset,
115.121 + ctx->priv_data);
115.122 + *block_nr = blk64;
115.123 + changed |= flags;
115.124 + if (flags & BLOCK_ABORT) {
115.125 + ret |= BLOCK_ABORT;
115.126 + break;
115.127 + }
115.128 + skip_sparse:
115.129 + offset += sizeof(blk_t);
115.130 + }
115.131 + }
115.132 + check_for_ro_violation_return(ctx, changed);
115.133 + if (changed & BLOCK_CHANGED) {
115.134 + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block,
115.135 + ctx->ind_buf);
115.136 + if (ctx->errcode)
115.137 + ret |= BLOCK_ERROR | BLOCK_ABORT;
115.138 + }
115.139 + if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
115.140 + !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
115.141 + !(ret & BLOCK_ABORT)) {
115.142 + blk64 = *ind_block;
115.143 + ret |= (*ctx->func)(ctx->fs, &blk64,
115.144 + BLOCK_COUNT_IND, ref_block,
115.145 + ref_offset, ctx->priv_data);
115.146 + *ind_block = blk64;
115.147 + }
115.148 + check_for_ro_violation_return(ctx, ret);
115.149 + return ret;
115.150 +}
115.151 +
115.152 +static int block_iterate_dind(blk_t *dind_block, blk_t ref_block,
115.153 + int ref_offset, struct block_context *ctx)
115.154 +{
115.155 + int ret = 0, changed = 0;
115.156 + int i, flags, limit, offset;
115.157 + blk_t *block_nr;
115.158 + blk64_t blk64;
115.159 +
115.160 + limit = ctx->fs->blocksize >> 2;
115.161 + if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
115.162 + BLOCK_FLAG_DATA_ONLY))) {
115.163 + blk64 = *dind_block;
115.164 + ret = (*ctx->func)(ctx->fs, &blk64,
115.165 + BLOCK_COUNT_DIND, ref_block,
115.166 + ref_offset, ctx->priv_data);
115.167 + *dind_block = blk64;
115.168 + }
115.169 + check_for_ro_violation_return(ctx, ret);
115.170 + if (!*dind_block || (ret & BLOCK_ABORT)) {
115.171 + ctx->bcount += limit*limit;
115.172 + return ret;
115.173 + }
115.174 + if (*dind_block >= ext2fs_blocks_count(ctx->fs->super) ||
115.175 + *dind_block < ctx->fs->super->s_first_data_block) {
115.176 + ctx->errcode = EXT2_ET_BAD_DIND_BLOCK;
115.177 + ret |= BLOCK_ERROR;
115.178 + return ret;
115.179 + }
115.180 + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block,
115.181 + ctx->dind_buf);
115.182 + if (ctx->errcode) {
115.183 + ret |= BLOCK_ERROR;
115.184 + return ret;
115.185 + }
115.186 +
115.187 + block_nr = (blk_t *) ctx->dind_buf;
115.188 + offset = 0;
115.189 + if (ctx->flags & BLOCK_FLAG_APPEND) {
115.190 + for (i = 0; i < limit; i++, block_nr++) {
115.191 + flags = block_iterate_ind(block_nr,
115.192 + *dind_block, offset,
115.193 + ctx);
115.194 + changed |= flags;
115.195 + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
115.196 + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
115.197 + break;
115.198 + }
115.199 + offset += sizeof(blk_t);
115.200 + }
115.201 + } else {
115.202 + for (i = 0; i < limit; i++, block_nr++) {
115.203 + if (*block_nr == 0) {
115.204 + ctx->bcount += limit;
115.205 + continue;
115.206 + }
115.207 + flags = block_iterate_ind(block_nr,
115.208 + *dind_block, offset,
115.209 + ctx);
115.210 + changed |= flags;
115.211 + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
115.212 + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
115.213 + break;
115.214 + }
115.215 + offset += sizeof(blk_t);
115.216 + }
115.217 + }
115.218 + check_for_ro_violation_return(ctx, changed);
115.219 + if (changed & BLOCK_CHANGED) {
115.220 + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block,
115.221 + ctx->dind_buf);
115.222 + if (ctx->errcode)
115.223 + ret |= BLOCK_ERROR | BLOCK_ABORT;
115.224 + }
115.225 + if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
115.226 + !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
115.227 + !(ret & BLOCK_ABORT)) {
115.228 + blk64 = *dind_block;
115.229 + ret |= (*ctx->func)(ctx->fs, &blk64,
115.230 + BLOCK_COUNT_DIND, ref_block,
115.231 + ref_offset, ctx->priv_data);
115.232 + *dind_block = blk64;
115.233 + }
115.234 + check_for_ro_violation_return(ctx, ret);
115.235 + return ret;
115.236 +}
115.237 +
115.238 +static int block_iterate_tind(blk_t *tind_block, blk_t ref_block,
115.239 + int ref_offset, struct block_context *ctx)
115.240 +{
115.241 + int ret = 0, changed = 0;
115.242 + int i, flags, limit, offset;
115.243 + blk_t *block_nr;
115.244 + blk64_t blk64;
115.245 +
115.246 + limit = ctx->fs->blocksize >> 2;
115.247 + if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
115.248 + BLOCK_FLAG_DATA_ONLY))) {
115.249 + blk64 = *tind_block;
115.250 + ret = (*ctx->func)(ctx->fs, &blk64,
115.251 + BLOCK_COUNT_TIND, ref_block,
115.252 + ref_offset, ctx->priv_data);
115.253 + *tind_block = blk64;
115.254 + }
115.255 + check_for_ro_violation_return(ctx, ret);
115.256 + if (!*tind_block || (ret & BLOCK_ABORT)) {
115.257 + ctx->bcount += ((unsigned long long) limit)*limit*limit;
115.258 + return ret;
115.259 + }
115.260 + if (*tind_block >= ext2fs_blocks_count(ctx->fs->super) ||
115.261 + *tind_block < ctx->fs->super->s_first_data_block) {
115.262 + ctx->errcode = EXT2_ET_BAD_TIND_BLOCK;
115.263 + ret |= BLOCK_ERROR;
115.264 + return ret;
115.265 + }
115.266 + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block,
115.267 + ctx->tind_buf);
115.268 + if (ctx->errcode) {
115.269 + ret |= BLOCK_ERROR;
115.270 + return ret;
115.271 + }
115.272 +
115.273 + block_nr = (blk_t *) ctx->tind_buf;
115.274 + offset = 0;
115.275 + if (ctx->flags & BLOCK_FLAG_APPEND) {
115.276 + for (i = 0; i < limit; i++, block_nr++) {
115.277 + flags = block_iterate_dind(block_nr,
115.278 + *tind_block,
115.279 + offset, ctx);
115.280 + changed |= flags;
115.281 + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
115.282 + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
115.283 + break;
115.284 + }
115.285 + offset += sizeof(blk_t);
115.286 + }
115.287 + } else {
115.288 + for (i = 0; i < limit; i++, block_nr++) {
115.289 + if (*block_nr == 0) {
115.290 + ctx->bcount += limit*limit;
115.291 + continue;
115.292 + }
115.293 + flags = block_iterate_dind(block_nr,
115.294 + *tind_block,
115.295 + offset, ctx);
115.296 + changed |= flags;
115.297 + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
115.298 + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
115.299 + break;
115.300 + }
115.301 + offset += sizeof(blk_t);
115.302 + }
115.303 + }
115.304 + check_for_ro_violation_return(ctx, changed);
115.305 + if (changed & BLOCK_CHANGED) {
115.306 + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block,
115.307 + ctx->tind_buf);
115.308 + if (ctx->errcode)
115.309 + ret |= BLOCK_ERROR | BLOCK_ABORT;
115.310 + }
115.311 + if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
115.312 + !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
115.313 + !(ret & BLOCK_ABORT)) {
115.314 + blk64 = *tind_block;
115.315 + ret |= (*ctx->func)(ctx->fs, &blk64,
115.316 + BLOCK_COUNT_TIND, ref_block,
115.317 + ref_offset, ctx->priv_data);
115.318 + *tind_block = blk64;
115.319 + }
115.320 + check_for_ro_violation_return(ctx, ret);
115.321 + return ret;
115.322 +}
115.323 +
115.324 +errcode_t ext2fs_block_iterate3(ext2_filsys fs,
115.325 + ext2_ino_t ino,
115.326 + int flags,
115.327 + char *block_buf,
115.328 + int (*func)(ext2_filsys fs,
115.329 + blk64_t *blocknr,
115.330 + e2_blkcnt_t blockcnt,
115.331 + blk64_t ref_blk,
115.332 + int ref_offset,
115.333 + void *priv_data),
115.334 + void *priv_data)
115.335 +{
115.336 + int i;
115.337 + int r, ret = 0;
115.338 + struct ext2_inode inode;
115.339 + errcode_t retval;
115.340 + struct block_context ctx;
115.341 + int limit;
115.342 + blk64_t blk64;
115.343 +
115.344 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
115.345 +
115.346 + ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
115.347 + if (ctx.errcode)
115.348 + return ctx.errcode;
115.349 +
115.350 + /*
115.351 + * An inode with inline data has no blocks over which to
115.352 + * iterate, so return an error code indicating this fact.
115.353 + */
115.354 + if (inode.i_flags & EXT4_INLINE_DATA_FL)
115.355 + return EXT2_ET_INLINE_DATA_CANT_ITERATE;
115.356 +
115.357 + /*
115.358 + * Check to see if we need to limit large files
115.359 + */
115.360 + if (flags & BLOCK_FLAG_NO_LARGE) {
115.361 + if (!LINUX_S_ISDIR(inode.i_mode) &&
115.362 + (inode.i_size_high != 0))
115.363 + return EXT2_ET_FILE_TOO_BIG;
115.364 + }
115.365 +
115.366 + limit = fs->blocksize >> 2;
115.367 +
115.368 + ctx.fs = fs;
115.369 + ctx.func = func;
115.370 + ctx.priv_data = priv_data;
115.371 + ctx.flags = flags;
115.372 + ctx.bcount = 0;
115.373 + if (block_buf) {
115.374 + ctx.ind_buf = block_buf;
115.375 + } else {
115.376 + retval = ext2fs_get_array(3, fs->blocksize, &ctx.ind_buf);
115.377 + if (retval)
115.378 + return retval;
115.379 + }
115.380 + ctx.dind_buf = ctx.ind_buf + fs->blocksize;
115.381 + ctx.tind_buf = ctx.dind_buf + fs->blocksize;
115.382 +
115.383 + /*
115.384 + * Iterate over the HURD translator block (if present)
115.385 + */
115.386 + if ((fs->super->s_creator_os == EXT2_OS_HURD) &&
115.387 + !(flags & BLOCK_FLAG_DATA_ONLY)) {
115.388 + if (inode.osd1.hurd1.h_i_translator) {
115.389 + blk64 = inode.osd1.hurd1.h_i_translator;
115.390 + ret |= (*ctx.func)(fs, &blk64,
115.391 + BLOCK_COUNT_TRANSLATOR,
115.392 + 0, 0, priv_data);
115.393 + inode.osd1.hurd1.h_i_translator = (blk_t) blk64;
115.394 + if (ret & BLOCK_ABORT)
115.395 + goto abort_exit;
115.396 + check_for_ro_violation_goto(&ctx, ret, abort_exit);
115.397 + }
115.398 + }
115.399 +
115.400 + if (inode.i_flags & EXT4_EXTENTS_FL) {
115.401 + ext2_extent_handle_t handle;
115.402 + struct ext2fs_extent extent, next;
115.403 + e2_blkcnt_t blockcnt = 0;
115.404 + blk64_t blk, new_blk;
115.405 + int op = EXT2_EXTENT_ROOT;
115.406 + int uninit;
115.407 + unsigned int j;
115.408 +
115.409 + ctx.errcode = ext2fs_extent_open2(fs, ino, &inode, &handle);
115.410 + if (ctx.errcode)
115.411 + goto abort_exit;
115.412 +
115.413 + while (1) {
115.414 + if (op == EXT2_EXTENT_CURRENT)
115.415 + ctx.errcode = 0;
115.416 + else
115.417 + ctx.errcode = ext2fs_extent_get(handle, op,
115.418 + &extent);
115.419 + if (ctx.errcode) {
115.420 + if (ctx.errcode != EXT2_ET_EXTENT_NO_NEXT)
115.421 + break;
115.422 + ctx.errcode = 0;
115.423 + if (!(flags & BLOCK_FLAG_APPEND))
115.424 + break;
115.425 + next_block_set:
115.426 + blk = 0;
115.427 + r = (*ctx.func)(fs, &blk, blockcnt,
115.428 + 0, 0, priv_data);
115.429 + ret |= r;
115.430 + check_for_ro_violation_goto(&ctx, ret,
115.431 + extent_done);
115.432 + if (r & BLOCK_CHANGED) {
115.433 + ctx.errcode =
115.434 + ext2fs_extent_set_bmap(handle,
115.435 + (blk64_t) blockcnt++,
115.436 + (blk64_t) blk, 0);
115.437 + if (ctx.errcode || (ret & BLOCK_ABORT))
115.438 + break;
115.439 + if (blk)
115.440 + goto next_block_set;
115.441 + }
115.442 + break;
115.443 + }
115.444 +
115.445 + op = EXT2_EXTENT_NEXT;
115.446 + blk = extent.e_pblk;
115.447 + if (!(extent.e_flags & EXT2_EXTENT_FLAGS_LEAF)) {
115.448 + if (ctx.flags & BLOCK_FLAG_DATA_ONLY)
115.449 + continue;
115.450 + if ((!(extent.e_flags &
115.451 + EXT2_EXTENT_FLAGS_SECOND_VISIT) &&
115.452 + !(ctx.flags & BLOCK_FLAG_DEPTH_TRAVERSE)) ||
115.453 + ((extent.e_flags &
115.454 + EXT2_EXTENT_FLAGS_SECOND_VISIT) &&
115.455 + (ctx.flags & BLOCK_FLAG_DEPTH_TRAVERSE))) {
115.456 + ret |= (*ctx.func)(fs, &blk,
115.457 + -1, 0, 0, priv_data);
115.458 + if (ret & BLOCK_CHANGED) {
115.459 + extent.e_pblk = blk;
115.460 + ctx.errcode =
115.461 + ext2fs_extent_replace(handle, 0, &extent);
115.462 + if (ctx.errcode)
115.463 + break;
115.464 + }
115.465 + if (ret & BLOCK_ABORT)
115.466 + break;
115.467 + }
115.468 + continue;
115.469 + }
115.470 + uninit = 0;
115.471 + if (extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
115.472 + uninit = EXT2_EXTENT_SET_BMAP_UNINIT;
115.473 +
115.474 + /*
115.475 + * Get the next extent before we start messing
115.476 + * with the current extent
115.477 + */
115.478 + retval = ext2fs_extent_get(handle, op, &next);
115.479 +
115.480 +#if 0
115.481 + printf("lblk %llu pblk %llu len %d blockcnt %llu\n",
115.482 + extent.e_lblk, extent.e_pblk,
115.483 + extent.e_len, blockcnt);
115.484 +#endif
115.485 + if (extent.e_lblk + extent.e_len <= (blk64_t) blockcnt)
115.486 + continue;
115.487 + if (extent.e_lblk > (blk64_t) blockcnt)
115.488 + blockcnt = extent.e_lblk;
115.489 + j = blockcnt - extent.e_lblk;
115.490 + blk += j;
115.491 + for (blockcnt = extent.e_lblk, j = 0;
115.492 + j < extent.e_len;
115.493 + blk++, blockcnt++, j++) {
115.494 + new_blk = blk;
115.495 + r = (*ctx.func)(fs, &new_blk, blockcnt,
115.496 + 0, 0, priv_data);
115.497 + ret |= r;
115.498 + check_for_ro_violation_goto(&ctx, ret,
115.499 + extent_done);
115.500 + if (r & BLOCK_CHANGED) {
115.501 + ctx.errcode =
115.502 + ext2fs_extent_set_bmap(handle,
115.503 + (blk64_t) blockcnt,
115.504 + new_blk, uninit);
115.505 + if (ctx.errcode)
115.506 + goto extent_done;
115.507 + }
115.508 + if (ret & BLOCK_ABORT)
115.509 + goto extent_done;
115.510 + }
115.511 + if (retval == 0) {
115.512 + extent = next;
115.513 + op = EXT2_EXTENT_CURRENT;
115.514 + }
115.515 + }
115.516 +
115.517 + extent_done:
115.518 + ext2fs_extent_free(handle);
115.519 + ret |= BLOCK_ERROR; /* ctx.errcode is always valid here */
115.520 + goto errout;
115.521 + }
115.522 +
115.523 + /*
115.524 + * Iterate over normal data blocks
115.525 + */
115.526 + for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) {
115.527 + if (inode.i_block[i] || (flags & BLOCK_FLAG_APPEND)) {
115.528 + blk64 = inode.i_block[i];
115.529 + ret |= (*ctx.func)(fs, &blk64, ctx.bcount, 0, i,
115.530 + priv_data);
115.531 + inode.i_block[i] = (blk_t) blk64;
115.532 + if (ret & BLOCK_ABORT)
115.533 + goto abort_exit;
115.534 + }
115.535 + }
115.536 + check_for_ro_violation_goto(&ctx, ret, abort_exit);
115.537 + if (inode.i_block[EXT2_IND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) {
115.538 + ret |= block_iterate_ind(&inode.i_block[EXT2_IND_BLOCK],
115.539 + 0, EXT2_IND_BLOCK, &ctx);
115.540 + if (ret & BLOCK_ABORT)
115.541 + goto abort_exit;
115.542 + } else
115.543 + ctx.bcount += limit;
115.544 + if (inode.i_block[EXT2_DIND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) {
115.545 + ret |= block_iterate_dind(&inode.i_block[EXT2_DIND_BLOCK],
115.546 + 0, EXT2_DIND_BLOCK, &ctx);
115.547 + if (ret & BLOCK_ABORT)
115.548 + goto abort_exit;
115.549 + } else
115.550 + ctx.bcount += limit * limit;
115.551 + if (inode.i_block[EXT2_TIND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) {
115.552 + ret |= block_iterate_tind(&inode.i_block[EXT2_TIND_BLOCK],
115.553 + 0, EXT2_TIND_BLOCK, &ctx);
115.554 + if (ret & BLOCK_ABORT)
115.555 + goto abort_exit;
115.556 + }
115.557 +
115.558 +abort_exit:
115.559 + if (ret & BLOCK_CHANGED) {
115.560 + retval = ext2fs_write_inode(fs, ino, &inode);
115.561 + if (retval) {
115.562 + ret |= BLOCK_ERROR;
115.563 + ctx.errcode = retval;
115.564 + }
115.565 + }
115.566 +errout:
115.567 + if (!block_buf)
115.568 + ext2fs_free_mem(&ctx.ind_buf);
115.569 +
115.570 + return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
115.571 +}
115.572 +
115.573 +/*
115.574 + * Emulate the old ext2fs_block_iterate function!
115.575 + */
115.576 +
115.577 +struct xlate64 {
115.578 + int (*func)(ext2_filsys fs,
115.579 + blk_t *blocknr,
115.580 + e2_blkcnt_t blockcnt,
115.581 + blk_t ref_blk,
115.582 + int ref_offset,
115.583 + void *priv_data);
115.584 + void *real_private;
115.585 +};
115.586 +
115.587 +static int xlate64_func(ext2_filsys fs, blk64_t *blocknr,
115.588 + e2_blkcnt_t blockcnt, blk64_t ref_blk,
115.589 + int ref_offset, void *priv_data)
115.590 +{
115.591 + struct xlate64 *xl = (struct xlate64 *) priv_data;
115.592 + int ret;
115.593 + blk_t block32 = *blocknr;
115.594 +
115.595 + ret = (*xl->func)(fs, &block32, blockcnt, (blk_t) ref_blk, ref_offset,
115.596 + xl->real_private);
115.597 + *blocknr = block32;
115.598 + return ret;
115.599 +}
115.600 +
115.601 +errcode_t ext2fs_block_iterate2(ext2_filsys fs,
115.602 + ext2_ino_t ino,
115.603 + int flags,
115.604 + char *block_buf,
115.605 + int (*func)(ext2_filsys fs,
115.606 + blk_t *blocknr,
115.607 + e2_blkcnt_t blockcnt,
115.608 + blk_t ref_blk,
115.609 + int ref_offset,
115.610 + void *priv_data),
115.611 + void *priv_data)
115.612 +{
115.613 + struct xlate64 xl;
115.614 +
115.615 + xl.real_private = priv_data;
115.616 + xl.func = func;
115.617 +
115.618 + return ext2fs_block_iterate3(fs, ino, flags, block_buf,
115.619 + xlate64_func, &xl);
115.620 +}
115.621 +
115.622 +
115.623 +struct xlate {
115.624 + int (*func)(ext2_filsys fs,
115.625 + blk_t *blocknr,
115.626 + int bcount,
115.627 + void *priv_data);
115.628 + void *real_private;
115.629 +};
115.630 +
115.631 +#ifdef __TURBOC__
115.632 + #pragma argsused
115.633 +#endif
115.634 +static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt,
115.635 + blk_t ref_block EXT2FS_ATTR((unused)),
115.636 + int ref_offset EXT2FS_ATTR((unused)),
115.637 + void *priv_data)
115.638 +{
115.639 + struct xlate *xl = (struct xlate *) priv_data;
115.640 +
115.641 + return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private);
115.642 +}
115.643 +
115.644 +errcode_t ext2fs_block_iterate(ext2_filsys fs,
115.645 + ext2_ino_t ino,
115.646 + int flags,
115.647 + char *block_buf,
115.648 + int (*func)(ext2_filsys fs,
115.649 + blk_t *blocknr,
115.650 + int blockcnt,
115.651 + void *priv_data),
115.652 + void *priv_data)
115.653 +{
115.654 + struct xlate xl;
115.655 +
115.656 + xl.real_private = priv_data;
115.657 + xl.func = func;
115.658 +
115.659 + return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags,
115.660 + block_buf, xlate_func, &xl);
115.661 +}
115.662 +
116.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
116.2 +++ b/libext2fs/lib/libext2fs/bmap.c Wed Aug 25 01:28:08 2021 +0200
116.3 @@ -0,0 +1,499 @@
116.4 +/*
116.5 + * bmap.c --- logical to physical block mapping
116.6 + *
116.7 + * Copyright (C) 1997 Theodore Ts'o.
116.8 + *
116.9 + * %Begin-Header%
116.10 + * This file may be redistributed under the terms of the GNU Library
116.11 + * General Public License, version 2.
116.12 + * %End-Header%
116.13 + */
116.14 +
116.15 +#include "config.h"
116.16 +#include <stdio.h>
116.17 +#include <string.h>
116.18 +#if HAVE_UNISTD_H
116.19 +#include <unistd.h>
116.20 +#endif
116.21 +#include <errno.h>
116.22 +
116.23 +#include "ext2_fs.h"
116.24 +#include "ext2fsP.h"
116.25 +
116.26 +#if defined(__GNUC__) && !defined(NO_INLINE_FUNCS)
116.27 +#define _BMAP_INLINE_ __inline__
116.28 +#else
116.29 +#define _BMAP_INLINE_
116.30 +#endif
116.31 +
116.32 +extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
116.33 + struct ext2_inode *inode,
116.34 + char *block_buf, int bmap_flags,
116.35 + blk_t block, blk_t *phys_blk);
116.36 +
116.37 +#define inode_bmap(inode, nr) ((inode)->i_block[(nr)])
116.38 +
116.39 +static _BMAP_INLINE_ errcode_t block_ind_bmap(ext2_filsys fs, int flags,
116.40 + blk_t ind, char *block_buf,
116.41 + int *blocks_alloc,
116.42 + blk_t nr, blk_t *ret_blk)
116.43 +{
116.44 + errcode_t retval;
116.45 + blk_t b;
116.46 +
116.47 + if (!ind) {
116.48 + if (flags & BMAP_SET)
116.49 + return EXT2_ET_SET_BMAP_NO_IND;
116.50 + *ret_blk = 0;
116.51 + return 0;
116.52 + }
116.53 + retval = io_channel_read_blk(fs->io, ind, 1, block_buf);
116.54 + if (retval)
116.55 + return retval;
116.56 +
116.57 + if (flags & BMAP_SET) {
116.58 + b = *ret_blk;
116.59 +#ifdef WORDS_BIGENDIAN
116.60 + b = ext2fs_swab32(b);
116.61 +#endif
116.62 + ((blk_t *) block_buf)[nr] = b;
116.63 + return io_channel_write_blk(fs->io, ind, 1, block_buf);
116.64 + }
116.65 +
116.66 + b = ((blk_t *) block_buf)[nr];
116.67 +
116.68 +#ifdef WORDS_BIGENDIAN
116.69 + b = ext2fs_swab32(b);
116.70 +#endif
116.71 +
116.72 + if (!b && (flags & BMAP_ALLOC)) {
116.73 + b = nr ? ext2fs_le32_to_cpu(((blk_t *)block_buf)[nr - 1]) : ind;
116.74 + retval = ext2fs_alloc_block(fs, b,
116.75 + block_buf + fs->blocksize, &b);
116.76 + if (retval)
116.77 + return retval;
116.78 +
116.79 +#ifdef WORDS_BIGENDIAN
116.80 + ((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
116.81 +#else
116.82 + ((blk_t *) block_buf)[nr] = b;
116.83 +#endif
116.84 +
116.85 + retval = io_channel_write_blk(fs->io, ind, 1, block_buf);
116.86 + if (retval)
116.87 + return retval;
116.88 +
116.89 + (*blocks_alloc)++;
116.90 + }
116.91 +
116.92 + *ret_blk = b;
116.93 + return 0;
116.94 +}
116.95 +
116.96 +static _BMAP_INLINE_ errcode_t block_dind_bmap(ext2_filsys fs, int flags,
116.97 + blk_t dind, char *block_buf,
116.98 + int *blocks_alloc,
116.99 + blk_t nr, blk_t *ret_blk)
116.100 +{
116.101 + blk_t b = 0;
116.102 + errcode_t retval;
116.103 + blk_t addr_per_block;
116.104 +
116.105 + addr_per_block = (blk_t) fs->blocksize >> 2;
116.106 +
116.107 + retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf,
116.108 + blocks_alloc, nr / addr_per_block, &b);
116.109 + if (retval)
116.110 + return retval;
116.111 + retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
116.112 + nr % addr_per_block, ret_blk);
116.113 + return retval;
116.114 +}
116.115 +
116.116 +static _BMAP_INLINE_ errcode_t block_tind_bmap(ext2_filsys fs, int flags,
116.117 + blk_t tind, char *block_buf,
116.118 + int *blocks_alloc,
116.119 + blk_t nr, blk_t *ret_blk)
116.120 +{
116.121 + blk_t b = 0;
116.122 + errcode_t retval;
116.123 + blk_t addr_per_block;
116.124 +
116.125 + addr_per_block = (blk_t) fs->blocksize >> 2;
116.126 +
116.127 + retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf,
116.128 + blocks_alloc, nr / addr_per_block, &b);
116.129 + if (retval)
116.130 + return retval;
116.131 + retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
116.132 + nr % addr_per_block, ret_blk);
116.133 + return retval;
116.134 +}
116.135 +
116.136 +static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino,
116.137 + struct ext2_inode *inode,
116.138 + ext2_extent_handle_t handle,
116.139 + char *block_buf, int bmap_flags, blk64_t block,
116.140 + int *ret_flags, int *blocks_alloc,
116.141 + blk64_t *phys_blk);
116.142 +
116.143 +static errcode_t implied_cluster_alloc(ext2_filsys fs, ext2_ino_t ino,
116.144 + struct ext2_inode *inode,
116.145 + ext2_extent_handle_t handle,
116.146 + blk64_t lblk, blk64_t *phys_blk)
116.147 +{
116.148 + blk64_t base_block, pblock = 0;
116.149 + int i;
116.150 +
116.151 + if (!ext2fs_has_feature_bigalloc(fs->super))
116.152 + return 0;
116.153 +
116.154 + base_block = lblk & ~EXT2FS_CLUSTER_MASK(fs);
116.155 + /*
116.156 + * Except for the logical block (lblk) that was passed in, search all
116.157 + * blocks in this logical cluster for a mapping to a physical cluster.
116.158 + * If any such map exists, calculate the physical block that maps to
116.159 + * the logical block and return that.
116.160 + *
116.161 + * The old code wouldn't even look if (block % cluster_ratio) == 0;
116.162 + * this is incorrect if we're allocating blocks in reverse order.
116.163 + */
116.164 + for (i = 0; i < EXT2FS_CLUSTER_RATIO(fs); i++) {
116.165 + if (base_block + i == lblk)
116.166 + continue;
116.167 + extent_bmap(fs, ino, inode, handle, 0, 0,
116.168 + base_block + i, 0, 0, &pblock);
116.169 + if (pblock)
116.170 + break;
116.171 + }
116.172 + if (pblock == 0)
116.173 + return 0;
116.174 + *phys_blk = pblock - i + (lblk - base_block);
116.175 + return 0;
116.176 +}
116.177 +
116.178 +/* Try to map a logical block to an already-allocated physical cluster. */
116.179 +errcode_t ext2fs_map_cluster_block(ext2_filsys fs, ext2_ino_t ino,
116.180 + struct ext2_inode *inode, blk64_t lblk,
116.181 + blk64_t *pblk)
116.182 +{
116.183 + ext2_extent_handle_t handle;
116.184 + errcode_t retval;
116.185 +
116.186 + /* Need bigalloc and extents to be enabled */
116.187 + *pblk = 0;
116.188 + if (!ext2fs_has_feature_bigalloc(fs->super) ||
116.189 + !(inode->i_flags & EXT4_EXTENTS_FL))
116.190 + return 0;
116.191 +
116.192 + retval = ext2fs_extent_open2(fs, ino, inode, &handle);
116.193 + if (retval)
116.194 + goto out;
116.195 +
116.196 + retval = implied_cluster_alloc(fs, ino, inode, handle, lblk, pblk);
116.197 + if (retval)
116.198 + goto out2;
116.199 +
116.200 +out2:
116.201 + ext2fs_extent_free(handle);
116.202 +out:
116.203 + return retval;
116.204 +}
116.205 +
116.206 +static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino,
116.207 + struct ext2_inode *inode,
116.208 + ext2_extent_handle_t handle,
116.209 + char *block_buf, int bmap_flags, blk64_t block,
116.210 + int *ret_flags, int *blocks_alloc,
116.211 + blk64_t *phys_blk)
116.212 +{
116.213 + struct blk_alloc_ctx alloc_ctx;
116.214 + struct ext2fs_extent extent;
116.215 + unsigned int offset;
116.216 + errcode_t retval = 0;
116.217 + blk64_t blk64 = 0;
116.218 + int alloc = 0;
116.219 + int set_flags;
116.220 +
116.221 + set_flags = bmap_flags & BMAP_UNINIT ? EXT2_EXTENT_SET_BMAP_UNINIT : 0;
116.222 +
116.223 + if (bmap_flags & BMAP_SET) {
116.224 + retval = ext2fs_extent_set_bmap(handle, block,
116.225 + *phys_blk, set_flags);
116.226 + return retval;
116.227 + }
116.228 + retval = ext2fs_extent_goto(handle, block);
116.229 + if (retval) {
116.230 + /* If the extent is not found, return phys_blk = 0 */
116.231 + if (retval == EXT2_ET_EXTENT_NOT_FOUND) {
116.232 + extent.e_lblk = block;
116.233 + goto got_block;
116.234 + }
116.235 + return retval;
116.236 + }
116.237 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
116.238 + if (retval)
116.239 + return retval;
116.240 + offset = block - extent.e_lblk;
116.241 + if (block >= extent.e_lblk && (offset <= extent.e_len)) {
116.242 + *phys_blk = extent.e_pblk + offset;
116.243 + if (ret_flags && extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
116.244 + *ret_flags |= BMAP_RET_UNINIT;
116.245 + }
116.246 +got_block:
116.247 + if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
116.248 + implied_cluster_alloc(fs, ino, inode, handle, block, &blk64);
116.249 + if (blk64)
116.250 + goto set_extent;
116.251 + retval = extent_bmap(fs, ino, inode, handle, block_buf,
116.252 + 0, block-1, 0, blocks_alloc, &blk64);
116.253 + if (retval)
116.254 + blk64 = ext2fs_find_inode_goal(fs, ino, inode, block);
116.255 + alloc_ctx.ino = ino;
116.256 + alloc_ctx.inode = inode;
116.257 + alloc_ctx.lblk = extent.e_lblk;
116.258 + alloc_ctx.flags = BLOCK_ALLOC_DATA;
116.259 + retval = ext2fs_alloc_block3(fs, blk64, block_buf, &blk64,
116.260 + &alloc_ctx);
116.261 + if (retval)
116.262 + return retval;
116.263 + blk64 &= ~EXT2FS_CLUSTER_MASK(fs);
116.264 + blk64 += EXT2FS_CLUSTER_MASK(fs) & block;
116.265 + alloc++;
116.266 + set_extent:
116.267 + retval = ext2fs_extent_set_bmap(handle, block,
116.268 + blk64, set_flags);
116.269 + if (retval) {
116.270 + ext2fs_block_alloc_stats2(fs, blk64, -1);
116.271 + return retval;
116.272 + }
116.273 + /* Update inode after setting extent */
116.274 + retval = ext2fs_read_inode(fs, ino, inode);
116.275 + if (retval)
116.276 + return retval;
116.277 + *blocks_alloc += alloc;
116.278 + *phys_blk = blk64;
116.279 + }
116.280 + return 0;
116.281 +}
116.282 +
116.283 +int ext2fs_file_block_offset_too_big(ext2_filsys fs,
116.284 + struct ext2_inode *inode,
116.285 + blk64_t offset)
116.286 +{
116.287 + blk64_t addr_per_block, max_map_block;
116.288 +
116.289 + /* Kernel seems to cut us off at 4294967294 blocks */
116.290 + if (offset >= (1ULL << 32) - 1)
116.291 + return 1;
116.292 +
116.293 + if (inode->i_flags & EXT4_EXTENTS_FL)
116.294 + return 0;
116.295 +
116.296 + addr_per_block = fs->blocksize >> 2;
116.297 + max_map_block = addr_per_block;
116.298 + max_map_block += addr_per_block * addr_per_block;
116.299 + max_map_block += addr_per_block * addr_per_block * addr_per_block;
116.300 + max_map_block += 12;
116.301 +
116.302 + return offset >= max_map_block;
116.303 +}
116.304 +
116.305 +errcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
116.306 + char *block_buf, int bmap_flags, blk64_t block,
116.307 + int *ret_flags, blk64_t *phys_blk)
116.308 +{
116.309 + struct ext2_inode inode_buf;
116.310 + ext2_extent_handle_t handle = 0;
116.311 + blk_t addr_per_block;
116.312 + blk_t b, blk32;
116.313 + blk64_t b64;
116.314 + char *buf = 0;
116.315 + errcode_t retval = 0;
116.316 + int blocks_alloc = 0, inode_dirty = 0;
116.317 + struct blk_alloc_ctx alloc_ctx = {
116.318 + .ino = ino,
116.319 + .inode = inode,
116.320 + .lblk = 0,
116.321 + .flags = BLOCK_ALLOC_DATA,
116.322 + };
116.323 +
116.324 + if (!(bmap_flags & BMAP_SET))
116.325 + *phys_blk = 0;
116.326 +
116.327 + if (ret_flags)
116.328 + *ret_flags = 0;
116.329 +
116.330 + /* Read inode structure if necessary */
116.331 + if (!inode) {
116.332 + retval = ext2fs_read_inode(fs, ino, &inode_buf);
116.333 + if (retval)
116.334 + return retval;
116.335 + inode = &inode_buf;
116.336 + }
116.337 + addr_per_block = (blk_t) fs->blocksize >> 2;
116.338 +
116.339 + if (ext2fs_file_block_offset_too_big(fs, inode, block))
116.340 + return EXT2_ET_FILE_TOO_BIG;
116.341 +
116.342 + /*
116.343 + * If an inode has inline data, that means that it doesn't have
116.344 + * any blocks and we shouldn't map any blocks for it.
116.345 + */
116.346 + if (inode->i_flags & EXT4_INLINE_DATA_FL)
116.347 + return EXT2_ET_INLINE_DATA_NO_BLOCK;
116.348 +
116.349 + if (!block_buf) {
116.350 + retval = ext2fs_get_array(2, fs->blocksize, &buf);
116.351 + if (retval)
116.352 + return retval;
116.353 + block_buf = buf;
116.354 + }
116.355 +
116.356 + if (inode->i_flags & EXT4_EXTENTS_FL) {
116.357 + retval = ext2fs_extent_open2(fs, ino, inode, &handle);
116.358 + if (retval)
116.359 + goto done;
116.360 + retval = extent_bmap(fs, ino, inode, handle, block_buf,
116.361 + bmap_flags, block, ret_flags,
116.362 + &blocks_alloc, phys_blk);
116.363 + goto done;
116.364 + }
116.365 +
116.366 + if (block < EXT2_NDIR_BLOCKS) {
116.367 + if (bmap_flags & BMAP_SET) {
116.368 + b = *phys_blk;
116.369 + inode_bmap(inode, block) = b;
116.370 + inode_dirty++;
116.371 + goto done;
116.372 + }
116.373 +
116.374 + *phys_blk = inode_bmap(inode, block);
116.375 + b = block ? inode_bmap(inode, block - 1) :
116.376 + ext2fs_find_inode_goal(fs, ino, inode, block);
116.377 +
116.378 + if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
116.379 + b64 = b;
116.380 + retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64,
116.381 + &alloc_ctx);
116.382 + b = b64;
116.383 + if (retval)
116.384 + goto done;
116.385 + inode_bmap(inode, block) = b;
116.386 + blocks_alloc++;
116.387 + *phys_blk = b;
116.388 + }
116.389 + goto done;
116.390 + }
116.391 +
116.392 + /* Indirect block */
116.393 + block -= EXT2_NDIR_BLOCKS;
116.394 + blk32 = *phys_blk;
116.395 + if (block < addr_per_block) {
116.396 + b = inode_bmap(inode, EXT2_IND_BLOCK);
116.397 + if (!b) {
116.398 + if (!(bmap_flags & BMAP_ALLOC)) {
116.399 + if (bmap_flags & BMAP_SET)
116.400 + retval = EXT2_ET_SET_BMAP_NO_IND;
116.401 + goto done;
116.402 + }
116.403 +
116.404 + b = inode_bmap(inode, EXT2_IND_BLOCK-1);
116.405 + b64 = b;
116.406 + retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64,
116.407 + &alloc_ctx);
116.408 + b = b64;
116.409 + if (retval)
116.410 + goto done;
116.411 + inode_bmap(inode, EXT2_IND_BLOCK) = b;
116.412 + blocks_alloc++;
116.413 + }
116.414 + retval = block_ind_bmap(fs, bmap_flags, b, block_buf,
116.415 + &blocks_alloc, block, &blk32);
116.416 + if (retval == 0)
116.417 + *phys_blk = blk32;
116.418 + goto done;
116.419 + }
116.420 +
116.421 + /* Doubly indirect block */
116.422 + block -= addr_per_block;
116.423 + if (block < addr_per_block * addr_per_block) {
116.424 + b = inode_bmap(inode, EXT2_DIND_BLOCK);
116.425 + if (!b) {
116.426 + if (!(bmap_flags & BMAP_ALLOC)) {
116.427 + if (bmap_flags & BMAP_SET)
116.428 + retval = EXT2_ET_SET_BMAP_NO_IND;
116.429 + goto done;
116.430 + }
116.431 +
116.432 + b = inode_bmap(inode, EXT2_IND_BLOCK);
116.433 + b64 = b;
116.434 + retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64,
116.435 + &alloc_ctx);
116.436 + b = b64;
116.437 + if (retval)
116.438 + goto done;
116.439 + inode_bmap(inode, EXT2_DIND_BLOCK) = b;
116.440 + blocks_alloc++;
116.441 + }
116.442 + retval = block_dind_bmap(fs, bmap_flags, b, block_buf,
116.443 + &blocks_alloc, block, &blk32);
116.444 + if (retval == 0)
116.445 + *phys_blk = blk32;
116.446 + goto done;
116.447 + }
116.448 +
116.449 + /* Triply indirect block */
116.450 + block -= addr_per_block * addr_per_block;
116.451 + b = inode_bmap(inode, EXT2_TIND_BLOCK);
116.452 + if (!b) {
116.453 + if (!(bmap_flags & BMAP_ALLOC)) {
116.454 + if (bmap_flags & BMAP_SET)
116.455 + retval = EXT2_ET_SET_BMAP_NO_IND;
116.456 + goto done;
116.457 + }
116.458 +
116.459 + b = inode_bmap(inode, EXT2_DIND_BLOCK);
116.460 + b64 = b;
116.461 + retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64,
116.462 + &alloc_ctx);
116.463 + b = b64;
116.464 + if (retval)
116.465 + goto done;
116.466 + inode_bmap(inode, EXT2_TIND_BLOCK) = b;
116.467 + blocks_alloc++;
116.468 + }
116.469 + retval = block_tind_bmap(fs, bmap_flags, b, block_buf,
116.470 + &blocks_alloc, block, &blk32);
116.471 + if (retval == 0)
116.472 + *phys_blk = blk32;
116.473 +done:
116.474 + if (*phys_blk && retval == 0 && (bmap_flags & BMAP_ZERO))
116.475 + retval = ext2fs_zero_blocks2(fs, *phys_blk, 1, NULL, NULL);
116.476 + if (buf)
116.477 + ext2fs_free_mem(&buf);
116.478 + if (handle)
116.479 + ext2fs_extent_free(handle);
116.480 + if ((retval == 0) && (blocks_alloc || inode_dirty)) {
116.481 + ext2fs_iblk_add_blocks(fs, inode, blocks_alloc);
116.482 + retval = ext2fs_write_inode(fs, ino, inode);
116.483 + }
116.484 + return retval;
116.485 +}
116.486 +
116.487 +errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
116.488 + char *block_buf, int bmap_flags, blk_t block,
116.489 + blk_t *phys_blk)
116.490 +{
116.491 + errcode_t ret;
116.492 + blk64_t ret_blk = *phys_blk;
116.493 +
116.494 + ret = ext2fs_bmap2(fs, ino, inode, block_buf, bmap_flags, block,
116.495 + 0, &ret_blk);
116.496 + if (ret)
116.497 + return ret;
116.498 + if (ret_blk >= ((long long) 1 << 32))
116.499 + return EOVERFLOW;
116.500 + *phys_blk = ret_blk;
116.501 + return 0;
116.502 +}
117.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
117.2 +++ b/libext2fs/lib/libext2fs/bmap64.h Wed Aug 25 01:28:08 2021 +0200
117.3 @@ -0,0 +1,104 @@
117.4 +/*
117.5 + * bmap64.h --- 64-bit bitmap structure
117.6 + *
117.7 + * Copyright (C) 2007, 2008 Theodore Ts'o.
117.8 + *
117.9 + * %Begin-Header%
117.10 + * This file may be redistributed under the terms of the GNU Public
117.11 + * License.
117.12 + * %End-Header%
117.13 + */
117.14 +
117.15 +struct ext2_bmap_statistics {
117.16 + int type;
117.17 + struct timeval created;
117.18 +
117.19 +#ifdef ENABLE_BMAP_STATS_OPS
117.20 + unsigned long copy_count;
117.21 + unsigned long resize_count;
117.22 + unsigned long mark_count;
117.23 + unsigned long unmark_count;
117.24 + unsigned long test_count;
117.25 + unsigned long mark_ext_count;
117.26 + unsigned long unmark_ext_count;
117.27 + unsigned long test_ext_count;
117.28 + unsigned long set_range_count;
117.29 + unsigned long get_range_count;
117.30 + unsigned long clear_count;
117.31 +
117.32 + blk64_t last_marked;
117.33 + blk64_t last_tested;
117.34 + blk64_t mark_back;
117.35 + blk64_t test_back;
117.36 +
117.37 + unsigned long mark_seq;
117.38 + unsigned long test_seq;
117.39 +#endif /* ENABLE_BMAP_STATS_OPS */
117.40 +};
117.41 +
117.42 +
117.43 +struct ext2fs_struct_generic_bitmap {
117.44 + errcode_t magic;
117.45 + ext2_filsys fs;
117.46 + struct ext2_bitmap_ops *bitmap_ops;
117.47 + int flags;
117.48 + __u64 start, end;
117.49 + __u64 real_end;
117.50 + int cluster_bits;
117.51 + char *description;
117.52 + void *private;
117.53 + errcode_t base_error_code;
117.54 +#ifdef ENABLE_BMAP_STATS
117.55 + struct ext2_bmap_statistics stats;
117.56 +#endif
117.57 +};
117.58 +
117.59 +#define EXT2FS_IS_32_BITMAP(bmap) \
117.60 + (((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) || \
117.61 + ((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP) || \
117.62 + ((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP))
117.63 +
117.64 +#define EXT2FS_IS_64_BITMAP(bmap) \
117.65 + (((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP64) || \
117.66 + ((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP64) || \
117.67 + ((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP64))
117.68 +
117.69 +struct ext2_bitmap_ops {
117.70 + int type;
117.71 + /* Generic bmap operators */
117.72 + errcode_t (*new_bmap)(ext2_filsys fs, ext2fs_generic_bitmap bmap);
117.73 + void (*free_bmap)(ext2fs_generic_bitmap bitmap);
117.74 + errcode_t (*copy_bmap)(ext2fs_generic_bitmap src,
117.75 + ext2fs_generic_bitmap dest);
117.76 + errcode_t (*resize_bmap)(ext2fs_generic_bitmap bitmap,
117.77 + __u64 new_end,
117.78 + __u64 new_real_end);
117.79 + /* bit set/test operators */
117.80 + int (*mark_bmap)(ext2fs_generic_bitmap bitmap, __u64 arg);
117.81 + int (*unmark_bmap)(ext2fs_generic_bitmap bitmap, __u64 arg);
117.82 + int (*test_bmap)(ext2fs_generic_bitmap bitmap, __u64 arg);
117.83 + void (*mark_bmap_extent)(ext2fs_generic_bitmap bitmap, __u64 arg,
117.84 + unsigned int num);
117.85 + void (*unmark_bmap_extent)(ext2fs_generic_bitmap bitmap, __u64 arg,
117.86 + unsigned int num);
117.87 + int (*test_clear_bmap_extent)(ext2fs_generic_bitmap bitmap,
117.88 + __u64 arg, unsigned int num);
117.89 + errcode_t (*set_bmap_range)(ext2fs_generic_bitmap bitmap,
117.90 + __u64 start, size_t num, void *in);
117.91 + errcode_t (*get_bmap_range)(ext2fs_generic_bitmap bitmap,
117.92 + __u64 start, size_t num, void *out);
117.93 + void (*clear_bmap)(ext2fs_generic_bitmap bitmap);
117.94 + void (*print_stats)(ext2fs_generic_bitmap);
117.95 +
117.96 + /* Find the first zero bit between start and end, inclusive.
117.97 + * May be NULL, in which case a generic function is used. */
117.98 + errcode_t (*find_first_zero)(ext2fs_generic_bitmap bitmap,
117.99 + __u64 start, __u64 end, __u64 *out);
117.100 + /* Find the first set bit between start and end, inclusive.
117.101 + * May be NULL, in which case a generic function is used. */
117.102 + errcode_t (*find_first_set)(ext2fs_generic_bitmap bitmap,
117.103 + __u64 start, __u64 end, __u64 *out);
117.104 +};
117.105 +
117.106 +extern struct ext2_bitmap_ops ext2fs_blkmap64_bitarray;
117.107 +extern struct ext2_bitmap_ops ext2fs_blkmap64_rbtree;
118.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
118.2 +++ b/libext2fs/lib/libext2fs/brel.h Wed Aug 25 01:28:08 2021 +0200
118.3 @@ -0,0 +1,86 @@
118.4 +/*
118.5 + * brel.h
118.6 + *
118.7 + * Copyright (C) 1996, 1997 Theodore Ts'o.
118.8 + *
118.9 + * %Begin-Header%
118.10 + * This file may be redistributed under the terms of the GNU Library
118.11 + * General Public License, version 2.
118.12 + * %End-Header%
118.13 + */
118.14 +
118.15 +struct ext2_block_relocate_entry {
118.16 + blk64_t new;
118.17 + __s16 offset;
118.18 + __u16 flags;
118.19 + union {
118.20 + blk64_t block_ref;
118.21 + ext2_ino_t inode_ref;
118.22 + } owner;
118.23 +};
118.24 +
118.25 +#define RELOCATE_TYPE_REF 0x0007
118.26 +#define RELOCATE_BLOCK_REF 0x0001
118.27 +#define RELOCATE_INODE_REF 0x0002
118.28 +
118.29 +typedef struct ext2_block_relocation_table *ext2_brel;
118.30 +
118.31 +struct ext2_block_relocation_table {
118.32 + __u32 magic;
118.33 + char *name;
118.34 + blk64_t current;
118.35 + void *priv_data;
118.36 +
118.37 + /*
118.38 + * Add a block relocation entry.
118.39 + */
118.40 + errcode_t (*put)(ext2_brel brel, blk64_t old,
118.41 + struct ext2_block_relocate_entry *ent);
118.42 +
118.43 + /*
118.44 + * Get a block relocation entry.
118.45 + */
118.46 + errcode_t (*get)(ext2_brel brel, blk64_t old,
118.47 + struct ext2_block_relocate_entry *ent);
118.48 +
118.49 + /*
118.50 + * Initialize for iterating over the block relocation entries.
118.51 + */
118.52 + errcode_t (*start_iter)(ext2_brel brel);
118.53 +
118.54 + /*
118.55 + * The iterator function for the inode relocation entries.
118.56 + * Returns an inode number of 0 when out of entries.
118.57 + */
118.58 + errcode_t (*next)(ext2_brel brel, blk64_t *old,
118.59 + struct ext2_block_relocate_entry *ent);
118.60 +
118.61 + /*
118.62 + * Move the inode relocation table from one block number to
118.63 + * another.
118.64 + */
118.65 + errcode_t (*move)(ext2_brel brel, blk64_t old, blk_t new);
118.66 +
118.67 + /*
118.68 + * Remove a block relocation entry.
118.69 + */
118.70 + errcode_t (*delete)(ext2_brel brel, blk64_t old);
118.71 +
118.72 +
118.73 + /*
118.74 + * Free the block relocation table.
118.75 + */
118.76 + errcode_t (*free)(ext2_brel brel);
118.77 +};
118.78 +
118.79 +errcode_t ext2fs_brel_memarray_create(char *name, blk64_t max_block,
118.80 + ext2_brel *brel);
118.81 +
118.82 +#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent))
118.83 +#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent))
118.84 +#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel)))
118.85 +#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent))
118.86 +#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new))
118.87 +#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old))
118.88 +#define ext2fs_brel_free(brel) ((brel)->free((brel)))
118.89 +
119.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
119.2 +++ b/libext2fs/lib/libext2fs/check_desc.c Wed Aug 25 01:28:08 2021 +0200
119.3 @@ -0,0 +1,104 @@
119.4 +/*
119.5 + * check_desc.c --- Check the group descriptors of an ext2 filesystem
119.6 + *
119.7 + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
119.8 + *
119.9 + * %Begin-Header%
119.10 + * This file may be redistributed under the terms of the GNU Library
119.11 + * General Public License, version 2.
119.12 + * %End-Header%
119.13 + */
119.14 +
119.15 +#include "config.h"
119.16 +#include <stdio.h>
119.17 +#include <string.h>
119.18 +#if HAVE_UNISTD_H
119.19 +#include <unistd.h>
119.20 +#endif
119.21 +#include <fcntl.h>
119.22 +#include <time.h>
119.23 +#if HAVE_SYS_STAT_H
119.24 +#include <sys/stat.h>
119.25 +#endif
119.26 +#if HAVE_SYS_TYPES_H
119.27 +#include <sys/types.h>
119.28 +#endif
119.29 +
119.30 +#include "ext2_fs.h"
119.31 +#include "ext2fs.h"
119.32 +
119.33 +/*
119.34 + * This routine sanity checks the group descriptors
119.35 + */
119.36 +errcode_t ext2fs_check_desc(ext2_filsys fs)
119.37 +{
119.38 + ext2fs_block_bitmap bmap;
119.39 + errcode_t retval;
119.40 + dgrp_t i;
119.41 + blk64_t first_block = fs->super->s_first_data_block;
119.42 + blk64_t last_block = ext2fs_blocks_count(fs->super)-1;
119.43 + blk64_t blk, b;
119.44 + unsigned int j;
119.45 +
119.46 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
119.47 +
119.48 + if (EXT2_DESC_SIZE(fs->super) & (EXT2_DESC_SIZE(fs->super) - 1))
119.49 + return EXT2_ET_BAD_DESC_SIZE;
119.50 +
119.51 + retval = ext2fs_allocate_subcluster_bitmap(fs, "check_desc map", &bmap);
119.52 + if (retval)
119.53 + return retval;
119.54 +
119.55 + for (i = 0; i < fs->group_desc_count; i++)
119.56 + ext2fs_reserve_super_and_bgd(fs, i, bmap);
119.57 +
119.58 + for (i = 0; i < fs->group_desc_count; i++) {
119.59 + if (!ext2fs_has_feature_flex_bg(fs->super)) {
119.60 + first_block = ext2fs_group_first_block2(fs, i);
119.61 + last_block = ext2fs_group_last_block2(fs, i);
119.62 + }
119.63 +
119.64 + /*
119.65 + * Check to make sure the block bitmap for group is sane
119.66 + */
119.67 + blk = ext2fs_block_bitmap_loc(fs, i);
119.68 + if (blk < first_block || blk > last_block ||
119.69 + ext2fs_test_block_bitmap2(bmap, blk)) {
119.70 + retval = EXT2_ET_GDESC_BAD_BLOCK_MAP;
119.71 + goto errout;
119.72 + }
119.73 + ext2fs_mark_block_bitmap2(bmap, blk);
119.74 +
119.75 + /*
119.76 + * Check to make sure the inode bitmap for group is sane
119.77 + */
119.78 + blk = ext2fs_inode_bitmap_loc(fs, i);
119.79 + if (blk < first_block || blk > last_block ||
119.80 + ext2fs_test_block_bitmap2(bmap, blk)) {
119.81 + retval = EXT2_ET_GDESC_BAD_INODE_MAP;
119.82 + goto errout;
119.83 + }
119.84 + ext2fs_mark_block_bitmap2(bmap, blk);
119.85 +
119.86 + /*
119.87 + * Check to make sure the inode table for group is sane
119.88 + */
119.89 + blk = ext2fs_inode_table_loc(fs, i);
119.90 + if (blk < first_block ||
119.91 + ((blk + fs->inode_blocks_per_group - 1) > last_block)) {
119.92 + retval = EXT2_ET_GDESC_BAD_INODE_TABLE;
119.93 + goto errout;
119.94 + }
119.95 + for (j = 0, b = blk; j < fs->inode_blocks_per_group;
119.96 + j++, b++) {
119.97 + if (ext2fs_test_block_bitmap2(bmap, b)) {
119.98 + retval = EXT2_ET_GDESC_BAD_INODE_TABLE;
119.99 + goto errout;
119.100 + }
119.101 + ext2fs_mark_block_bitmap2(bmap, b);
119.102 + }
119.103 + }
119.104 +errout:
119.105 + ext2fs_free_block_bitmap(bmap);
119.106 + return retval;
119.107 +}
120.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
120.2 +++ b/libext2fs/lib/libext2fs/closefs.c Wed Aug 25 01:28:08 2021 +0200
120.3 @@ -0,0 +1,512 @@
120.4 +/*
120.5 + * closefs.c --- close an ext2 filesystem
120.6 + *
120.7 + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
120.8 + *
120.9 + * %Begin-Header%
120.10 + * This file may be redistributed under the terms of the GNU Library
120.11 + * General Public License, version 2.
120.12 + * %End-Header%
120.13 + */
120.14 +
120.15 +#include "config.h"
120.16 +#include <stdio.h>
120.17 +#if HAVE_UNISTD_H
120.18 +#include <unistd.h>
120.19 +#endif
120.20 +#include <time.h>
120.21 +#include <string.h>
120.22 +
120.23 +#include "ext2_fs.h"
120.24 +#include "ext2fsP.h"
120.25 +
120.26 +static int test_root(unsigned int a, unsigned int b)
120.27 +{
120.28 + while (1) {
120.29 + if (a < b)
120.30 + return 0;
120.31 + if (a == b)
120.32 + return 1;
120.33 + if (a % b)
120.34 + return 0;
120.35 + a = a / b;
120.36 + }
120.37 +}
120.38 +
120.39 +int ext2fs_bg_has_super(ext2_filsys fs, dgrp_t group)
120.40 +{
120.41 + if (group == 0)
120.42 + return 1;
120.43 + if (ext2fs_has_feature_sparse_super2(fs->super)) {
120.44 + if (group == fs->super->s_backup_bgs[0] ||
120.45 + group == fs->super->s_backup_bgs[1])
120.46 + return 1;
120.47 + return 0;
120.48 + }
120.49 + if ((group <= 1) || !ext2fs_has_feature_sparse_super(fs->super))
120.50 + return 1;
120.51 + if (!(group & 1))
120.52 + return 0;
120.53 + if (test_root(group, 3) || (test_root(group, 5)) ||
120.54 + test_root(group, 7))
120.55 + return 1;
120.56 +
120.57 + return 0;
120.58 +}
120.59 +
120.60 +/*
120.61 + * ext2fs_super_and_bgd_loc2()
120.62 + * @fs: ext2 fs pointer
120.63 + * @group given block group
120.64 + * @ret_super_blk: if !NULL, returns super block location
120.65 + * @ret_old_desc_blk: if !NULL, returns location of the old block
120.66 + * group descriptor
120.67 + * @ret_new_desc_blk: if !NULL, returns location of meta_bg block
120.68 + * group descriptor
120.69 + * @ret_used_blks: if !NULL, returns number of blocks used by
120.70 + * super block and group_descriptors.
120.71 + *
120.72 + * Returns errcode_t of 0
120.73 + */
120.74 +errcode_t ext2fs_super_and_bgd_loc2(ext2_filsys fs,
120.75 + dgrp_t group,
120.76 + blk64_t *ret_super_blk,
120.77 + blk64_t *ret_old_desc_blk,
120.78 + blk64_t *ret_new_desc_blk,
120.79 + blk_t *ret_used_blks)
120.80 +{
120.81 + blk64_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0;
120.82 + unsigned int meta_bg, meta_bg_size;
120.83 + blk_t numblocks = 0;
120.84 + blk64_t old_desc_blocks;
120.85 + int has_super;
120.86 +
120.87 + group_block = ext2fs_group_first_block2(fs, group);
120.88 + if (group_block == 0 && fs->blocksize == 1024)
120.89 + group_block = 1; /* Deal with 1024 blocksize && bigalloc */
120.90 +
120.91 + if (ext2fs_has_feature_meta_bg(fs->super))
120.92 + old_desc_blocks = fs->super->s_first_meta_bg;
120.93 + else
120.94 + old_desc_blocks =
120.95 + fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
120.96 +
120.97 + has_super = ext2fs_bg_has_super(fs, group);
120.98 +
120.99 + if (has_super) {
120.100 + super_blk = group_block;
120.101 + numblocks++;
120.102 + }
120.103 + meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
120.104 + meta_bg = group / meta_bg_size;
120.105 +
120.106 + if (!ext2fs_has_feature_meta_bg(fs->super) ||
120.107 + (meta_bg < fs->super->s_first_meta_bg)) {
120.108 + if (has_super) {
120.109 + old_desc_blk = group_block + 1;
120.110 + numblocks += old_desc_blocks;
120.111 + }
120.112 + } else {
120.113 + if (((group % meta_bg_size) == 0) ||
120.114 + ((group % meta_bg_size) == 1) ||
120.115 + ((group % meta_bg_size) == (meta_bg_size-1))) {
120.116 + if (has_super)
120.117 + has_super = 1;
120.118 + new_desc_blk = group_block + has_super;
120.119 + numblocks++;
120.120 + }
120.121 + }
120.122 +
120.123 + if (ret_super_blk)
120.124 + *ret_super_blk = super_blk;
120.125 + if (ret_old_desc_blk)
120.126 + *ret_old_desc_blk = old_desc_blk;
120.127 + if (ret_new_desc_blk)
120.128 + *ret_new_desc_blk = new_desc_blk;
120.129 + if (ret_used_blks)
120.130 + *ret_used_blks = numblocks;
120.131 +
120.132 + return 0;
120.133 +}
120.134 +
120.135 +/*
120.136 + * This function returns the location of the superblock, block group
120.137 + * descriptors for a given block group. It currently returns the
120.138 + * number of free blocks assuming that inode table and allocation
120.139 + * bitmaps will be in the group. This is not necessarily the case
120.140 + * when the flex_bg feature is enabled, so callers should take care!
120.141 + * It was only really intended for use by mke2fs, and even there it's
120.142 + * not that useful.
120.143 + *
120.144 + * The ext2fs_super_and_bgd_loc2() function is 64-bit block number
120.145 + * capable and returns the number of blocks used by super block and
120.146 + * group descriptors.
120.147 + */
120.148 +int ext2fs_super_and_bgd_loc(ext2_filsys fs,
120.149 + dgrp_t group,
120.150 + blk_t *ret_super_blk,
120.151 + blk_t *ret_old_desc_blk,
120.152 + blk_t *ret_new_desc_blk,
120.153 + int *ret_meta_bg)
120.154 +{
120.155 + blk64_t ret_super_blk2;
120.156 + blk64_t ret_old_desc_blk2;
120.157 + blk64_t ret_new_desc_blk2;
120.158 + blk_t ret_used_blks;
120.159 + blk_t numblocks;
120.160 + unsigned int meta_bg_size;
120.161 +
120.162 + ext2fs_super_and_bgd_loc2(fs, group, &ret_super_blk2,
120.163 + &ret_old_desc_blk2,
120.164 + &ret_new_desc_blk2,
120.165 + &ret_used_blks);
120.166 +
120.167 + numblocks = ext2fs_group_blocks_count(fs, group);
120.168 +
120.169 + if (ret_super_blk)
120.170 + *ret_super_blk = (blk_t)ret_super_blk2;
120.171 + if (ret_old_desc_blk)
120.172 + *ret_old_desc_blk = (blk_t)ret_old_desc_blk2;
120.173 + if (ret_new_desc_blk)
120.174 + *ret_new_desc_blk = (blk_t)ret_new_desc_blk2;
120.175 + if (ret_meta_bg) {
120.176 + meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
120.177 + *ret_meta_bg = group / meta_bg_size;
120.178 + }
120.179 +
120.180 + numblocks -= 2 + fs->inode_blocks_per_group + ret_used_blks;
120.181 +
120.182 + return numblocks;
120.183 +}
120.184 +
120.185 +/*
120.186 + * This function forces out the primary superblock. We need to only
120.187 + * write out those fields which we have changed, since if the
120.188 + * filesystem is mounted, it may have changed some of the other
120.189 + * fields.
120.190 + *
120.191 + * It takes as input a superblock which has already been byte swapped
120.192 + * (if necessary).
120.193 + *
120.194 + */
120.195 +static errcode_t write_primary_superblock(ext2_filsys fs,
120.196 + struct ext2_super_block *super)
120.197 +{
120.198 + __u16 *old_super, *new_super;
120.199 + int check_idx, write_idx, size;
120.200 + errcode_t retval;
120.201 +
120.202 + if (!fs->io->manager->write_byte || !fs->orig_super) {
120.203 + fallback:
120.204 + io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
120.205 + retval = io_channel_write_blk64(fs->io, 1, -SUPERBLOCK_SIZE,
120.206 + super);
120.207 + io_channel_set_blksize(fs->io, fs->blocksize);
120.208 + return retval;
120.209 + }
120.210 +
120.211 + old_super = (__u16 *) fs->orig_super;
120.212 + new_super = (__u16 *) super;
120.213 +
120.214 + for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) {
120.215 + if (old_super[check_idx] == new_super[check_idx])
120.216 + continue;
120.217 + write_idx = check_idx;
120.218 + for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++)
120.219 + if (old_super[check_idx] == new_super[check_idx])
120.220 + break;
120.221 + size = 2 * (check_idx - write_idx);
120.222 +#if 0
120.223 + printf("Writing %d bytes starting at %d\n",
120.224 + size, write_idx*2);
120.225 +#endif
120.226 + retval = io_channel_write_byte(fs->io,
120.227 + SUPERBLOCK_OFFSET + (2 * write_idx), size,
120.228 + new_super + write_idx);
120.229 + if (retval == EXT2_ET_UNIMPLEMENTED)
120.230 + goto fallback;
120.231 + if (retval)
120.232 + return retval;
120.233 + }
120.234 + memcpy(fs->orig_super, super, SUPERBLOCK_SIZE);
120.235 + return 0;
120.236 +}
120.237 +
120.238 +
120.239 +/*
120.240 + * Updates the revision to EXT2_DYNAMIC_REV
120.241 + */
120.242 +void ext2fs_update_dynamic_rev(ext2_filsys fs)
120.243 +{
120.244 + struct ext2_super_block *sb = fs->super;
120.245 +
120.246 + if (sb->s_rev_level > EXT2_GOOD_OLD_REV)
120.247 + return;
120.248 +
120.249 + sb->s_rev_level = EXT2_DYNAMIC_REV;
120.250 + sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
120.251 + sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
120.252 + /* s_uuid is handled by e2fsck already */
120.253 + /* other fields should be left alone */
120.254 +}
120.255 +
120.256 +static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group,
120.257 + blk64_t group_block,
120.258 + struct ext2_super_block *super_shadow)
120.259 +{
120.260 + errcode_t retval;
120.261 + dgrp_t sgrp = group;
120.262 +
120.263 + if (sgrp > ((1 << 16) - 1))
120.264 + sgrp = (1 << 16) - 1;
120.265 +
120.266 + super_shadow->s_block_group_nr = ext2fs_cpu_to_le16(sgrp);
120.267 +
120.268 + retval = ext2fs_superblock_csum_set(fs, super_shadow);
120.269 + if (retval)
120.270 + return retval;
120.271 +
120.272 + return io_channel_write_blk64(fs->io, group_block, -SUPERBLOCK_SIZE,
120.273 + super_shadow);
120.274 +}
120.275 +
120.276 +errcode_t ext2fs_flush(ext2_filsys fs)
120.277 +{
120.278 + return ext2fs_flush2(fs, 0);
120.279 +}
120.280 +
120.281 +errcode_t ext2fs_flush2(ext2_filsys fs, int flags)
120.282 +{
120.283 + dgrp_t i;
120.284 + errcode_t retval;
120.285 + unsigned long fs_state;
120.286 + __u32 feature_incompat;
120.287 + struct ext2_super_block *super_shadow = 0;
120.288 + struct opaque_ext2_group_desc *group_shadow = 0;
120.289 +#ifdef WORDS_BIGENDIAN
120.290 + struct ext2_group_desc *gdp;
120.291 + dgrp_t j;
120.292 +#endif
120.293 + char *group_ptr;
120.294 + blk64_t old_desc_blocks;
120.295 + struct ext2fs_numeric_progress_struct progress;
120.296 +
120.297 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
120.298 +
120.299 + fs_state = fs->super->s_state;
120.300 + feature_incompat = fs->super->s_feature_incompat;
120.301 +
120.302 + fs->super->s_wtime = fs->now ? fs->now : time(NULL);
120.303 + fs->super->s_block_group_nr = 0;
120.304 +
120.305 + /*
120.306 + * If the write_bitmaps() function is present, call it to
120.307 + * flush the bitmaps. This is done this way so that a simple
120.308 + * program that doesn't mess with the bitmaps doesn't need to
120.309 + * drag in the bitmaps.c code.
120.310 + *
120.311 + * Bitmap checksums live in the group descriptor, so the
120.312 + * bitmaps need to be written before the descriptors.
120.313 + */
120.314 + if (fs->write_bitmaps) {
120.315 + retval = fs->write_bitmaps(fs);
120.316 + if (retval)
120.317 + goto errout;
120.318 + }
120.319 +
120.320 + /*
120.321 + * Set the state of the FS to be non-valid. (The state has
120.322 + * already been backed up earlier, and will be restored after
120.323 + * we write out the backup superblocks.)
120.324 + */
120.325 + fs->super->s_state &= ~EXT2_VALID_FS;
120.326 + ext2fs_clear_feature_journal_needs_recovery(fs->super);
120.327 +
120.328 + /* Byte swap the superblock and the group descriptors if necessary */
120.329 +#ifdef WORDS_BIGENDIAN
120.330 + retval = EXT2_ET_NO_MEMORY;
120.331 + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
120.332 + if (retval)
120.333 + goto errout;
120.334 + retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
120.335 + &group_shadow);
120.336 + if (retval)
120.337 + goto errout;
120.338 + memcpy(super_shadow, fs->super, sizeof(struct ext2_super_block));
120.339 + memcpy(group_shadow, fs->group_desc, (size_t) fs->blocksize *
120.340 + fs->desc_blocks);
120.341 +
120.342 + ext2fs_swap_super(super_shadow);
120.343 + for (j = 0; j < fs->group_desc_count; j++) {
120.344 + gdp = ext2fs_group_desc(fs, group_shadow, j);
120.345 + ext2fs_swap_group_desc2(fs, gdp);
120.346 + }
120.347 +#else
120.348 + super_shadow = fs->super;
120.349 + group_shadow = fs->group_desc;
120.350 +#endif
120.351 +
120.352 + /*
120.353 + * If this is an external journal device, don't write out the
120.354 + * block group descriptors or any of the backup superblocks
120.355 + */
120.356 + if (ext2fs_has_feature_journal_dev(fs->super))
120.357 + goto write_primary_superblock_only;
120.358 +
120.359 + /*
120.360 + * Write out the master group descriptors, and the backup
120.361 + * superblocks and group descriptors.
120.362 + */
120.363 + group_ptr = (char *) group_shadow;
120.364 + if (ext2fs_has_feature_meta_bg(fs->super)) {
120.365 + old_desc_blocks = fs->super->s_first_meta_bg;
120.366 + if (old_desc_blocks > fs->desc_blocks)
120.367 + old_desc_blocks = fs->desc_blocks;
120.368 + } else
120.369 + old_desc_blocks = fs->desc_blocks;
120.370 +
120.371 + if (fs->progress_ops && fs->progress_ops->init)
120.372 + (fs->progress_ops->init)(fs, &progress, NULL,
120.373 + fs->group_desc_count);
120.374 +
120.375 +
120.376 + for (i = 0; i < fs->group_desc_count; i++) {
120.377 + blk64_t super_blk, old_desc_blk, new_desc_blk;
120.378 +
120.379 + if (fs->progress_ops && fs->progress_ops->update)
120.380 + (fs->progress_ops->update)(fs, &progress, i);
120.381 + ext2fs_super_and_bgd_loc2(fs, i, &super_blk, &old_desc_blk,
120.382 + &new_desc_blk, 0);
120.383 +
120.384 + if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) {
120.385 + retval = write_backup_super(fs, i, super_blk,
120.386 + super_shadow);
120.387 + if (retval)
120.388 + goto errout;
120.389 + }
120.390 + if (fs->flags & EXT2_FLAG_SUPER_ONLY)
120.391 + continue;
120.392 + if ((old_desc_blk) &&
120.393 + (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) {
120.394 + retval = io_channel_write_blk64(fs->io,
120.395 + old_desc_blk, old_desc_blocks, group_ptr);
120.396 + if (retval)
120.397 + goto errout;
120.398 + }
120.399 + if (new_desc_blk) {
120.400 + int meta_bg = i / EXT2_DESC_PER_BLOCK(fs->super);
120.401 +
120.402 + retval = io_channel_write_blk64(fs->io, new_desc_blk,
120.403 + 1, group_ptr + (meta_bg*fs->blocksize));
120.404 + if (retval)
120.405 + goto errout;
120.406 + }
120.407 + }
120.408 +
120.409 + if (fs->progress_ops && fs->progress_ops->close)
120.410 + (fs->progress_ops->close)(fs, &progress, NULL);
120.411 +
120.412 +write_primary_superblock_only:
120.413 + /*
120.414 + * Write out master superblock. This has to be done
120.415 + * separately, since it is located at a fixed location
120.416 + * (SUPERBLOCK_OFFSET). We flush all other pending changes
120.417 + * out to disk first, just to avoid a race condition with an
120.418 + * insy-tinsy window....
120.419 + */
120.420 +
120.421 + fs->super->s_block_group_nr = 0;
120.422 + fs->super->s_state = fs_state;
120.423 + fs->super->s_feature_incompat = feature_incompat;
120.424 +#ifdef WORDS_BIGENDIAN
120.425 + *super_shadow = *fs->super;
120.426 + ext2fs_swap_super(super_shadow);
120.427 +#endif
120.428 +
120.429 + retval = ext2fs_superblock_csum_set(fs, super_shadow);
120.430 + if (retval)
120.431 + return retval;
120.432 +
120.433 + if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC)) {
120.434 + retval = io_channel_flush(fs->io);
120.435 + if (retval)
120.436 + goto errout;
120.437 + }
120.438 + retval = write_primary_superblock(fs, super_shadow);
120.439 + if (retval)
120.440 + goto errout;
120.441 +
120.442 + fs->flags &= ~EXT2_FLAG_DIRTY;
120.443 +
120.444 + if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC)) {
120.445 + retval = io_channel_flush(fs->io);
120.446 + if (retval)
120.447 + goto errout;
120.448 + }
120.449 +errout:
120.450 + fs->super->s_state = fs_state;
120.451 +#ifdef WORDS_BIGENDIAN
120.452 + if (super_shadow)
120.453 + ext2fs_free_mem(&super_shadow);
120.454 + if (group_shadow)
120.455 + ext2fs_free_mem(&group_shadow);
120.456 +#endif
120.457 + return retval;
120.458 +}
120.459 +
120.460 +errcode_t ext2fs_close_free(ext2_filsys *fs_ptr)
120.461 +{
120.462 + errcode_t ret;
120.463 + ext2_filsys fs = *fs_ptr;
120.464 +
120.465 + ret = ext2fs_close2(fs, 0);
120.466 + if (ret)
120.467 + ext2fs_free(fs);
120.468 + *fs_ptr = NULL;
120.469 + return ret;
120.470 +}
120.471 +
120.472 +errcode_t ext2fs_close(ext2_filsys fs)
120.473 +{
120.474 + return ext2fs_close2(fs, 0);
120.475 +}
120.476 +
120.477 +errcode_t ext2fs_close2(ext2_filsys fs, int flags)
120.478 +{
120.479 + errcode_t retval;
120.480 + int meta_blks;
120.481 + io_stats stats = 0;
120.482 +
120.483 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
120.484 +
120.485 + if (fs->write_bitmaps) {
120.486 + retval = fs->write_bitmaps(fs);
120.487 + if (retval)
120.488 + return retval;
120.489 + }
120.490 + if (fs->super->s_kbytes_written &&
120.491 + fs->io->manager->get_stats)
120.492 + fs->io->manager->get_stats(fs->io, &stats);
120.493 + if (stats && stats->bytes_written && (fs->flags & EXT2_FLAG_RW)) {
120.494 + fs->super->s_kbytes_written += stats->bytes_written >> 10;
120.495 + meta_blks = fs->desc_blocks + 1;
120.496 + if (!(fs->flags & EXT2_FLAG_SUPER_ONLY))
120.497 + fs->super->s_kbytes_written += meta_blks /
120.498 + (fs->blocksize / 1024);
120.499 + if ((fs->flags & EXT2_FLAG_DIRTY) == 0)
120.500 + fs->flags |= EXT2_FLAG_SUPER_ONLY | EXT2_FLAG_DIRTY;
120.501 + }
120.502 + if (fs->flags & EXT2_FLAG_DIRTY) {
120.503 + retval = ext2fs_flush2(fs, flags);
120.504 + if (retval)
120.505 + return retval;
120.506 + }
120.507 +
120.508 + retval = ext2fs_mmp_stop(fs);
120.509 + if (retval)
120.510 + return retval;
120.511 +
120.512 + ext2fs_free(fs);
120.513 + return 0;
120.514 +}
120.515 +
121.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
121.2 +++ b/libext2fs/lib/libext2fs/crc16.c Wed Aug 25 01:28:08 2021 +0200
121.3 @@ -0,0 +1,74 @@
121.4 +/*
121.5 + * crc16.c
121.6 + *
121.7 + * This source code is licensed under the GNU General Public License,
121.8 + * Version 2. See the file COPYING for more details.
121.9 + */
121.10 +
121.11 +#include "config.h"
121.12 +#if HAVE_SYS_TYPES_H
121.13 +#include <sys/types.h>
121.14 +#endif
121.15 +#include <ext2fs/ext2_types.h>
121.16 +
121.17 +#include "crc16.h"
121.18 +
121.19 +/** CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1) */
121.20 +static __u16 const crc16_table[256] = {
121.21 + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
121.22 + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
121.23 + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
121.24 + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
121.25 + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
121.26 + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
121.27 + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
121.28 + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
121.29 + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
121.30 + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
121.31 + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
121.32 + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
121.33 + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
121.34 + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
121.35 + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
121.36 + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
121.37 + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
121.38 + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
121.39 + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
121.40 + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
121.41 + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
121.42 + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
121.43 + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
121.44 + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
121.45 + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
121.46 + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
121.47 + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
121.48 + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
121.49 + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
121.50 + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
121.51 + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
121.52 + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
121.53 +};
121.54 +
121.55 +/**
121.56 + * Compute the CRC-16 for the data buffer
121.57 + *
121.58 + * @param crc previous CRC value
121.59 + * @param buffer data pointer
121.60 + * @param len number of bytes in the buffer
121.61 + * @return the updated CRC value
121.62 + */
121.63 +crc16_t ext2fs_crc16(crc16_t crc, const void *buffer, unsigned int len)
121.64 +{
121.65 + const unsigned char *cp = buffer;
121.66 +
121.67 + while (len--)
121.68 + /*
121.69 + * for an unknown reason, PPC treats __u16 as signed
121.70 + * and keeps doing sign extension on the value.
121.71 + * Instead, use only the low 16 bits of an unsigned
121.72 + * int for holding the CRC value to avoid this.
121.73 + */
121.74 + crc = (((crc >> 8) & 0xffU) ^
121.75 + crc16_table[(crc ^ *cp++) & 0xffU]) & 0x0000ffffU;
121.76 + return crc;
121.77 +}
122.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
122.2 +++ b/libext2fs/lib/libext2fs/crc16.h Wed Aug 25 01:28:08 2021 +0200
122.3 @@ -0,0 +1,26 @@
122.4 +/*
122.5 + * crc16.h - CRC-16 routine
122.6 + *
122.7 + * Implements the standard CRC-16:
122.8 + * Width 16
122.9 + * Poly 0x8005 (x16 + x15 + x2 + 1)
122.10 + * Init 0
122.11 + *
122.12 + * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
122.13 + *
122.14 + * This source code is licensed under the GNU General Public License,
122.15 + * Version 2. See the file COPYING for more details.
122.16 + */
122.17 +
122.18 +#ifndef __CRC16_H
122.19 +#define __CRC16_H
122.20 +
122.21 +/* for an unknown reason, PPC treats __u16 as signed and keeps doing sign
122.22 + * extension on the value. Instead, use only the low 16 bits of an
122.23 + * unsigned int for holding the CRC value to avoid this.
122.24 + */
122.25 +typedef unsigned int crc16_t;
122.26 +
122.27 +extern crc16_t ext2fs_crc16(crc16_t crc, const void *buffer, unsigned int len);
122.28 +
122.29 +#endif /* __CRC16_H */
123.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
123.2 +++ b/libext2fs/lib/libext2fs/crc32c.c Wed Aug 25 01:28:08 2021 +0200
123.3 @@ -0,0 +1,932 @@
123.4 +/*
123.5 + * crc32c.c
123.6 + *
123.7 + * August 26, 2011 Darrick J. Wong <djwong at us.ibm.com>
123.8 + * Reuse Bob Pearson's slice-by-8 implementation for e2fsprogs.
123.9 + *
123.10 + * July 20, 2011 Bob Pearson <rpearson at systemfabricworks.com>
123.11 + * added slice by 8 algorithm to the existing conventional and
123.12 + * slice by 4 algorithms.
123.13 + *
123.14 + * Oct 15, 2000 Matt Domsch <Matt_Domsch@dell.com>
123.15 + * Nicer crc32 functions/docs submitted by linux@horizon.com. Thanks!
123.16 + * Code was from the public domain, copyright abandoned. Code was
123.17 + * subsequently included in the kernel, thus was re-licensed under the
123.18 + * GNU GPL v2.
123.19 + *
123.20 + * Oct 12, 2000 Matt Domsch <Matt_Domsch@dell.com>
123.21 + * Same crc32 function was used in 5 other places in the kernel.
123.22 + * I made one version, and deleted the others.
123.23 + * There are various incantations of crc32(). Some use a seed of 0 or ~0.
123.24 + * Some xor at the end with ~0. The generic crc32() function takes
123.25 + * seed as an argument, and doesn't xor at the end. Then individual
123.26 + * users can do whatever they need.
123.27 + * drivers/net/smc9194.c uses seed ~0, doesn't xor with ~0.
123.28 + * fs/jffs2 uses seed 0, doesn't xor with ~0.
123.29 + * fs/partitions/efi.c uses seed ~0, xor's with ~0.
123.30 + *
123.31 + * This source code is licensed under the GNU General Public License,
123.32 + * Version 2. See the file COPYING for more details.
123.33 + */
123.34 +#include "config.h"
123.35 +#include <stdint.h>
123.36 +#include <stdlib.h>
123.37 +#include <stdio.h>
123.38 +#define min(x, y) ((x) > (y) ? (y) : (x))
123.39 +#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
123.40 +#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (__typeof__(x))(a) - 1)
123.41 +#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
123.42 +#define PTR_ALIGN(p, a) ((__typeof__(p))ALIGN((unsigned long)(p), (a)))
123.43 +#include "crc32c_defs.h"
123.44 +
123.45 +#include "ext2fs.h"
123.46 +#ifdef WORDS_BIGENDIAN
123.47 +#define __constant_cpu_to_le32(x) ___constant_swab32((x))
123.48 +#define __constant_cpu_to_be32(x) (x)
123.49 +#define __be32_to_cpu(x) (x)
123.50 +#define __cpu_to_be32(x) (x)
123.51 +#define __cpu_to_le32(x) (ext2fs_cpu_to_le32((x)))
123.52 +#define __le32_to_cpu(x) (ext2fs_le32_to_cpu((x)))
123.53 +#else
123.54 +#define __constant_cpu_to_le32(x) (x)
123.55 +#define __constant_cpu_to_be32(x) ___constant_swab32((x))
123.56 +#define __be32_to_cpu(x) (ext2fs_be32_to_cpu((x)))
123.57 +#define __cpu_to_be32(x) (ext2fs_cpu_to_be32((x)))
123.58 +#define __cpu_to_le32(x) (x)
123.59 +#define __le32_to_cpu(x) (x)
123.60 +#endif
123.61 +
123.62 +#if CRC_LE_BITS > 8
123.63 +# define tole(x) __constant_cpu_to_le32(x)
123.64 +#else
123.65 +# define tole(x) (x)
123.66 +#endif
123.67 +
123.68 +#if CRC_BE_BITS > 8
123.69 +# define tobe(x) __constant_cpu_to_be32(x)
123.70 +#else
123.71 +# define tobe(x) (x)
123.72 +#endif
123.73 +
123.74 +#include "crc32c_table.h"
123.75 +
123.76 +#if CRC_LE_BITS > 8 || CRC_BE_BITS > 8
123.77 +
123.78 +/* implements slicing-by-4 or slicing-by-8 algorithm */
123.79 +static inline uint32_t
123.80 +crc32_body(uint32_t crc, unsigned char const *buf, size_t len,
123.81 + const uint32_t (*tab)[256])
123.82 +{
123.83 +# ifndef WORDS_BIGENDIAN
123.84 +# define DO_CRC(x) (crc = t0[(crc ^ (x)) & 255] ^ (crc >> 8))
123.85 +# define DO_CRC4 (t3[(q) & 255] ^ t2[(q >> 8) & 255] ^ \
123.86 + t1[(q >> 16) & 255] ^ t0[(q >> 24) & 255])
123.87 +# define DO_CRC8 (t7[(q) & 255] ^ t6[(q >> 8) & 255] ^ \
123.88 + t5[(q >> 16) & 255] ^ t4[(q >> 24) & 255])
123.89 +# else
123.90 +# define DO_CRC(x) (crc = t0[((crc >> 24) ^ (x)) & 255] ^ (crc << 8))
123.91 +# define DO_CRC4 (t0[(q) & 255] ^ t1[(q >> 8) & 255] ^ \
123.92 + t2[(q >> 16) & 255] ^ t3[(q >> 24) & 255])
123.93 +# define DO_CRC8 (t4[(q) & 255] ^ t5[(q >> 8) & 255] ^ \
123.94 + t6[(q >> 16) & 255] ^ t7[(q >> 24) & 255])
123.95 +# endif
123.96 + const uint32_t *b;
123.97 + size_t rem_len;
123.98 + const uint32_t *t0 = tab[0], *t1 = tab[1], *t2 = tab[2], *t3 = tab[3];
123.99 + const uint32_t *t4 = tab[4], *t5 = tab[5], *t6 = tab[6], *t7 = tab[7];
123.100 + uint32_t q;
123.101 +
123.102 + /* Align it */
123.103 + if (unlikely((uintptr_t)buf & 3 && len)) {
123.104 + do {
123.105 + DO_CRC(*buf++);
123.106 + } while ((--len) && ((uintptr_t)buf)&3);
123.107 + }
123.108 +
123.109 +# if CRC_LE_BITS == 32
123.110 + rem_len = len & 3;
123.111 + len = len >> 2;
123.112 +# else
123.113 + rem_len = len & 7;
123.114 + len = len >> 3;
123.115 +# endif
123.116 +
123.117 + b = (const uint32_t *)buf;
123.118 + for (--b; len; --len) {
123.119 + q = crc ^ *++b; /* use pre increment for speed */
123.120 +# if CRC_LE_BITS == 32
123.121 + crc = DO_CRC4;
123.122 +# else
123.123 + crc = DO_CRC8;
123.124 + q = *++b;
123.125 + crc ^= DO_CRC4;
123.126 +# endif
123.127 + }
123.128 + len = rem_len;
123.129 + /* And the last few bytes */
123.130 + if (len) {
123.131 + const uint8_t *p = (const uint8_t *)(b + 1) - 1;
123.132 + do {
123.133 + DO_CRC(*++p); /* use pre increment for speed */
123.134 + } while (--len);
123.135 + }
123.136 + return crc;
123.137 +#undef DO_CRC
123.138 +#undef DO_CRC4
123.139 +#undef DO_CRC8
123.140 +}
123.141 +#endif
123.142 +
123.143 +/**
123.144 + * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32
123.145 + * @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for
123.146 + * other uses, or the previous crc32 value if computing incrementally.
123.147 + * @p: pointer to buffer over which CRC is run
123.148 + * @len: length of buffer @p
123.149 + */
123.150 +static inline uint32_t crc32_le_generic(uint32_t crc, unsigned char const *p,
123.151 + size_t len, const uint32_t (*tab)[256],
123.152 + uint32_t polynomial EXT2FS_ATTR((unused)))
123.153 +{
123.154 +#if CRC_LE_BITS == 1
123.155 + int i;
123.156 + while (len--) {
123.157 + crc ^= *p++;
123.158 + for (i = 0; i < 8; i++)
123.159 + crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0);
123.160 + }
123.161 +# elif CRC_LE_BITS == 2
123.162 + while (len--) {
123.163 + crc ^= *p++;
123.164 + crc = (crc >> 2) ^ tab[0][crc & 3];
123.165 + crc = (crc >> 2) ^ tab[0][crc & 3];
123.166 + crc = (crc >> 2) ^ tab[0][crc & 3];
123.167 + crc = (crc >> 2) ^ tab[0][crc & 3];
123.168 + }
123.169 +# elif CRC_LE_BITS == 4
123.170 + while (len--) {
123.171 + crc ^= *p++;
123.172 + crc = (crc >> 4) ^ tab[0][crc & 15];
123.173 + crc = (crc >> 4) ^ tab[0][crc & 15];
123.174 + }
123.175 +# elif CRC_LE_BITS == 8
123.176 + /* aka Sarwate algorithm */
123.177 + while (len--) {
123.178 + crc ^= *p++;
123.179 + crc = (crc >> 8) ^ tab[0][crc & 255];
123.180 + }
123.181 +# else
123.182 + crc = __cpu_to_le32(crc);
123.183 + crc = crc32_body(crc, p, len, tab);
123.184 + crc = __le32_to_cpu(crc);
123.185 +#endif
123.186 + return crc;
123.187 +}
123.188 +
123.189 +uint32_t ext2fs_crc32c_le(uint32_t crc, unsigned char const *p, size_t len)
123.190 +{
123.191 + return crc32_le_generic(crc, p, len, crc32ctable_le, CRC32C_POLY_LE);
123.192 +}
123.193 +
123.194 +/**
123.195 + * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32
123.196 + * @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for
123.197 + * other uses, or the previous crc32 value if computing incrementally.
123.198 + * @p: pointer to buffer over which CRC is run
123.199 + * @len: length of buffer @p
123.200 + */
123.201 +static inline uint32_t crc32_be_generic(uint32_t crc, unsigned char const *p,
123.202 + size_t len, const uint32_t (*tab)[256],
123.203 + uint32_t polynomial EXT2FS_ATTR((unused)))
123.204 +{
123.205 +#if CRC_BE_BITS == 1
123.206 + int i;
123.207 + while (len--) {
123.208 + crc ^= *p++ << 24;
123.209 + for (i = 0; i < 8; i++)
123.210 + crc =
123.211 + (crc << 1) ^ ((crc & 0x80000000) ? polynomial :
123.212 + 0);
123.213 + }
123.214 +# elif CRC_BE_BITS == 2
123.215 + while (len--) {
123.216 + crc ^= *p++ << 24;
123.217 + crc = (crc << 2) ^ tab[0][crc >> 30];
123.218 + crc = (crc << 2) ^ tab[0][crc >> 30];
123.219 + crc = (crc << 2) ^ tab[0][crc >> 30];
123.220 + crc = (crc << 2) ^ tab[0][crc >> 30];
123.221 + }
123.222 +# elif CRC_BE_BITS == 4
123.223 + while (len--) {
123.224 + crc ^= *p++ << 24;
123.225 + crc = (crc << 4) ^ tab[0][crc >> 28];
123.226 + crc = (crc << 4) ^ tab[0][crc >> 28];
123.227 + }
123.228 +# elif CRC_BE_BITS == 8
123.229 + while (len--) {
123.230 + crc ^= *p++ << 24;
123.231 + crc = (crc << 8) ^ tab[0][crc >> 24];
123.232 + }
123.233 +# else
123.234 + crc = __cpu_to_be32(crc);
123.235 + crc = crc32_body(crc, p, len, tab);
123.236 + crc = __be32_to_cpu(crc);
123.237 +# endif
123.238 + return crc;
123.239 +}
123.240 +
123.241 +uint32_t ext2fs_crc32_be(uint32_t crc, unsigned char const *p, size_t len)
123.242 +{
123.243 + return crc32_be_generic(crc, p, len, crc32table_be, CRCPOLY_BE);
123.244 +}
123.245 +
123.246 +#ifdef UNITTEST
123.247 +static uint8_t test_buf[] = {
123.248 + 0xd9, 0xd7, 0x6a, 0x13, 0x3a, 0xb1, 0x05, 0x48,
123.249 + 0xda, 0xad, 0x14, 0xbd, 0x03, 0x3a, 0x58, 0x5e,
123.250 + 0x6e, 0xd1, 0x56, 0xc9, 0x2e, 0xc4, 0xcb, 0x6b,
123.251 + 0xe8, 0x77, 0x52, 0x37, 0x4e, 0x0f, 0x55, 0xd2,
123.252 + 0x12, 0x65, 0x90, 0xc2, 0x41, 0x49, 0x81, 0x01,
123.253 + 0xf5, 0x01, 0xeb, 0x2d, 0x78, 0x74, 0x23, 0x5d,
123.254 + 0x84, 0x5c, 0x81, 0x92, 0x21, 0xe9, 0x8d, 0x1d,
123.255 + 0x89, 0xf2, 0x4a, 0xac, 0xdd, 0xf9, 0xaf, 0xee,
123.256 + 0x44, 0xe7, 0x6e, 0xed, 0xfb, 0xd8, 0x89, 0x0e,
123.257 + 0x96, 0x62, 0xcd, 0xa4, 0x4b, 0xa9, 0xe5, 0x45,
123.258 + 0xb1, 0x29, 0x9b, 0x0f, 0xfc, 0xbd, 0x83, 0xab,
123.259 + 0xa8, 0x54, 0x96, 0x44, 0x2c, 0x7f, 0xbb, 0xe7,
123.260 + 0x52, 0x29, 0x08, 0xee, 0x14, 0xc5, 0xc2, 0xec,
123.261 + 0x5a, 0xeb, 0x40, 0x40, 0xea, 0xd1, 0x3d, 0x15,
123.262 + 0x73, 0xaa, 0x8c, 0x73, 0xfc, 0xf2, 0x2b, 0x49,
123.263 + 0x0b, 0x13, 0x96, 0xd9, 0x8e, 0x4b, 0xbc, 0xe0,
123.264 + 0xf4, 0xd2, 0xe0, 0x2e, 0x7a, 0xf0, 0x5d, 0x1f,
123.265 + 0xd2, 0x92, 0x97, 0xe0, 0xaa, 0x59, 0xab, 0xc9,
123.266 + 0x5c, 0xa6, 0x51, 0x1a, 0xe3, 0xd6, 0x06, 0xb9,
123.267 + 0xae, 0xb8, 0x76, 0x36, 0x79, 0x37, 0x52, 0xf6,
123.268 + 0x34, 0xaf, 0x27, 0x19, 0xe1, 0xc0, 0x2b, 0xdd,
123.269 + 0x01, 0x15, 0xcd, 0xce, 0x44, 0xf6, 0x4c, 0x18,
123.270 + 0x92, 0x69, 0xbe, 0x8a, 0x76, 0x23, 0x52, 0x13,
123.271 + 0x3f, 0xf9, 0xe0, 0xf5, 0x06, 0x28, 0x7c, 0xc7,
123.272 + 0xf3, 0x42, 0x0f, 0xdd, 0x40, 0x33, 0xf7, 0x99,
123.273 + 0xe2, 0xad, 0x26, 0xd9, 0x53, 0x10, 0x72, 0x0c,
123.274 + 0x4e, 0x43, 0x4c, 0x61, 0xfe, 0xd9, 0xc1, 0x16,
123.275 + 0xa1, 0x93, 0xca, 0x3c, 0x75, 0x7f, 0x07, 0x7a,
123.276 + 0x65, 0xb3, 0x53, 0x2a, 0x52, 0x00, 0xa0, 0x62,
123.277 + 0xe0, 0xa3, 0x1f, 0xad, 0xd7, 0xbb, 0xc0, 0x83,
123.278 + 0x5d, 0x54, 0x87, 0x5f, 0xc8, 0x2f, 0xc8, 0xbf,
123.279 + 0x69, 0x04, 0x91, 0xc8, 0xa6, 0x1d, 0x4d, 0x46,
123.280 + 0x91, 0xfc, 0x26, 0xf4, 0x16, 0xd1, 0xa4, 0xbf,
123.281 + 0x5c, 0xa2, 0x6c, 0xdd, 0xb4, 0x40, 0xf2, 0x2e,
123.282 + 0xa2, 0xad, 0xf7, 0xf4, 0xa5, 0x8a, 0x3e, 0x23,
123.283 + 0x64, 0x08, 0xc8, 0xa1, 0xa0, 0xf0, 0x5d, 0x70,
123.284 + 0xd2, 0x77, 0xfd, 0xc8, 0x50, 0x83, 0x0f, 0xd6,
123.285 + 0x2b, 0xe4, 0x1f, 0x52, 0x34, 0x33, 0x68, 0xfd,
123.286 + 0x92, 0xbe, 0x9f, 0x97, 0x6b, 0x8d, 0x81, 0x91,
123.287 + 0x0f, 0xef, 0x65, 0xc8, 0x0d, 0x15, 0x01, 0x77,
123.288 + 0x58, 0xb2, 0xf4, 0x1b, 0x06, 0x7e, 0xf5, 0xca,
123.289 + 0x15, 0x2e, 0x38, 0xd8, 0x81, 0x1c, 0x1c, 0xa0,
123.290 + 0xb6, 0x13, 0x6a, 0x2b, 0x71, 0x34, 0x52, 0xd7,
123.291 + 0x1d, 0xbd, 0x37, 0x59, 0xbc, 0x86, 0x25, 0x2b,
123.292 + 0xa8, 0x93, 0xce, 0x1a, 0x03, 0x16, 0xfe, 0x01,
123.293 + 0x57, 0x99, 0x24, 0x25, 0x2c, 0xb3, 0xab, 0x1e,
123.294 + 0x2d, 0x65, 0x20, 0x89, 0x17, 0x02, 0x0e, 0x0a,
123.295 + 0xf5, 0x1e, 0xc7, 0xff, 0x1f, 0x61, 0xa9, 0x54,
123.296 + 0x18, 0xd4, 0xba, 0x50, 0x57, 0x02, 0xa1, 0xab,
123.297 + 0x22, 0x2e, 0x07, 0xea, 0xa9, 0xa3, 0x83, 0x4f,
123.298 + 0x27, 0xf5, 0xc5, 0xee, 0x3c, 0x3b, 0x10, 0xad,
123.299 + 0x32, 0x2b, 0x1c, 0x03, 0xcb, 0xaf, 0x98, 0x83,
123.300 + 0x54, 0xc3, 0x68, 0x63, 0xd4, 0xe0, 0x0e, 0x3c,
123.301 + 0x1a, 0x4e, 0xc0, 0x81, 0xd0, 0xe8, 0x6a, 0x62,
123.302 + 0x6b, 0x3e, 0x6f, 0xc4, 0xc6, 0x33, 0x4e, 0x26,
123.303 + 0x21, 0xf5, 0x04, 0xdf, 0xfa, 0xce, 0x45, 0xaf,
123.304 + 0xdc, 0x5e, 0x1b, 0xad, 0x93, 0xca, 0xf5, 0xcf,
123.305 + 0xd7, 0xee, 0x0c, 0x5c, 0x5e, 0xb4, 0xf0, 0x92,
123.306 + 0xd2, 0xf2, 0xf0, 0xa9, 0x1e, 0xab, 0x80, 0x68,
123.307 + 0x46, 0xef, 0xcc, 0x26, 0x0c, 0x5c, 0xdd, 0x4e,
123.308 + 0x83, 0xb8, 0xb9, 0x53, 0x6e, 0xf8, 0x93, 0x38,
123.309 + 0x67, 0xa4, 0x41, 0x87, 0x72, 0xe7, 0x7e, 0x86,
123.310 + 0xc9, 0x49, 0x00, 0x33, 0xb1, 0x38, 0x6c, 0x71,
123.311 + 0xd7, 0x1d, 0x8e, 0x61, 0x01, 0xb6, 0x57, 0xa9,
123.312 + 0xf1, 0xac, 0x15, 0xc2, 0x83, 0x77, 0xca, 0x64,
123.313 + 0xca, 0x7b, 0x6c, 0xa1, 0x10, 0x1b, 0x13, 0xd0,
123.314 + 0xd3, 0x9e, 0x9e, 0x10, 0x70, 0xc8, 0x1a, 0xbb,
123.315 + 0x3f, 0x19, 0x86, 0xab, 0x01, 0x0e, 0xea, 0x34,
123.316 + 0x22, 0xea, 0xe2, 0x15, 0xb7, 0xed, 0x21, 0x21,
123.317 + 0x75, 0xa5, 0xe7, 0x08, 0xa1, 0x38, 0xe0, 0x91,
123.318 + 0x05, 0x60, 0xea, 0xa7, 0x50, 0x27, 0x18, 0x07,
123.319 + 0x9d, 0xe0, 0x18, 0x2b, 0xd4, 0x07, 0x59, 0x00,
123.320 + 0xe6, 0x45, 0x18, 0x2a, 0x30, 0x6e, 0xf3, 0xb4,
123.321 + 0xd0, 0xef, 0xa6, 0x5b, 0x71, 0xa2, 0x5a, 0x3b,
123.322 + 0x89, 0x4c, 0xaf, 0x3f, 0xcb, 0x9f, 0x03, 0xfb,
123.323 + 0x43, 0x7c, 0x6b, 0xd3, 0x6a, 0xea, 0xce, 0x4a,
123.324 + 0x5f, 0x64, 0xb5, 0x62, 0xda, 0x5d, 0x27, 0xb7,
123.325 + 0xb8, 0x11, 0xca, 0x33, 0x30, 0xec, 0x70, 0xf0,
123.326 + 0x1b, 0x03, 0x50, 0xff, 0x5e, 0xa6, 0x08, 0xde,
123.327 + 0x37, 0x70, 0xc0, 0x81, 0x55, 0x60, 0x17, 0xa1,
123.328 + 0x85, 0xae, 0x26, 0x44, 0xe4, 0x67, 0x3c, 0x91,
123.329 + 0xfd, 0xc4, 0x3d, 0x97, 0x72, 0x23, 0xf3, 0x3c,
123.330 + 0x8f, 0xe0, 0xe2, 0xf2, 0x09, 0x96, 0x10, 0x67,
123.331 + 0xb5, 0xfe, 0xff, 0x3d, 0x4a, 0xc8, 0x62, 0x11,
123.332 + 0xa5, 0x98, 0xc1, 0x2d, 0x40, 0x82, 0x88, 0x8b,
123.333 + 0xe5, 0xb0, 0x75, 0xbf, 0x2f, 0xa8, 0x6a, 0x55,
123.334 + 0x49, 0x2e, 0x9c, 0x29, 0xd2, 0x7c, 0xbf, 0xf3,
123.335 + 0xaa, 0x3a, 0x16, 0x4a, 0xa4, 0x15, 0xf3, 0x48,
123.336 + 0xde, 0x38, 0x13, 0x44, 0x26, 0x02, 0xe6, 0xe9,
123.337 + 0xa8, 0x24, 0x89, 0xb5, 0x43, 0x95, 0xe4, 0x4c,
123.338 + 0xc3, 0xa0, 0xdf, 0xcc, 0x42, 0xf8, 0x8d, 0xb0,
123.339 + 0x3b, 0xea, 0x10, 0xb7, 0xe1, 0x40, 0x54, 0xb9,
123.340 + 0xa3, 0x2d, 0xfb, 0xb4, 0x91, 0xc0, 0x3e, 0x94,
123.341 + 0xf1, 0xa1, 0x3c, 0xbe, 0xef, 0xb8, 0x70, 0x55,
123.342 + 0x0a, 0x26, 0x93, 0xbf, 0xe6, 0x21, 0x92, 0x32,
123.343 + 0x3c, 0x39, 0x27, 0x6a, 0x23, 0x48, 0x02, 0x35,
123.344 + 0x3c, 0xd4, 0xcc, 0x04, 0xc0, 0x4e, 0xa7, 0x02,
123.345 + 0x63, 0x37, 0xc2, 0xb8, 0x56, 0x1d, 0x57, 0x57,
123.346 + 0x42, 0x04, 0x8d, 0xee, 0xcf, 0x8b, 0xc9, 0xc3,
123.347 + 0xba, 0x3b, 0x15, 0xd7, 0xaf, 0xbf, 0x9e, 0xcd,
123.348 + 0x44, 0xcf, 0xf0, 0x00, 0xb7, 0x3a, 0xfc, 0xa8,
123.349 + 0x12, 0xab, 0x3a, 0x62, 0x01, 0x21, 0x46, 0xe9,
123.350 + 0x1e, 0x48, 0x37, 0xfc, 0x13, 0x4d, 0xf6, 0x2a,
123.351 + 0x72, 0x40, 0x75, 0x38, 0x71, 0xf2, 0x17, 0x20,
123.352 + 0x2c, 0xdd, 0xc0, 0x49, 0xbc, 0x63, 0x33, 0xea,
123.353 + 0x06, 0x75, 0x41, 0xe7, 0x5c, 0x1f, 0xfb, 0xf9,
123.354 + 0x68, 0x83, 0xc2, 0x5a, 0x4a, 0x1e, 0x61, 0x08,
123.355 + 0x57, 0xf3, 0x00, 0xba, 0x77, 0x92, 0x63, 0xa5,
123.356 + 0xb7, 0xfe, 0x97, 0x22, 0xda, 0x5e, 0xd3, 0xaf,
123.357 + 0xbc, 0x89, 0x0d, 0x4c, 0x37, 0xa9, 0x27, 0x4a,
123.358 + 0x7f, 0xdb, 0x81, 0x39, 0x11, 0x86, 0x12, 0xf9,
123.359 + 0x10, 0x50, 0xe4, 0xdb, 0x72, 0xf9, 0xae, 0x10,
123.360 + 0x7c, 0xed, 0x50, 0x5c, 0x61, 0xeb, 0x42, 0x1e,
123.361 + 0xa4, 0xf4, 0xf0, 0xfa, 0x45, 0x4d, 0x95, 0x2b,
123.362 + 0xd4, 0x67, 0x4a, 0xe3, 0x8a, 0x15, 0x55, 0x92,
123.363 + 0x77, 0x64, 0x8c, 0x51, 0x38, 0xf9, 0x26, 0x3e,
123.364 + 0x68, 0xe2, 0xac, 0xbb, 0x64, 0x77, 0xe2, 0x82,
123.365 + 0xa4, 0x42, 0x41, 0x38, 0xa0, 0xf0, 0xc9, 0xd8,
123.366 + 0x6c, 0xe0, 0xef, 0x4c, 0xda, 0xb4, 0x92, 0xef,
123.367 + 0x1b, 0xe3, 0x9b, 0xc1, 0x44, 0x3c, 0xb9, 0xb7,
123.368 + 0x39, 0xac, 0x5c, 0x32, 0x39, 0xb4, 0x21, 0x85,
123.369 + 0x93, 0xbc, 0xf2, 0x51, 0x43, 0xb7, 0xae, 0x1e,
123.370 + 0x61, 0x9c, 0x38, 0x9c, 0xaa, 0xff, 0xde, 0xfc,
123.371 + 0xbf, 0x85, 0xef, 0x17, 0x34, 0x36, 0x71, 0x5f,
123.372 + 0x04, 0x16, 0xa6, 0x9e, 0xfd, 0x3a, 0x03, 0xd8,
123.373 + 0xbf, 0x71, 0x70, 0x20, 0x8f, 0x7c, 0xfb, 0xff,
123.374 + 0x61, 0xe0, 0xe2, 0x60, 0xa7, 0xb1, 0xc0, 0xe0,
123.375 + 0xd9, 0x3f, 0xdc, 0x8d, 0x4a, 0xa4, 0x52, 0x61,
123.376 + 0xaf, 0x9d, 0xdf, 0x8a, 0x0d, 0x41, 0xc0, 0x25,
123.377 + 0x68, 0x12, 0x7b, 0xd5, 0xc7, 0xdb, 0x68, 0x70,
123.378 + 0x2d, 0x7d, 0x95, 0x12, 0x03, 0x23, 0x0c, 0xe8,
123.379 + 0x14, 0x41, 0x11, 0x28, 0xec, 0x9d, 0xd3, 0x28,
123.380 + 0x77, 0x7a, 0x3c, 0x93, 0x8e, 0x5c, 0x7e, 0xb3,
123.381 + 0x42, 0x9a, 0x18, 0x25, 0x93, 0xc8, 0xea, 0x43,
123.382 + 0x1b, 0xbe, 0xd5, 0x27, 0xf1, 0xd4, 0xe0, 0x1e,
123.383 + 0xce, 0xc7, 0xc7, 0x2c, 0x25, 0x35, 0x58, 0xb8,
123.384 + 0x6c, 0xf3, 0xa2, 0xad, 0xe7, 0x58, 0x49, 0x47,
123.385 + 0xf7, 0xca, 0xde, 0x8b, 0x81, 0xb7, 0x75, 0xf4,
123.386 + 0x95, 0xa7, 0x5c, 0xc3, 0x2c, 0x0e, 0x1c, 0x52,
123.387 + 0x9a, 0xc3, 0x2a, 0x00, 0x21, 0xa7, 0x51, 0x6b,
123.388 + 0xf0, 0x05, 0x87, 0x8c, 0x42, 0x1b, 0xc3, 0x2e,
123.389 + 0xa3, 0x76, 0x22, 0xd5, 0x7f, 0x56, 0x10, 0xef,
123.390 + 0x98, 0x85, 0x65, 0x86, 0x71, 0x87, 0xd2, 0x8c,
123.391 + 0xc0, 0x47, 0x20, 0xe8, 0xb5, 0x1c, 0xe3, 0xdd,
123.392 + 0x3c, 0x5c, 0x03, 0xbb, 0x0e, 0x97, 0x3b, 0xe1,
123.393 + 0x56, 0x9a, 0xd5, 0x0a, 0x63, 0xd5, 0x33, 0xaf,
123.394 + 0x36, 0xca, 0xcf, 0x8f, 0x00, 0x28, 0xa3, 0x45,
123.395 + 0xb8, 0xcd, 0xde, 0x73, 0xd4, 0xfa, 0x2d, 0x6f,
123.396 + 0xdb, 0x93, 0xaa, 0xdd, 0x7f, 0xd2, 0x22, 0x9c,
123.397 + 0x96, 0x48, 0x1e, 0xa8, 0x63, 0xbe, 0xbc, 0x0d,
123.398 + 0x14, 0x3c, 0x2e, 0x11, 0x1f, 0xd2, 0xf4, 0x57,
123.399 + 0xb3, 0x47, 0xf8, 0xa6, 0x1b, 0xc3, 0xa7, 0x95,
123.400 + 0x2d, 0xd4, 0xca, 0xb8, 0x0d, 0xfb, 0x06, 0x85,
123.401 + 0xda, 0x63, 0xf0, 0x3e, 0x9d, 0x5e, 0xee, 0xce,
123.402 + 0xed, 0x74, 0x1d, 0x2c, 0x97, 0x3f, 0x71, 0x95,
123.403 + 0x12, 0x03, 0xc5, 0x92, 0x46, 0x84, 0x1b, 0x07,
123.404 + 0xe6, 0xb4, 0x1d, 0x3a, 0xf1, 0x89, 0x90, 0x50,
123.405 + 0x10, 0x29, 0x34, 0xc0, 0x90, 0xbe, 0x4a, 0xa9,
123.406 + 0x0d, 0xb0, 0x7b, 0xfb, 0x35, 0xee, 0x4e, 0x34,
123.407 + 0xec, 0x5a, 0x58, 0xbc, 0xb8, 0xda, 0x38, 0x88,
123.408 + 0x8c, 0x74, 0x1e, 0xc9, 0xab, 0x78, 0x2e, 0x2a,
123.409 + 0x17, 0x8a, 0x43, 0x3d, 0xa1, 0x2a, 0x41, 0xb5,
123.410 + 0xd6, 0xe8, 0x5b, 0xc5, 0x4a, 0x1c, 0x3c, 0x9f,
123.411 + 0x8d, 0x3a, 0x69, 0x88, 0xf8, 0x80, 0xd2, 0x11,
123.412 + 0xfc, 0x7e, 0x80, 0x8e, 0x7f, 0x85, 0x64, 0x9c,
123.413 + 0x46, 0x58, 0xc8, 0x48, 0x98, 0x4b, 0xf5, 0x73,
123.414 + 0x3f, 0x49, 0xce, 0x53, 0x2c, 0xd5, 0xfc, 0x33,
123.415 + 0xf1, 0x6f, 0xd8, 0xe9, 0x2e, 0x70, 0x2e, 0xdc,
123.416 + 0xe5, 0x43, 0x80, 0x38, 0xf2, 0x87, 0xed, 0x85,
123.417 + 0xe4, 0x3e, 0x45, 0x14, 0x20, 0xcf, 0xa0, 0x61,
123.418 + 0x4f, 0xe8, 0xd7, 0x5b, 0xb3, 0x0d, 0x0e, 0x4e,
123.419 + 0x4d, 0xce, 0xbe, 0xba, 0xaa, 0x90, 0x09, 0xcb,
123.420 + 0x4b, 0x5d, 0x08, 0xff, 0x52, 0xd5, 0x23, 0xbc,
123.421 + 0xad, 0x8d, 0xd3, 0x06, 0x4a, 0xa0, 0x51, 0x56,
123.422 + 0xa7, 0xd8, 0x33, 0xab, 0xbc, 0xd0, 0xdf, 0x92,
123.423 + 0x87, 0x20, 0x2d, 0x7b, 0x5e, 0xfa, 0x30, 0xa7,
123.424 + 0x06, 0x06, 0xe5, 0x4f, 0x2c, 0xb5, 0x61, 0xd7,
123.425 + 0x54, 0xd3, 0xdf, 0xd0, 0x0a, 0xb0, 0x06, 0xce,
123.426 + 0xf6, 0x86, 0xb7, 0x8e, 0xaa, 0x7b, 0x78, 0xd5,
123.427 + 0xb9, 0xeb, 0x07, 0xac, 0x5f, 0xc5, 0xd2, 0x8c,
123.428 + 0x40, 0xe0, 0x7f, 0x98, 0xd4, 0xe5, 0x4b, 0xca,
123.429 + 0xfb, 0x47, 0xef, 0xef, 0xb9, 0x4d, 0x6d, 0x8f,
123.430 + 0x82, 0x68, 0x74, 0x84, 0xe0, 0x0a, 0x93, 0x0f,
123.431 + 0xb2, 0x01, 0xa9, 0x9f, 0x68, 0x6a, 0xe8, 0xf7,
123.432 + 0xfb, 0x0b, 0xde, 0x17, 0xe0, 0x30, 0x38, 0x51,
123.433 + 0xbc, 0x07, 0xb8, 0x2c, 0x91, 0x0f, 0xc1, 0x0e,
123.434 + 0xa6, 0xf9, 0xf0, 0xd5, 0x48, 0x76, 0x8a, 0xde,
123.435 + 0x74, 0xe3, 0x30, 0x65, 0x56, 0xb3, 0x5c, 0xe2,
123.436 + 0x89, 0x8d, 0xda, 0x80, 0xad, 0x0f, 0x22, 0xfb,
123.437 + 0x24, 0x1d, 0x16, 0xdd, 0x34, 0x4b, 0x90, 0x58,
123.438 + 0x4e, 0x0c, 0x13, 0x28, 0xcf, 0x1d, 0xa4, 0xaa,
123.439 + 0xb7, 0xf3, 0xb1, 0x66, 0xad, 0x3b, 0xcf, 0x79,
123.440 + 0x12, 0x04, 0xd7, 0x79, 0xd9, 0x5f, 0xdf, 0x89,
123.441 + 0xb2, 0x5b, 0xa7, 0x9a, 0x26, 0x1e, 0x67, 0x46,
123.442 + 0x7c, 0x66, 0x95, 0x67, 0xe6, 0x45, 0x8b, 0x1f,
123.443 + 0x65, 0x79, 0x9f, 0x6d, 0x11, 0x81, 0x17, 0x0d,
123.444 + 0x11, 0xb0, 0x5c, 0xb4, 0xc7, 0x27, 0x87, 0xab,
123.445 + 0x5d, 0x0a, 0x18, 0xae, 0x4e, 0x06, 0xa3, 0x3d,
123.446 + 0xc7, 0xb0, 0x22, 0xba, 0x03, 0xa4, 0x0f, 0xe5,
123.447 + 0x1c, 0x72, 0x2a, 0x04, 0xce, 0x83, 0xe9, 0xf3,
123.448 + 0xd7, 0xc9, 0x67, 0x6c, 0x1e, 0x6b, 0x3c, 0x9b,
123.449 + 0x0b, 0x5e, 0x6a, 0xa6, 0x79, 0x0a, 0xf1, 0xbe,
123.450 + 0xd7, 0xb4, 0x6f, 0x45, 0x1e, 0xfb, 0x78, 0x97,
123.451 + 0xaf, 0x34, 0x76, 0x95, 0x52, 0xf7, 0x3d, 0x5d,
123.452 + 0x07, 0x28, 0x57, 0x9c, 0x4a, 0x0f, 0xcf, 0x0b,
123.453 + 0x1b, 0xc4, 0xc2, 0x72, 0xd7, 0x72, 0x38, 0x9b,
123.454 + 0xea, 0xeb, 0xee, 0xae, 0x34, 0xc8, 0x01, 0xd7,
123.455 + 0xa5, 0xe3, 0xce, 0x41, 0xad, 0x02, 0x60, 0x23,
123.456 + 0x18, 0x36, 0xba, 0x17, 0xfa, 0xcf, 0xe4, 0xda,
123.457 + 0xdc, 0xfc, 0x82, 0xdc, 0x7c, 0x11, 0xf4, 0xb8,
123.458 + 0x52, 0x5d, 0xf7, 0x2f, 0xc8, 0xfe, 0x4a, 0xe6,
123.459 + 0xb9, 0xaf, 0x4b, 0x17, 0x18, 0x91, 0xc2, 0xfe,
123.460 + 0xd7, 0x3a, 0x77, 0x0c, 0xa0, 0x43, 0x9c, 0x6f,
123.461 + 0x13, 0x06, 0xbe, 0x6e, 0xe0, 0x1a, 0x3c, 0xf3,
123.462 + 0xf5, 0xcc, 0x78, 0xfb, 0x5d, 0xd5, 0xda, 0xb7,
123.463 + 0x58, 0xea, 0x86, 0x42, 0x6b, 0x32, 0xff, 0xb2,
123.464 + 0xe2, 0xee, 0x03, 0x1f, 0xf4, 0xef, 0xdb, 0x53,
123.465 + 0x79, 0xd5, 0x4e, 0xaf, 0x60, 0x8e, 0x02, 0xc2,
123.466 + 0xcc, 0x39, 0x97, 0x7b, 0xfd, 0xa1, 0xf8, 0x7a,
123.467 + 0x26, 0xe8, 0x55, 0xd6, 0xa4, 0x8b, 0xa0, 0x1b,
123.468 + 0x2d, 0x63, 0xaa, 0x73, 0x71, 0x6e, 0xbf, 0x8b,
123.469 + 0x3b, 0xe3, 0x1b, 0x0d, 0xbb, 0x2e, 0x44, 0x09,
123.470 + 0x64, 0xac, 0xc7, 0x9e, 0xb5, 0xc6, 0x77, 0xb0,
123.471 + 0x79, 0xb3, 0xaa, 0xfc, 0x67, 0x57, 0x9a, 0x50,
123.472 + 0x81, 0x37, 0x14, 0x7c, 0xd7, 0xa0, 0xd4, 0x6a,
123.473 + 0x79, 0x84, 0x51, 0x0e, 0x95, 0x0a, 0x30, 0xa3,
123.474 + 0x60, 0x55, 0x48, 0x05, 0x16, 0xae, 0x43, 0x90,
123.475 + 0xdc, 0x8e, 0x09, 0xbe, 0x79, 0xf6, 0x90, 0x74,
123.476 + 0xf8, 0x20, 0x96, 0x4d, 0xa7, 0xf5, 0x1a, 0x2b,
123.477 + 0xc7, 0x15, 0x9d, 0x18, 0xf7, 0x94, 0x87, 0xf7,
123.478 + 0xf4, 0xfb, 0x0d, 0x61, 0xb6, 0xd7, 0xbe, 0x10,
123.479 + 0x8e, 0x47, 0x3c, 0x10, 0x44, 0x90, 0x52, 0x21,
123.480 + 0x83, 0xc0, 0xf5, 0x99, 0xaa, 0xbc, 0xf6, 0x55,
123.481 + 0xae, 0xf5, 0xb2, 0xa4, 0xcd, 0x4d, 0xb9, 0x38,
123.482 + 0x6c, 0xbc, 0x80, 0xc3, 0xad, 0xf4, 0x46, 0x31,
123.483 + 0x01, 0x58, 0x2d, 0x88, 0x57, 0xc3, 0x23, 0xd1,
123.484 + 0x64, 0xc9, 0xa3, 0x21, 0x6b, 0x8b, 0x8a, 0x23,
123.485 + 0x2c, 0x4f, 0xa9, 0xcd, 0x67, 0xfa, 0x77, 0xad,
123.486 + 0xa3, 0x16, 0xa2, 0xe5, 0x19, 0x14, 0x70, 0x41,
123.487 + 0x5b, 0xda, 0x14, 0xde, 0xe3, 0xe5, 0xc1, 0x15,
123.488 + 0xb4, 0x77, 0xa4, 0x9b, 0xb8, 0xb1, 0x28, 0x51,
123.489 + 0x30, 0xb4, 0xf1, 0xf3, 0xf8, 0x6d, 0xd0, 0xc3,
123.490 + 0x8c, 0x4c, 0x76, 0xb0, 0x9a, 0xdf, 0xc8, 0xbe,
123.491 + 0xf8, 0x4a, 0x61, 0x6e, 0x3e, 0xd6, 0x3c, 0xe8,
123.492 + 0xde, 0x56, 0xa0, 0x9c, 0x25, 0xbe, 0xce, 0x93,
123.493 + 0x1f, 0x88, 0xfb, 0x9a, 0x1a, 0xe2, 0xff, 0x88,
123.494 + 0xad, 0x10, 0xcb, 0x6c, 0xd6, 0xe7, 0x39, 0x0b,
123.495 + 0xe5, 0x1a, 0x06, 0x05, 0x64, 0x5b, 0x0a, 0xdf,
123.496 + 0x22, 0x58, 0xd7, 0xfb, 0x88, 0x12, 0xdd, 0xb7,
123.497 + 0x52, 0x3a, 0xc9, 0xbf, 0x49, 0xdf, 0x8c, 0x87,
123.498 + 0x9f, 0x84, 0xb5, 0x0a, 0xf6, 0x00, 0x52, 0xae,
123.499 + 0x67, 0x12, 0x1a, 0x8c, 0x71, 0x15, 0xf5, 0xa1,
123.500 + 0x13, 0x39, 0xf0, 0x91, 0x7e, 0x88, 0x7c, 0xb3,
123.501 + 0x95, 0x50, 0x02, 0xa6, 0x63, 0xb5, 0x64, 0xfb,
123.502 + 0x90, 0x87, 0x61, 0xe2, 0x27, 0xaf, 0x11, 0x0c,
123.503 + 0x73, 0x83, 0xef, 0xa9, 0x28, 0xfe, 0xc8, 0x85,
123.504 + 0x1a, 0x3a, 0xde, 0xf2, 0xe5, 0x25, 0x64, 0x6d,
123.505 + 0xaa, 0x41, 0x4c, 0x80, 0x2e, 0x84, 0xff, 0xc1,
123.506 + 0xc0, 0x54, 0x0c, 0x29, 0x1b, 0xa3, 0x07, 0x7c,
123.507 + 0x33, 0x4c, 0x10, 0xf6, 0x6f, 0x79, 0xdf, 0xd3,
123.508 + 0xf0, 0x24, 0x57, 0xf1, 0x60, 0xe1, 0xf0, 0xbd,
123.509 + 0xc4, 0x1f, 0xf4, 0x67, 0xd2, 0xd3, 0xcc, 0x6a,
123.510 + 0x07, 0x72, 0x44, 0x16, 0x85, 0x46, 0xd0, 0x73,
123.511 + 0x87, 0xa9, 0xc7, 0x2f, 0xd1, 0xf5, 0xec, 0xe3,
123.512 + 0x28, 0xa3, 0x93, 0x4f, 0xd7, 0x76, 0xc1, 0x3c,
123.513 + 0x0d, 0x13, 0x33, 0xcf, 0x5b, 0xbd, 0x6a, 0x52,
123.514 + 0x4e, 0xee, 0xc8, 0x5e, 0xa1, 0x58, 0x4a, 0x08,
123.515 + 0x81, 0xd9, 0x23, 0xcc, 0xfb, 0x1c, 0xb2, 0xd8,
123.516 + 0xa3, 0xe4, 0x53, 0xfe, 0xf4, 0x4b, 0x48, 0xc1,
123.517 + 0x20, 0xa4, 0x97, 0xf8, 0x38, 0xa3, 0x69, 0xc1,
123.518 + 0x11, 0xf0, 0xa1, 0x3b, 0xa9, 0x9a, 0x12, 0x61,
123.519 + 0xe8, 0x8d, 0x99, 0x44, 0x3f, 0x94, 0x72, 0x82,
123.520 + 0x19, 0x96, 0x62, 0xb0, 0xa6, 0x64, 0x05, 0x19,
123.521 + 0x8f, 0xd6, 0x5d, 0x05, 0xbf, 0x79, 0x9e, 0x9d,
123.522 + 0xe4, 0x93, 0x4c, 0xad, 0x61, 0x8c, 0x18, 0xda,
123.523 + 0xb6, 0x2e, 0xb3, 0xca, 0x14, 0x4d, 0x53, 0xa4,
123.524 + 0x97, 0x27, 0x10, 0x56, 0xa2, 0x67, 0x5a, 0x5a,
123.525 + 0x5e, 0x13, 0xc0, 0xdb, 0xa7, 0x9f, 0x45, 0x5b,
123.526 + 0xeb, 0x1a, 0x14, 0x0c, 0x8c, 0x38, 0x5e, 0x77,
123.527 + 0x9a, 0xec, 0x75, 0x68, 0x93, 0x65, 0x02, 0x9c,
123.528 + 0xfb, 0x62, 0x60, 0x49, 0xdd, 0xb2, 0x2a, 0x67,
123.529 + 0x86, 0xe3, 0x8a, 0x7d, 0x8c, 0x46, 0x78, 0x81,
123.530 + 0x60, 0x69, 0xf2, 0x3f, 0x74, 0x11, 0x35, 0xff,
123.531 + 0x77, 0xa3, 0x66, 0x20, 0xfc, 0x98, 0x4a, 0x35,
123.532 + 0x7a, 0x52, 0xe4, 0x90, 0x13, 0x80, 0xb9, 0xa6,
123.533 + 0x73, 0x7a, 0x7d, 0x66, 0x6e, 0x6b, 0xb6, 0x43,
123.534 + 0x10, 0xd5, 0x91, 0x2b, 0x66, 0xdd, 0x89, 0x87,
123.535 + 0xe3, 0x8c, 0x58, 0x53, 0x2f, 0x40, 0x74, 0x45,
123.536 + 0x1b, 0x77, 0x7a, 0xa4, 0x44, 0x19, 0x78, 0xba,
123.537 + 0x87, 0x10, 0x41, 0x31, 0x32, 0x5f, 0x87, 0x68,
123.538 + 0xde, 0x43, 0x4a, 0xef, 0x33, 0xb3, 0x11, 0x83,
123.539 + 0xa9, 0xc2, 0x6f, 0x8d, 0x34, 0xe2, 0x95, 0x84,
123.540 + 0x3a, 0x4f, 0x6f, 0x8c, 0x31, 0x1d, 0xb6, 0xf5,
123.541 + 0x95, 0x0d, 0x01, 0x11, 0x20, 0xdf, 0x72, 0xf3,
123.542 + 0x3f, 0x9a, 0x33, 0xaa, 0xb1, 0x06, 0x6a, 0x63,
123.543 + 0x47, 0x91, 0x01, 0xdf, 0xb3, 0x54, 0x36, 0xfd,
123.544 + 0x06, 0x2d, 0xb8, 0x08, 0xe3, 0xd3, 0x65, 0xac,
123.545 + 0x66, 0x03, 0xee, 0xa4, 0x63, 0xbd, 0xd4, 0xce,
123.546 + 0xbd, 0x79, 0xa7, 0x48, 0x38, 0xc5, 0x7d, 0xb5,
123.547 + 0x71, 0x9a, 0x3c, 0x11, 0x7c, 0x6c, 0xe2, 0x54,
123.548 + 0x02, 0x5d, 0x42, 0xab, 0x25, 0x93, 0x66, 0x01,
123.549 + 0x37, 0x78, 0x35, 0x4a, 0x8c, 0x19, 0x4d, 0x00,
123.550 + 0x75, 0x4f, 0xcc, 0xc0, 0x26, 0x82, 0xc1, 0x35,
123.551 + 0x8c, 0xc7, 0xc2, 0x59, 0x01, 0x3e, 0x98, 0x22,
123.552 + 0x88, 0x9c, 0x90, 0x75, 0x05, 0x33, 0x07, 0xb9,
123.553 + 0x39, 0x81, 0x38, 0x58, 0x10, 0x29, 0xcf, 0xc8,
123.554 + 0x98, 0xb2, 0x03, 0xd7, 0x5b, 0xb3, 0x18, 0xba,
123.555 + 0x34, 0x0c, 0x9f, 0xab, 0xd7, 0xed, 0x29, 0x82,
123.556 + 0x41, 0xe0, 0x20, 0x97, 0x57, 0x92, 0xb2, 0xb8,
123.557 + 0x10, 0x2d, 0x0b, 0xa2, 0xc5, 0x8f, 0x90, 0x6f,
123.558 + 0xed, 0x12, 0x56, 0x25, 0xbe, 0xfd, 0x75, 0xf7,
123.559 + 0xb6, 0xf8, 0x40, 0x67, 0x39, 0x11, 0xfa, 0x15,
123.560 + 0xae, 0x6a, 0x54, 0x5f, 0x32, 0x2b, 0xf8, 0x48,
123.561 + 0x55, 0xbe, 0x86, 0x2f, 0x69, 0x48, 0x5b, 0x5d,
123.562 + 0x4d, 0xb7, 0x35, 0xaa, 0xb6, 0x91, 0x88, 0x19,
123.563 + 0x96, 0x1c, 0x68, 0xf6, 0x85, 0x9e, 0xb3, 0xb2,
123.564 + 0xa3, 0x32, 0xd4, 0x52, 0x70, 0xb7, 0x62, 0xe3,
123.565 + 0x14, 0xb6, 0x78, 0x5f, 0x1b, 0x1d, 0x04, 0x9c,
123.566 + 0x26, 0x0c, 0x33, 0x94, 0xb1, 0x97, 0x08, 0xdb,
123.567 + 0x0b, 0x39, 0x29, 0xd4, 0xbc, 0x6d, 0xdf, 0x02,
123.568 + 0xc6, 0x99, 0xab, 0x99, 0x32, 0xe5, 0xce, 0x51,
123.569 + 0x4f, 0xae, 0xb8, 0x8b, 0xe0, 0xaf, 0x07, 0xc4,
123.570 + 0xf9, 0x41, 0x7c, 0x59, 0xa0, 0xac, 0x74, 0x4d,
123.571 + 0x7e, 0x43, 0x77, 0x9c, 0x06, 0x49, 0x79, 0x8a,
123.572 + 0x14, 0x73, 0x93, 0xa8, 0x5b, 0x1b, 0x34, 0x29,
123.573 + 0x78, 0x04, 0x2f, 0xd7, 0x1f, 0x13, 0x90, 0xe0,
123.574 + 0xdd, 0x3b, 0x42, 0x6b, 0x79, 0x6e, 0x52, 0xc7,
123.575 + 0x0f, 0x38, 0xda, 0x01, 0x2c, 0x8d, 0xe6, 0x94,
123.576 + 0x5d, 0x59, 0x27, 0x1d, 0x10, 0x4e, 0x11, 0x36,
123.577 + 0xfb, 0x53, 0x16, 0x05, 0x25, 0xf2, 0x64, 0xd8,
123.578 + 0xf9, 0xcd, 0x5c, 0xfe, 0xb4, 0x18, 0x44, 0x80,
123.579 + 0x10, 0xbc, 0x3d, 0xf3, 0x1d, 0x5a, 0xf0, 0xc1,
123.580 + 0xc3, 0x55, 0xff, 0x41, 0x3e, 0xe3, 0xef, 0x44,
123.581 + 0xb2, 0xc0, 0x01, 0x18, 0xa2, 0x49, 0x88, 0x78,
123.582 + 0x0d, 0x4c, 0xc8, 0x73, 0xcf, 0x30, 0x85, 0x3a,
123.583 + 0x88, 0x90, 0x01, 0xcf, 0x69, 0x53, 0xa3, 0x18,
123.584 + 0x3f, 0xd6, 0xe7, 0x94, 0x14, 0xa7, 0xae, 0xcd,
123.585 + 0x6f, 0x11, 0x72, 0xfe, 0x2b, 0xb0, 0x81, 0x53,
123.586 + 0xea, 0x67, 0xd6, 0xe4, 0xca, 0x42, 0xa0, 0xf9,
123.587 + 0xb1, 0xd4, 0xb5, 0x3b, 0xc9, 0xf0, 0x36, 0xc1,
123.588 + 0x1c, 0xf4, 0xb1, 0xf6, 0x84, 0xd0, 0x86, 0x6c,
123.589 + 0x76, 0x9a, 0x03, 0xc2, 0xb6, 0x2e, 0x9a, 0x46,
123.590 + 0xf5, 0x5f, 0x2c, 0x38, 0xac, 0xad, 0x6f, 0x2e,
123.591 + 0x7a, 0x18, 0x2d, 0x22, 0x95, 0x5e, 0x5e, 0xc9,
123.592 + 0x7a, 0x0a, 0x56, 0xe1, 0xc7, 0x15, 0xfd, 0xbf,
123.593 + 0xff, 0xf7, 0x7e, 0x85, 0x20, 0xa9, 0x8a, 0x9c,
123.594 + 0xa9, 0x7d, 0xe8, 0xed, 0xfc, 0x7f, 0xbb, 0xf0,
123.595 + 0x05, 0x3f, 0xce, 0x4f, 0x4c, 0xee, 0xa4, 0xa0,
123.596 + 0xcc, 0x9c, 0x62, 0x1e, 0xd6, 0xd0, 0x30, 0x37,
123.597 + 0xb8, 0x98, 0x56, 0x1d, 0xaa, 0xd6, 0x5e, 0x73,
123.598 + 0x12, 0xe4, 0x88, 0x82, 0x48, 0x64, 0x06, 0xd7,
123.599 + 0x2a, 0x31, 0x50, 0x7b, 0x10, 0x17, 0xb8, 0x4c,
123.600 + 0x5a, 0x8d, 0xf1, 0xfc, 0xf1, 0x33, 0x3b, 0x98,
123.601 + 0x42, 0x18, 0x5b, 0x35, 0x78, 0xca, 0x8e, 0x41,
123.602 + 0x52, 0xae, 0x6d, 0xe1, 0xa2, 0x9d, 0x5b, 0xbd,
123.603 + 0xf3, 0x5f, 0x49, 0xc1, 0x27, 0x06, 0xc1, 0xaf,
123.604 + 0xc0, 0xa3, 0x9d, 0xf3, 0x1c, 0x8e, 0x90, 0x8a,
123.605 + 0xb0, 0x69, 0xb0, 0xc5, 0x11, 0x0c, 0x91, 0x14,
123.606 + 0x1f, 0x5e, 0x10, 0xe1, 0x1d, 0x14, 0x30, 0x54,
123.607 + 0x1e, 0x17, 0x3d, 0x31, 0x7b, 0xbf, 0x2f, 0x9d,
123.608 + 0x6d, 0x63, 0x32, 0xf0, 0x9d, 0x9f, 0x95, 0x3d,
123.609 + 0x0b, 0xd2, 0x4d, 0x10, 0xe2, 0x3f, 0x67, 0x69,
123.610 + 0x43, 0x9a, 0x4a, 0x2c, 0x54, 0x71, 0xa8, 0xa0,
123.611 + 0x9e, 0x9f, 0x10, 0xaf, 0x1b, 0xce, 0x99, 0xe3,
123.612 + 0x25, 0x32, 0x10, 0x54, 0x80, 0xfe, 0xda, 0x57,
123.613 + 0xd0, 0xb2, 0x92, 0x7f, 0xbb, 0x5f, 0xe7, 0x4d,
123.614 + 0x1b, 0x3d, 0x46, 0x4d, 0xe4, 0x4c, 0xd6, 0xaf,
123.615 + 0x1a, 0x32, 0x12, 0x40, 0xb8, 0x84, 0x8e, 0xe4,
123.616 + 0x80, 0xce, 0x7e, 0xc1, 0x13, 0x8b, 0xb0, 0xb7,
123.617 + 0x6f, 0x24, 0xba, 0x85, 0x50, 0x83, 0xc3, 0xcf,
123.618 + 0x19, 0xb3, 0xf0, 0xc7, 0xee, 0x68, 0xbe, 0x9e,
123.619 + 0x6d, 0xb9, 0xfb, 0xd5, 0x29, 0xce, 0x82, 0xcd,
123.620 + 0x69, 0x16, 0x68, 0x6b, 0x6a, 0xf4, 0x02, 0x32,
123.621 + 0xce, 0x60, 0x37, 0x0c, 0xb9, 0x38, 0x92, 0x9c,
123.622 + 0x42, 0xa9, 0x0b, 0x53, 0x96, 0xfe, 0x39, 0xc1,
123.623 + 0x24, 0x65, 0x9b, 0xcd, 0xe7, 0x8d, 0x36, 0x07,
123.624 + 0x9f, 0x1d, 0x35, 0x8e, 0xdc, 0x4c, 0xb5, 0x68,
123.625 + 0xc5, 0xfd, 0x44, 0x19, 0xf2, 0x6c, 0x59, 0x1c,
123.626 + 0xb1, 0x0b, 0x35, 0x48, 0x86, 0x1a, 0x05, 0x22,
123.627 + 0x03, 0x0c, 0x0c, 0xa2, 0x92, 0x90, 0x35, 0xfb,
123.628 + 0x37, 0x94, 0xc7, 0x15, 0x84, 0xae, 0xe8, 0x05,
123.629 + 0xa0, 0xf7, 0x30, 0x11, 0x5c, 0xe4, 0x5d, 0x3e,
123.630 + 0x12, 0x54, 0x80, 0x54, 0x6b, 0x09, 0x8c, 0xce,
123.631 + 0x80, 0x5e, 0xa7, 0xc8, 0x6a, 0x0c, 0x56, 0xe1,
123.632 + 0x18, 0x7d, 0xc9, 0x39, 0xc1, 0xef, 0xe3, 0x25,
123.633 + 0xa0, 0x8b, 0x2f, 0x60, 0x3a, 0x43, 0x39, 0xa6,
123.634 + 0x28, 0x28, 0x7b, 0x4c, 0x77, 0xd4, 0x49, 0x61,
123.635 + 0x46, 0xe9, 0x1b, 0x45, 0xd6, 0xb1, 0x56, 0xe1,
123.636 + 0x7d, 0x34, 0xcd, 0x06, 0xb6, 0x67, 0x8d, 0x7d,
123.637 + 0x7a, 0xe2, 0xbe, 0x68, 0x35, 0xa6, 0x78, 0xe5,
123.638 + 0x47, 0x48, 0xb7, 0xc7, 0xde, 0xcd, 0xc9, 0x05,
123.639 + 0xb4, 0xe7, 0x50, 0x48, 0xe1, 0x4b, 0xfe, 0x76,
123.640 + 0x77, 0xc6, 0xf7, 0x5f, 0xcb, 0xc2, 0xa8, 0xd7,
123.641 + 0xd6, 0x8a, 0xe5, 0x49, 0xd9, 0xca, 0x45, 0xf4,
123.642 + 0xda, 0xcd, 0x33, 0xd1, 0x59, 0x2d, 0x9e, 0xc1,
123.643 + 0x5c, 0xe6, 0x01, 0x18, 0xb8, 0xf0, 0x5e, 0xb1,
123.644 + 0x69, 0x95, 0x2f, 0x02, 0x2a, 0xe7, 0x4a, 0xd7,
123.645 + 0xd1, 0xc3, 0xd5, 0x6f, 0x15, 0xc8, 0xdc, 0x29,
123.646 + 0xde, 0xb9, 0x3f, 0x8b, 0xa6, 0xbc, 0xdd, 0x25,
123.647 + 0x84, 0x35, 0x3c, 0x90, 0x2d, 0xc2, 0x1e, 0x98,
123.648 + 0x8a, 0x50, 0x09, 0x77, 0x42, 0xe9, 0x35, 0x8a,
123.649 + 0x7c, 0x97, 0xbf, 0xe8, 0xbf, 0x56, 0xd0, 0x8b,
123.650 + 0x65, 0xd3, 0xaf, 0x1e, 0x05, 0x94, 0xfa, 0xac,
123.651 + 0xa8, 0x2b, 0x28, 0xcb, 0x37, 0x3e, 0xe8, 0xbb,
123.652 + 0x66, 0x3a, 0xed, 0xb2, 0x48, 0x10, 0x0f, 0x3a,
123.653 + 0x5a, 0xc5, 0xdb, 0x26, 0x0e, 0xaa, 0x5e, 0x69,
123.654 + 0x15, 0xd6, 0x81, 0xae, 0xbd, 0xe6, 0x03, 0xf1,
123.655 + 0xf6, 0x37, 0xc8, 0xde, 0x70, 0x1f, 0x64, 0xb9,
123.656 + 0x5e, 0xbf, 0x2e, 0x4f, 0xb1, 0xea, 0xa0, 0x17,
123.657 + 0xe6, 0x7c, 0xf9, 0x2f, 0x1e, 0xd8, 0x58, 0xde,
123.658 + 0xa7, 0xf0, 0x46, 0x52, 0x95, 0xdf, 0xa4, 0x96,
123.659 + 0xd0, 0xc4, 0x97, 0x2b, 0x95, 0xcd, 0x5e, 0x40,
123.660 + 0x23, 0x5c, 0x10, 0xee, 0xba, 0x72, 0x9b, 0xcf,
123.661 + 0x0b, 0xe8, 0x18, 0x3a, 0x70, 0xd2, 0x5e, 0x07,
123.662 + 0x68, 0x93, 0xef, 0x4a, 0x5b, 0x8d, 0x72, 0x41,
123.663 + 0x4e, 0xea, 0x33, 0x6a, 0x0a, 0x5e, 0xfb, 0x02,
123.664 + 0x3f, 0xd4, 0xed, 0x5b, 0xe0, 0x42, 0x84, 0xd4,
123.665 + 0xaa, 0x85, 0xdc, 0x5b, 0x67, 0xee, 0x71, 0x67,
123.666 + 0xba, 0x8e, 0xd2, 0xbe, 0x61, 0xdf, 0x5a, 0x26,
123.667 + 0xb9, 0xf0, 0x77, 0x81, 0x53, 0x24, 0x16, 0xcb,
123.668 + 0x8c, 0xb8, 0x06, 0x6e, 0x68, 0xda, 0xc8, 0x2d,
123.669 + 0x17, 0x54, 0xdb, 0x46, 0xcb, 0xfd, 0x1f, 0x3d,
123.670 + 0x94, 0x81, 0x09, 0x4b, 0xfa, 0xb1, 0x46, 0xd9,
123.671 + 0x11, 0xa3, 0xb7, 0x31, 0x9c, 0xd2, 0x38, 0xd6,
123.672 + 0xba, 0x3d, 0xa3, 0x74, 0xd8, 0xf1, 0x24, 0xe8,
123.673 + 0x9c, 0xcb, 0x1d, 0xf9, 0x4a, 0xf7, 0xc8, 0x4b,
123.674 + 0xfe, 0x97, 0x7c, 0xa1, 0x02, 0xeb, 0x40, 0xc3,
123.675 + 0x89, 0x71, 0x01, 0xcd, 0x33, 0x2a, 0xc2, 0x82,
123.676 + 0xce, 0x62, 0x8d, 0x53, 0x7c, 0xdf, 0xce, 0xd7,
123.677 + 0xf5, 0xa8, 0x4f, 0xf2, 0xf2, 0x2e, 0xc1, 0xeb,
123.678 + 0x97, 0x99, 0x37, 0x3c, 0x53, 0xa6, 0xb4, 0x46,
123.679 + 0x05, 0x64, 0x92, 0x87, 0x08, 0x3c, 0x23, 0x4b,
123.680 + 0x9d, 0x67, 0x18, 0xf9, 0xe2, 0x0b, 0x1c, 0x39,
123.681 + 0xd3, 0x87, 0x70, 0xc0, 0xb9, 0x1e, 0x52, 0x0a,
123.682 + 0x0f, 0x48, 0xe2, 0xe7, 0x51, 0x72, 0x94, 0xf7,
123.683 + 0xa3, 0xdc, 0xe5, 0x66, 0x33, 0x39, 0x54, 0x06,
123.684 + 0x55, 0x93, 0x30, 0xf9, 0x5e, 0x76, 0x8f, 0xe0,
123.685 + 0x59, 0x4d, 0x0d, 0xa7, 0xf5, 0xbe, 0xdb, 0x20,
123.686 + 0xad, 0x0d, 0x76, 0x88, 0x5f, 0x9c, 0x7c, 0x75,
123.687 + 0x2f, 0x2a, 0x0b, 0x79, 0x6e, 0xd3, 0xe2, 0x66,
123.688 + 0xf5, 0x4a, 0x2d, 0x87, 0x87, 0x49, 0x84, 0x17,
123.689 + 0xa2, 0x62, 0x4c, 0xbb, 0xe4, 0x6e, 0x98, 0x10,
123.690 + 0xc9, 0xfb, 0x8a, 0x04, 0x68, 0x8d, 0x22, 0x66,
123.691 + 0xad, 0xea, 0x2a, 0xc9, 0x97, 0x2d, 0x3c, 0xbc,
123.692 + 0xd0, 0x77, 0x5f, 0xe6, 0xb8, 0x7f, 0xe6, 0xf6,
123.693 + 0x39, 0xbf, 0x56, 0x0e, 0x26, 0x6d, 0xc5, 0x3e,
123.694 + 0x53, 0x19, 0xd6, 0xb4, 0x57, 0x36, 0xa3, 0xc6,
123.695 + 0xd3, 0x3d, 0x66, 0x79, 0x30, 0x5c, 0x14, 0x0c,
123.696 + 0x0f, 0x3e, 0x96, 0xae, 0x90, 0x97, 0xab, 0x0d,
123.697 + 0x9f, 0xc3, 0xe7, 0x66, 0x3e, 0xe0, 0x31, 0x43,
123.698 + 0x4b, 0x01, 0xb3, 0x0e, 0x9e, 0x8c, 0x82, 0x4a,
123.699 + 0x8c, 0xc7, 0x79, 0x85, 0xdf, 0x75, 0x0d, 0xb4,
123.700 + 0x2b, 0x03, 0x14, 0xef, 0x72, 0x58, 0xfd, 0x64,
123.701 + 0xc8, 0xe3, 0x0d, 0x9a, 0x14, 0x6f, 0x76, 0xf9,
123.702 + 0x46, 0xd1, 0xd2, 0x81, 0xb3, 0x16, 0x6e, 0xc7,
123.703 + 0x76, 0x82, 0xce, 0xf4, 0xee, 0x33, 0x00, 0xe6,
123.704 + 0x77, 0xc4, 0xad, 0x4f, 0x06, 0xa7, 0x48, 0x80,
123.705 + 0x9e, 0x21, 0x66, 0xca, 0x75, 0x69, 0x57, 0xcb,
123.706 + 0xf0, 0x67, 0x6a, 0xaa, 0x8f, 0x88, 0x14, 0xbd,
123.707 + 0x65, 0x62, 0xe2, 0xad, 0xcc, 0x22, 0x88, 0x7b,
123.708 + 0x94, 0xbd, 0x0e, 0xcd, 0xb6, 0x69, 0xa2, 0xcb,
123.709 + 0x7d, 0x57, 0x5c, 0xb4, 0x92, 0x80, 0x13, 0x99,
123.710 + 0x84, 0xf3, 0x79, 0x0a, 0x2d, 0x70, 0xa4, 0xe0,
123.711 + 0xde, 0xc6, 0x32, 0xb0, 0x8a, 0x62, 0xb5, 0xcf,
123.712 + 0xfa, 0x5e, 0x5a, 0x92, 0x32, 0x7d, 0x34, 0x07,
123.713 + 0xb5, 0x52, 0x3a, 0xb5, 0x7d, 0x0f, 0xa1, 0xba,
123.714 + 0x56, 0xd0, 0x07, 0x76, 0x11, 0xf2, 0xc3, 0x33,
123.715 + 0x9d, 0xbd, 0x12, 0x35, 0x5e, 0xf7, 0x05, 0x88,
123.716 + 0x76, 0x94, 0xa6, 0xbf, 0xed, 0xb8, 0xa4, 0xa2,
123.717 + 0x0c, 0xbe, 0x0f, 0x6a, 0xaf, 0xf3, 0x1b, 0x33,
123.718 + 0x4a, 0xb7, 0x68, 0x3f, 0xbe, 0x95, 0x13, 0x97,
123.719 + 0x0f, 0x15, 0x17, 0x1b, 0x23, 0xaa, 0x08, 0x78,
123.720 + 0xa6, 0x5b, 0x08, 0xa2, 0x9d, 0x03, 0xa8, 0xa7,
123.721 + 0x39, 0xdc, 0xbc, 0x9a, 0x85, 0xf5, 0xe5, 0x55,
123.722 + 0x59, 0x3c, 0xef, 0xf9, 0x3f, 0x22, 0x8e, 0xf8,
123.723 + 0xd8, 0x3e, 0x02, 0x0b, 0xd8, 0x78, 0x4b, 0x15,
123.724 + 0x7f, 0xaa, 0x2c, 0xff, 0xbe, 0x77, 0x33, 0xc7,
123.725 + 0x6a, 0x12, 0xaa, 0xa4, 0xbe, 0xc0, 0x3b, 0xcb,
123.726 + 0x13, 0x9d, 0x9c, 0x5a, 0x9f, 0x8a, 0x57, 0x36,
123.727 + 0x4f, 0x02, 0x5a, 0xf8, 0x1d, 0x97, 0x77, 0x43,
123.728 + 0xc8, 0xa5, 0xb7, 0x9b, 0x10, 0x98, 0xfd, 0x58,
123.729 + 0xbf, 0x42, 0xf6, 0xbf, 0xff, 0x6c, 0x40, 0x18,
123.730 + 0x18, 0xdf, 0xac, 0x57, 0x71, 0xea, 0xcc, 0x8e,
123.731 + 0xfd, 0xfe, 0x10, 0xfb, 0xb9, 0xfe, 0xbc, 0x9a,
123.732 + 0x9c, 0x27, 0xe4, 0x10, 0x15, 0x94, 0x41, 0xa1,
123.733 + 0xcc, 0xf6, 0x25, 0x49, 0x4f, 0x96, 0xc1, 0x8c,
123.734 + 0x9e, 0x3e, 0x18, 0x29, 0x49, 0x92, 0xe7, 0xfe,
123.735 + 0x22, 0xff, 0xed, 0x02, 0x16, 0x90, 0xef, 0xac,
123.736 + 0xec, 0x95, 0x1d, 0x5b, 0x94, 0x9c, 0xf6, 0x7c,
123.737 + 0x1b, 0x5a, 0x9d, 0xb0, 0x9b, 0x05, 0x36, 0xbf,
123.738 + 0xef, 0xec, 0x63, 0x35, 0x40, 0x24, 0x45, 0x40,
123.739 + 0x30, 0x1a, 0x9b, 0x90, 0xc3, 0xc2, 0xf7, 0x37,
123.740 + 0xfb, 0x08, 0x8e, 0x48, 0x19, 0x48, 0xed, 0xa8,
123.741 + 0xa8, 0x04, 0x6f, 0xd0, 0x33, 0xe9, 0xb8, 0x8d,
123.742 + 0xe7, 0x1e, 0x5c, 0x47, 0x74, 0xc0, 0x66, 0x30,
123.743 + 0x4e, 0xa7, 0x86, 0x73, 0xf1, 0xe5, 0x78, 0xa6,
123.744 + 0xe0, 0xc1, 0xda, 0x13, 0x72, 0x07, 0x85, 0x34,
123.745 + 0x63, 0x95, 0x49, 0x30, 0x4b, 0x9d, 0x03, 0xf1,
123.746 + 0x7a, 0x6b, 0x91, 0xa2, 0x85, 0x41, 0xf9, 0x4a,
123.747 + 0xd6, 0xff, 0xff, 0x86, 0xf7, 0xf0, 0xce, 0xb9,
123.748 + 0x07, 0xf1, 0x88, 0x04, 0x33, 0xaa, 0xeb, 0x54,
123.749 + 0xb2, 0x1c, 0x8e, 0x2e, 0x7b, 0x04, 0xa8, 0xcc,
123.750 + 0x2c, 0x7a, 0xb3, 0xad, 0x1a, 0x89, 0x38, 0x89,
123.751 + 0xd7, 0x11, 0x3a, 0x8c, 0xcf, 0xe3, 0xc5, 0xba,
123.752 + 0xb0, 0xcc, 0xc4, 0xe3, 0x33, 0xf3, 0x18, 0xba,
123.753 + 0xec, 0x56, 0xd9, 0x1c, 0x40, 0x70, 0x0d, 0x4e,
123.754 + 0x97, 0x01, 0x23, 0xf3, 0x5a, 0xdc, 0xbf, 0x68,
123.755 + 0x93, 0xc2, 0x1d, 0x8a, 0x96, 0xb7, 0xac, 0x18,
123.756 + 0x6f, 0xf7, 0x84, 0x71, 0x0d, 0x3d, 0xf8, 0xba,
123.757 + 0xdf, 0xb6, 0x89, 0x1d, 0x78, 0x19, 0xf2, 0x59,
123.758 + 0xe9, 0x15, 0x55, 0x29, 0x73, 0x50, 0x59, 0x14,
123.759 + 0x02, 0x21, 0x16, 0x8f, 0x0f, 0xdf, 0xa5, 0xf0,
123.760 +};
123.761 +
123.762 +static struct crc_test {
123.763 + uint32_t crc; /* random starting crc */
123.764 + uint32_t start; /* random offset in buf */
123.765 + uint32_t length; /* random length of test */
123.766 + uint32_t crc32c_le; /* expected crc32c_le result */
123.767 + uint32_t crc32_be; /* expected crc32_be result */
123.768 +} test[] = {
123.769 + {0xffffffff, 0x00000000, 0x00001000, 0x13934bef, 0xd8ddcdc3},
123.770 + {0xfe7328ea, 0x00000763, 0x00000717, 0xed2c0d70, 0xc863aef8},
123.771 + {0x4c40684e, 0x00000721, 0x0000011e, 0xd7f46ccc, 0x173a11c4},
123.772 + {0x6b487f90, 0x00000264, 0x000007bc, 0x759e9939, 0xd6307c56},
123.773 + {0x9f5810db, 0x00000afa, 0x00000255, 0x2685197f, 0x2e5c9201},
123.774 + {0xb15c4755, 0x00000d5b, 0x000002a4, 0xd8fadcb5, 0xf682c4be},
123.775 + {0x06518253, 0x00000ffb, 0x00000004, 0xabee2433, 0x3d8abdf9},
123.776 + {0xd9e71c55, 0x00000a2a, 0x00000259, 0x96682af2, 0x47b4d26c},
123.777 + {0x0c1ae843, 0x00000ce4, 0x0000031b, 0x7b637c43, 0x62b47e8b},
123.778 + {0xec3cd517, 0x000002ff, 0x00000566, 0x5d719a77, 0xff5bc5b7},
123.779 + {0x77828e95, 0x0000067f, 0x0000038f, 0x43ee5b6c, 0x1a0cfacd},
123.780 + {0xec87b4e3, 0x00000d1c, 0x000002e3, 0x2ddd2eee, 0x275118a7},
123.781 + {0x412158bb, 0x00000eee, 0x00000111, 0x67b38ba2, 0xa74ecff5},
123.782 + {0x2e52de3e, 0x00000c4a, 0x000003b5, 0xbcc5d61d, 0xbd800707},
123.783 + {0x6ddaae8b, 0x00000d99, 0x00000266, 0x8b535544, 0xecbde1a1},
123.784 + {0x049b6cb1, 0x000009c5, 0x000000b0, 0xfc22cabc, 0xfb78eb9f},
123.785 + {0x77d4b954, 0x0000028a, 0x000007fa, 0x71d00923, 0x8c116f85},
123.786 + {0x5e192355, 0x00000ac1, 0x000001fa, 0xb966b81a, 0x5aa17bbe},
123.787 + {0x7d80b71d, 0x00000213, 0x000001e0, 0x2bba371a, 0xb5906aa6},
123.788 + {0x01f6f1e4, 0x000001d6, 0x00000395, 0xb7e8a647, 0x3ad112b1},
123.789 + {0x1dfabb13, 0x00000e14, 0x000001eb, 0x53917fba, 0xbaee0339},
123.790 + {0xb00a4449, 0x00000bf6, 0x00000409, 0xedecb577, 0x6f3a3979},
123.791 + {0x7ecd3981, 0x0000083f, 0x0000016b, 0xefef62b9, 0xe3e52eed},
123.792 + {0xf8f330d2, 0x000004be, 0x00000757, 0x9357c9f3, 0x0835bc1b},
123.793 + {0x03c38af2, 0x00000d23, 0x000002dc, 0x360fa8c0, 0x2ca885e6},
123.794 + {0x687bb79b, 0x00000f3d, 0x000000c2, 0x448d3be2, 0x79be2f78},
123.795 + {0x6710f550, 0x000009e9, 0x00000603, 0xdbfd1998, 0x1d25f627},
123.796 + {0x873171d1, 0x00000787, 0x000004d5, 0xab7f1b62, 0xa76a5656},
123.797 + {0x373b1314, 0x00000f0f, 0x000000f0, 0x184098ab, 0xba273974},
123.798 + {0x90fad9cd, 0x00000ead, 0x00000152, 0x23ce52ff, 0xb7bc958c},
123.799 + {0x19676fe7, 0x0000007d, 0x0000070d, 0xf8a76f1e, 0xf882b644},
123.800 + {0x89facd45, 0x000005f3, 0x00000473, 0x4331a006, 0xe9dc1396},
123.801 + {0x6f173747, 0x00000fc3, 0x0000003c, 0xb012f08e, 0xc6b888ee},
123.802 + {0x4b44a106, 0x0000075a, 0x0000008b, 0xf6f7ac38, 0x60cd2b74},
123.803 + {0xb620ad06, 0x00000774, 0x0000017e, 0xd34558e6, 0x3a0a615b},
123.804 + {0x976f21e9, 0x000008d7, 0x0000034a, 0xe533aa3a, 0xa99e60be},
123.805 + {0x687628c0, 0x000006c5, 0x0000061b, 0x3a840b15, 0x9bfcaef2},
123.806 + {0xe24ac108, 0x00000cd0, 0x0000032f, 0x51010ae8, 0x20958672},
123.807 + {0x361c44a3, 0x00000304, 0x00000719, 0xfd7bd481, 0xd70ff2b2},
123.808 + {0xd93ff95e, 0x00000db7, 0x0000008e, 0xcfbbc304, 0xad716acd},
123.809 + {0xed752d12, 0x00000883, 0x00000091, 0x65a6c868, 0x95c71c7b},
123.810 + {0xb4ff4b54, 0x000003d3, 0x000001c1, 0xf82597e7, 0x44b7f99b},
123.811 + {0x111b520f, 0x00000708, 0x000000eb, 0xc3e109f3, 0x71bc01ee},
123.812 + {0x62c806f2, 0x00000ba3, 0x0000045c, 0x874d3a72, 0xc539b753},
123.813 + {0x40d97470, 0x000005e1, 0x0000058d, 0x87a9684f, 0xea6073a5},
123.814 + {0x4312179c, 0x00000056, 0x0000070e, 0x809a00f5, 0x209aea3b},
123.815 + {0x13d5f84c, 0x00000a2d, 0x00000104, 0xf3d27578, 0xe087a8b6},
123.816 + {0x1f302cb2, 0x00000151, 0x00000014, 0x1e162693, 0x95e4b90e},
123.817 + {0xe491db24, 0x00000600, 0x000006f6, 0x7ff09615, 0x77611523},
123.818 + {0xf9a98069, 0x000002ba, 0x000002ad, 0x01af7387, 0xea925faa},
123.819 + {0xe9c477ad, 0x0000015f, 0x00000778, 0x6facf9a0, 0x1130f736},
123.820 + {0x353f32b2, 0x0000087c, 0x00000783, 0x6cc964ea, 0x32459994},
123.821 + {0x78e1b24f, 0x00000650, 0x000006a8, 0xb3bb7c27, 0x5a632f78},
123.822 + {0x61aa400e, 0x00000049, 0x00000254, 0xb8cd1681, 0xdf2652d5},
123.823 + {0xb84b10b0, 0x00000f73, 0x0000008c, 0x406a6450, 0x3619d31b},
123.824 + {0x9fa99c9c, 0x00000a7c, 0x000004d7, 0xfb3d21b4, 0xea31c743},
123.825 + {0x3fc9ebe3, 0x00000cd9, 0x000000d6, 0x43803f9c, 0x1f76a809},
123.826 + {0x529879cd, 0x000002f2, 0x00000595, 0x78b4c6a6, 0x63b9b93f},
123.827 + {0x3a933019, 0x00000516, 0x00000266, 0xdcb45436, 0x8f99c98c},
123.828 + {0x887b4977, 0x00000227, 0x0000038d, 0xc5f7c3d9, 0xaf5e3091},
123.829 + {0x770745de, 0x000008c6, 0x00000739, 0xf69145e8, 0x53d0dce1},
123.830 + {0x28be3b47, 0x00000c46, 0x0000032b, 0x764c028f, 0x106d0905},
123.831 + {0x5013a050, 0x00000cf6, 0x00000309, 0xea8fe164, 0x62180b57},
123.832 + {0x2ec4c9ba, 0x000006e8, 0x0000078d, 0xa35557a9, 0xf44430a4},
123.833 + {0xa9f950c9, 0x00000d33, 0x000002cc, 0x41ea8618, 0x587b4eb3},
123.834 + {0x5b520229, 0x000007b2, 0x00000484, 0x44569f1f, 0x92406c32},
123.835 + {0xd8dcbbfc, 0x0000002f, 0x0000048c, 0xdb88ab8b, 0x13bfe70e},
123.836 + {0x25529792, 0x00000d1d, 0x000002e2, 0x20cda404, 0x19d3b4e4},
123.837 + {0x9f3f6d71, 0x00000238, 0x0000079a, 0x0720443e, 0x3c107021},
123.838 + {0x64121215, 0x000007ff, 0x0000038f, 0x6aacff2c, 0xb82fdc3e},
123.839 + {0xfb6cdde0, 0x00000ef8, 0x00000107, 0xbd43a0f1, 0xab0d3c1d},
123.840 + {0x221c9d6f, 0x000007b6, 0x0000014f, 0xb67f834b, 0x1371ad05},
123.841 + {0x030e1de4, 0x00000836, 0x000004b4, 0x0d67d26a, 0xe2e72df1},
123.842 + {0xb56fa6cf, 0x00000c07, 0x000003f8, 0x60601ac1, 0x039de73e},
123.843 + {0xb55c89f5, 0x0000098e, 0x000001d4, 0x2400efbe, 0xfe39a2bb},
123.844 + {0x5e90b6d5, 0x0000070b, 0x000003ea, 0x3bb5d6ea, 0xf0f794a0},
123.845 + {0x2a7045ae, 0x00000961, 0x00000633, 0xfca89e4b, 0xe66ce41c},
123.846 + {0x8b374ea9, 0x000006ba, 0x00000780, 0xbce036ed, 0x4cb28ef7},
123.847 + {0x8bd90bc9, 0x00000562, 0x00000369, 0xcb26a24b, 0x40236d1d},
123.848 + {0x5b1b1762, 0x000000fd, 0x0000051a, 0x33cdda07, 0xc32e420a},
123.849 + {0xa4153555, 0x0000058f, 0x000005c7, 0xbe50eeca, 0x83a67f35},
123.850 + {0x0be1f931, 0x00000651, 0x00000672, 0x95a25753, 0x88f1aac1},
123.851 + {0xb7e78618, 0x00000a7f, 0x000002bb, 0xe06bcc1c, 0x74274f66},
123.852 + {0x4a9bc41b, 0x00000e51, 0x000001ae, 0x709e8d2c, 0x54eff534},
123.853 + {0xfc359d13, 0x00000440, 0x000002f8, 0x0a58451f, 0x55e9363f},
123.854 + {0x5aa48619, 0x000006d1, 0x00000284, 0x928ead83, 0x31041c06},
123.855 + {0xa609afa8, 0x0000053e, 0x00000272, 0xb048c141, 0x4704efba},
123.856 + {0x3f108afb, 0x00000949, 0x00000150, 0x9a6bb5bc, 0x4e4430c8},
123.857 + {0x79bec2d3, 0x000008ed, 0x00000712, 0x32692d57, 0x11d52a7b},
123.858 + {0x9429e067, 0x00000bc3, 0x0000043c, 0x5295ceff, 0x04640f4d},
123.859 + {0xae58b96a, 0x0000082d, 0x000007d2, 0xc2a681ba, 0xf7ca4a2c},
123.860 + {0x95df24be, 0x00000985, 0x000004c1, 0x3a287765, 0x2c4af003},
123.861 + {0x5e94976f, 0x00000596, 0x000004ed, 0xff00c489, 0x5ae11687},
123.862 + {0xf5e5f1de, 0x00000d31, 0x000002ce, 0x35f28e91, 0x30d47957},
123.863 + {0xa2c219cf, 0x00000a3c, 0x00000374, 0x707d21eb, 0x2a14a255},
123.864 + {0xf21b6ceb, 0x00000919, 0x00000135, 0x0847fb8b, 0xcb8d3b93},
123.865 + {0xaa988728, 0x00000787, 0x00000771, 0x885aeaa4, 0x6531b509},
123.866 + {0xaa5dfaac, 0x000003e5, 0x0000051b, 0x52c48ab7, 0xe43cc5e9},
123.867 + {0x0a053968, 0x00000d2a, 0x000002d5, 0x7a90256d, 0x8004765c},
123.868 + {0x1421dc20, 0x00000eef, 0x00000110, 0x97d6da24, 0x1378f6ff},
123.869 + {0xb47c2166, 0x00000a6a, 0x00000209, 0xcfd6cc52, 0x676e14a5},
123.870 + {0x77dd1955, 0x000000de, 0x00000266, 0xba74bcaa, 0xc71b429c},
123.871 + {0x68a03cc2, 0x0000082f, 0x000007b0, 0x752bd5d8, 0x19ed14aa},
123.872 + {0x0226b0a3, 0x00000a5f, 0x000005a0, 0x82de4970, 0xf654d3ed},
123.873 + {0x637bf3b1, 0x00000d93, 0x0000026c, 0x5c7115cb, 0x3cccb57e},
123.874 + {0x3b120edf, 0x00000c13, 0x000003ec, 0x80d7d20f, 0x92132798},
123.875 + {0xe2456780, 0x000002eb, 0x00000641, 0xc0a5d289, 0x6160c87a},
123.876 + {0x9b2e7125, 0x00000c0c, 0x000003f3, 0xcc15f57e, 0x6f00f637},
123.877 + {0x153033ef, 0x00000787, 0x000006b6, 0x3cde443b, 0xb46caa6e},
123.878 + {0x18458b3f, 0x0000066c, 0x00000561, 0x9a2bd8c6, 0xb6c29121},
123.879 + {0x4ff9d4b9, 0x00000c8f, 0x0000033a, 0xd0ee6d6d, 0xc81cf380},
123.880 + {0xdf84b5d9, 0x00000802, 0x0000029a, 0xdab0d74a, 0xb2464559},
123.881 + {0x81ee15df, 0x000003ce, 0x00000725, 0x9942e2de, 0x4ccf571b},
123.882 + {0x5c768e04, 0x00000afd, 0x00000160, 0x36110831, 0xae0b305a},
123.883 + {0xe5e18094, 0x00000b4b, 0x000000a0, 0xffa3e4a7, 0x6c8a4f09},
123.884 + {0xed7263b6, 0x00000d0d, 0x000002f2, 0xb0006a35, 0x7e04af8c},
123.885 + {0x5bfde7d7, 0x000006fb, 0x00000554, 0xa4193b76, 0xb3a91d12},
123.886 + {0x67f4a743, 0x00000b85, 0x0000047a, 0xf05c8d8f, 0xfb472fdf},
123.887 + {0xf13bdf22, 0x00000ff7, 0x00000008, 0x816351eb, 0xf347f235},
123.888 + {0x08ecc608, 0x00000d5d, 0x00000098, 0x90492772, 0x0b7f1521},
123.889 + {0x296f52ba, 0x000004f9, 0x00000788, 0x5e5a4896, 0x1cc67088},
123.890 + {0xbe4624c2, 0x00000427, 0x000004ef, 0xcd267b94, 0x550caefd},
123.891 + {0x906f7c7c, 0x00000a05, 0x0000003f, 0x03fcfc33, 0x9ed82a02},
123.892 + {0x8f7b323e, 0x00000458, 0x000004c7, 0xcd4969c8, 0x633c38a8},
123.893 + {0x88d6593d, 0x00000597, 0x000005b5, 0xf199cd3b, 0x0491452f},
123.894 + {0x978a7768, 0x00000268, 0x000001d3, 0xb28c95bd, 0x1a42fe61},
123.895 + {0x857a621e, 0x000007a7, 0x000003a8, 0xf4bf84ab, 0xcd0694c6},
123.896 + {0xb0e121ef, 0x000005be, 0x00000644, 0x28747c14, 0xf0510c72},
123.897 + {0, 0, 0, 0, 0},
123.898 +};
123.899 +
123.900 +static int test_crc32c(void)
123.901 +{
123.902 + struct crc_test *t = test;
123.903 + int failures = 0;
123.904 +
123.905 + while (t->length) {
123.906 + uint32_t be, le;
123.907 + le = ext2fs_crc32c_le(t->crc, test_buf + t->start, t->length);
123.908 + be = ext2fs_crc32_be(t->crc, test_buf + t->start, t->length);
123.909 + if (le != t->crc32c_le) {
123.910 + printf("Test %d LE fails, %x != %x\n",
123.911 + (int) (t - test), le, t->crc32c_le);
123.912 + failures++;
123.913 + }
123.914 + if (be != t->crc32_be) {
123.915 + printf("Test %d BE fails, %x != %x\n",
123.916 + (int) (t - test), be, t->crc32_be);
123.917 + failures++;
123.918 + }
123.919 + t++;
123.920 + }
123.921 +
123.922 + return failures;
123.923 +}
123.924 +
123.925 +int main(int argc, char *argv[])
123.926 +{
123.927 + int ret;
123.928 +
123.929 + ret = test_crc32c();
123.930 + if (!ret)
123.931 + printf("No failures.\n");
123.932 +
123.933 + return ret;
123.934 +}
123.935 +#endif /* UNITTEST */
124.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
124.2 +++ b/libext2fs/lib/libext2fs/crc32c_defs.h Wed Aug 25 01:28:08 2021 +0200
124.3 @@ -0,0 +1,59 @@
124.4 +/*
124.5 + * There are multiple 16-bit CRC polynomials in common use, but this is
124.6 + * *the* standard CRC-32 polynomial, first popularized by Ethernet.
124.7 + * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0
124.8 + */
124.9 +#define CRCPOLY_LE 0xedb88320
124.10 +#define CRCPOLY_BE 0x04c11db7
124.11 +
124.12 +/*
124.13 + * This is the CRC32c polynomial, as outlined by Castagnoli.
124.14 + * x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+x^10+x^9+
124.15 + * x^8+x^6+x^0
124.16 + */
124.17 +#define CRC32C_POLY_LE 0x82F63B78
124.18 +#define CRC32C_POLY_BE 0x1EDC6F41
124.19 +
124.20 +/* How many bits at a time to use. Valid values are 1, 2, 4, 8, 32 and 64. */
124.21 +/* For less performance-sensitive, use 4 */
124.22 +#ifndef CRC_LE_BITS
124.23 +# define CRC_LE_BITS 64
124.24 +#endif
124.25 +#ifndef CRC_BE_BITS
124.26 +# define CRC_BE_BITS 64
124.27 +#endif
124.28 +
124.29 +/*
124.30 + * Little-endian CRC computation. Used with serial bit streams sent
124.31 + * lsbit-first. Be sure to use cpu_to_le32() to append the computed CRC.
124.32 + */
124.33 +#if CRC_LE_BITS > 64 || CRC_LE_BITS < 1 || CRC_LE_BITS == 16 || \
124.34 + CRC_LE_BITS & CRC_LE_BITS-1
124.35 +# error "CRC_LE_BITS must be one of {1, 2, 4, 8, 32, 64}"
124.36 +#endif
124.37 +
124.38 +/*
124.39 + * Big-endian CRC computation. Used with serial bit streams sent
124.40 + * msbit-first. Be sure to use cpu_to_be32() to append the computed CRC.
124.41 + */
124.42 +#if CRC_BE_BITS > 64 || CRC_BE_BITS < 1 || CRC_BE_BITS == 16 || \
124.43 + CRC_BE_BITS & CRC_BE_BITS-1
124.44 +# error "CRC_BE_BITS must be one of {1, 2, 4, 8, 32, 64}"
124.45 +#endif
124.46 +
124.47 +
124.48 +#define ___constant_swab32(x) \
124.49 + ((uint32_t)( \
124.50 + (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
124.51 + (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
124.52 + (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
124.53 + (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
124.54 +
124.55 +
124.56 +#if (__GNUC__ >= 3)
124.57 +#define likely(x) __builtin_expect(!!(x), 1)
124.58 +#define unlikely(x) __builtin_expect(!!(x), 0)
124.59 +#else
124.60 +#define likely(x) (x)
124.61 +#define unlikely(x) (x)
124.62 +#endif
125.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
125.2 +++ b/libext2fs/lib/libext2fs/crc32c_table.h Wed Aug 25 01:28:08 2021 +0200
125.3 @@ -0,0 +1,1044 @@
125.4 +/* this file is generated - do not edit */
125.5 +
125.6 +static const uint32_t crc32table_be[8][256] = {{
125.7 +tobe(0x00000000L), tobe(0x04c11db7L), tobe(0x09823b6eL), tobe(0x0d4326d9L),
125.8 +tobe(0x130476dcL), tobe(0x17c56b6bL), tobe(0x1a864db2L), tobe(0x1e475005L),
125.9 +tobe(0x2608edb8L), tobe(0x22c9f00fL), tobe(0x2f8ad6d6L), tobe(0x2b4bcb61L),
125.10 +tobe(0x350c9b64L), tobe(0x31cd86d3L), tobe(0x3c8ea00aL), tobe(0x384fbdbdL),
125.11 +tobe(0x4c11db70L), tobe(0x48d0c6c7L), tobe(0x4593e01eL), tobe(0x4152fda9L),
125.12 +tobe(0x5f15adacL), tobe(0x5bd4b01bL), tobe(0x569796c2L), tobe(0x52568b75L),
125.13 +tobe(0x6a1936c8L), tobe(0x6ed82b7fL), tobe(0x639b0da6L), tobe(0x675a1011L),
125.14 +tobe(0x791d4014L), tobe(0x7ddc5da3L), tobe(0x709f7b7aL), tobe(0x745e66cdL),
125.15 +tobe(0x9823b6e0L), tobe(0x9ce2ab57L), tobe(0x91a18d8eL), tobe(0x95609039L),
125.16 +tobe(0x8b27c03cL), tobe(0x8fe6dd8bL), tobe(0x82a5fb52L), tobe(0x8664e6e5L),
125.17 +tobe(0xbe2b5b58L), tobe(0xbaea46efL), tobe(0xb7a96036L), tobe(0xb3687d81L),
125.18 +tobe(0xad2f2d84L), tobe(0xa9ee3033L), tobe(0xa4ad16eaL), tobe(0xa06c0b5dL),
125.19 +tobe(0xd4326d90L), tobe(0xd0f37027L), tobe(0xddb056feL), tobe(0xd9714b49L),
125.20 +tobe(0xc7361b4cL), tobe(0xc3f706fbL), tobe(0xceb42022L), tobe(0xca753d95L),
125.21 +tobe(0xf23a8028L), tobe(0xf6fb9d9fL), tobe(0xfbb8bb46L), tobe(0xff79a6f1L),
125.22 +tobe(0xe13ef6f4L), tobe(0xe5ffeb43L), tobe(0xe8bccd9aL), tobe(0xec7dd02dL),
125.23 +tobe(0x34867077L), tobe(0x30476dc0L), tobe(0x3d044b19L), tobe(0x39c556aeL),
125.24 +tobe(0x278206abL), tobe(0x23431b1cL), tobe(0x2e003dc5L), tobe(0x2ac12072L),
125.25 +tobe(0x128e9dcfL), tobe(0x164f8078L), tobe(0x1b0ca6a1L), tobe(0x1fcdbb16L),
125.26 +tobe(0x018aeb13L), tobe(0x054bf6a4L), tobe(0x0808d07dL), tobe(0x0cc9cdcaL),
125.27 +tobe(0x7897ab07L), tobe(0x7c56b6b0L), tobe(0x71159069L), tobe(0x75d48ddeL),
125.28 +tobe(0x6b93dddbL), tobe(0x6f52c06cL), tobe(0x6211e6b5L), tobe(0x66d0fb02L),
125.29 +tobe(0x5e9f46bfL), tobe(0x5a5e5b08L), tobe(0x571d7dd1L), tobe(0x53dc6066L),
125.30 +tobe(0x4d9b3063L), tobe(0x495a2dd4L), tobe(0x44190b0dL), tobe(0x40d816baL),
125.31 +tobe(0xaca5c697L), tobe(0xa864db20L), tobe(0xa527fdf9L), tobe(0xa1e6e04eL),
125.32 +tobe(0xbfa1b04bL), tobe(0xbb60adfcL), tobe(0xb6238b25L), tobe(0xb2e29692L),
125.33 +tobe(0x8aad2b2fL), tobe(0x8e6c3698L), tobe(0x832f1041L), tobe(0x87ee0df6L),
125.34 +tobe(0x99a95df3L), tobe(0x9d684044L), tobe(0x902b669dL), tobe(0x94ea7b2aL),
125.35 +tobe(0xe0b41de7L), tobe(0xe4750050L), tobe(0xe9362689L), tobe(0xedf73b3eL),
125.36 +tobe(0xf3b06b3bL), tobe(0xf771768cL), tobe(0xfa325055L), tobe(0xfef34de2L),
125.37 +tobe(0xc6bcf05fL), tobe(0xc27dede8L), tobe(0xcf3ecb31L), tobe(0xcbffd686L),
125.38 +tobe(0xd5b88683L), tobe(0xd1799b34L), tobe(0xdc3abdedL), tobe(0xd8fba05aL),
125.39 +tobe(0x690ce0eeL), tobe(0x6dcdfd59L), tobe(0x608edb80L), tobe(0x644fc637L),
125.40 +tobe(0x7a089632L), tobe(0x7ec98b85L), tobe(0x738aad5cL), tobe(0x774bb0ebL),
125.41 +tobe(0x4f040d56L), tobe(0x4bc510e1L), tobe(0x46863638L), tobe(0x42472b8fL),
125.42 +tobe(0x5c007b8aL), tobe(0x58c1663dL), tobe(0x558240e4L), tobe(0x51435d53L),
125.43 +tobe(0x251d3b9eL), tobe(0x21dc2629L), tobe(0x2c9f00f0L), tobe(0x285e1d47L),
125.44 +tobe(0x36194d42L), tobe(0x32d850f5L), tobe(0x3f9b762cL), tobe(0x3b5a6b9bL),
125.45 +tobe(0x0315d626L), tobe(0x07d4cb91L), tobe(0x0a97ed48L), tobe(0x0e56f0ffL),
125.46 +tobe(0x1011a0faL), tobe(0x14d0bd4dL), tobe(0x19939b94L), tobe(0x1d528623L),
125.47 +tobe(0xf12f560eL), tobe(0xf5ee4bb9L), tobe(0xf8ad6d60L), tobe(0xfc6c70d7L),
125.48 +tobe(0xe22b20d2L), tobe(0xe6ea3d65L), tobe(0xeba91bbcL), tobe(0xef68060bL),
125.49 +tobe(0xd727bbb6L), tobe(0xd3e6a601L), tobe(0xdea580d8L), tobe(0xda649d6fL),
125.50 +tobe(0xc423cd6aL), tobe(0xc0e2d0ddL), tobe(0xcda1f604L), tobe(0xc960ebb3L),
125.51 +tobe(0xbd3e8d7eL), tobe(0xb9ff90c9L), tobe(0xb4bcb610L), tobe(0xb07daba7L),
125.52 +tobe(0xae3afba2L), tobe(0xaafbe615L), tobe(0xa7b8c0ccL), tobe(0xa379dd7bL),
125.53 +tobe(0x9b3660c6L), tobe(0x9ff77d71L), tobe(0x92b45ba8L), tobe(0x9675461fL),
125.54 +tobe(0x8832161aL), tobe(0x8cf30badL), tobe(0x81b02d74L), tobe(0x857130c3L),
125.55 +tobe(0x5d8a9099L), tobe(0x594b8d2eL), tobe(0x5408abf7L), tobe(0x50c9b640L),
125.56 +tobe(0x4e8ee645L), tobe(0x4a4ffbf2L), tobe(0x470cdd2bL), tobe(0x43cdc09cL),
125.57 +tobe(0x7b827d21L), tobe(0x7f436096L), tobe(0x7200464fL), tobe(0x76c15bf8L),
125.58 +tobe(0x68860bfdL), tobe(0x6c47164aL), tobe(0x61043093L), tobe(0x65c52d24L),
125.59 +tobe(0x119b4be9L), tobe(0x155a565eL), tobe(0x18197087L), tobe(0x1cd86d30L),
125.60 +tobe(0x029f3d35L), tobe(0x065e2082L), tobe(0x0b1d065bL), tobe(0x0fdc1becL),
125.61 +tobe(0x3793a651L), tobe(0x3352bbe6L), tobe(0x3e119d3fL), tobe(0x3ad08088L),
125.62 +tobe(0x2497d08dL), tobe(0x2056cd3aL), tobe(0x2d15ebe3L), tobe(0x29d4f654L),
125.63 +tobe(0xc5a92679L), tobe(0xc1683bceL), tobe(0xcc2b1d17L), tobe(0xc8ea00a0L),
125.64 +tobe(0xd6ad50a5L), tobe(0xd26c4d12L), tobe(0xdf2f6bcbL), tobe(0xdbee767cL),
125.65 +tobe(0xe3a1cbc1L), tobe(0xe760d676L), tobe(0xea23f0afL), tobe(0xeee2ed18L),
125.66 +tobe(0xf0a5bd1dL), tobe(0xf464a0aaL), tobe(0xf9278673L), tobe(0xfde69bc4L),
125.67 +tobe(0x89b8fd09L), tobe(0x8d79e0beL), tobe(0x803ac667L), tobe(0x84fbdbd0L),
125.68 +tobe(0x9abc8bd5L), tobe(0x9e7d9662L), tobe(0x933eb0bbL), tobe(0x97ffad0cL),
125.69 +tobe(0xafb010b1L), tobe(0xab710d06L), tobe(0xa6322bdfL), tobe(0xa2f33668L),
125.70 +tobe(0xbcb4666dL), tobe(0xb8757bdaL), tobe(0xb5365d03L), tobe(0xb1f740b4L)},
125.71 +{
125.72 +tobe(0x00000000L), tobe(0xd219c1dcL), tobe(0xa0f29e0fL), tobe(0x72eb5fd3L),
125.73 +tobe(0x452421a9L), tobe(0x973de075L), tobe(0xe5d6bfa6L), tobe(0x37cf7e7aL),
125.74 +tobe(0x8a484352L), tobe(0x5851828eL), tobe(0x2abadd5dL), tobe(0xf8a31c81L),
125.75 +tobe(0xcf6c62fbL), tobe(0x1d75a327L), tobe(0x6f9efcf4L), tobe(0xbd873d28L),
125.76 +tobe(0x10519b13L), tobe(0xc2485acfL), tobe(0xb0a3051cL), tobe(0x62bac4c0L),
125.77 +tobe(0x5575babaL), tobe(0x876c7b66L), tobe(0xf58724b5L), tobe(0x279ee569L),
125.78 +tobe(0x9a19d841L), tobe(0x4800199dL), tobe(0x3aeb464eL), tobe(0xe8f28792L),
125.79 +tobe(0xdf3df9e8L), tobe(0x0d243834L), tobe(0x7fcf67e7L), tobe(0xadd6a63bL),
125.80 +tobe(0x20a33626L), tobe(0xf2baf7faL), tobe(0x8051a829L), tobe(0x524869f5L),
125.81 +tobe(0x6587178fL), tobe(0xb79ed653L), tobe(0xc5758980L), tobe(0x176c485cL),
125.82 +tobe(0xaaeb7574L), tobe(0x78f2b4a8L), tobe(0x0a19eb7bL), tobe(0xd8002aa7L),
125.83 +tobe(0xefcf54ddL), tobe(0x3dd69501L), tobe(0x4f3dcad2L), tobe(0x9d240b0eL),
125.84 +tobe(0x30f2ad35L), tobe(0xe2eb6ce9L), tobe(0x9000333aL), tobe(0x4219f2e6L),
125.85 +tobe(0x75d68c9cL), tobe(0xa7cf4d40L), tobe(0xd5241293L), tobe(0x073dd34fL),
125.86 +tobe(0xbabaee67L), tobe(0x68a32fbbL), tobe(0x1a487068L), tobe(0xc851b1b4L),
125.87 +tobe(0xff9ecfceL), tobe(0x2d870e12L), tobe(0x5f6c51c1L), tobe(0x8d75901dL),
125.88 +tobe(0x41466c4cL), tobe(0x935fad90L), tobe(0xe1b4f243L), tobe(0x33ad339fL),
125.89 +tobe(0x04624de5L), tobe(0xd67b8c39L), tobe(0xa490d3eaL), tobe(0x76891236L),
125.90 +tobe(0xcb0e2f1eL), tobe(0x1917eec2L), tobe(0x6bfcb111L), tobe(0xb9e570cdL),
125.91 +tobe(0x8e2a0eb7L), tobe(0x5c33cf6bL), tobe(0x2ed890b8L), tobe(0xfcc15164L),
125.92 +tobe(0x5117f75fL), tobe(0x830e3683L), tobe(0xf1e56950L), tobe(0x23fca88cL),
125.93 +tobe(0x1433d6f6L), tobe(0xc62a172aL), tobe(0xb4c148f9L), tobe(0x66d88925L),
125.94 +tobe(0xdb5fb40dL), tobe(0x094675d1L), tobe(0x7bad2a02L), tobe(0xa9b4ebdeL),
125.95 +tobe(0x9e7b95a4L), tobe(0x4c625478L), tobe(0x3e890babL), tobe(0xec90ca77L),
125.96 +tobe(0x61e55a6aL), tobe(0xb3fc9bb6L), tobe(0xc117c465L), tobe(0x130e05b9L),
125.97 +tobe(0x24c17bc3L), tobe(0xf6d8ba1fL), tobe(0x8433e5ccL), tobe(0x562a2410L),
125.98 +tobe(0xebad1938L), tobe(0x39b4d8e4L), tobe(0x4b5f8737L), tobe(0x994646ebL),
125.99 +tobe(0xae893891L), tobe(0x7c90f94dL), tobe(0x0e7ba69eL), tobe(0xdc626742L),
125.100 +tobe(0x71b4c179L), tobe(0xa3ad00a5L), tobe(0xd1465f76L), tobe(0x035f9eaaL),
125.101 +tobe(0x3490e0d0L), tobe(0xe689210cL), tobe(0x94627edfL), tobe(0x467bbf03L),
125.102 +tobe(0xfbfc822bL), tobe(0x29e543f7L), tobe(0x5b0e1c24L), tobe(0x8917ddf8L),
125.103 +tobe(0xbed8a382L), tobe(0x6cc1625eL), tobe(0x1e2a3d8dL), tobe(0xcc33fc51L),
125.104 +tobe(0x828cd898L), tobe(0x50951944L), tobe(0x227e4697L), tobe(0xf067874bL),
125.105 +tobe(0xc7a8f931L), tobe(0x15b138edL), tobe(0x675a673eL), tobe(0xb543a6e2L),
125.106 +tobe(0x08c49bcaL), tobe(0xdadd5a16L), tobe(0xa83605c5L), tobe(0x7a2fc419L),
125.107 +tobe(0x4de0ba63L), tobe(0x9ff97bbfL), tobe(0xed12246cL), tobe(0x3f0be5b0L),
125.108 +tobe(0x92dd438bL), tobe(0x40c48257L), tobe(0x322fdd84L), tobe(0xe0361c58L),
125.109 +tobe(0xd7f96222L), tobe(0x05e0a3feL), tobe(0x770bfc2dL), tobe(0xa5123df1L),
125.110 +tobe(0x189500d9L), tobe(0xca8cc105L), tobe(0xb8679ed6L), tobe(0x6a7e5f0aL),
125.111 +tobe(0x5db12170L), tobe(0x8fa8e0acL), tobe(0xfd43bf7fL), tobe(0x2f5a7ea3L),
125.112 +tobe(0xa22feebeL), tobe(0x70362f62L), tobe(0x02dd70b1L), tobe(0xd0c4b16dL),
125.113 +tobe(0xe70bcf17L), tobe(0x35120ecbL), tobe(0x47f95118L), tobe(0x95e090c4L),
125.114 +tobe(0x2867adecL), tobe(0xfa7e6c30L), tobe(0x889533e3L), tobe(0x5a8cf23fL),
125.115 +tobe(0x6d438c45L), tobe(0xbf5a4d99L), tobe(0xcdb1124aL), tobe(0x1fa8d396L),
125.116 +tobe(0xb27e75adL), tobe(0x6067b471L), tobe(0x128ceba2L), tobe(0xc0952a7eL),
125.117 +tobe(0xf75a5404L), tobe(0x254395d8L), tobe(0x57a8ca0bL), tobe(0x85b10bd7L),
125.118 +tobe(0x383636ffL), tobe(0xea2ff723L), tobe(0x98c4a8f0L), tobe(0x4add692cL),
125.119 +tobe(0x7d121756L), tobe(0xaf0bd68aL), tobe(0xdde08959L), tobe(0x0ff94885L),
125.120 +tobe(0xc3cab4d4L), tobe(0x11d37508L), tobe(0x63382adbL), tobe(0xb121eb07L),
125.121 +tobe(0x86ee957dL), tobe(0x54f754a1L), tobe(0x261c0b72L), tobe(0xf405caaeL),
125.122 +tobe(0x4982f786L), tobe(0x9b9b365aL), tobe(0xe9706989L), tobe(0x3b69a855L),
125.123 +tobe(0x0ca6d62fL), tobe(0xdebf17f3L), tobe(0xac544820L), tobe(0x7e4d89fcL),
125.124 +tobe(0xd39b2fc7L), tobe(0x0182ee1bL), tobe(0x7369b1c8L), tobe(0xa1707014L),
125.125 +tobe(0x96bf0e6eL), tobe(0x44a6cfb2L), tobe(0x364d9061L), tobe(0xe45451bdL),
125.126 +tobe(0x59d36c95L), tobe(0x8bcaad49L), tobe(0xf921f29aL), tobe(0x2b383346L),
125.127 +tobe(0x1cf74d3cL), tobe(0xceee8ce0L), tobe(0xbc05d333L), tobe(0x6e1c12efL),
125.128 +tobe(0xe36982f2L), tobe(0x3170432eL), tobe(0x439b1cfdL), tobe(0x9182dd21L),
125.129 +tobe(0xa64da35bL), tobe(0x74546287L), tobe(0x06bf3d54L), tobe(0xd4a6fc88L),
125.130 +tobe(0x6921c1a0L), tobe(0xbb38007cL), tobe(0xc9d35fafL), tobe(0x1bca9e73L),
125.131 +tobe(0x2c05e009L), tobe(0xfe1c21d5L), tobe(0x8cf77e06L), tobe(0x5eeebfdaL),
125.132 +tobe(0xf33819e1L), tobe(0x2121d83dL), tobe(0x53ca87eeL), tobe(0x81d34632L),
125.133 +tobe(0xb61c3848L), tobe(0x6405f994L), tobe(0x16eea647L), tobe(0xc4f7679bL),
125.134 +tobe(0x79705ab3L), tobe(0xab699b6fL), tobe(0xd982c4bcL), tobe(0x0b9b0560L),
125.135 +tobe(0x3c547b1aL), tobe(0xee4dbac6L), tobe(0x9ca6e515L), tobe(0x4ebf24c9L)},
125.136 +{
125.137 +tobe(0x00000000L), tobe(0x01d8ac87L), tobe(0x03b1590eL), tobe(0x0269f589L),
125.138 +tobe(0x0762b21cL), tobe(0x06ba1e9bL), tobe(0x04d3eb12L), tobe(0x050b4795L),
125.139 +tobe(0x0ec56438L), tobe(0x0f1dc8bfL), tobe(0x0d743d36L), tobe(0x0cac91b1L),
125.140 +tobe(0x09a7d624L), tobe(0x087f7aa3L), tobe(0x0a168f2aL), tobe(0x0bce23adL),
125.141 +tobe(0x1d8ac870L), tobe(0x1c5264f7L), tobe(0x1e3b917eL), tobe(0x1fe33df9L),
125.142 +tobe(0x1ae87a6cL), tobe(0x1b30d6ebL), tobe(0x19592362L), tobe(0x18818fe5L),
125.143 +tobe(0x134fac48L), tobe(0x129700cfL), tobe(0x10fef546L), tobe(0x112659c1L),
125.144 +tobe(0x142d1e54L), tobe(0x15f5b2d3L), tobe(0x179c475aL), tobe(0x1644ebddL),
125.145 +tobe(0x3b1590e0L), tobe(0x3acd3c67L), tobe(0x38a4c9eeL), tobe(0x397c6569L),
125.146 +tobe(0x3c7722fcL), tobe(0x3daf8e7bL), tobe(0x3fc67bf2L), tobe(0x3e1ed775L),
125.147 +tobe(0x35d0f4d8L), tobe(0x3408585fL), tobe(0x3661add6L), tobe(0x37b90151L),
125.148 +tobe(0x32b246c4L), tobe(0x336aea43L), tobe(0x31031fcaL), tobe(0x30dbb34dL),
125.149 +tobe(0x269f5890L), tobe(0x2747f417L), tobe(0x252e019eL), tobe(0x24f6ad19L),
125.150 +tobe(0x21fdea8cL), tobe(0x2025460bL), tobe(0x224cb382L), tobe(0x23941f05L),
125.151 +tobe(0x285a3ca8L), tobe(0x2982902fL), tobe(0x2beb65a6L), tobe(0x2a33c921L),
125.152 +tobe(0x2f388eb4L), tobe(0x2ee02233L), tobe(0x2c89d7baL), tobe(0x2d517b3dL),
125.153 +tobe(0x762b21c0L), tobe(0x77f38d47L), tobe(0x759a78ceL), tobe(0x7442d449L),
125.154 +tobe(0x714993dcL), tobe(0x70913f5bL), tobe(0x72f8cad2L), tobe(0x73206655L),
125.155 +tobe(0x78ee45f8L), tobe(0x7936e97fL), tobe(0x7b5f1cf6L), tobe(0x7a87b071L),
125.156 +tobe(0x7f8cf7e4L), tobe(0x7e545b63L), tobe(0x7c3daeeaL), tobe(0x7de5026dL),
125.157 +tobe(0x6ba1e9b0L), tobe(0x6a794537L), tobe(0x6810b0beL), tobe(0x69c81c39L),
125.158 +tobe(0x6cc35bacL), tobe(0x6d1bf72bL), tobe(0x6f7202a2L), tobe(0x6eaaae25L),
125.159 +tobe(0x65648d88L), tobe(0x64bc210fL), tobe(0x66d5d486L), tobe(0x670d7801L),
125.160 +tobe(0x62063f94L), tobe(0x63de9313L), tobe(0x61b7669aL), tobe(0x606fca1dL),
125.161 +tobe(0x4d3eb120L), tobe(0x4ce61da7L), tobe(0x4e8fe82eL), tobe(0x4f5744a9L),
125.162 +tobe(0x4a5c033cL), tobe(0x4b84afbbL), tobe(0x49ed5a32L), tobe(0x4835f6b5L),
125.163 +tobe(0x43fbd518L), tobe(0x4223799fL), tobe(0x404a8c16L), tobe(0x41922091L),
125.164 +tobe(0x44996704L), tobe(0x4541cb83L), tobe(0x47283e0aL), tobe(0x46f0928dL),
125.165 +tobe(0x50b47950L), tobe(0x516cd5d7L), tobe(0x5305205eL), tobe(0x52dd8cd9L),
125.166 +tobe(0x57d6cb4cL), tobe(0x560e67cbL), tobe(0x54679242L), tobe(0x55bf3ec5L),
125.167 +tobe(0x5e711d68L), tobe(0x5fa9b1efL), tobe(0x5dc04466L), tobe(0x5c18e8e1L),
125.168 +tobe(0x5913af74L), tobe(0x58cb03f3L), tobe(0x5aa2f67aL), tobe(0x5b7a5afdL),
125.169 +tobe(0xec564380L), tobe(0xed8eef07L), tobe(0xefe71a8eL), tobe(0xee3fb609L),
125.170 +tobe(0xeb34f19cL), tobe(0xeaec5d1bL), tobe(0xe885a892L), tobe(0xe95d0415L),
125.171 +tobe(0xe29327b8L), tobe(0xe34b8b3fL), tobe(0xe1227eb6L), tobe(0xe0fad231L),
125.172 +tobe(0xe5f195a4L), tobe(0xe4293923L), tobe(0xe640ccaaL), tobe(0xe798602dL),
125.173 +tobe(0xf1dc8bf0L), tobe(0xf0042777L), tobe(0xf26dd2feL), tobe(0xf3b57e79L),
125.174 +tobe(0xf6be39ecL), tobe(0xf766956bL), tobe(0xf50f60e2L), tobe(0xf4d7cc65L),
125.175 +tobe(0xff19efc8L), tobe(0xfec1434fL), tobe(0xfca8b6c6L), tobe(0xfd701a41L),
125.176 +tobe(0xf87b5dd4L), tobe(0xf9a3f153L), tobe(0xfbca04daL), tobe(0xfa12a85dL),
125.177 +tobe(0xd743d360L), tobe(0xd69b7fe7L), tobe(0xd4f28a6eL), tobe(0xd52a26e9L),
125.178 +tobe(0xd021617cL), tobe(0xd1f9cdfbL), tobe(0xd3903872L), tobe(0xd24894f5L),
125.179 +tobe(0xd986b758L), tobe(0xd85e1bdfL), tobe(0xda37ee56L), tobe(0xdbef42d1L),
125.180 +tobe(0xdee40544L), tobe(0xdf3ca9c3L), tobe(0xdd555c4aL), tobe(0xdc8df0cdL),
125.181 +tobe(0xcac91b10L), tobe(0xcb11b797L), tobe(0xc978421eL), tobe(0xc8a0ee99L),
125.182 +tobe(0xcdaba90cL), tobe(0xcc73058bL), tobe(0xce1af002L), tobe(0xcfc25c85L),
125.183 +tobe(0xc40c7f28L), tobe(0xc5d4d3afL), tobe(0xc7bd2626L), tobe(0xc6658aa1L),
125.184 +tobe(0xc36ecd34L), tobe(0xc2b661b3L), tobe(0xc0df943aL), tobe(0xc10738bdL),
125.185 +tobe(0x9a7d6240L), tobe(0x9ba5cec7L), tobe(0x99cc3b4eL), tobe(0x981497c9L),
125.186 +tobe(0x9d1fd05cL), tobe(0x9cc77cdbL), tobe(0x9eae8952L), tobe(0x9f7625d5L),
125.187 +tobe(0x94b80678L), tobe(0x9560aaffL), tobe(0x97095f76L), tobe(0x96d1f3f1L),
125.188 +tobe(0x93dab464L), tobe(0x920218e3L), tobe(0x906bed6aL), tobe(0x91b341edL),
125.189 +tobe(0x87f7aa30L), tobe(0x862f06b7L), tobe(0x8446f33eL), tobe(0x859e5fb9L),
125.190 +tobe(0x8095182cL), tobe(0x814db4abL), tobe(0x83244122L), tobe(0x82fceda5L),
125.191 +tobe(0x8932ce08L), tobe(0x88ea628fL), tobe(0x8a839706L), tobe(0x8b5b3b81L),
125.192 +tobe(0x8e507c14L), tobe(0x8f88d093L), tobe(0x8de1251aL), tobe(0x8c39899dL),
125.193 +tobe(0xa168f2a0L), tobe(0xa0b05e27L), tobe(0xa2d9abaeL), tobe(0xa3010729L),
125.194 +tobe(0xa60a40bcL), tobe(0xa7d2ec3bL), tobe(0xa5bb19b2L), tobe(0xa463b535L),
125.195 +tobe(0xafad9698L), tobe(0xae753a1fL), tobe(0xac1ccf96L), tobe(0xadc46311L),
125.196 +tobe(0xa8cf2484L), tobe(0xa9178803L), tobe(0xab7e7d8aL), tobe(0xaaa6d10dL),
125.197 +tobe(0xbce23ad0L), tobe(0xbd3a9657L), tobe(0xbf5363deL), tobe(0xbe8bcf59L),
125.198 +tobe(0xbb8088ccL), tobe(0xba58244bL), tobe(0xb831d1c2L), tobe(0xb9e97d45L),
125.199 +tobe(0xb2275ee8L), tobe(0xb3fff26fL), tobe(0xb19607e6L), tobe(0xb04eab61L),
125.200 +tobe(0xb545ecf4L), tobe(0xb49d4073L), tobe(0xb6f4b5faL), tobe(0xb72c197dL)},
125.201 +{
125.202 +tobe(0x00000000L), tobe(0xdc6d9ab7L), tobe(0xbc1a28d9L), tobe(0x6077b26eL),
125.203 +tobe(0x7cf54c05L), tobe(0xa098d6b2L), tobe(0xc0ef64dcL), tobe(0x1c82fe6bL),
125.204 +tobe(0xf9ea980aL), tobe(0x258702bdL), tobe(0x45f0b0d3L), tobe(0x999d2a64L),
125.205 +tobe(0x851fd40fL), tobe(0x59724eb8L), tobe(0x3905fcd6L), tobe(0xe5686661L),
125.206 +tobe(0xf7142da3L), tobe(0x2b79b714L), tobe(0x4b0e057aL), tobe(0x97639fcdL),
125.207 +tobe(0x8be161a6L), tobe(0x578cfb11L), tobe(0x37fb497fL), tobe(0xeb96d3c8L),
125.208 +tobe(0x0efeb5a9L), tobe(0xd2932f1eL), tobe(0xb2e49d70L), tobe(0x6e8907c7L),
125.209 +tobe(0x720bf9acL), tobe(0xae66631bL), tobe(0xce11d175L), tobe(0x127c4bc2L),
125.210 +tobe(0xeae946f1L), tobe(0x3684dc46L), tobe(0x56f36e28L), tobe(0x8a9ef49fL),
125.211 +tobe(0x961c0af4L), tobe(0x4a719043L), tobe(0x2a06222dL), tobe(0xf66bb89aL),
125.212 +tobe(0x1303defbL), tobe(0xcf6e444cL), tobe(0xaf19f622L), tobe(0x73746c95L),
125.213 +tobe(0x6ff692feL), tobe(0xb39b0849L), tobe(0xd3ecba27L), tobe(0x0f812090L),
125.214 +tobe(0x1dfd6b52L), tobe(0xc190f1e5L), tobe(0xa1e7438bL), tobe(0x7d8ad93cL),
125.215 +tobe(0x61082757L), tobe(0xbd65bde0L), tobe(0xdd120f8eL), tobe(0x017f9539L),
125.216 +tobe(0xe417f358L), tobe(0x387a69efL), tobe(0x580ddb81L), tobe(0x84604136L),
125.217 +tobe(0x98e2bf5dL), tobe(0x448f25eaL), tobe(0x24f89784L), tobe(0xf8950d33L),
125.218 +tobe(0xd1139055L), tobe(0x0d7e0ae2L), tobe(0x6d09b88cL), tobe(0xb164223bL),
125.219 +tobe(0xade6dc50L), tobe(0x718b46e7L), tobe(0x11fcf489L), tobe(0xcd916e3eL),
125.220 +tobe(0x28f9085fL), tobe(0xf49492e8L), tobe(0x94e32086L), tobe(0x488eba31L),
125.221 +tobe(0x540c445aL), tobe(0x8861deedL), tobe(0xe8166c83L), tobe(0x347bf634L),
125.222 +tobe(0x2607bdf6L), tobe(0xfa6a2741L), tobe(0x9a1d952fL), tobe(0x46700f98L),
125.223 +tobe(0x5af2f1f3L), tobe(0x869f6b44L), tobe(0xe6e8d92aL), tobe(0x3a85439dL),
125.224 +tobe(0xdfed25fcL), tobe(0x0380bf4bL), tobe(0x63f70d25L), tobe(0xbf9a9792L),
125.225 +tobe(0xa31869f9L), tobe(0x7f75f34eL), tobe(0x1f024120L), tobe(0xc36fdb97L),
125.226 +tobe(0x3bfad6a4L), tobe(0xe7974c13L), tobe(0x87e0fe7dL), tobe(0x5b8d64caL),
125.227 +tobe(0x470f9aa1L), tobe(0x9b620016L), tobe(0xfb15b278L), tobe(0x277828cfL),
125.228 +tobe(0xc2104eaeL), tobe(0x1e7dd419L), tobe(0x7e0a6677L), tobe(0xa267fcc0L),
125.229 +tobe(0xbee502abL), tobe(0x6288981cL), tobe(0x02ff2a72L), tobe(0xde92b0c5L),
125.230 +tobe(0xcceefb07L), tobe(0x108361b0L), tobe(0x70f4d3deL), tobe(0xac994969L),
125.231 +tobe(0xb01bb702L), tobe(0x6c762db5L), tobe(0x0c019fdbL), tobe(0xd06c056cL),
125.232 +tobe(0x3504630dL), tobe(0xe969f9baL), tobe(0x891e4bd4L), tobe(0x5573d163L),
125.233 +tobe(0x49f12f08L), tobe(0x959cb5bfL), tobe(0xf5eb07d1L), tobe(0x29869d66L),
125.234 +tobe(0xa6e63d1dL), tobe(0x7a8ba7aaL), tobe(0x1afc15c4L), tobe(0xc6918f73L),
125.235 +tobe(0xda137118L), tobe(0x067eebafL), tobe(0x660959c1L), tobe(0xba64c376L),
125.236 +tobe(0x5f0ca517L), tobe(0x83613fa0L), tobe(0xe3168dceL), tobe(0x3f7b1779L),
125.237 +tobe(0x23f9e912L), tobe(0xff9473a5L), tobe(0x9fe3c1cbL), tobe(0x438e5b7cL),
125.238 +tobe(0x51f210beL), tobe(0x8d9f8a09L), tobe(0xede83867L), tobe(0x3185a2d0L),
125.239 +tobe(0x2d075cbbL), tobe(0xf16ac60cL), tobe(0x911d7462L), tobe(0x4d70eed5L),
125.240 +tobe(0xa81888b4L), tobe(0x74751203L), tobe(0x1402a06dL), tobe(0xc86f3adaL),
125.241 +tobe(0xd4edc4b1L), tobe(0x08805e06L), tobe(0x68f7ec68L), tobe(0xb49a76dfL),
125.242 +tobe(0x4c0f7becL), tobe(0x9062e15bL), tobe(0xf0155335L), tobe(0x2c78c982L),
125.243 +tobe(0x30fa37e9L), tobe(0xec97ad5eL), tobe(0x8ce01f30L), tobe(0x508d8587L),
125.244 +tobe(0xb5e5e3e6L), tobe(0x69887951L), tobe(0x09ffcb3fL), tobe(0xd5925188L),
125.245 +tobe(0xc910afe3L), tobe(0x157d3554L), tobe(0x750a873aL), tobe(0xa9671d8dL),
125.246 +tobe(0xbb1b564fL), tobe(0x6776ccf8L), tobe(0x07017e96L), tobe(0xdb6ce421L),
125.247 +tobe(0xc7ee1a4aL), tobe(0x1b8380fdL), tobe(0x7bf43293L), tobe(0xa799a824L),
125.248 +tobe(0x42f1ce45L), tobe(0x9e9c54f2L), tobe(0xfeebe69cL), tobe(0x22867c2bL),
125.249 +tobe(0x3e048240L), tobe(0xe26918f7L), tobe(0x821eaa99L), tobe(0x5e73302eL),
125.250 +tobe(0x77f5ad48L), tobe(0xab9837ffL), tobe(0xcbef8591L), tobe(0x17821f26L),
125.251 +tobe(0x0b00e14dL), tobe(0xd76d7bfaL), tobe(0xb71ac994L), tobe(0x6b775323L),
125.252 +tobe(0x8e1f3542L), tobe(0x5272aff5L), tobe(0x32051d9bL), tobe(0xee68872cL),
125.253 +tobe(0xf2ea7947L), tobe(0x2e87e3f0L), tobe(0x4ef0519eL), tobe(0x929dcb29L),
125.254 +tobe(0x80e180ebL), tobe(0x5c8c1a5cL), tobe(0x3cfba832L), tobe(0xe0963285L),
125.255 +tobe(0xfc14cceeL), tobe(0x20795659L), tobe(0x400ee437L), tobe(0x9c637e80L),
125.256 +tobe(0x790b18e1L), tobe(0xa5668256L), tobe(0xc5113038L), tobe(0x197caa8fL),
125.257 +tobe(0x05fe54e4L), tobe(0xd993ce53L), tobe(0xb9e47c3dL), tobe(0x6589e68aL),
125.258 +tobe(0x9d1cebb9L), tobe(0x4171710eL), tobe(0x2106c360L), tobe(0xfd6b59d7L),
125.259 +tobe(0xe1e9a7bcL), tobe(0x3d843d0bL), tobe(0x5df38f65L), tobe(0x819e15d2L),
125.260 +tobe(0x64f673b3L), tobe(0xb89be904L), tobe(0xd8ec5b6aL), tobe(0x0481c1ddL),
125.261 +tobe(0x18033fb6L), tobe(0xc46ea501L), tobe(0xa419176fL), tobe(0x78748dd8L),
125.262 +tobe(0x6a08c61aL), tobe(0xb6655cadL), tobe(0xd612eec3L), tobe(0x0a7f7474L),
125.263 +tobe(0x16fd8a1fL), tobe(0xca9010a8L), tobe(0xaae7a2c6L), tobe(0x768a3871L),
125.264 +tobe(0x93e25e10L), tobe(0x4f8fc4a7L), tobe(0x2ff876c9L), tobe(0xf395ec7eL),
125.265 +tobe(0xef171215L), tobe(0x337a88a2L), tobe(0x530d3accL), tobe(0x8f60a07bL)},
125.266 +{
125.267 +tobe(0x00000000L), tobe(0x490d678dL), tobe(0x921acf1aL), tobe(0xdb17a897L),
125.268 +tobe(0x20f48383L), tobe(0x69f9e40eL), tobe(0xb2ee4c99L), tobe(0xfbe32b14L),
125.269 +tobe(0x41e90706L), tobe(0x08e4608bL), tobe(0xd3f3c81cL), tobe(0x9afeaf91L),
125.270 +tobe(0x611d8485L), tobe(0x2810e308L), tobe(0xf3074b9fL), tobe(0xba0a2c12L),
125.271 +tobe(0x83d20e0cL), tobe(0xcadf6981L), tobe(0x11c8c116L), tobe(0x58c5a69bL),
125.272 +tobe(0xa3268d8fL), tobe(0xea2bea02L), tobe(0x313c4295L), tobe(0x78312518L),
125.273 +tobe(0xc23b090aL), tobe(0x8b366e87L), tobe(0x5021c610L), tobe(0x192ca19dL),
125.274 +tobe(0xe2cf8a89L), tobe(0xabc2ed04L), tobe(0x70d54593L), tobe(0x39d8221eL),
125.275 +tobe(0x036501afL), tobe(0x4a686622L), tobe(0x917fceb5L), tobe(0xd872a938L),
125.276 +tobe(0x2391822cL), tobe(0x6a9ce5a1L), tobe(0xb18b4d36L), tobe(0xf8862abbL),
125.277 +tobe(0x428c06a9L), tobe(0x0b816124L), tobe(0xd096c9b3L), tobe(0x999bae3eL),
125.278 +tobe(0x6278852aL), tobe(0x2b75e2a7L), tobe(0xf0624a30L), tobe(0xb96f2dbdL),
125.279 +tobe(0x80b70fa3L), tobe(0xc9ba682eL), tobe(0x12adc0b9L), tobe(0x5ba0a734L),
125.280 +tobe(0xa0438c20L), tobe(0xe94eebadL), tobe(0x3259433aL), tobe(0x7b5424b7L),
125.281 +tobe(0xc15e08a5L), tobe(0x88536f28L), tobe(0x5344c7bfL), tobe(0x1a49a032L),
125.282 +tobe(0xe1aa8b26L), tobe(0xa8a7ecabL), tobe(0x73b0443cL), tobe(0x3abd23b1L),
125.283 +tobe(0x06ca035eL), tobe(0x4fc764d3L), tobe(0x94d0cc44L), tobe(0xddddabc9L),
125.284 +tobe(0x263e80ddL), tobe(0x6f33e750L), tobe(0xb4244fc7L), tobe(0xfd29284aL),
125.285 +tobe(0x47230458L), tobe(0x0e2e63d5L), tobe(0xd539cb42L), tobe(0x9c34accfL),
125.286 +tobe(0x67d787dbL), tobe(0x2edae056L), tobe(0xf5cd48c1L), tobe(0xbcc02f4cL),
125.287 +tobe(0x85180d52L), tobe(0xcc156adfL), tobe(0x1702c248L), tobe(0x5e0fa5c5L),
125.288 +tobe(0xa5ec8ed1L), tobe(0xece1e95cL), tobe(0x37f641cbL), tobe(0x7efb2646L),
125.289 +tobe(0xc4f10a54L), tobe(0x8dfc6dd9L), tobe(0x56ebc54eL), tobe(0x1fe6a2c3L),
125.290 +tobe(0xe40589d7L), tobe(0xad08ee5aL), tobe(0x761f46cdL), tobe(0x3f122140L),
125.291 +tobe(0x05af02f1L), tobe(0x4ca2657cL), tobe(0x97b5cdebL), tobe(0xdeb8aa66L),
125.292 +tobe(0x255b8172L), tobe(0x6c56e6ffL), tobe(0xb7414e68L), tobe(0xfe4c29e5L),
125.293 +tobe(0x444605f7L), tobe(0x0d4b627aL), tobe(0xd65ccaedL), tobe(0x9f51ad60L),
125.294 +tobe(0x64b28674L), tobe(0x2dbfe1f9L), tobe(0xf6a8496eL), tobe(0xbfa52ee3L),
125.295 +tobe(0x867d0cfdL), tobe(0xcf706b70L), tobe(0x1467c3e7L), tobe(0x5d6aa46aL),
125.296 +tobe(0xa6898f7eL), tobe(0xef84e8f3L), tobe(0x34934064L), tobe(0x7d9e27e9L),
125.297 +tobe(0xc7940bfbL), tobe(0x8e996c76L), tobe(0x558ec4e1L), tobe(0x1c83a36cL),
125.298 +tobe(0xe7608878L), tobe(0xae6deff5L), tobe(0x757a4762L), tobe(0x3c7720efL),
125.299 +tobe(0x0d9406bcL), tobe(0x44996131L), tobe(0x9f8ec9a6L), tobe(0xd683ae2bL),
125.300 +tobe(0x2d60853fL), tobe(0x646de2b2L), tobe(0xbf7a4a25L), tobe(0xf6772da8L),
125.301 +tobe(0x4c7d01baL), tobe(0x05706637L), tobe(0xde67cea0L), tobe(0x976aa92dL),
125.302 +tobe(0x6c898239L), tobe(0x2584e5b4L), tobe(0xfe934d23L), tobe(0xb79e2aaeL),
125.303 +tobe(0x8e4608b0L), tobe(0xc74b6f3dL), tobe(0x1c5cc7aaL), tobe(0x5551a027L),
125.304 +tobe(0xaeb28b33L), tobe(0xe7bfecbeL), tobe(0x3ca84429L), tobe(0x75a523a4L),
125.305 +tobe(0xcfaf0fb6L), tobe(0x86a2683bL), tobe(0x5db5c0acL), tobe(0x14b8a721L),
125.306 +tobe(0xef5b8c35L), tobe(0xa656ebb8L), tobe(0x7d41432fL), tobe(0x344c24a2L),
125.307 +tobe(0x0ef10713L), tobe(0x47fc609eL), tobe(0x9cebc809L), tobe(0xd5e6af84L),
125.308 +tobe(0x2e058490L), tobe(0x6708e31dL), tobe(0xbc1f4b8aL), tobe(0xf5122c07L),
125.309 +tobe(0x4f180015L), tobe(0x06156798L), tobe(0xdd02cf0fL), tobe(0x940fa882L),
125.310 +tobe(0x6fec8396L), tobe(0x26e1e41bL), tobe(0xfdf64c8cL), tobe(0xb4fb2b01L),
125.311 +tobe(0x8d23091fL), tobe(0xc42e6e92L), tobe(0x1f39c605L), tobe(0x5634a188L),
125.312 +tobe(0xadd78a9cL), tobe(0xe4daed11L), tobe(0x3fcd4586L), tobe(0x76c0220bL),
125.313 +tobe(0xccca0e19L), tobe(0x85c76994L), tobe(0x5ed0c103L), tobe(0x17dda68eL),
125.314 +tobe(0xec3e8d9aL), tobe(0xa533ea17L), tobe(0x7e244280L), tobe(0x3729250dL),
125.315 +tobe(0x0b5e05e2L), tobe(0x4253626fL), tobe(0x9944caf8L), tobe(0xd049ad75L),
125.316 +tobe(0x2baa8661L), tobe(0x62a7e1ecL), tobe(0xb9b0497bL), tobe(0xf0bd2ef6L),
125.317 +tobe(0x4ab702e4L), tobe(0x03ba6569L), tobe(0xd8adcdfeL), tobe(0x91a0aa73L),
125.318 +tobe(0x6a438167L), tobe(0x234ee6eaL), tobe(0xf8594e7dL), tobe(0xb15429f0L),
125.319 +tobe(0x888c0beeL), tobe(0xc1816c63L), tobe(0x1a96c4f4L), tobe(0x539ba379L),
125.320 +tobe(0xa878886dL), tobe(0xe175efe0L), tobe(0x3a624777L), tobe(0x736f20faL),
125.321 +tobe(0xc9650ce8L), tobe(0x80686b65L), tobe(0x5b7fc3f2L), tobe(0x1272a47fL),
125.322 +tobe(0xe9918f6bL), tobe(0xa09ce8e6L), tobe(0x7b8b4071L), tobe(0x328627fcL),
125.323 +tobe(0x083b044dL), tobe(0x413663c0L), tobe(0x9a21cb57L), tobe(0xd32cacdaL),
125.324 +tobe(0x28cf87ceL), tobe(0x61c2e043L), tobe(0xbad548d4L), tobe(0xf3d82f59L),
125.325 +tobe(0x49d2034bL), tobe(0x00df64c6L), tobe(0xdbc8cc51L), tobe(0x92c5abdcL),
125.326 +tobe(0x692680c8L), tobe(0x202be745L), tobe(0xfb3c4fd2L), tobe(0xb231285fL),
125.327 +tobe(0x8be90a41L), tobe(0xc2e46dccL), tobe(0x19f3c55bL), tobe(0x50fea2d6L),
125.328 +tobe(0xab1d89c2L), tobe(0xe210ee4fL), tobe(0x390746d8L), tobe(0x700a2155L),
125.329 +tobe(0xca000d47L), tobe(0x830d6acaL), tobe(0x581ac25dL), tobe(0x1117a5d0L),
125.330 +tobe(0xeaf48ec4L), tobe(0xa3f9e949L), tobe(0x78ee41deL), tobe(0x31e32653L)},
125.331 +{
125.332 +tobe(0x00000000L), tobe(0x1b280d78L), tobe(0x36501af0L), tobe(0x2d781788L),
125.333 +tobe(0x6ca035e0L), tobe(0x77883898L), tobe(0x5af02f10L), tobe(0x41d82268L),
125.334 +tobe(0xd9406bc0L), tobe(0xc26866b8L), tobe(0xef107130L), tobe(0xf4387c48L),
125.335 +tobe(0xb5e05e20L), tobe(0xaec85358L), tobe(0x83b044d0L), tobe(0x989849a8L),
125.336 +tobe(0xb641ca37L), tobe(0xad69c74fL), tobe(0x8011d0c7L), tobe(0x9b39ddbfL),
125.337 +tobe(0xdae1ffd7L), tobe(0xc1c9f2afL), tobe(0xecb1e527L), tobe(0xf799e85fL),
125.338 +tobe(0x6f01a1f7L), tobe(0x7429ac8fL), tobe(0x5951bb07L), tobe(0x4279b67fL),
125.339 +tobe(0x03a19417L), tobe(0x1889996fL), tobe(0x35f18ee7L), tobe(0x2ed9839fL),
125.340 +tobe(0x684289d9L), tobe(0x736a84a1L), tobe(0x5e129329L), tobe(0x453a9e51L),
125.341 +tobe(0x04e2bc39L), tobe(0x1fcab141L), tobe(0x32b2a6c9L), tobe(0x299aabb1L),
125.342 +tobe(0xb102e219L), tobe(0xaa2aef61L), tobe(0x8752f8e9L), tobe(0x9c7af591L),
125.343 +tobe(0xdda2d7f9L), tobe(0xc68ada81L), tobe(0xebf2cd09L), tobe(0xf0dac071L),
125.344 +tobe(0xde0343eeL), tobe(0xc52b4e96L), tobe(0xe853591eL), tobe(0xf37b5466L),
125.345 +tobe(0xb2a3760eL), tobe(0xa98b7b76L), tobe(0x84f36cfeL), tobe(0x9fdb6186L),
125.346 +tobe(0x0743282eL), tobe(0x1c6b2556L), tobe(0x311332deL), tobe(0x2a3b3fa6L),
125.347 +tobe(0x6be31dceL), tobe(0x70cb10b6L), tobe(0x5db3073eL), tobe(0x469b0a46L),
125.348 +tobe(0xd08513b2L), tobe(0xcbad1ecaL), tobe(0xe6d50942L), tobe(0xfdfd043aL),
125.349 +tobe(0xbc252652L), tobe(0xa70d2b2aL), tobe(0x8a753ca2L), tobe(0x915d31daL),
125.350 +tobe(0x09c57872L), tobe(0x12ed750aL), tobe(0x3f956282L), tobe(0x24bd6ffaL),
125.351 +tobe(0x65654d92L), tobe(0x7e4d40eaL), tobe(0x53355762L), tobe(0x481d5a1aL),
125.352 +tobe(0x66c4d985L), tobe(0x7decd4fdL), tobe(0x5094c375L), tobe(0x4bbcce0dL),
125.353 +tobe(0x0a64ec65L), tobe(0x114ce11dL), tobe(0x3c34f695L), tobe(0x271cfbedL),
125.354 +tobe(0xbf84b245L), tobe(0xa4acbf3dL), tobe(0x89d4a8b5L), tobe(0x92fca5cdL),
125.355 +tobe(0xd32487a5L), tobe(0xc80c8addL), tobe(0xe5749d55L), tobe(0xfe5c902dL),
125.356 +tobe(0xb8c79a6bL), tobe(0xa3ef9713L), tobe(0x8e97809bL), tobe(0x95bf8de3L),
125.357 +tobe(0xd467af8bL), tobe(0xcf4fa2f3L), tobe(0xe237b57bL), tobe(0xf91fb803L),
125.358 +tobe(0x6187f1abL), tobe(0x7aaffcd3L), tobe(0x57d7eb5bL), tobe(0x4cffe623L),
125.359 +tobe(0x0d27c44bL), tobe(0x160fc933L), tobe(0x3b77debbL), tobe(0x205fd3c3L),
125.360 +tobe(0x0e86505cL), tobe(0x15ae5d24L), tobe(0x38d64aacL), tobe(0x23fe47d4L),
125.361 +tobe(0x622665bcL), tobe(0x790e68c4L), tobe(0x54767f4cL), tobe(0x4f5e7234L),
125.362 +tobe(0xd7c63b9cL), tobe(0xccee36e4L), tobe(0xe196216cL), tobe(0xfabe2c14L),
125.363 +tobe(0xbb660e7cL), tobe(0xa04e0304L), tobe(0x8d36148cL), tobe(0x961e19f4L),
125.364 +tobe(0xa5cb3ad3L), tobe(0xbee337abL), tobe(0x939b2023L), tobe(0x88b32d5bL),
125.365 +tobe(0xc96b0f33L), tobe(0xd243024bL), tobe(0xff3b15c3L), tobe(0xe41318bbL),
125.366 +tobe(0x7c8b5113L), tobe(0x67a35c6bL), tobe(0x4adb4be3L), tobe(0x51f3469bL),
125.367 +tobe(0x102b64f3L), tobe(0x0b03698bL), tobe(0x267b7e03L), tobe(0x3d53737bL),
125.368 +tobe(0x138af0e4L), tobe(0x08a2fd9cL), tobe(0x25daea14L), tobe(0x3ef2e76cL),
125.369 +tobe(0x7f2ac504L), tobe(0x6402c87cL), tobe(0x497adff4L), tobe(0x5252d28cL),
125.370 +tobe(0xcaca9b24L), tobe(0xd1e2965cL), tobe(0xfc9a81d4L), tobe(0xe7b28cacL),
125.371 +tobe(0xa66aaec4L), tobe(0xbd42a3bcL), tobe(0x903ab434L), tobe(0x8b12b94cL),
125.372 +tobe(0xcd89b30aL), tobe(0xd6a1be72L), tobe(0xfbd9a9faL), tobe(0xe0f1a482L),
125.373 +tobe(0xa12986eaL), tobe(0xba018b92L), tobe(0x97799c1aL), tobe(0x8c519162L),
125.374 +tobe(0x14c9d8caL), tobe(0x0fe1d5b2L), tobe(0x2299c23aL), tobe(0x39b1cf42L),
125.375 +tobe(0x7869ed2aL), tobe(0x6341e052L), tobe(0x4e39f7daL), tobe(0x5511faa2L),
125.376 +tobe(0x7bc8793dL), tobe(0x60e07445L), tobe(0x4d9863cdL), tobe(0x56b06eb5L),
125.377 +tobe(0x17684cddL), tobe(0x0c4041a5L), tobe(0x2138562dL), tobe(0x3a105b55L),
125.378 +tobe(0xa28812fdL), tobe(0xb9a01f85L), tobe(0x94d8080dL), tobe(0x8ff00575L),
125.379 +tobe(0xce28271dL), tobe(0xd5002a65L), tobe(0xf8783dedL), tobe(0xe3503095L),
125.380 +tobe(0x754e2961L), tobe(0x6e662419L), tobe(0x431e3391L), tobe(0x58363ee9L),
125.381 +tobe(0x19ee1c81L), tobe(0x02c611f9L), tobe(0x2fbe0671L), tobe(0x34960b09L),
125.382 +tobe(0xac0e42a1L), tobe(0xb7264fd9L), tobe(0x9a5e5851L), tobe(0x81765529L),
125.383 +tobe(0xc0ae7741L), tobe(0xdb867a39L), tobe(0xf6fe6db1L), tobe(0xedd660c9L),
125.384 +tobe(0xc30fe356L), tobe(0xd827ee2eL), tobe(0xf55ff9a6L), tobe(0xee77f4deL),
125.385 +tobe(0xafafd6b6L), tobe(0xb487dbceL), tobe(0x99ffcc46L), tobe(0x82d7c13eL),
125.386 +tobe(0x1a4f8896L), tobe(0x016785eeL), tobe(0x2c1f9266L), tobe(0x37379f1eL),
125.387 +tobe(0x76efbd76L), tobe(0x6dc7b00eL), tobe(0x40bfa786L), tobe(0x5b97aafeL),
125.388 +tobe(0x1d0ca0b8L), tobe(0x0624adc0L), tobe(0x2b5cba48L), tobe(0x3074b730L),
125.389 +tobe(0x71ac9558L), tobe(0x6a849820L), tobe(0x47fc8fa8L), tobe(0x5cd482d0L),
125.390 +tobe(0xc44ccb78L), tobe(0xdf64c600L), tobe(0xf21cd188L), tobe(0xe934dcf0L),
125.391 +tobe(0xa8ecfe98L), tobe(0xb3c4f3e0L), tobe(0x9ebce468L), tobe(0x8594e910L),
125.392 +tobe(0xab4d6a8fL), tobe(0xb06567f7L), tobe(0x9d1d707fL), tobe(0x86357d07L),
125.393 +tobe(0xc7ed5f6fL), tobe(0xdcc55217L), tobe(0xf1bd459fL), tobe(0xea9548e7L),
125.394 +tobe(0x720d014fL), tobe(0x69250c37L), tobe(0x445d1bbfL), tobe(0x5f7516c7L),
125.395 +tobe(0x1ead34afL), tobe(0x058539d7L), tobe(0x28fd2e5fL), tobe(0x33d52327L)},
125.396 +{
125.397 +tobe(0x00000000L), tobe(0x4f576811L), tobe(0x9eaed022L), tobe(0xd1f9b833L),
125.398 +tobe(0x399cbdf3L), tobe(0x76cbd5e2L), tobe(0xa7326dd1L), tobe(0xe86505c0L),
125.399 +tobe(0x73397be6L), tobe(0x3c6e13f7L), tobe(0xed97abc4L), tobe(0xa2c0c3d5L),
125.400 +tobe(0x4aa5c615L), tobe(0x05f2ae04L), tobe(0xd40b1637L), tobe(0x9b5c7e26L),
125.401 +tobe(0xe672f7ccL), tobe(0xa9259fddL), tobe(0x78dc27eeL), tobe(0x378b4fffL),
125.402 +tobe(0xdfee4a3fL), tobe(0x90b9222eL), tobe(0x41409a1dL), tobe(0x0e17f20cL),
125.403 +tobe(0x954b8c2aL), tobe(0xda1ce43bL), tobe(0x0be55c08L), tobe(0x44b23419L),
125.404 +tobe(0xacd731d9L), tobe(0xe38059c8L), tobe(0x3279e1fbL), tobe(0x7d2e89eaL),
125.405 +tobe(0xc824f22fL), tobe(0x87739a3eL), tobe(0x568a220dL), tobe(0x19dd4a1cL),
125.406 +tobe(0xf1b84fdcL), tobe(0xbeef27cdL), tobe(0x6f169ffeL), tobe(0x2041f7efL),
125.407 +tobe(0xbb1d89c9L), tobe(0xf44ae1d8L), tobe(0x25b359ebL), tobe(0x6ae431faL),
125.408 +tobe(0x8281343aL), tobe(0xcdd65c2bL), tobe(0x1c2fe418L), tobe(0x53788c09L),
125.409 +tobe(0x2e5605e3L), tobe(0x61016df2L), tobe(0xb0f8d5c1L), tobe(0xffafbdd0L),
125.410 +tobe(0x17cab810L), tobe(0x589dd001L), tobe(0x89646832L), tobe(0xc6330023L),
125.411 +tobe(0x5d6f7e05L), tobe(0x12381614L), tobe(0xc3c1ae27L), tobe(0x8c96c636L),
125.412 +tobe(0x64f3c3f6L), tobe(0x2ba4abe7L), tobe(0xfa5d13d4L), tobe(0xb50a7bc5L),
125.413 +tobe(0x9488f9e9L), tobe(0xdbdf91f8L), tobe(0x0a2629cbL), tobe(0x457141daL),
125.414 +tobe(0xad14441aL), tobe(0xe2432c0bL), tobe(0x33ba9438L), tobe(0x7cedfc29L),
125.415 +tobe(0xe7b1820fL), tobe(0xa8e6ea1eL), tobe(0x791f522dL), tobe(0x36483a3cL),
125.416 +tobe(0xde2d3ffcL), tobe(0x917a57edL), tobe(0x4083efdeL), tobe(0x0fd487cfL),
125.417 +tobe(0x72fa0e25L), tobe(0x3dad6634L), tobe(0xec54de07L), tobe(0xa303b616L),
125.418 +tobe(0x4b66b3d6L), tobe(0x0431dbc7L), tobe(0xd5c863f4L), tobe(0x9a9f0be5L),
125.419 +tobe(0x01c375c3L), tobe(0x4e941dd2L), tobe(0x9f6da5e1L), tobe(0xd03acdf0L),
125.420 +tobe(0x385fc830L), tobe(0x7708a021L), tobe(0xa6f11812L), tobe(0xe9a67003L),
125.421 +tobe(0x5cac0bc6L), tobe(0x13fb63d7L), tobe(0xc202dbe4L), tobe(0x8d55b3f5L),
125.422 +tobe(0x6530b635L), tobe(0x2a67de24L), tobe(0xfb9e6617L), tobe(0xb4c90e06L),
125.423 +tobe(0x2f957020L), tobe(0x60c21831L), tobe(0xb13ba002L), tobe(0xfe6cc813L),
125.424 +tobe(0x1609cdd3L), tobe(0x595ea5c2L), tobe(0x88a71df1L), tobe(0xc7f075e0L),
125.425 +tobe(0xbadefc0aL), tobe(0xf589941bL), tobe(0x24702c28L), tobe(0x6b274439L),
125.426 +tobe(0x834241f9L), tobe(0xcc1529e8L), tobe(0x1dec91dbL), tobe(0x52bbf9caL),
125.427 +tobe(0xc9e787ecL), tobe(0x86b0effdL), tobe(0x574957ceL), tobe(0x181e3fdfL),
125.428 +tobe(0xf07b3a1fL), tobe(0xbf2c520eL), tobe(0x6ed5ea3dL), tobe(0x2182822cL),
125.429 +tobe(0x2dd0ee65L), tobe(0x62878674L), tobe(0xb37e3e47L), tobe(0xfc295656L),
125.430 +tobe(0x144c5396L), tobe(0x5b1b3b87L), tobe(0x8ae283b4L), tobe(0xc5b5eba5L),
125.431 +tobe(0x5ee99583L), tobe(0x11befd92L), tobe(0xc04745a1L), tobe(0x8f102db0L),
125.432 +tobe(0x67752870L), tobe(0x28224061L), tobe(0xf9dbf852L), tobe(0xb68c9043L),
125.433 +tobe(0xcba219a9L), tobe(0x84f571b8L), tobe(0x550cc98bL), tobe(0x1a5ba19aL),
125.434 +tobe(0xf23ea45aL), tobe(0xbd69cc4bL), tobe(0x6c907478L), tobe(0x23c71c69L),
125.435 +tobe(0xb89b624fL), tobe(0xf7cc0a5eL), tobe(0x2635b26dL), tobe(0x6962da7cL),
125.436 +tobe(0x8107dfbcL), tobe(0xce50b7adL), tobe(0x1fa90f9eL), tobe(0x50fe678fL),
125.437 +tobe(0xe5f41c4aL), tobe(0xaaa3745bL), tobe(0x7b5acc68L), tobe(0x340da479L),
125.438 +tobe(0xdc68a1b9L), tobe(0x933fc9a8L), tobe(0x42c6719bL), tobe(0x0d91198aL),
125.439 +tobe(0x96cd67acL), tobe(0xd99a0fbdL), tobe(0x0863b78eL), tobe(0x4734df9fL),
125.440 +tobe(0xaf51da5fL), tobe(0xe006b24eL), tobe(0x31ff0a7dL), tobe(0x7ea8626cL),
125.441 +tobe(0x0386eb86L), tobe(0x4cd18397L), tobe(0x9d283ba4L), tobe(0xd27f53b5L),
125.442 +tobe(0x3a1a5675L), tobe(0x754d3e64L), tobe(0xa4b48657L), tobe(0xebe3ee46L),
125.443 +tobe(0x70bf9060L), tobe(0x3fe8f871L), tobe(0xee114042L), tobe(0xa1462853L),
125.444 +tobe(0x49232d93L), tobe(0x06744582L), tobe(0xd78dfdb1L), tobe(0x98da95a0L),
125.445 +tobe(0xb958178cL), tobe(0xf60f7f9dL), tobe(0x27f6c7aeL), tobe(0x68a1afbfL),
125.446 +tobe(0x80c4aa7fL), tobe(0xcf93c26eL), tobe(0x1e6a7a5dL), tobe(0x513d124cL),
125.447 +tobe(0xca616c6aL), tobe(0x8536047bL), tobe(0x54cfbc48L), tobe(0x1b98d459L),
125.448 +tobe(0xf3fdd199L), tobe(0xbcaab988L), tobe(0x6d5301bbL), tobe(0x220469aaL),
125.449 +tobe(0x5f2ae040L), tobe(0x107d8851L), tobe(0xc1843062L), tobe(0x8ed35873L),
125.450 +tobe(0x66b65db3L), tobe(0x29e135a2L), tobe(0xf8188d91L), tobe(0xb74fe580L),
125.451 +tobe(0x2c139ba6L), tobe(0x6344f3b7L), tobe(0xb2bd4b84L), tobe(0xfdea2395L),
125.452 +tobe(0x158f2655L), tobe(0x5ad84e44L), tobe(0x8b21f677L), tobe(0xc4769e66L),
125.453 +tobe(0x717ce5a3L), tobe(0x3e2b8db2L), tobe(0xefd23581L), tobe(0xa0855d90L),
125.454 +tobe(0x48e05850L), tobe(0x07b73041L), tobe(0xd64e8872L), tobe(0x9919e063L),
125.455 +tobe(0x02459e45L), tobe(0x4d12f654L), tobe(0x9ceb4e67L), tobe(0xd3bc2676L),
125.456 +tobe(0x3bd923b6L), tobe(0x748e4ba7L), tobe(0xa577f394L), tobe(0xea209b85L),
125.457 +tobe(0x970e126fL), tobe(0xd8597a7eL), tobe(0x09a0c24dL), tobe(0x46f7aa5cL),
125.458 +tobe(0xae92af9cL), tobe(0xe1c5c78dL), tobe(0x303c7fbeL), tobe(0x7f6b17afL),
125.459 +tobe(0xe4376989L), tobe(0xab600198L), tobe(0x7a99b9abL), tobe(0x35ced1baL),
125.460 +tobe(0xddabd47aL), tobe(0x92fcbc6bL), tobe(0x43050458L), tobe(0x0c526c49L)},
125.461 +{
125.462 +tobe(0x00000000L), tobe(0x5ba1dccaL), tobe(0xb743b994L), tobe(0xece2655eL),
125.463 +tobe(0x6a466e9fL), tobe(0x31e7b255L), tobe(0xdd05d70bL), tobe(0x86a40bc1L),
125.464 +tobe(0xd48cdd3eL), tobe(0x8f2d01f4L), tobe(0x63cf64aaL), tobe(0x386eb860L),
125.465 +tobe(0xbecab3a1L), tobe(0xe56b6f6bL), tobe(0x09890a35L), tobe(0x5228d6ffL),
125.466 +tobe(0xadd8a7cbL), tobe(0xf6797b01L), tobe(0x1a9b1e5fL), tobe(0x413ac295L),
125.467 +tobe(0xc79ec954L), tobe(0x9c3f159eL), tobe(0x70dd70c0L), tobe(0x2b7cac0aL),
125.468 +tobe(0x79547af5L), tobe(0x22f5a63fL), tobe(0xce17c361L), tobe(0x95b61fabL),
125.469 +tobe(0x1312146aL), tobe(0x48b3c8a0L), tobe(0xa451adfeL), tobe(0xfff07134L),
125.470 +tobe(0x5f705221L), tobe(0x04d18eebL), tobe(0xe833ebb5L), tobe(0xb392377fL),
125.471 +tobe(0x35363cbeL), tobe(0x6e97e074L), tobe(0x8275852aL), tobe(0xd9d459e0L),
125.472 +tobe(0x8bfc8f1fL), tobe(0xd05d53d5L), tobe(0x3cbf368bL), tobe(0x671eea41L),
125.473 +tobe(0xe1bae180L), tobe(0xba1b3d4aL), tobe(0x56f95814L), tobe(0x0d5884deL),
125.474 +tobe(0xf2a8f5eaL), tobe(0xa9092920L), tobe(0x45eb4c7eL), tobe(0x1e4a90b4L),
125.475 +tobe(0x98ee9b75L), tobe(0xc34f47bfL), tobe(0x2fad22e1L), tobe(0x740cfe2bL),
125.476 +tobe(0x262428d4L), tobe(0x7d85f41eL), tobe(0x91679140L), tobe(0xcac64d8aL),
125.477 +tobe(0x4c62464bL), tobe(0x17c39a81L), tobe(0xfb21ffdfL), tobe(0xa0802315L),
125.478 +tobe(0xbee0a442L), tobe(0xe5417888L), tobe(0x09a31dd6L), tobe(0x5202c11cL),
125.479 +tobe(0xd4a6caddL), tobe(0x8f071617L), tobe(0x63e57349L), tobe(0x3844af83L),
125.480 +tobe(0x6a6c797cL), tobe(0x31cda5b6L), tobe(0xdd2fc0e8L), tobe(0x868e1c22L),
125.481 +tobe(0x002a17e3L), tobe(0x5b8bcb29L), tobe(0xb769ae77L), tobe(0xecc872bdL),
125.482 +tobe(0x13380389L), tobe(0x4899df43L), tobe(0xa47bba1dL), tobe(0xffda66d7L),
125.483 +tobe(0x797e6d16L), tobe(0x22dfb1dcL), tobe(0xce3dd482L), tobe(0x959c0848L),
125.484 +tobe(0xc7b4deb7L), tobe(0x9c15027dL), tobe(0x70f76723L), tobe(0x2b56bbe9L),
125.485 +tobe(0xadf2b028L), tobe(0xf6536ce2L), tobe(0x1ab109bcL), tobe(0x4110d576L),
125.486 +tobe(0xe190f663L), tobe(0xba312aa9L), tobe(0x56d34ff7L), tobe(0x0d72933dL),
125.487 +tobe(0x8bd698fcL), tobe(0xd0774436L), tobe(0x3c952168L), tobe(0x6734fda2L),
125.488 +tobe(0x351c2b5dL), tobe(0x6ebdf797L), tobe(0x825f92c9L), tobe(0xd9fe4e03L),
125.489 +tobe(0x5f5a45c2L), tobe(0x04fb9908L), tobe(0xe819fc56L), tobe(0xb3b8209cL),
125.490 +tobe(0x4c4851a8L), tobe(0x17e98d62L), tobe(0xfb0be83cL), tobe(0xa0aa34f6L),
125.491 +tobe(0x260e3f37L), tobe(0x7dafe3fdL), tobe(0x914d86a3L), tobe(0xcaec5a69L),
125.492 +tobe(0x98c48c96L), tobe(0xc365505cL), tobe(0x2f873502L), tobe(0x7426e9c8L),
125.493 +tobe(0xf282e209L), tobe(0xa9233ec3L), tobe(0x45c15b9dL), tobe(0x1e608757L),
125.494 +tobe(0x79005533L), tobe(0x22a189f9L), tobe(0xce43eca7L), tobe(0x95e2306dL),
125.495 +tobe(0x13463bacL), tobe(0x48e7e766L), tobe(0xa4058238L), tobe(0xffa45ef2L),
125.496 +tobe(0xad8c880dL), tobe(0xf62d54c7L), tobe(0x1acf3199L), tobe(0x416eed53L),
125.497 +tobe(0xc7cae692L), tobe(0x9c6b3a58L), tobe(0x70895f06L), tobe(0x2b2883ccL),
125.498 +tobe(0xd4d8f2f8L), tobe(0x8f792e32L), tobe(0x639b4b6cL), tobe(0x383a97a6L),
125.499 +tobe(0xbe9e9c67L), tobe(0xe53f40adL), tobe(0x09dd25f3L), tobe(0x527cf939L),
125.500 +tobe(0x00542fc6L), tobe(0x5bf5f30cL), tobe(0xb7179652L), tobe(0xecb64a98L),
125.501 +tobe(0x6a124159L), tobe(0x31b39d93L), tobe(0xdd51f8cdL), tobe(0x86f02407L),
125.502 +tobe(0x26700712L), tobe(0x7dd1dbd8L), tobe(0x9133be86L), tobe(0xca92624cL),
125.503 +tobe(0x4c36698dL), tobe(0x1797b547L), tobe(0xfb75d019L), tobe(0xa0d40cd3L),
125.504 +tobe(0xf2fcda2cL), tobe(0xa95d06e6L), tobe(0x45bf63b8L), tobe(0x1e1ebf72L),
125.505 +tobe(0x98bab4b3L), tobe(0xc31b6879L), tobe(0x2ff90d27L), tobe(0x7458d1edL),
125.506 +tobe(0x8ba8a0d9L), tobe(0xd0097c13L), tobe(0x3ceb194dL), tobe(0x674ac587L),
125.507 +tobe(0xe1eece46L), tobe(0xba4f128cL), tobe(0x56ad77d2L), tobe(0x0d0cab18L),
125.508 +tobe(0x5f247de7L), tobe(0x0485a12dL), tobe(0xe867c473L), tobe(0xb3c618b9L),
125.509 +tobe(0x35621378L), tobe(0x6ec3cfb2L), tobe(0x8221aaecL), tobe(0xd9807626L),
125.510 +tobe(0xc7e0f171L), tobe(0x9c412dbbL), tobe(0x70a348e5L), tobe(0x2b02942fL),
125.511 +tobe(0xada69feeL), tobe(0xf6074324L), tobe(0x1ae5267aL), tobe(0x4144fab0L),
125.512 +tobe(0x136c2c4fL), tobe(0x48cdf085L), tobe(0xa42f95dbL), tobe(0xff8e4911L),
125.513 +tobe(0x792a42d0L), tobe(0x228b9e1aL), tobe(0xce69fb44L), tobe(0x95c8278eL),
125.514 +tobe(0x6a3856baL), tobe(0x31998a70L), tobe(0xdd7bef2eL), tobe(0x86da33e4L),
125.515 +tobe(0x007e3825L), tobe(0x5bdfe4efL), tobe(0xb73d81b1L), tobe(0xec9c5d7bL),
125.516 +tobe(0xbeb48b84L), tobe(0xe515574eL), tobe(0x09f73210L), tobe(0x5256eedaL),
125.517 +tobe(0xd4f2e51bL), tobe(0x8f5339d1L), tobe(0x63b15c8fL), tobe(0x38108045L),
125.518 +tobe(0x9890a350L), tobe(0xc3317f9aL), tobe(0x2fd31ac4L), tobe(0x7472c60eL),
125.519 +tobe(0xf2d6cdcfL), tobe(0xa9771105L), tobe(0x4595745bL), tobe(0x1e34a891L),
125.520 +tobe(0x4c1c7e6eL), tobe(0x17bda2a4L), tobe(0xfb5fc7faL), tobe(0xa0fe1b30L),
125.521 +tobe(0x265a10f1L), tobe(0x7dfbcc3bL), tobe(0x9119a965L), tobe(0xcab875afL),
125.522 +tobe(0x3548049bL), tobe(0x6ee9d851L), tobe(0x820bbd0fL), tobe(0xd9aa61c5L),
125.523 +tobe(0x5f0e6a04L), tobe(0x04afb6ceL), tobe(0xe84dd390L), tobe(0xb3ec0f5aL),
125.524 +tobe(0xe1c4d9a5L), tobe(0xba65056fL), tobe(0x56876031L), tobe(0x0d26bcfbL),
125.525 +tobe(0x8b82b73aL), tobe(0xd0236bf0L), tobe(0x3cc10eaeL), tobe(0x6760d264L)},
125.526 +};
125.527 +static const uint32_t crc32ctable_le[8][256] = {{
125.528 +tole(0x00000000L), tole(0xf26b8303L), tole(0xe13b70f7L), tole(0x1350f3f4L),
125.529 +tole(0xc79a971fL), tole(0x35f1141cL), tole(0x26a1e7e8L), tole(0xd4ca64ebL),
125.530 +tole(0x8ad958cfL), tole(0x78b2dbccL), tole(0x6be22838L), tole(0x9989ab3bL),
125.531 +tole(0x4d43cfd0L), tole(0xbf284cd3L), tole(0xac78bf27L), tole(0x5e133c24L),
125.532 +tole(0x105ec76fL), tole(0xe235446cL), tole(0xf165b798L), tole(0x030e349bL),
125.533 +tole(0xd7c45070L), tole(0x25afd373L), tole(0x36ff2087L), tole(0xc494a384L),
125.534 +tole(0x9a879fa0L), tole(0x68ec1ca3L), tole(0x7bbcef57L), tole(0x89d76c54L),
125.535 +tole(0x5d1d08bfL), tole(0xaf768bbcL), tole(0xbc267848L), tole(0x4e4dfb4bL),
125.536 +tole(0x20bd8edeL), tole(0xd2d60dddL), tole(0xc186fe29L), tole(0x33ed7d2aL),
125.537 +tole(0xe72719c1L), tole(0x154c9ac2L), tole(0x061c6936L), tole(0xf477ea35L),
125.538 +tole(0xaa64d611L), tole(0x580f5512L), tole(0x4b5fa6e6L), tole(0xb93425e5L),
125.539 +tole(0x6dfe410eL), tole(0x9f95c20dL), tole(0x8cc531f9L), tole(0x7eaeb2faL),
125.540 +tole(0x30e349b1L), tole(0xc288cab2L), tole(0xd1d83946L), tole(0x23b3ba45L),
125.541 +tole(0xf779deaeL), tole(0x05125dadL), tole(0x1642ae59L), tole(0xe4292d5aL),
125.542 +tole(0xba3a117eL), tole(0x4851927dL), tole(0x5b016189L), tole(0xa96ae28aL),
125.543 +tole(0x7da08661L), tole(0x8fcb0562L), tole(0x9c9bf696L), tole(0x6ef07595L),
125.544 +tole(0x417b1dbcL), tole(0xb3109ebfL), tole(0xa0406d4bL), tole(0x522bee48L),
125.545 +tole(0x86e18aa3L), tole(0x748a09a0L), tole(0x67dafa54L), tole(0x95b17957L),
125.546 +tole(0xcba24573L), tole(0x39c9c670L), tole(0x2a993584L), tole(0xd8f2b687L),
125.547 +tole(0x0c38d26cL), tole(0xfe53516fL), tole(0xed03a29bL), tole(0x1f682198L),
125.548 +tole(0x5125dad3L), tole(0xa34e59d0L), tole(0xb01eaa24L), tole(0x42752927L),
125.549 +tole(0x96bf4dccL), tole(0x64d4cecfL), tole(0x77843d3bL), tole(0x85efbe38L),
125.550 +tole(0xdbfc821cL), tole(0x2997011fL), tole(0x3ac7f2ebL), tole(0xc8ac71e8L),
125.551 +tole(0x1c661503L), tole(0xee0d9600L), tole(0xfd5d65f4L), tole(0x0f36e6f7L),
125.552 +tole(0x61c69362L), tole(0x93ad1061L), tole(0x80fde395L), tole(0x72966096L),
125.553 +tole(0xa65c047dL), tole(0x5437877eL), tole(0x4767748aL), tole(0xb50cf789L),
125.554 +tole(0xeb1fcbadL), tole(0x197448aeL), tole(0x0a24bb5aL), tole(0xf84f3859L),
125.555 +tole(0x2c855cb2L), tole(0xdeeedfb1L), tole(0xcdbe2c45L), tole(0x3fd5af46L),
125.556 +tole(0x7198540dL), tole(0x83f3d70eL), tole(0x90a324faL), tole(0x62c8a7f9L),
125.557 +tole(0xb602c312L), tole(0x44694011L), tole(0x5739b3e5L), tole(0xa55230e6L),
125.558 +tole(0xfb410cc2L), tole(0x092a8fc1L), tole(0x1a7a7c35L), tole(0xe811ff36L),
125.559 +tole(0x3cdb9bddL), tole(0xceb018deL), tole(0xdde0eb2aL), tole(0x2f8b6829L),
125.560 +tole(0x82f63b78L), tole(0x709db87bL), tole(0x63cd4b8fL), tole(0x91a6c88cL),
125.561 +tole(0x456cac67L), tole(0xb7072f64L), tole(0xa457dc90L), tole(0x563c5f93L),
125.562 +tole(0x082f63b7L), tole(0xfa44e0b4L), tole(0xe9141340L), tole(0x1b7f9043L),
125.563 +tole(0xcfb5f4a8L), tole(0x3dde77abL), tole(0x2e8e845fL), tole(0xdce5075cL),
125.564 +tole(0x92a8fc17L), tole(0x60c37f14L), tole(0x73938ce0L), tole(0x81f80fe3L),
125.565 +tole(0x55326b08L), tole(0xa759e80bL), tole(0xb4091bffL), tole(0x466298fcL),
125.566 +tole(0x1871a4d8L), tole(0xea1a27dbL), tole(0xf94ad42fL), tole(0x0b21572cL),
125.567 +tole(0xdfeb33c7L), tole(0x2d80b0c4L), tole(0x3ed04330L), tole(0xccbbc033L),
125.568 +tole(0xa24bb5a6L), tole(0x502036a5L), tole(0x4370c551L), tole(0xb11b4652L),
125.569 +tole(0x65d122b9L), tole(0x97baa1baL), tole(0x84ea524eL), tole(0x7681d14dL),
125.570 +tole(0x2892ed69L), tole(0xdaf96e6aL), tole(0xc9a99d9eL), tole(0x3bc21e9dL),
125.571 +tole(0xef087a76L), tole(0x1d63f975L), tole(0x0e330a81L), tole(0xfc588982L),
125.572 +tole(0xb21572c9L), tole(0x407ef1caL), tole(0x532e023eL), tole(0xa145813dL),
125.573 +tole(0x758fe5d6L), tole(0x87e466d5L), tole(0x94b49521L), tole(0x66df1622L),
125.574 +tole(0x38cc2a06L), tole(0xcaa7a905L), tole(0xd9f75af1L), tole(0x2b9cd9f2L),
125.575 +tole(0xff56bd19L), tole(0x0d3d3e1aL), tole(0x1e6dcdeeL), tole(0xec064eedL),
125.576 +tole(0xc38d26c4L), tole(0x31e6a5c7L), tole(0x22b65633L), tole(0xd0ddd530L),
125.577 +tole(0x0417b1dbL), tole(0xf67c32d8L), tole(0xe52cc12cL), tole(0x1747422fL),
125.578 +tole(0x49547e0bL), tole(0xbb3ffd08L), tole(0xa86f0efcL), tole(0x5a048dffL),
125.579 +tole(0x8ecee914L), tole(0x7ca56a17L), tole(0x6ff599e3L), tole(0x9d9e1ae0L),
125.580 +tole(0xd3d3e1abL), tole(0x21b862a8L), tole(0x32e8915cL), tole(0xc083125fL),
125.581 +tole(0x144976b4L), tole(0xe622f5b7L), tole(0xf5720643L), tole(0x07198540L),
125.582 +tole(0x590ab964L), tole(0xab613a67L), tole(0xb831c993L), tole(0x4a5a4a90L),
125.583 +tole(0x9e902e7bL), tole(0x6cfbad78L), tole(0x7fab5e8cL), tole(0x8dc0dd8fL),
125.584 +tole(0xe330a81aL), tole(0x115b2b19L), tole(0x020bd8edL), tole(0xf0605beeL),
125.585 +tole(0x24aa3f05L), tole(0xd6c1bc06L), tole(0xc5914ff2L), tole(0x37faccf1L),
125.586 +tole(0x69e9f0d5L), tole(0x9b8273d6L), tole(0x88d28022L), tole(0x7ab90321L),
125.587 +tole(0xae7367caL), tole(0x5c18e4c9L), tole(0x4f48173dL), tole(0xbd23943eL),
125.588 +tole(0xf36e6f75L), tole(0x0105ec76L), tole(0x12551f82L), tole(0xe03e9c81L),
125.589 +tole(0x34f4f86aL), tole(0xc69f7b69L), tole(0xd5cf889dL), tole(0x27a40b9eL),
125.590 +tole(0x79b737baL), tole(0x8bdcb4b9L), tole(0x988c474dL), tole(0x6ae7c44eL),
125.591 +tole(0xbe2da0a5L), tole(0x4c4623a6L), tole(0x5f16d052L), tole(0xad7d5351L)},
125.592 +{
125.593 +tole(0x00000000L), tole(0x13a29877L), tole(0x274530eeL), tole(0x34e7a899L),
125.594 +tole(0x4e8a61dcL), tole(0x5d28f9abL), tole(0x69cf5132L), tole(0x7a6dc945L),
125.595 +tole(0x9d14c3b8L), tole(0x8eb65bcfL), tole(0xba51f356L), tole(0xa9f36b21L),
125.596 +tole(0xd39ea264L), tole(0xc03c3a13L), tole(0xf4db928aL), tole(0xe7790afdL),
125.597 +tole(0x3fc5f181L), tole(0x2c6769f6L), tole(0x1880c16fL), tole(0x0b225918L),
125.598 +tole(0x714f905dL), tole(0x62ed082aL), tole(0x560aa0b3L), tole(0x45a838c4L),
125.599 +tole(0xa2d13239L), tole(0xb173aa4eL), tole(0x859402d7L), tole(0x96369aa0L),
125.600 +tole(0xec5b53e5L), tole(0xfff9cb92L), tole(0xcb1e630bL), tole(0xd8bcfb7cL),
125.601 +tole(0x7f8be302L), tole(0x6c297b75L), tole(0x58ced3ecL), tole(0x4b6c4b9bL),
125.602 +tole(0x310182deL), tole(0x22a31aa9L), tole(0x1644b230L), tole(0x05e62a47L),
125.603 +tole(0xe29f20baL), tole(0xf13db8cdL), tole(0xc5da1054L), tole(0xd6788823L),
125.604 +tole(0xac154166L), tole(0xbfb7d911L), tole(0x8b507188L), tole(0x98f2e9ffL),
125.605 +tole(0x404e1283L), tole(0x53ec8af4L), tole(0x670b226dL), tole(0x74a9ba1aL),
125.606 +tole(0x0ec4735fL), tole(0x1d66eb28L), tole(0x298143b1L), tole(0x3a23dbc6L),
125.607 +tole(0xdd5ad13bL), tole(0xcef8494cL), tole(0xfa1fe1d5L), tole(0xe9bd79a2L),
125.608 +tole(0x93d0b0e7L), tole(0x80722890L), tole(0xb4958009L), tole(0xa737187eL),
125.609 +tole(0xff17c604L), tole(0xecb55e73L), tole(0xd852f6eaL), tole(0xcbf06e9dL),
125.610 +tole(0xb19da7d8L), tole(0xa23f3fafL), tole(0x96d89736L), tole(0x857a0f41L),
125.611 +tole(0x620305bcL), tole(0x71a19dcbL), tole(0x45463552L), tole(0x56e4ad25L),
125.612 +tole(0x2c896460L), tole(0x3f2bfc17L), tole(0x0bcc548eL), tole(0x186eccf9L),
125.613 +tole(0xc0d23785L), tole(0xd370aff2L), tole(0xe797076bL), tole(0xf4359f1cL),
125.614 +tole(0x8e585659L), tole(0x9dface2eL), tole(0xa91d66b7L), tole(0xbabffec0L),
125.615 +tole(0x5dc6f43dL), tole(0x4e646c4aL), tole(0x7a83c4d3L), tole(0x69215ca4L),
125.616 +tole(0x134c95e1L), tole(0x00ee0d96L), tole(0x3409a50fL), tole(0x27ab3d78L),
125.617 +tole(0x809c2506L), tole(0x933ebd71L), tole(0xa7d915e8L), tole(0xb47b8d9fL),
125.618 +tole(0xce1644daL), tole(0xddb4dcadL), tole(0xe9537434L), tole(0xfaf1ec43L),
125.619 +tole(0x1d88e6beL), tole(0x0e2a7ec9L), tole(0x3acdd650L), tole(0x296f4e27L),
125.620 +tole(0x53028762L), tole(0x40a01f15L), tole(0x7447b78cL), tole(0x67e52ffbL),
125.621 +tole(0xbf59d487L), tole(0xacfb4cf0L), tole(0x981ce469L), tole(0x8bbe7c1eL),
125.622 +tole(0xf1d3b55bL), tole(0xe2712d2cL), tole(0xd69685b5L), tole(0xc5341dc2L),
125.623 +tole(0x224d173fL), tole(0x31ef8f48L), tole(0x050827d1L), tole(0x16aabfa6L),
125.624 +tole(0x6cc776e3L), tole(0x7f65ee94L), tole(0x4b82460dL), tole(0x5820de7aL),
125.625 +tole(0xfbc3faf9L), tole(0xe861628eL), tole(0xdc86ca17L), tole(0xcf245260L),
125.626 +tole(0xb5499b25L), tole(0xa6eb0352L), tole(0x920cabcbL), tole(0x81ae33bcL),
125.627 +tole(0x66d73941L), tole(0x7575a136L), tole(0x419209afL), tole(0x523091d8L),
125.628 +tole(0x285d589dL), tole(0x3bffc0eaL), tole(0x0f186873L), tole(0x1cbaf004L),
125.629 +tole(0xc4060b78L), tole(0xd7a4930fL), tole(0xe3433b96L), tole(0xf0e1a3e1L),
125.630 +tole(0x8a8c6aa4L), tole(0x992ef2d3L), tole(0xadc95a4aL), tole(0xbe6bc23dL),
125.631 +tole(0x5912c8c0L), tole(0x4ab050b7L), tole(0x7e57f82eL), tole(0x6df56059L),
125.632 +tole(0x1798a91cL), tole(0x043a316bL), tole(0x30dd99f2L), tole(0x237f0185L),
125.633 +tole(0x844819fbL), tole(0x97ea818cL), tole(0xa30d2915L), tole(0xb0afb162L),
125.634 +tole(0xcac27827L), tole(0xd960e050L), tole(0xed8748c9L), tole(0xfe25d0beL),
125.635 +tole(0x195cda43L), tole(0x0afe4234L), tole(0x3e19eaadL), tole(0x2dbb72daL),
125.636 +tole(0x57d6bb9fL), tole(0x447423e8L), tole(0x70938b71L), tole(0x63311306L),
125.637 +tole(0xbb8de87aL), tole(0xa82f700dL), tole(0x9cc8d894L), tole(0x8f6a40e3L),
125.638 +tole(0xf50789a6L), tole(0xe6a511d1L), tole(0xd242b948L), tole(0xc1e0213fL),
125.639 +tole(0x26992bc2L), tole(0x353bb3b5L), tole(0x01dc1b2cL), tole(0x127e835bL),
125.640 +tole(0x68134a1eL), tole(0x7bb1d269L), tole(0x4f567af0L), tole(0x5cf4e287L),
125.641 +tole(0x04d43cfdL), tole(0x1776a48aL), tole(0x23910c13L), tole(0x30339464L),
125.642 +tole(0x4a5e5d21L), tole(0x59fcc556L), tole(0x6d1b6dcfL), tole(0x7eb9f5b8L),
125.643 +tole(0x99c0ff45L), tole(0x8a626732L), tole(0xbe85cfabL), tole(0xad2757dcL),
125.644 +tole(0xd74a9e99L), tole(0xc4e806eeL), tole(0xf00fae77L), tole(0xe3ad3600L),
125.645 +tole(0x3b11cd7cL), tole(0x28b3550bL), tole(0x1c54fd92L), tole(0x0ff665e5L),
125.646 +tole(0x759baca0L), tole(0x663934d7L), tole(0x52de9c4eL), tole(0x417c0439L),
125.647 +tole(0xa6050ec4L), tole(0xb5a796b3L), tole(0x81403e2aL), tole(0x92e2a65dL),
125.648 +tole(0xe88f6f18L), tole(0xfb2df76fL), tole(0xcfca5ff6L), tole(0xdc68c781L),
125.649 +tole(0x7b5fdfffL), tole(0x68fd4788L), tole(0x5c1aef11L), tole(0x4fb87766L),
125.650 +tole(0x35d5be23L), tole(0x26772654L), tole(0x12908ecdL), tole(0x013216baL),
125.651 +tole(0xe64b1c47L), tole(0xf5e98430L), tole(0xc10e2ca9L), tole(0xd2acb4deL),
125.652 +tole(0xa8c17d9bL), tole(0xbb63e5ecL), tole(0x8f844d75L), tole(0x9c26d502L),
125.653 +tole(0x449a2e7eL), tole(0x5738b609L), tole(0x63df1e90L), tole(0x707d86e7L),
125.654 +tole(0x0a104fa2L), tole(0x19b2d7d5L), tole(0x2d557f4cL), tole(0x3ef7e73bL),
125.655 +tole(0xd98eedc6L), tole(0xca2c75b1L), tole(0xfecbdd28L), tole(0xed69455fL),
125.656 +tole(0x97048c1aL), tole(0x84a6146dL), tole(0xb041bcf4L), tole(0xa3e32483L)},
125.657 +{
125.658 +tole(0x00000000L), tole(0xa541927eL), tole(0x4f6f520dL), tole(0xea2ec073L),
125.659 +tole(0x9edea41aL), tole(0x3b9f3664L), tole(0xd1b1f617L), tole(0x74f06469L),
125.660 +tole(0x38513ec5L), tole(0x9d10acbbL), tole(0x773e6cc8L), tole(0xd27ffeb6L),
125.661 +tole(0xa68f9adfL), tole(0x03ce08a1L), tole(0xe9e0c8d2L), tole(0x4ca15aacL),
125.662 +tole(0x70a27d8aL), tole(0xd5e3eff4L), tole(0x3fcd2f87L), tole(0x9a8cbdf9L),
125.663 +tole(0xee7cd990L), tole(0x4b3d4beeL), tole(0xa1138b9dL), tole(0x045219e3L),
125.664 +tole(0x48f3434fL), tole(0xedb2d131L), tole(0x079c1142L), tole(0xa2dd833cL),
125.665 +tole(0xd62de755L), tole(0x736c752bL), tole(0x9942b558L), tole(0x3c032726L),
125.666 +tole(0xe144fb14L), tole(0x4405696aL), tole(0xae2ba919L), tole(0x0b6a3b67L),
125.667 +tole(0x7f9a5f0eL), tole(0xdadbcd70L), tole(0x30f50d03L), tole(0x95b49f7dL),
125.668 +tole(0xd915c5d1L), tole(0x7c5457afL), tole(0x967a97dcL), tole(0x333b05a2L),
125.669 +tole(0x47cb61cbL), tole(0xe28af3b5L), tole(0x08a433c6L), tole(0xade5a1b8L),
125.670 +tole(0x91e6869eL), tole(0x34a714e0L), tole(0xde89d493L), tole(0x7bc846edL),
125.671 +tole(0x0f382284L), tole(0xaa79b0faL), tole(0x40577089L), tole(0xe516e2f7L),
125.672 +tole(0xa9b7b85bL), tole(0x0cf62a25L), tole(0xe6d8ea56L), tole(0x43997828L),
125.673 +tole(0x37691c41L), tole(0x92288e3fL), tole(0x78064e4cL), tole(0xdd47dc32L),
125.674 +tole(0xc76580d9L), tole(0x622412a7L), tole(0x880ad2d4L), tole(0x2d4b40aaL),
125.675 +tole(0x59bb24c3L), tole(0xfcfab6bdL), tole(0x16d476ceL), tole(0xb395e4b0L),
125.676 +tole(0xff34be1cL), tole(0x5a752c62L), tole(0xb05bec11L), tole(0x151a7e6fL),
125.677 +tole(0x61ea1a06L), tole(0xc4ab8878L), tole(0x2e85480bL), tole(0x8bc4da75L),
125.678 +tole(0xb7c7fd53L), tole(0x12866f2dL), tole(0xf8a8af5eL), tole(0x5de93d20L),
125.679 +tole(0x29195949L), tole(0x8c58cb37L), tole(0x66760b44L), tole(0xc337993aL),
125.680 +tole(0x8f96c396L), tole(0x2ad751e8L), tole(0xc0f9919bL), tole(0x65b803e5L),
125.681 +tole(0x1148678cL), tole(0xb409f5f2L), tole(0x5e273581L), tole(0xfb66a7ffL),
125.682 +tole(0x26217bcdL), tole(0x8360e9b3L), tole(0x694e29c0L), tole(0xcc0fbbbeL),
125.683 +tole(0xb8ffdfd7L), tole(0x1dbe4da9L), tole(0xf7908ddaL), tole(0x52d11fa4L),
125.684 +tole(0x1e704508L), tole(0xbb31d776L), tole(0x511f1705L), tole(0xf45e857bL),
125.685 +tole(0x80aee112L), tole(0x25ef736cL), tole(0xcfc1b31fL), tole(0x6a802161L),
125.686 +tole(0x56830647L), tole(0xf3c29439L), tole(0x19ec544aL), tole(0xbcadc634L),
125.687 +tole(0xc85da25dL), tole(0x6d1c3023L), tole(0x8732f050L), tole(0x2273622eL),
125.688 +tole(0x6ed23882L), tole(0xcb93aafcL), tole(0x21bd6a8fL), tole(0x84fcf8f1L),
125.689 +tole(0xf00c9c98L), tole(0x554d0ee6L), tole(0xbf63ce95L), tole(0x1a225cebL),
125.690 +tole(0x8b277743L), tole(0x2e66e53dL), tole(0xc448254eL), tole(0x6109b730L),
125.691 +tole(0x15f9d359L), tole(0xb0b84127L), tole(0x5a968154L), tole(0xffd7132aL),
125.692 +tole(0xb3764986L), tole(0x1637dbf8L), tole(0xfc191b8bL), tole(0x595889f5L),
125.693 +tole(0x2da8ed9cL), tole(0x88e97fe2L), tole(0x62c7bf91L), tole(0xc7862defL),
125.694 +tole(0xfb850ac9L), tole(0x5ec498b7L), tole(0xb4ea58c4L), tole(0x11abcabaL),
125.695 +tole(0x655baed3L), tole(0xc01a3cadL), tole(0x2a34fcdeL), tole(0x8f756ea0L),
125.696 +tole(0xc3d4340cL), tole(0x6695a672L), tole(0x8cbb6601L), tole(0x29faf47fL),
125.697 +tole(0x5d0a9016L), tole(0xf84b0268L), tole(0x1265c21bL), tole(0xb7245065L),
125.698 +tole(0x6a638c57L), tole(0xcf221e29L), tole(0x250cde5aL), tole(0x804d4c24L),
125.699 +tole(0xf4bd284dL), tole(0x51fcba33L), tole(0xbbd27a40L), tole(0x1e93e83eL),
125.700 +tole(0x5232b292L), tole(0xf77320ecL), tole(0x1d5de09fL), tole(0xb81c72e1L),
125.701 +tole(0xccec1688L), tole(0x69ad84f6L), tole(0x83834485L), tole(0x26c2d6fbL),
125.702 +tole(0x1ac1f1ddL), tole(0xbf8063a3L), tole(0x55aea3d0L), tole(0xf0ef31aeL),
125.703 +tole(0x841f55c7L), tole(0x215ec7b9L), tole(0xcb7007caL), tole(0x6e3195b4L),
125.704 +tole(0x2290cf18L), tole(0x87d15d66L), tole(0x6dff9d15L), tole(0xc8be0f6bL),
125.705 +tole(0xbc4e6b02L), tole(0x190ff97cL), tole(0xf321390fL), tole(0x5660ab71L),
125.706 +tole(0x4c42f79aL), tole(0xe90365e4L), tole(0x032da597L), tole(0xa66c37e9L),
125.707 +tole(0xd29c5380L), tole(0x77ddc1feL), tole(0x9df3018dL), tole(0x38b293f3L),
125.708 +tole(0x7413c95fL), tole(0xd1525b21L), tole(0x3b7c9b52L), tole(0x9e3d092cL),
125.709 +tole(0xeacd6d45L), tole(0x4f8cff3bL), tole(0xa5a23f48L), tole(0x00e3ad36L),
125.710 +tole(0x3ce08a10L), tole(0x99a1186eL), tole(0x738fd81dL), tole(0xd6ce4a63L),
125.711 +tole(0xa23e2e0aL), tole(0x077fbc74L), tole(0xed517c07L), tole(0x4810ee79L),
125.712 +tole(0x04b1b4d5L), tole(0xa1f026abL), tole(0x4bdee6d8L), tole(0xee9f74a6L),
125.713 +tole(0x9a6f10cfL), tole(0x3f2e82b1L), tole(0xd50042c2L), tole(0x7041d0bcL),
125.714 +tole(0xad060c8eL), tole(0x08479ef0L), tole(0xe2695e83L), tole(0x4728ccfdL),
125.715 +tole(0x33d8a894L), tole(0x96993aeaL), tole(0x7cb7fa99L), tole(0xd9f668e7L),
125.716 +tole(0x9557324bL), tole(0x3016a035L), tole(0xda386046L), tole(0x7f79f238L),
125.717 +tole(0x0b899651L), tole(0xaec8042fL), tole(0x44e6c45cL), tole(0xe1a75622L),
125.718 +tole(0xdda47104L), tole(0x78e5e37aL), tole(0x92cb2309L), tole(0x378ab177L),
125.719 +tole(0x437ad51eL), tole(0xe63b4760L), tole(0x0c158713L), tole(0xa954156dL),
125.720 +tole(0xe5f54fc1L), tole(0x40b4ddbfL), tole(0xaa9a1dccL), tole(0x0fdb8fb2L),
125.721 +tole(0x7b2bebdbL), tole(0xde6a79a5L), tole(0x3444b9d6L), tole(0x91052ba8L)},
125.722 +{
125.723 +tole(0x00000000L), tole(0xdd45aab8L), tole(0xbf672381L), tole(0x62228939L),
125.724 +tole(0x7b2231f3L), tole(0xa6679b4bL), tole(0xc4451272L), tole(0x1900b8caL),
125.725 +tole(0xf64463e6L), tole(0x2b01c95eL), tole(0x49234067L), tole(0x9466eadfL),
125.726 +tole(0x8d665215L), tole(0x5023f8adL), tole(0x32017194L), tole(0xef44db2cL),
125.727 +tole(0xe964b13dL), tole(0x34211b85L), tole(0x560392bcL), tole(0x8b463804L),
125.728 +tole(0x924680ceL), tole(0x4f032a76L), tole(0x2d21a34fL), tole(0xf06409f7L),
125.729 +tole(0x1f20d2dbL), tole(0xc2657863L), tole(0xa047f15aL), tole(0x7d025be2L),
125.730 +tole(0x6402e328L), tole(0xb9474990L), tole(0xdb65c0a9L), tole(0x06206a11L),
125.731 +tole(0xd725148bL), tole(0x0a60be33L), tole(0x6842370aL), tole(0xb5079db2L),
125.732 +tole(0xac072578L), tole(0x71428fc0L), tole(0x136006f9L), tole(0xce25ac41L),
125.733 +tole(0x2161776dL), tole(0xfc24ddd5L), tole(0x9e0654ecL), tole(0x4343fe54L),
125.734 +tole(0x5a43469eL), tole(0x8706ec26L), tole(0xe524651fL), tole(0x3861cfa7L),
125.735 +tole(0x3e41a5b6L), tole(0xe3040f0eL), tole(0x81268637L), tole(0x5c632c8fL),
125.736 +tole(0x45639445L), tole(0x98263efdL), tole(0xfa04b7c4L), tole(0x27411d7cL),
125.737 +tole(0xc805c650L), tole(0x15406ce8L), tole(0x7762e5d1L), tole(0xaa274f69L),
125.738 +tole(0xb327f7a3L), tole(0x6e625d1bL), tole(0x0c40d422L), tole(0xd1057e9aL),
125.739 +tole(0xaba65fe7L), tole(0x76e3f55fL), tole(0x14c17c66L), tole(0xc984d6deL),
125.740 +tole(0xd0846e14L), tole(0x0dc1c4acL), tole(0x6fe34d95L), tole(0xb2a6e72dL),
125.741 +tole(0x5de23c01L), tole(0x80a796b9L), tole(0xe2851f80L), tole(0x3fc0b538L),
125.742 +tole(0x26c00df2L), tole(0xfb85a74aL), tole(0x99a72e73L), tole(0x44e284cbL),
125.743 +tole(0x42c2eedaL), tole(0x9f874462L), tole(0xfda5cd5bL), tole(0x20e067e3L),
125.744 +tole(0x39e0df29L), tole(0xe4a57591L), tole(0x8687fca8L), tole(0x5bc25610L),
125.745 +tole(0xb4868d3cL), tole(0x69c32784L), tole(0x0be1aebdL), tole(0xd6a40405L),
125.746 +tole(0xcfa4bccfL), tole(0x12e11677L), tole(0x70c39f4eL), tole(0xad8635f6L),
125.747 +tole(0x7c834b6cL), tole(0xa1c6e1d4L), tole(0xc3e468edL), tole(0x1ea1c255L),
125.748 +tole(0x07a17a9fL), tole(0xdae4d027L), tole(0xb8c6591eL), tole(0x6583f3a6L),
125.749 +tole(0x8ac7288aL), tole(0x57828232L), tole(0x35a00b0bL), tole(0xe8e5a1b3L),
125.750 +tole(0xf1e51979L), tole(0x2ca0b3c1L), tole(0x4e823af8L), tole(0x93c79040L),
125.751 +tole(0x95e7fa51L), tole(0x48a250e9L), tole(0x2a80d9d0L), tole(0xf7c57368L),
125.752 +tole(0xeec5cba2L), tole(0x3380611aL), tole(0x51a2e823L), tole(0x8ce7429bL),
125.753 +tole(0x63a399b7L), tole(0xbee6330fL), tole(0xdcc4ba36L), tole(0x0181108eL),
125.754 +tole(0x1881a844L), tole(0xc5c402fcL), tole(0xa7e68bc5L), tole(0x7aa3217dL),
125.755 +tole(0x52a0c93fL), tole(0x8fe56387L), tole(0xedc7eabeL), tole(0x30824006L),
125.756 +tole(0x2982f8ccL), tole(0xf4c75274L), tole(0x96e5db4dL), tole(0x4ba071f5L),
125.757 +tole(0xa4e4aad9L), tole(0x79a10061L), tole(0x1b838958L), tole(0xc6c623e0L),
125.758 +tole(0xdfc69b2aL), tole(0x02833192L), tole(0x60a1b8abL), tole(0xbde41213L),
125.759 +tole(0xbbc47802L), tole(0x6681d2baL), tole(0x04a35b83L), tole(0xd9e6f13bL),
125.760 +tole(0xc0e649f1L), tole(0x1da3e349L), tole(0x7f816a70L), tole(0xa2c4c0c8L),
125.761 +tole(0x4d801be4L), tole(0x90c5b15cL), tole(0xf2e73865L), tole(0x2fa292ddL),
125.762 +tole(0x36a22a17L), tole(0xebe780afL), tole(0x89c50996L), tole(0x5480a32eL),
125.763 +tole(0x8585ddb4L), tole(0x58c0770cL), tole(0x3ae2fe35L), tole(0xe7a7548dL),
125.764 +tole(0xfea7ec47L), tole(0x23e246ffL), tole(0x41c0cfc6L), tole(0x9c85657eL),
125.765 +tole(0x73c1be52L), tole(0xae8414eaL), tole(0xcca69dd3L), tole(0x11e3376bL),
125.766 +tole(0x08e38fa1L), tole(0xd5a62519L), tole(0xb784ac20L), tole(0x6ac10698L),
125.767 +tole(0x6ce16c89L), tole(0xb1a4c631L), tole(0xd3864f08L), tole(0x0ec3e5b0L),
125.768 +tole(0x17c35d7aL), tole(0xca86f7c2L), tole(0xa8a47efbL), tole(0x75e1d443L),
125.769 +tole(0x9aa50f6fL), tole(0x47e0a5d7L), tole(0x25c22ceeL), tole(0xf8878656L),
125.770 +tole(0xe1873e9cL), tole(0x3cc29424L), tole(0x5ee01d1dL), tole(0x83a5b7a5L),
125.771 +tole(0xf90696d8L), tole(0x24433c60L), tole(0x4661b559L), tole(0x9b241fe1L),
125.772 +tole(0x8224a72bL), tole(0x5f610d93L), tole(0x3d4384aaL), tole(0xe0062e12L),
125.773 +tole(0x0f42f53eL), tole(0xd2075f86L), tole(0xb025d6bfL), tole(0x6d607c07L),
125.774 +tole(0x7460c4cdL), tole(0xa9256e75L), tole(0xcb07e74cL), tole(0x16424df4L),
125.775 +tole(0x106227e5L), tole(0xcd278d5dL), tole(0xaf050464L), tole(0x7240aedcL),
125.776 +tole(0x6b401616L), tole(0xb605bcaeL), tole(0xd4273597L), tole(0x09629f2fL),
125.777 +tole(0xe6264403L), tole(0x3b63eebbL), tole(0x59416782L), tole(0x8404cd3aL),
125.778 +tole(0x9d0475f0L), tole(0x4041df48L), tole(0x22635671L), tole(0xff26fcc9L),
125.779 +tole(0x2e238253L), tole(0xf36628ebL), tole(0x9144a1d2L), tole(0x4c010b6aL),
125.780 +tole(0x5501b3a0L), tole(0x88441918L), tole(0xea669021L), tole(0x37233a99L),
125.781 +tole(0xd867e1b5L), tole(0x05224b0dL), tole(0x6700c234L), tole(0xba45688cL),
125.782 +tole(0xa345d046L), tole(0x7e007afeL), tole(0x1c22f3c7L), tole(0xc167597fL),
125.783 +tole(0xc747336eL), tole(0x1a0299d6L), tole(0x782010efL), tole(0xa565ba57L),
125.784 +tole(0xbc65029dL), tole(0x6120a825L), tole(0x0302211cL), tole(0xde478ba4L),
125.785 +tole(0x31035088L), tole(0xec46fa30L), tole(0x8e647309L), tole(0x5321d9b1L),
125.786 +tole(0x4a21617bL), tole(0x9764cbc3L), tole(0xf54642faL), tole(0x2803e842L)},
125.787 +{
125.788 +tole(0x00000000L), tole(0x38116facL), tole(0x7022df58L), tole(0x4833b0f4L),
125.789 +tole(0xe045beb0L), tole(0xd854d11cL), tole(0x906761e8L), tole(0xa8760e44L),
125.790 +tole(0xc5670b91L), tole(0xfd76643dL), tole(0xb545d4c9L), tole(0x8d54bb65L),
125.791 +tole(0x2522b521L), tole(0x1d33da8dL), tole(0x55006a79L), tole(0x6d1105d5L),
125.792 +tole(0x8f2261d3L), tole(0xb7330e7fL), tole(0xff00be8bL), tole(0xc711d127L),
125.793 +tole(0x6f67df63L), tole(0x5776b0cfL), tole(0x1f45003bL), tole(0x27546f97L),
125.794 +tole(0x4a456a42L), tole(0x725405eeL), tole(0x3a67b51aL), tole(0x0276dab6L),
125.795 +tole(0xaa00d4f2L), tole(0x9211bb5eL), tole(0xda220baaL), tole(0xe2336406L),
125.796 +tole(0x1ba8b557L), tole(0x23b9dafbL), tole(0x6b8a6a0fL), tole(0x539b05a3L),
125.797 +tole(0xfbed0be7L), tole(0xc3fc644bL), tole(0x8bcfd4bfL), tole(0xb3debb13L),
125.798 +tole(0xdecfbec6L), tole(0xe6ded16aL), tole(0xaeed619eL), tole(0x96fc0e32L),
125.799 +tole(0x3e8a0076L), tole(0x069b6fdaL), tole(0x4ea8df2eL), tole(0x76b9b082L),
125.800 +tole(0x948ad484L), tole(0xac9bbb28L), tole(0xe4a80bdcL), tole(0xdcb96470L),
125.801 +tole(0x74cf6a34L), tole(0x4cde0598L), tole(0x04edb56cL), tole(0x3cfcdac0L),
125.802 +tole(0x51eddf15L), tole(0x69fcb0b9L), tole(0x21cf004dL), tole(0x19de6fe1L),
125.803 +tole(0xb1a861a5L), tole(0x89b90e09L), tole(0xc18abefdL), tole(0xf99bd151L),
125.804 +tole(0x37516aaeL), tole(0x0f400502L), tole(0x4773b5f6L), tole(0x7f62da5aL),
125.805 +tole(0xd714d41eL), tole(0xef05bbb2L), tole(0xa7360b46L), tole(0x9f2764eaL),
125.806 +tole(0xf236613fL), tole(0xca270e93L), tole(0x8214be67L), tole(0xba05d1cbL),
125.807 +tole(0x1273df8fL), tole(0x2a62b023L), tole(0x625100d7L), tole(0x5a406f7bL),
125.808 +tole(0xb8730b7dL), tole(0x806264d1L), tole(0xc851d425L), tole(0xf040bb89L),
125.809 +tole(0x5836b5cdL), tole(0x6027da61L), tole(0x28146a95L), tole(0x10050539L),
125.810 +tole(0x7d1400ecL), tole(0x45056f40L), tole(0x0d36dfb4L), tole(0x3527b018L),
125.811 +tole(0x9d51be5cL), tole(0xa540d1f0L), tole(0xed736104L), tole(0xd5620ea8L),
125.812 +tole(0x2cf9dff9L), tole(0x14e8b055L), tole(0x5cdb00a1L), tole(0x64ca6f0dL),
125.813 +tole(0xccbc6149L), tole(0xf4ad0ee5L), tole(0xbc9ebe11L), tole(0x848fd1bdL),
125.814 +tole(0xe99ed468L), tole(0xd18fbbc4L), tole(0x99bc0b30L), tole(0xa1ad649cL),
125.815 +tole(0x09db6ad8L), tole(0x31ca0574L), tole(0x79f9b580L), tole(0x41e8da2cL),
125.816 +tole(0xa3dbbe2aL), tole(0x9bcad186L), tole(0xd3f96172L), tole(0xebe80edeL),
125.817 +tole(0x439e009aL), tole(0x7b8f6f36L), tole(0x33bcdfc2L), tole(0x0badb06eL),
125.818 +tole(0x66bcb5bbL), tole(0x5eadda17L), tole(0x169e6ae3L), tole(0x2e8f054fL),
125.819 +tole(0x86f90b0bL), tole(0xbee864a7L), tole(0xf6dbd453L), tole(0xcecabbffL),
125.820 +tole(0x6ea2d55cL), tole(0x56b3baf0L), tole(0x1e800a04L), tole(0x269165a8L),
125.821 +tole(0x8ee76becL), tole(0xb6f60440L), tole(0xfec5b4b4L), tole(0xc6d4db18L),
125.822 +tole(0xabc5decdL), tole(0x93d4b161L), tole(0xdbe70195L), tole(0xe3f66e39L),
125.823 +tole(0x4b80607dL), tole(0x73910fd1L), tole(0x3ba2bf25L), tole(0x03b3d089L),
125.824 +tole(0xe180b48fL), tole(0xd991db23L), tole(0x91a26bd7L), tole(0xa9b3047bL),
125.825 +tole(0x01c50a3fL), tole(0x39d46593L), tole(0x71e7d567L), tole(0x49f6bacbL),
125.826 +tole(0x24e7bf1eL), tole(0x1cf6d0b2L), tole(0x54c56046L), tole(0x6cd40feaL),
125.827 +tole(0xc4a201aeL), tole(0xfcb36e02L), tole(0xb480def6L), tole(0x8c91b15aL),
125.828 +tole(0x750a600bL), tole(0x4d1b0fa7L), tole(0x0528bf53L), tole(0x3d39d0ffL),
125.829 +tole(0x954fdebbL), tole(0xad5eb117L), tole(0xe56d01e3L), tole(0xdd7c6e4fL),
125.830 +tole(0xb06d6b9aL), tole(0x887c0436L), tole(0xc04fb4c2L), tole(0xf85edb6eL),
125.831 +tole(0x5028d52aL), tole(0x6839ba86L), tole(0x200a0a72L), tole(0x181b65deL),
125.832 +tole(0xfa2801d8L), tole(0xc2396e74L), tole(0x8a0ade80L), tole(0xb21bb12cL),
125.833 +tole(0x1a6dbf68L), tole(0x227cd0c4L), tole(0x6a4f6030L), tole(0x525e0f9cL),
125.834 +tole(0x3f4f0a49L), tole(0x075e65e5L), tole(0x4f6dd511L), tole(0x777cbabdL),
125.835 +tole(0xdf0ab4f9L), tole(0xe71bdb55L), tole(0xaf286ba1L), tole(0x9739040dL),
125.836 +tole(0x59f3bff2L), tole(0x61e2d05eL), tole(0x29d160aaL), tole(0x11c00f06L),
125.837 +tole(0xb9b60142L), tole(0x81a76eeeL), tole(0xc994de1aL), tole(0xf185b1b6L),
125.838 +tole(0x9c94b463L), tole(0xa485dbcfL), tole(0xecb66b3bL), tole(0xd4a70497L),
125.839 +tole(0x7cd10ad3L), tole(0x44c0657fL), tole(0x0cf3d58bL), tole(0x34e2ba27L),
125.840 +tole(0xd6d1de21L), tole(0xeec0b18dL), tole(0xa6f30179L), tole(0x9ee26ed5L),
125.841 +tole(0x36946091L), tole(0x0e850f3dL), tole(0x46b6bfc9L), tole(0x7ea7d065L),
125.842 +tole(0x13b6d5b0L), tole(0x2ba7ba1cL), tole(0x63940ae8L), tole(0x5b856544L),
125.843 +tole(0xf3f36b00L), tole(0xcbe204acL), tole(0x83d1b458L), tole(0xbbc0dbf4L),
125.844 +tole(0x425b0aa5L), tole(0x7a4a6509L), tole(0x3279d5fdL), tole(0x0a68ba51L),
125.845 +tole(0xa21eb415L), tole(0x9a0fdbb9L), tole(0xd23c6b4dL), tole(0xea2d04e1L),
125.846 +tole(0x873c0134L), tole(0xbf2d6e98L), tole(0xf71ede6cL), tole(0xcf0fb1c0L),
125.847 +tole(0x6779bf84L), tole(0x5f68d028L), tole(0x175b60dcL), tole(0x2f4a0f70L),
125.848 +tole(0xcd796b76L), tole(0xf56804daL), tole(0xbd5bb42eL), tole(0x854adb82L),
125.849 +tole(0x2d3cd5c6L), tole(0x152dba6aL), tole(0x5d1e0a9eL), tole(0x650f6532L),
125.850 +tole(0x081e60e7L), tole(0x300f0f4bL), tole(0x783cbfbfL), tole(0x402dd013L),
125.851 +tole(0xe85bde57L), tole(0xd04ab1fbL), tole(0x9879010fL), tole(0xa0686ea3L)},
125.852 +{
125.853 +tole(0x00000000L), tole(0xef306b19L), tole(0xdb8ca0c3L), tole(0x34bccbdaL),
125.854 +tole(0xb2f53777L), tole(0x5dc55c6eL), tole(0x697997b4L), tole(0x8649fcadL),
125.855 +tole(0x6006181fL), tole(0x8f367306L), tole(0xbb8ab8dcL), tole(0x54bad3c5L),
125.856 +tole(0xd2f32f68L), tole(0x3dc34471L), tole(0x097f8fabL), tole(0xe64fe4b2L),
125.857 +tole(0xc00c303eL), tole(0x2f3c5b27L), tole(0x1b8090fdL), tole(0xf4b0fbe4L),
125.858 +tole(0x72f90749L), tole(0x9dc96c50L), tole(0xa975a78aL), tole(0x4645cc93L),
125.859 +tole(0xa00a2821L), tole(0x4f3a4338L), tole(0x7b8688e2L), tole(0x94b6e3fbL),
125.860 +tole(0x12ff1f56L), tole(0xfdcf744fL), tole(0xc973bf95L), tole(0x2643d48cL),
125.861 +tole(0x85f4168dL), tole(0x6ac47d94L), tole(0x5e78b64eL), tole(0xb148dd57L),
125.862 +tole(0x370121faL), tole(0xd8314ae3L), tole(0xec8d8139L), tole(0x03bdea20L),
125.863 +tole(0xe5f20e92L), tole(0x0ac2658bL), tole(0x3e7eae51L), tole(0xd14ec548L),
125.864 +tole(0x570739e5L), tole(0xb83752fcL), tole(0x8c8b9926L), tole(0x63bbf23fL),
125.865 +tole(0x45f826b3L), tole(0xaac84daaL), tole(0x9e748670L), tole(0x7144ed69L),
125.866 +tole(0xf70d11c4L), tole(0x183d7addL), tole(0x2c81b107L), tole(0xc3b1da1eL),
125.867 +tole(0x25fe3eacL), tole(0xcace55b5L), tole(0xfe729e6fL), tole(0x1142f576L),
125.868 +tole(0x970b09dbL), tole(0x783b62c2L), tole(0x4c87a918L), tole(0xa3b7c201L),
125.869 +tole(0x0e045bebL), tole(0xe13430f2L), tole(0xd588fb28L), tole(0x3ab89031L),
125.870 +tole(0xbcf16c9cL), tole(0x53c10785L), tole(0x677dcc5fL), tole(0x884da746L),
125.871 +tole(0x6e0243f4L), tole(0x813228edL), tole(0xb58ee337L), tole(0x5abe882eL),
125.872 +tole(0xdcf77483L), tole(0x33c71f9aL), tole(0x077bd440L), tole(0xe84bbf59L),
125.873 +tole(0xce086bd5L), tole(0x213800ccL), tole(0x1584cb16L), tole(0xfab4a00fL),
125.874 +tole(0x7cfd5ca2L), tole(0x93cd37bbL), tole(0xa771fc61L), tole(0x48419778L),
125.875 +tole(0xae0e73caL), tole(0x413e18d3L), tole(0x7582d309L), tole(0x9ab2b810L),
125.876 +tole(0x1cfb44bdL), tole(0xf3cb2fa4L), tole(0xc777e47eL), tole(0x28478f67L),
125.877 +tole(0x8bf04d66L), tole(0x64c0267fL), tole(0x507ceda5L), tole(0xbf4c86bcL),
125.878 +tole(0x39057a11L), tole(0xd6351108L), tole(0xe289dad2L), tole(0x0db9b1cbL),
125.879 +tole(0xebf65579L), tole(0x04c63e60L), tole(0x307af5baL), tole(0xdf4a9ea3L),
125.880 +tole(0x5903620eL), tole(0xb6330917L), tole(0x828fc2cdL), tole(0x6dbfa9d4L),
125.881 +tole(0x4bfc7d58L), tole(0xa4cc1641L), tole(0x9070dd9bL), tole(0x7f40b682L),
125.882 +tole(0xf9094a2fL), tole(0x16392136L), tole(0x2285eaecL), tole(0xcdb581f5L),
125.883 +tole(0x2bfa6547L), tole(0xc4ca0e5eL), tole(0xf076c584L), tole(0x1f46ae9dL),
125.884 +tole(0x990f5230L), tole(0x763f3929L), tole(0x4283f2f3L), tole(0xadb399eaL),
125.885 +tole(0x1c08b7d6L), tole(0xf338dccfL), tole(0xc7841715L), tole(0x28b47c0cL),
125.886 +tole(0xaefd80a1L), tole(0x41cdebb8L), tole(0x75712062L), tole(0x9a414b7bL),
125.887 +tole(0x7c0eafc9L), tole(0x933ec4d0L), tole(0xa7820f0aL), tole(0x48b26413L),
125.888 +tole(0xcefb98beL), tole(0x21cbf3a7L), tole(0x1577387dL), tole(0xfa475364L),
125.889 +tole(0xdc0487e8L), tole(0x3334ecf1L), tole(0x0788272bL), tole(0xe8b84c32L),
125.890 +tole(0x6ef1b09fL), tole(0x81c1db86L), tole(0xb57d105cL), tole(0x5a4d7b45L),
125.891 +tole(0xbc029ff7L), tole(0x5332f4eeL), tole(0x678e3f34L), tole(0x88be542dL),
125.892 +tole(0x0ef7a880L), tole(0xe1c7c399L), tole(0xd57b0843L), tole(0x3a4b635aL),
125.893 +tole(0x99fca15bL), tole(0x76ccca42L), tole(0x42700198L), tole(0xad406a81L),
125.894 +tole(0x2b09962cL), tole(0xc439fd35L), tole(0xf08536efL), tole(0x1fb55df6L),
125.895 +tole(0xf9fab944L), tole(0x16cad25dL), tole(0x22761987L), tole(0xcd46729eL),
125.896 +tole(0x4b0f8e33L), tole(0xa43fe52aL), tole(0x90832ef0L), tole(0x7fb345e9L),
125.897 +tole(0x59f09165L), tole(0xb6c0fa7cL), tole(0x827c31a6L), tole(0x6d4c5abfL),
125.898 +tole(0xeb05a612L), tole(0x0435cd0bL), tole(0x308906d1L), tole(0xdfb96dc8L),
125.899 +tole(0x39f6897aL), tole(0xd6c6e263L), tole(0xe27a29b9L), tole(0x0d4a42a0L),
125.900 +tole(0x8b03be0dL), tole(0x6433d514L), tole(0x508f1eceL), tole(0xbfbf75d7L),
125.901 +tole(0x120cec3dL), tole(0xfd3c8724L), tole(0xc9804cfeL), tole(0x26b027e7L),
125.902 +tole(0xa0f9db4aL), tole(0x4fc9b053L), tole(0x7b757b89L), tole(0x94451090L),
125.903 +tole(0x720af422L), tole(0x9d3a9f3bL), tole(0xa98654e1L), tole(0x46b63ff8L),
125.904 +tole(0xc0ffc355L), tole(0x2fcfa84cL), tole(0x1b736396L), tole(0xf443088fL),
125.905 +tole(0xd200dc03L), tole(0x3d30b71aL), tole(0x098c7cc0L), tole(0xe6bc17d9L),
125.906 +tole(0x60f5eb74L), tole(0x8fc5806dL), tole(0xbb794bb7L), tole(0x544920aeL),
125.907 +tole(0xb206c41cL), tole(0x5d36af05L), tole(0x698a64dfL), tole(0x86ba0fc6L),
125.908 +tole(0x00f3f36bL), tole(0xefc39872L), tole(0xdb7f53a8L), tole(0x344f38b1L),
125.909 +tole(0x97f8fab0L), tole(0x78c891a9L), tole(0x4c745a73L), tole(0xa344316aL),
125.910 +tole(0x250dcdc7L), tole(0xca3da6deL), tole(0xfe816d04L), tole(0x11b1061dL),
125.911 +tole(0xf7fee2afL), tole(0x18ce89b6L), tole(0x2c72426cL), tole(0xc3422975L),
125.912 +tole(0x450bd5d8L), tole(0xaa3bbec1L), tole(0x9e87751bL), tole(0x71b71e02L),
125.913 +tole(0x57f4ca8eL), tole(0xb8c4a197L), tole(0x8c786a4dL), tole(0x63480154L),
125.914 +tole(0xe501fdf9L), tole(0x0a3196e0L), tole(0x3e8d5d3aL), tole(0xd1bd3623L),
125.915 +tole(0x37f2d291L), tole(0xd8c2b988L), tole(0xec7e7252L), tole(0x034e194bL),
125.916 +tole(0x8507e5e6L), tole(0x6a378effL), tole(0x5e8b4525L), tole(0xb1bb2e3cL)},
125.917 +{
125.918 +tole(0x00000000L), tole(0x68032cc8L), tole(0xd0065990L), tole(0xb8057558L),
125.919 +tole(0xa5e0c5d1L), tole(0xcde3e919L), tole(0x75e69c41L), tole(0x1de5b089L),
125.920 +tole(0x4e2dfd53L), tole(0x262ed19bL), tole(0x9e2ba4c3L), tole(0xf628880bL),
125.921 +tole(0xebcd3882L), tole(0x83ce144aL), tole(0x3bcb6112L), tole(0x53c84ddaL),
125.922 +tole(0x9c5bfaa6L), tole(0xf458d66eL), tole(0x4c5da336L), tole(0x245e8ffeL),
125.923 +tole(0x39bb3f77L), tole(0x51b813bfL), tole(0xe9bd66e7L), tole(0x81be4a2fL),
125.924 +tole(0xd27607f5L), tole(0xba752b3dL), tole(0x02705e65L), tole(0x6a7372adL),
125.925 +tole(0x7796c224L), tole(0x1f95eeecL), tole(0xa7909bb4L), tole(0xcf93b77cL),
125.926 +tole(0x3d5b83bdL), tole(0x5558af75L), tole(0xed5dda2dL), tole(0x855ef6e5L),
125.927 +tole(0x98bb466cL), tole(0xf0b86aa4L), tole(0x48bd1ffcL), tole(0x20be3334L),
125.928 +tole(0x73767eeeL), tole(0x1b755226L), tole(0xa370277eL), tole(0xcb730bb6L),
125.929 +tole(0xd696bb3fL), tole(0xbe9597f7L), tole(0x0690e2afL), tole(0x6e93ce67L),
125.930 +tole(0xa100791bL), tole(0xc90355d3L), tole(0x7106208bL), tole(0x19050c43L),
125.931 +tole(0x04e0bccaL), tole(0x6ce39002L), tole(0xd4e6e55aL), tole(0xbce5c992L),
125.932 +tole(0xef2d8448L), tole(0x872ea880L), tole(0x3f2bddd8L), tole(0x5728f110L),
125.933 +tole(0x4acd4199L), tole(0x22ce6d51L), tole(0x9acb1809L), tole(0xf2c834c1L),
125.934 +tole(0x7ab7077aL), tole(0x12b42bb2L), tole(0xaab15eeaL), tole(0xc2b27222L),
125.935 +tole(0xdf57c2abL), tole(0xb754ee63L), tole(0x0f519b3bL), tole(0x6752b7f3L),
125.936 +tole(0x349afa29L), tole(0x5c99d6e1L), tole(0xe49ca3b9L), tole(0x8c9f8f71L),
125.937 +tole(0x917a3ff8L), tole(0xf9791330L), tole(0x417c6668L), tole(0x297f4aa0L),
125.938 +tole(0xe6ecfddcL), tole(0x8eefd114L), tole(0x36eaa44cL), tole(0x5ee98884L),
125.939 +tole(0x430c380dL), tole(0x2b0f14c5L), tole(0x930a619dL), tole(0xfb094d55L),
125.940 +tole(0xa8c1008fL), tole(0xc0c22c47L), tole(0x78c7591fL), tole(0x10c475d7L),
125.941 +tole(0x0d21c55eL), tole(0x6522e996L), tole(0xdd279cceL), tole(0xb524b006L),
125.942 +tole(0x47ec84c7L), tole(0x2fefa80fL), tole(0x97eadd57L), tole(0xffe9f19fL),
125.943 +tole(0xe20c4116L), tole(0x8a0f6ddeL), tole(0x320a1886L), tole(0x5a09344eL),
125.944 +tole(0x09c17994L), tole(0x61c2555cL), tole(0xd9c72004L), tole(0xb1c40cccL),
125.945 +tole(0xac21bc45L), tole(0xc422908dL), tole(0x7c27e5d5L), tole(0x1424c91dL),
125.946 +tole(0xdbb77e61L), tole(0xb3b452a9L), tole(0x0bb127f1L), tole(0x63b20b39L),
125.947 +tole(0x7e57bbb0L), tole(0x16549778L), tole(0xae51e220L), tole(0xc652cee8L),
125.948 +tole(0x959a8332L), tole(0xfd99affaL), tole(0x459cdaa2L), tole(0x2d9ff66aL),
125.949 +tole(0x307a46e3L), tole(0x58796a2bL), tole(0xe07c1f73L), tole(0x887f33bbL),
125.950 +tole(0xf56e0ef4L), tole(0x9d6d223cL), tole(0x25685764L), tole(0x4d6b7bacL),
125.951 +tole(0x508ecb25L), tole(0x388de7edL), tole(0x808892b5L), tole(0xe88bbe7dL),
125.952 +tole(0xbb43f3a7L), tole(0xd340df6fL), tole(0x6b45aa37L), tole(0x034686ffL),
125.953 +tole(0x1ea33676L), tole(0x76a01abeL), tole(0xcea56fe6L), tole(0xa6a6432eL),
125.954 +tole(0x6935f452L), tole(0x0136d89aL), tole(0xb933adc2L), tole(0xd130810aL),
125.955 +tole(0xccd53183L), tole(0xa4d61d4bL), tole(0x1cd36813L), tole(0x74d044dbL),
125.956 +tole(0x27180901L), tole(0x4f1b25c9L), tole(0xf71e5091L), tole(0x9f1d7c59L),
125.957 +tole(0x82f8ccd0L), tole(0xeafbe018L), tole(0x52fe9540L), tole(0x3afdb988L),
125.958 +tole(0xc8358d49L), tole(0xa036a181L), tole(0x1833d4d9L), tole(0x7030f811L),
125.959 +tole(0x6dd54898L), tole(0x05d66450L), tole(0xbdd31108L), tole(0xd5d03dc0L),
125.960 +tole(0x8618701aL), tole(0xee1b5cd2L), tole(0x561e298aL), tole(0x3e1d0542L),
125.961 +tole(0x23f8b5cbL), tole(0x4bfb9903L), tole(0xf3feec5bL), tole(0x9bfdc093L),
125.962 +tole(0x546e77efL), tole(0x3c6d5b27L), tole(0x84682e7fL), tole(0xec6b02b7L),
125.963 +tole(0xf18eb23eL), tole(0x998d9ef6L), tole(0x2188ebaeL), tole(0x498bc766L),
125.964 +tole(0x1a438abcL), tole(0x7240a674L), tole(0xca45d32cL), tole(0xa246ffe4L),
125.965 +tole(0xbfa34f6dL), tole(0xd7a063a5L), tole(0x6fa516fdL), tole(0x07a63a35L),
125.966 +tole(0x8fd9098eL), tole(0xe7da2546L), tole(0x5fdf501eL), tole(0x37dc7cd6L),
125.967 +tole(0x2a39cc5fL), tole(0x423ae097L), tole(0xfa3f95cfL), tole(0x923cb907L),
125.968 +tole(0xc1f4f4ddL), tole(0xa9f7d815L), tole(0x11f2ad4dL), tole(0x79f18185L),
125.969 +tole(0x6414310cL), tole(0x0c171dc4L), tole(0xb412689cL), tole(0xdc114454L),
125.970 +tole(0x1382f328L), tole(0x7b81dfe0L), tole(0xc384aab8L), tole(0xab878670L),
125.971 +tole(0xb66236f9L), tole(0xde611a31L), tole(0x66646f69L), tole(0x0e6743a1L),
125.972 +tole(0x5daf0e7bL), tole(0x35ac22b3L), tole(0x8da957ebL), tole(0xe5aa7b23L),
125.973 +tole(0xf84fcbaaL), tole(0x904ce762L), tole(0x2849923aL), tole(0x404abef2L),
125.974 +tole(0xb2828a33L), tole(0xda81a6fbL), tole(0x6284d3a3L), tole(0x0a87ff6bL),
125.975 +tole(0x17624fe2L), tole(0x7f61632aL), tole(0xc7641672L), tole(0xaf673abaL),
125.976 +tole(0xfcaf7760L), tole(0x94ac5ba8L), tole(0x2ca92ef0L), tole(0x44aa0238L),
125.977 +tole(0x594fb2b1L), tole(0x314c9e79L), tole(0x8949eb21L), tole(0xe14ac7e9L),
125.978 +tole(0x2ed97095L), tole(0x46da5c5dL), tole(0xfedf2905L), tole(0x96dc05cdL),
125.979 +tole(0x8b39b544L), tole(0xe33a998cL), tole(0x5b3fecd4L), tole(0x333cc01cL),
125.980 +tole(0x60f48dc6L), tole(0x08f7a10eL), tole(0xb0f2d456L), tole(0xd8f1f89eL),
125.981 +tole(0xc5144817L), tole(0xad1764dfL), tole(0x15121187L), tole(0x7d113d4fL)},
125.982 +{
125.983 +tole(0x00000000L), tole(0x493c7d27L), tole(0x9278fa4eL), tole(0xdb448769L),
125.984 +tole(0x211d826dL), tole(0x6821ff4aL), tole(0xb3657823L), tole(0xfa590504L),
125.985 +tole(0x423b04daL), tole(0x0b0779fdL), tole(0xd043fe94L), tole(0x997f83b3L),
125.986 +tole(0x632686b7L), tole(0x2a1afb90L), tole(0xf15e7cf9L), tole(0xb86201deL),
125.987 +tole(0x847609b4L), tole(0xcd4a7493L), tole(0x160ef3faL), tole(0x5f328eddL),
125.988 +tole(0xa56b8bd9L), tole(0xec57f6feL), tole(0x37137197L), tole(0x7e2f0cb0L),
125.989 +tole(0xc64d0d6eL), tole(0x8f717049L), tole(0x5435f720L), tole(0x1d098a07L),
125.990 +tole(0xe7508f03L), tole(0xae6cf224L), tole(0x7528754dL), tole(0x3c14086aL),
125.991 +tole(0x0d006599L), tole(0x443c18beL), tole(0x9f789fd7L), tole(0xd644e2f0L),
125.992 +tole(0x2c1de7f4L), tole(0x65219ad3L), tole(0xbe651dbaL), tole(0xf759609dL),
125.993 +tole(0x4f3b6143L), tole(0x06071c64L), tole(0xdd439b0dL), tole(0x947fe62aL),
125.994 +tole(0x6e26e32eL), tole(0x271a9e09L), tole(0xfc5e1960L), tole(0xb5626447L),
125.995 +tole(0x89766c2dL), tole(0xc04a110aL), tole(0x1b0e9663L), tole(0x5232eb44L),
125.996 +tole(0xa86bee40L), tole(0xe1579367L), tole(0x3a13140eL), tole(0x732f6929L),
125.997 +tole(0xcb4d68f7L), tole(0x827115d0L), tole(0x593592b9L), tole(0x1009ef9eL),
125.998 +tole(0xea50ea9aL), tole(0xa36c97bdL), tole(0x782810d4L), tole(0x31146df3L),
125.999 +tole(0x1a00cb32L), tole(0x533cb615L), tole(0x8878317cL), tole(0xc1444c5bL),
125.1000 +tole(0x3b1d495fL), tole(0x72213478L), tole(0xa965b311L), tole(0xe059ce36L),
125.1001 +tole(0x583bcfe8L), tole(0x1107b2cfL), tole(0xca4335a6L), tole(0x837f4881L),
125.1002 +tole(0x79264d85L), tole(0x301a30a2L), tole(0xeb5eb7cbL), tole(0xa262caecL),
125.1003 +tole(0x9e76c286L), tole(0xd74abfa1L), tole(0x0c0e38c8L), tole(0x453245efL),
125.1004 +tole(0xbf6b40ebL), tole(0xf6573dccL), tole(0x2d13baa5L), tole(0x642fc782L),
125.1005 +tole(0xdc4dc65cL), tole(0x9571bb7bL), tole(0x4e353c12L), tole(0x07094135L),
125.1006 +tole(0xfd504431L), tole(0xb46c3916L), tole(0x6f28be7fL), tole(0x2614c358L),
125.1007 +tole(0x1700aeabL), tole(0x5e3cd38cL), tole(0x857854e5L), tole(0xcc4429c2L),
125.1008 +tole(0x361d2cc6L), tole(0x7f2151e1L), tole(0xa465d688L), tole(0xed59abafL),
125.1009 +tole(0x553baa71L), tole(0x1c07d756L), tole(0xc743503fL), tole(0x8e7f2d18L),
125.1010 +tole(0x7426281cL), tole(0x3d1a553bL), tole(0xe65ed252L), tole(0xaf62af75L),
125.1011 +tole(0x9376a71fL), tole(0xda4ada38L), tole(0x010e5d51L), tole(0x48322076L),
125.1012 +tole(0xb26b2572L), tole(0xfb575855L), tole(0x2013df3cL), tole(0x692fa21bL),
125.1013 +tole(0xd14da3c5L), tole(0x9871dee2L), tole(0x4335598bL), tole(0x0a0924acL),
125.1014 +tole(0xf05021a8L), tole(0xb96c5c8fL), tole(0x6228dbe6L), tole(0x2b14a6c1L),
125.1015 +tole(0x34019664L), tole(0x7d3deb43L), tole(0xa6796c2aL), tole(0xef45110dL),
125.1016 +tole(0x151c1409L), tole(0x5c20692eL), tole(0x8764ee47L), tole(0xce589360L),
125.1017 +tole(0x763a92beL), tole(0x3f06ef99L), tole(0xe44268f0L), tole(0xad7e15d7L),
125.1018 +tole(0x572710d3L), tole(0x1e1b6df4L), tole(0xc55fea9dL), tole(0x8c6397baL),
125.1019 +tole(0xb0779fd0L), tole(0xf94be2f7L), tole(0x220f659eL), tole(0x6b3318b9L),
125.1020 +tole(0x916a1dbdL), tole(0xd856609aL), tole(0x0312e7f3L), tole(0x4a2e9ad4L),
125.1021 +tole(0xf24c9b0aL), tole(0xbb70e62dL), tole(0x60346144L), tole(0x29081c63L),
125.1022 +tole(0xd3511967L), tole(0x9a6d6440L), tole(0x4129e329L), tole(0x08159e0eL),
125.1023 +tole(0x3901f3fdL), tole(0x703d8edaL), tole(0xab7909b3L), tole(0xe2457494L),
125.1024 +tole(0x181c7190L), tole(0x51200cb7L), tole(0x8a648bdeL), tole(0xc358f6f9L),
125.1025 +tole(0x7b3af727L), tole(0x32068a00L), tole(0xe9420d69L), tole(0xa07e704eL),
125.1026 +tole(0x5a27754aL), tole(0x131b086dL), tole(0xc85f8f04L), tole(0x8163f223L),
125.1027 +tole(0xbd77fa49L), tole(0xf44b876eL), tole(0x2f0f0007L), tole(0x66337d20L),
125.1028 +tole(0x9c6a7824L), tole(0xd5560503L), tole(0x0e12826aL), tole(0x472eff4dL),
125.1029 +tole(0xff4cfe93L), tole(0xb67083b4L), tole(0x6d3404ddL), tole(0x240879faL),
125.1030 +tole(0xde517cfeL), tole(0x976d01d9L), tole(0x4c2986b0L), tole(0x0515fb97L),
125.1031 +tole(0x2e015d56L), tole(0x673d2071L), tole(0xbc79a718L), tole(0xf545da3fL),
125.1032 +tole(0x0f1cdf3bL), tole(0x4620a21cL), tole(0x9d642575L), tole(0xd4585852L),
125.1033 +tole(0x6c3a598cL), tole(0x250624abL), tole(0xfe42a3c2L), tole(0xb77edee5L),
125.1034 +tole(0x4d27dbe1L), tole(0x041ba6c6L), tole(0xdf5f21afL), tole(0x96635c88L),
125.1035 +tole(0xaa7754e2L), tole(0xe34b29c5L), tole(0x380faeacL), tole(0x7133d38bL),
125.1036 +tole(0x8b6ad68fL), tole(0xc256aba8L), tole(0x19122cc1L), tole(0x502e51e6L),
125.1037 +tole(0xe84c5038L), tole(0xa1702d1fL), tole(0x7a34aa76L), tole(0x3308d751L),
125.1038 +tole(0xc951d255L), tole(0x806daf72L), tole(0x5b29281bL), tole(0x1215553cL),
125.1039 +tole(0x230138cfL), tole(0x6a3d45e8L), tole(0xb179c281L), tole(0xf845bfa6L),
125.1040 +tole(0x021cbaa2L), tole(0x4b20c785L), tole(0x906440ecL), tole(0xd9583dcbL),
125.1041 +tole(0x613a3c15L), tole(0x28064132L), tole(0xf342c65bL), tole(0xba7ebb7cL),
125.1042 +tole(0x4027be78L), tole(0x091bc35fL), tole(0xd25f4436L), tole(0x9b633911L),
125.1043 +tole(0xa777317bL), tole(0xee4b4c5cL), tole(0x350fcb35L), tole(0x7c33b612L),
125.1044 +tole(0x866ab316L), tole(0xcf56ce31L), tole(0x14124958L), tole(0x5d2e347fL),
125.1045 +tole(0xe54c35a1L), tole(0xac704886L), tole(0x7734cfefL), tole(0x3e08b2c8L),
125.1046 +tole(0xc451b7ccL), tole(0x8d6dcaebL), tole(0x56294d82L), tole(0x1f1530a5L)},
125.1047 +};
126.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
126.2 +++ b/libext2fs/lib/libext2fs/csum.c Wed Aug 25 01:28:08 2021 +0200
126.3 @@ -0,0 +1,1020 @@
126.4 +/*
126.5 + * csum.c --- checksumming of ext3 structures
126.6 + *
126.7 + * Copyright (C) 2006 Cluster File Systems, Inc.
126.8 + * Copyright (C) 2006, 2007 by Andreas Dilger <adilger@clusterfs.com>
126.9 + *
126.10 + * %Begin-Header%
126.11 + * This file may be redistributed under the terms of the GNU Library
126.12 + * General Public License, version 2.
126.13 + * %End-Header%
126.14 + */
126.15 +
126.16 +#include "config.h"
126.17 +#if HAVE_SYS_TYPES_H
126.18 +#include <sys/types.h>
126.19 +#endif
126.20 +
126.21 +#include "ext2_fs.h"
126.22 +#include "ext2fs.h"
126.23 +#include "crc16.h"
126.24 +#include <assert.h>
126.25 +
126.26 +#ifndef offsetof
126.27 +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
126.28 +#endif
126.29 +
126.30 +#ifdef DEBUG
126.31 +#define STATIC
126.32 +#else
126.33 +#define STATIC static
126.34 +#endif
126.35 +
126.36 +void ext2fs_init_csum_seed(ext2_filsys fs)
126.37 +{
126.38 + if (ext2fs_has_feature_csum_seed(fs->super))
126.39 + fs->csum_seed = fs->super->s_checksum_seed;
126.40 + else if (ext2fs_has_feature_metadata_csum(fs->super) ||
126.41 + ext2fs_has_feature_ea_inode(fs->super))
126.42 + fs->csum_seed = ext2fs_crc32c_le(~0, fs->super->s_uuid,
126.43 + sizeof(fs->super->s_uuid));
126.44 +}
126.45 +
126.46 +static __u32 ext2fs_mmp_csum(ext2_filsys fs, struct mmp_struct *mmp)
126.47 +{
126.48 + int offset = offsetof(struct mmp_struct, mmp_checksum);
126.49 +
126.50 + return ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)mmp, offset);
126.51 +}
126.52 +
126.53 +int ext2fs_mmp_csum_verify(ext2_filsys fs, struct mmp_struct *mmp)
126.54 +{
126.55 + __u32 calculated;
126.56 +
126.57 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.58 + return 1;
126.59 +
126.60 + calculated = ext2fs_mmp_csum(fs, mmp);
126.61 +
126.62 + return ext2fs_le32_to_cpu(mmp->mmp_checksum) == calculated;
126.63 +}
126.64 +
126.65 +errcode_t ext2fs_mmp_csum_set(ext2_filsys fs, struct mmp_struct *mmp)
126.66 +{
126.67 + __u32 crc;
126.68 +
126.69 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.70 + return 0;
126.71 +
126.72 + crc = ext2fs_mmp_csum(fs, mmp);
126.73 + mmp->mmp_checksum = ext2fs_cpu_to_le32(crc);
126.74 +
126.75 + return 0;
126.76 +}
126.77 +
126.78 +int ext2fs_verify_csum_type(ext2_filsys fs, struct ext2_super_block *sb)
126.79 +{
126.80 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.81 + return 1;
126.82 +
126.83 + return sb->s_checksum_type == EXT2_CRC32C_CHKSUM;
126.84 +}
126.85 +
126.86 +static __u32 ext2fs_superblock_csum(ext2_filsys fs EXT2FS_ATTR((unused)),
126.87 + struct ext2_super_block *sb)
126.88 +{
126.89 + int offset = offsetof(struct ext2_super_block, s_checksum);
126.90 +
126.91 + return ext2fs_crc32c_le(~0, (unsigned char *)sb, offset);
126.92 +}
126.93 +
126.94 +/* NOTE: The input to this function MUST be in LE order */
126.95 +int ext2fs_superblock_csum_verify(ext2_filsys fs, struct ext2_super_block *sb)
126.96 +{
126.97 + __u32 flag, calculated;
126.98 +
126.99 + if (fs->flags & EXT2_FLAG_SWAP_BYTES)
126.100 + flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
126.101 + else
126.102 + flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
126.103 +
126.104 + if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag))
126.105 + return 1;
126.106 +
126.107 + calculated = ext2fs_superblock_csum(fs, sb);
126.108 +
126.109 + return ext2fs_le32_to_cpu(sb->s_checksum) == calculated;
126.110 +}
126.111 +
126.112 +/* NOTE: The input to this function MUST be in LE order */
126.113 +errcode_t ext2fs_superblock_csum_set(ext2_filsys fs,
126.114 + struct ext2_super_block *sb)
126.115 +{
126.116 + __u32 flag, crc;
126.117 +
126.118 + if (fs->flags & EXT2_FLAG_SWAP_BYTES)
126.119 + flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
126.120 + else
126.121 + flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
126.122 +
126.123 + if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag))
126.124 + return 0;
126.125 +
126.126 + crc = ext2fs_superblock_csum(fs, sb);
126.127 + sb->s_checksum = ext2fs_cpu_to_le32(crc);
126.128 +
126.129 + return 0;
126.130 +}
126.131 +
126.132 +static errcode_t ext2fs_ext_attr_block_csum(ext2_filsys fs,
126.133 + ext2_ino_t inum EXT2FS_ATTR((unused)),
126.134 + blk64_t block,
126.135 + struct ext2_ext_attr_header *hdr,
126.136 + __u32 *crc)
126.137 +{
126.138 + char *buf = (char *)hdr;
126.139 + __u32 old_crc = hdr->h_checksum;
126.140 +
126.141 + hdr->h_checksum = 0;
126.142 + block = ext2fs_cpu_to_le64(block);
126.143 + *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&block,
126.144 + sizeof(block));
126.145 + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, fs->blocksize);
126.146 + hdr->h_checksum = old_crc;
126.147 +
126.148 + return 0;
126.149 +}
126.150 +
126.151 +int ext2fs_ext_attr_block_csum_verify(ext2_filsys fs, ext2_ino_t inum,
126.152 + blk64_t block,
126.153 + struct ext2_ext_attr_header *hdr)
126.154 +{
126.155 + __u32 calculated;
126.156 + errcode_t retval;
126.157 +
126.158 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.159 + return 1;
126.160 +
126.161 + retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &calculated);
126.162 + if (retval)
126.163 + return 0;
126.164 +
126.165 + return ext2fs_le32_to_cpu(hdr->h_checksum) == calculated;
126.166 +}
126.167 +
126.168 +errcode_t ext2fs_ext_attr_block_csum_set(ext2_filsys fs, ext2_ino_t inum,
126.169 + blk64_t block,
126.170 + struct ext2_ext_attr_header *hdr)
126.171 +{
126.172 + errcode_t retval;
126.173 + __u32 crc;
126.174 +
126.175 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.176 + return 0;
126.177 +
126.178 + retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &crc);
126.179 + if (retval)
126.180 + return retval;
126.181 + hdr->h_checksum = ext2fs_cpu_to_le32(crc);
126.182 + return 0;
126.183 +}
126.184 +
126.185 +static __u16 do_nothing16(__u16 x)
126.186 +{
126.187 + return x;
126.188 +}
126.189 +
126.190 +static __u16 disk_to_host16(__u16 x)
126.191 +{
126.192 + return ext2fs_le16_to_cpu(x);
126.193 +}
126.194 +
126.195 +static errcode_t __get_dx_countlimit(ext2_filsys fs,
126.196 + struct ext2_dir_entry *dirent,
126.197 + struct ext2_dx_countlimit **cc,
126.198 + int *offset,
126.199 + int need_swab)
126.200 +{
126.201 + struct ext2_dir_entry *dp;
126.202 + struct ext2_dx_root_info *root;
126.203 + struct ext2_dx_countlimit *c;
126.204 + int count_offset, max_sane_entries;
126.205 + unsigned int rec_len;
126.206 + __u16 (*translate)(__u16) = (need_swab ? disk_to_host16 : do_nothing16);
126.207 +
126.208 + rec_len = translate(dirent->rec_len);
126.209 +
126.210 + if (rec_len == fs->blocksize && translate(dirent->name_len) == 0)
126.211 + count_offset = 8;
126.212 + else if (rec_len == 12) {
126.213 + dp = (struct ext2_dir_entry *)(((char *)dirent) + rec_len);
126.214 + rec_len = translate(dp->rec_len);
126.215 + if (rec_len != fs->blocksize - 12)
126.216 + return EXT2_ET_DB_NOT_FOUND;
126.217 + root = (struct ext2_dx_root_info *)(((char *)dp + 12));
126.218 + if (root->reserved_zero ||
126.219 + root->info_length != sizeof(struct ext2_dx_root_info))
126.220 + return EXT2_ET_DB_NOT_FOUND;
126.221 + count_offset = 32;
126.222 + } else
126.223 + return EXT2_ET_DB_NOT_FOUND;
126.224 +
126.225 + c = (struct ext2_dx_countlimit *)(((char *)dirent) + count_offset);
126.226 + max_sane_entries = (fs->blocksize - count_offset) /
126.227 + sizeof(struct ext2_dx_entry);
126.228 + if (ext2fs_le16_to_cpu(c->limit) > max_sane_entries ||
126.229 + ext2fs_le16_to_cpu(c->count) > max_sane_entries)
126.230 + return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
126.231 +
126.232 + if (offset)
126.233 + *offset = count_offset;
126.234 + if (cc)
126.235 + *cc = c;
126.236 +
126.237 + return 0;
126.238 +}
126.239 +
126.240 +errcode_t ext2fs_get_dx_countlimit(ext2_filsys fs,
126.241 + struct ext2_dir_entry *dirent,
126.242 + struct ext2_dx_countlimit **cc,
126.243 + int *offset)
126.244 +{
126.245 + return __get_dx_countlimit(fs, dirent, cc, offset, 0);
126.246 +}
126.247 +
126.248 +void ext2fs_initialize_dirent_tail(ext2_filsys fs,
126.249 + struct ext2_dir_entry_tail *t)
126.250 +{
126.251 + memset(t, 0, sizeof(struct ext2_dir_entry_tail));
126.252 + ext2fs_set_rec_len(fs, sizeof(struct ext2_dir_entry_tail),
126.253 + (struct ext2_dir_entry *)t);
126.254 + t->det_reserved_name_len = EXT2_DIR_NAME_LEN_CSUM;
126.255 +}
126.256 +
126.257 +static errcode_t __get_dirent_tail(ext2_filsys fs,
126.258 + struct ext2_dir_entry *dirent,
126.259 + struct ext2_dir_entry_tail **tt,
126.260 + int need_swab)
126.261 +{
126.262 + struct ext2_dir_entry *d;
126.263 + void *top;
126.264 + struct ext2_dir_entry_tail *t;
126.265 + unsigned int rec_len;
126.266 + errcode_t retval = 0;
126.267 + __u16 (*translate)(__u16) = (need_swab ? disk_to_host16 : do_nothing16);
126.268 +
126.269 + d = dirent;
126.270 + top = EXT2_DIRENT_TAIL(dirent, fs->blocksize);
126.271 +
126.272 + rec_len = translate(d->rec_len);
126.273 + while (rec_len && !(rec_len & 0x3)) {
126.274 + d = (struct ext2_dir_entry *)(((char *)d) + rec_len);
126.275 + if ((void *)d >= top)
126.276 + break;
126.277 + rec_len = translate(d->rec_len);
126.278 + }
126.279 +
126.280 + if (d != top)
126.281 + return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
126.282 +
126.283 + t = (struct ext2_dir_entry_tail *)d;
126.284 + if (t->det_reserved_zero1 ||
126.285 + translate(t->det_rec_len) != sizeof(struct ext2_dir_entry_tail) ||
126.286 + translate(t->det_reserved_name_len) != EXT2_DIR_NAME_LEN_CSUM)
126.287 + return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
126.288 +
126.289 + if (tt)
126.290 + *tt = t;
126.291 + return retval;
126.292 +}
126.293 +
126.294 +int ext2fs_dirent_has_tail(ext2_filsys fs, struct ext2_dir_entry *dirent)
126.295 +{
126.296 + return __get_dirent_tail(fs, dirent, NULL, 0) == 0;
126.297 +}
126.298 +
126.299 +static errcode_t ext2fs_dirent_csum(ext2_filsys fs, ext2_ino_t inum,
126.300 + struct ext2_dir_entry *dirent, __u32 *crc,
126.301 + int size)
126.302 +{
126.303 + errcode_t retval;
126.304 + char *buf = (char *)dirent;
126.305 + __u32 gen;
126.306 + struct ext2_inode inode;
126.307 +
126.308 + retval = ext2fs_read_inode(fs, inum, &inode);
126.309 + if (retval)
126.310 + return retval;
126.311 +
126.312 + inum = ext2fs_cpu_to_le32(inum);
126.313 + gen = ext2fs_cpu_to_le32(inode.i_generation);
126.314 + *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum,
126.315 + sizeof(inum));
126.316 + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen));
126.317 + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size);
126.318 +
126.319 + return 0;
126.320 +}
126.321 +
126.322 +int ext2fs_dirent_csum_verify(ext2_filsys fs, ext2_ino_t inum,
126.323 + struct ext2_dir_entry *dirent)
126.324 +{
126.325 + errcode_t retval;
126.326 + __u32 calculated;
126.327 + struct ext2_dir_entry_tail *t;
126.328 +
126.329 + retval = __get_dirent_tail(fs, dirent, &t, 1);
126.330 + if (retval)
126.331 + return 1;
126.332 +
126.333 + /*
126.334 + * The checksum field is overlaid with the dirent->name field
126.335 + * so the swapfs.c functions won't change the endianness.
126.336 + */
126.337 + retval = ext2fs_dirent_csum(fs, inum, dirent, &calculated,
126.338 + (char *)t - (char *)dirent);
126.339 + if (retval)
126.340 + return 0;
126.341 + return ext2fs_le32_to_cpu(t->det_checksum) == calculated;
126.342 +}
126.343 +
126.344 +static errcode_t ext2fs_dirent_csum_set(ext2_filsys fs, ext2_ino_t inum,
126.345 + struct ext2_dir_entry *dirent)
126.346 +{
126.347 + errcode_t retval;
126.348 + __u32 crc;
126.349 + struct ext2_dir_entry_tail *t;
126.350 +
126.351 + retval = __get_dirent_tail(fs, dirent, &t, 1);
126.352 + if (retval)
126.353 + return retval;
126.354 +
126.355 + /* swapfs.c functions don't change the checksum endianness */
126.356 + retval = ext2fs_dirent_csum(fs, inum, dirent, &crc,
126.357 + (char *)t - (char *)dirent);
126.358 + if (retval)
126.359 + return retval;
126.360 + t->det_checksum = ext2fs_cpu_to_le32(crc);
126.361 + return 0;
126.362 +}
126.363 +
126.364 +static errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum,
126.365 + struct ext2_dir_entry *dirent,
126.366 + __u32 *crc, int count_offset, int count,
126.367 + struct ext2_dx_tail *t)
126.368 +{
126.369 + errcode_t retval;
126.370 + char *buf = (char *)dirent;
126.371 + int size;
126.372 + __u32 old_csum, gen;
126.373 + struct ext2_inode inode;
126.374 +
126.375 + size = count_offset + (count * sizeof(struct ext2_dx_entry));
126.376 + old_csum = t->dt_checksum;
126.377 + t->dt_checksum = 0;
126.378 +
126.379 + retval = ext2fs_read_inode(fs, inum, &inode);
126.380 + if (retval)
126.381 + return retval;
126.382 +
126.383 + inum = ext2fs_cpu_to_le32(inum);
126.384 + gen = ext2fs_cpu_to_le32(inode.i_generation);
126.385 + *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum,
126.386 + sizeof(inum));
126.387 + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen));
126.388 + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size);
126.389 + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)t,
126.390 + sizeof(struct ext2_dx_tail));
126.391 + t->dt_checksum = old_csum;
126.392 +
126.393 + return 0;
126.394 +}
126.395 +
126.396 +static int ext2fs_dx_csum_verify(ext2_filsys fs, ext2_ino_t inum,
126.397 + struct ext2_dir_entry *dirent)
126.398 +{
126.399 + __u32 calculated;
126.400 + errcode_t retval;
126.401 + struct ext2_dx_countlimit *c;
126.402 + struct ext2_dx_tail *t;
126.403 + int count_offset, limit, count;
126.404 +
126.405 + retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1);
126.406 + if (retval)
126.407 + return 1;
126.408 + limit = ext2fs_le16_to_cpu(c->limit);
126.409 + count = ext2fs_le16_to_cpu(c->count);
126.410 + if (count_offset + (limit * sizeof(struct ext2_dx_entry)) >
126.411 + fs->blocksize - sizeof(struct ext2_dx_tail))
126.412 + return 0;
126.413 + /* htree structs are accessed in LE order */
126.414 + t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit);
126.415 + retval = ext2fs_dx_csum(fs, inum, dirent, &calculated, count_offset,
126.416 + count, t);
126.417 + if (retval)
126.418 + return 0;
126.419 +
126.420 + return ext2fs_le32_to_cpu(t->dt_checksum) == calculated;
126.421 +}
126.422 +
126.423 +static errcode_t ext2fs_dx_csum_set(ext2_filsys fs, ext2_ino_t inum,
126.424 + struct ext2_dir_entry *dirent)
126.425 +{
126.426 + __u32 crc;
126.427 + errcode_t retval = 0;
126.428 + struct ext2_dx_countlimit *c;
126.429 + struct ext2_dx_tail *t;
126.430 + int count_offset, limit, count;
126.431 +
126.432 + retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1);
126.433 + if (retval)
126.434 + return retval;
126.435 + limit = ext2fs_le16_to_cpu(c->limit);
126.436 + count = ext2fs_le16_to_cpu(c->count);
126.437 + if (count_offset + (limit * sizeof(struct ext2_dx_entry)) >
126.438 + fs->blocksize - sizeof(struct ext2_dx_tail))
126.439 + return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
126.440 + t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit);
126.441 +
126.442 + /* htree structs are accessed in LE order */
126.443 + retval = ext2fs_dx_csum(fs, inum, dirent, &crc, count_offset, count, t);
126.444 + if (retval)
126.445 + return retval;
126.446 + t->dt_checksum = ext2fs_cpu_to_le32(crc);
126.447 + return retval;
126.448 +}
126.449 +
126.450 +int ext2fs_dir_block_csum_verify(ext2_filsys fs, ext2_ino_t inum,
126.451 + struct ext2_dir_entry *dirent)
126.452 +{
126.453 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.454 + return 1;
126.455 +
126.456 + if (__get_dirent_tail(fs, dirent, NULL, 1) == 0)
126.457 + return ext2fs_dirent_csum_verify(fs, inum, dirent);
126.458 + if (__get_dx_countlimit(fs, dirent, NULL, NULL, 1) == 0)
126.459 + return ext2fs_dx_csum_verify(fs, inum, dirent);
126.460 +
126.461 + return 0;
126.462 +}
126.463 +
126.464 +errcode_t ext2fs_dir_block_csum_set(ext2_filsys fs, ext2_ino_t inum,
126.465 + struct ext2_dir_entry *dirent)
126.466 +{
126.467 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.468 + return 0;
126.469 +
126.470 + if (__get_dirent_tail(fs, dirent, NULL, 1) == 0)
126.471 + return ext2fs_dirent_csum_set(fs, inum, dirent);
126.472 + if (__get_dx_countlimit(fs, dirent, NULL, NULL, 1) == 0)
126.473 + return ext2fs_dx_csum_set(fs, inum, dirent);
126.474 +
126.475 + if (fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS)
126.476 + return 0;
126.477 + return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
126.478 +}
126.479 +
126.480 +#define EXT3_EXTENT_TAIL_OFFSET(hdr) (sizeof(struct ext3_extent_header) + \
126.481 + (sizeof(struct ext3_extent) * ext2fs_le16_to_cpu((hdr)->eh_max)))
126.482 +
126.483 +static struct ext3_extent_tail *get_extent_tail(struct ext3_extent_header *h)
126.484 +{
126.485 + return (struct ext3_extent_tail *)(((char *)h) +
126.486 + EXT3_EXTENT_TAIL_OFFSET(h));
126.487 +}
126.488 +
126.489 +static errcode_t ext2fs_extent_block_csum(ext2_filsys fs, ext2_ino_t inum,
126.490 + struct ext3_extent_header *eh,
126.491 + __u32 *crc)
126.492 +{
126.493 + int size;
126.494 + __u32 gen;
126.495 + errcode_t retval;
126.496 + struct ext2_inode inode;
126.497 +
126.498 + size = EXT3_EXTENT_TAIL_OFFSET(eh) + offsetof(struct ext3_extent_tail,
126.499 + et_checksum);
126.500 +
126.501 + retval = ext2fs_read_inode(fs, inum, &inode);
126.502 + if (retval)
126.503 + return retval;
126.504 + inum = ext2fs_cpu_to_le32(inum);
126.505 + gen = ext2fs_cpu_to_le32(inode.i_generation);
126.506 + *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum,
126.507 + sizeof(inum));
126.508 + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen));
126.509 + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)eh, size);
126.510 +
126.511 + return 0;
126.512 +}
126.513 +
126.514 +int ext2fs_extent_block_csum_verify(ext2_filsys fs, ext2_ino_t inum,
126.515 + struct ext3_extent_header *eh)
126.516 +{
126.517 + errcode_t retval;
126.518 + __u32 provided, calculated;
126.519 + struct ext3_extent_tail *t = get_extent_tail(eh);
126.520 +
126.521 + /*
126.522 + * The extent tree structures are accessed in LE order, so we must
126.523 + * swap the checksum bytes here.
126.524 + */
126.525 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.526 + return 1;
126.527 +
126.528 + provided = ext2fs_le32_to_cpu(t->et_checksum);
126.529 + retval = ext2fs_extent_block_csum(fs, inum, eh, &calculated);
126.530 + if (retval)
126.531 + return 0;
126.532 +
126.533 + return provided == calculated;
126.534 +}
126.535 +
126.536 +errcode_t ext2fs_extent_block_csum_set(ext2_filsys fs, ext2_ino_t inum,
126.537 + struct ext3_extent_header *eh)
126.538 +{
126.539 + errcode_t retval;
126.540 + __u32 crc;
126.541 + struct ext3_extent_tail *t = get_extent_tail(eh);
126.542 +
126.543 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.544 + return 0;
126.545 +
126.546 + /*
126.547 + * The extent tree structures are accessed in LE order, so we must
126.548 + * swap the checksum bytes here.
126.549 + */
126.550 + retval = ext2fs_extent_block_csum(fs, inum, eh, &crc);
126.551 + if (retval)
126.552 + return retval;
126.553 + t->et_checksum = ext2fs_cpu_to_le32(crc);
126.554 + return retval;
126.555 +}
126.556 +
126.557 +int ext2fs_inode_bitmap_csum_verify(ext2_filsys fs, dgrp_t group,
126.558 + char *bitmap, int size)
126.559 +{
126.560 + struct ext4_group_desc *gdp = (struct ext4_group_desc *)
126.561 + ext2fs_group_desc(fs, fs->group_desc, group);
126.562 + __u32 provided, calculated;
126.563 +
126.564 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.565 + return 1;
126.566 + provided = gdp->bg_inode_bitmap_csum_lo;
126.567 + calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap,
126.568 + size);
126.569 + if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
126.570 + provided |= (__u32)gdp->bg_inode_bitmap_csum_hi << 16;
126.571 + else
126.572 + calculated &= 0xFFFF;
126.573 +
126.574 + return provided == calculated;
126.575 +}
126.576 +
126.577 +errcode_t ext2fs_inode_bitmap_csum_set(ext2_filsys fs, dgrp_t group,
126.578 + char *bitmap, int size)
126.579 +{
126.580 + __u32 crc;
126.581 + struct ext4_group_desc *gdp = (struct ext4_group_desc *)
126.582 + ext2fs_group_desc(fs, fs->group_desc, group);
126.583 +
126.584 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.585 + return 0;
126.586 +
126.587 + crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size);
126.588 + gdp->bg_inode_bitmap_csum_lo = crc & 0xFFFF;
126.589 + if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
126.590 + gdp->bg_inode_bitmap_csum_hi = crc >> 16;
126.591 +
126.592 + return 0;
126.593 +}
126.594 +
126.595 +int ext2fs_block_bitmap_csum_verify(ext2_filsys fs, dgrp_t group,
126.596 + char *bitmap, int size)
126.597 +{
126.598 + struct ext4_group_desc *gdp = (struct ext4_group_desc *)
126.599 + ext2fs_group_desc(fs, fs->group_desc, group);
126.600 + __u32 provided, calculated;
126.601 +
126.602 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.603 + return 1;
126.604 + provided = gdp->bg_block_bitmap_csum_lo;
126.605 + calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap,
126.606 + size);
126.607 + if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
126.608 + provided |= (__u32)gdp->bg_block_bitmap_csum_hi << 16;
126.609 + else
126.610 + calculated &= 0xFFFF;
126.611 +
126.612 + return provided == calculated;
126.613 +}
126.614 +
126.615 +errcode_t ext2fs_block_bitmap_csum_set(ext2_filsys fs, dgrp_t group,
126.616 + char *bitmap, int size)
126.617 +{
126.618 + __u32 crc;
126.619 + struct ext4_group_desc *gdp = (struct ext4_group_desc *)
126.620 + ext2fs_group_desc(fs, fs->group_desc, group);
126.621 +
126.622 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.623 + return 0;
126.624 +
126.625 + crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size);
126.626 + gdp->bg_block_bitmap_csum_lo = crc & 0xFFFF;
126.627 + if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
126.628 + gdp->bg_block_bitmap_csum_hi = crc >> 16;
126.629 +
126.630 + return 0;
126.631 +}
126.632 +
126.633 +static errcode_t ext2fs_inode_csum(ext2_filsys fs, ext2_ino_t inum,
126.634 + struct ext2_inode_large *inode,
126.635 + __u32 *crc, int has_hi)
126.636 +{
126.637 + __u32 gen;
126.638 + struct ext2_inode_large *desc = inode;
126.639 + size_t size = EXT2_INODE_SIZE(fs->super);
126.640 + __u16 old_lo;
126.641 + __u16 old_hi = 0;
126.642 +
126.643 + old_lo = inode->i_checksum_lo;
126.644 + inode->i_checksum_lo = 0;
126.645 + if (has_hi) {
126.646 + old_hi = inode->i_checksum_hi;
126.647 + inode->i_checksum_hi = 0;
126.648 + }
126.649 +
126.650 + inum = ext2fs_cpu_to_le32(inum);
126.651 + gen = inode->i_generation;
126.652 + *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum,
126.653 + sizeof(inum));
126.654 + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen));
126.655 + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)desc, size);
126.656 +
126.657 + inode->i_checksum_lo = old_lo;
126.658 + if (has_hi)
126.659 + inode->i_checksum_hi = old_hi;
126.660 + return 0;
126.661 +}
126.662 +
126.663 +int ext2fs_inode_csum_verify(ext2_filsys fs, ext2_ino_t inum,
126.664 + struct ext2_inode_large *inode)
126.665 +{
126.666 + errcode_t retval;
126.667 + __u32 provided, calculated;
126.668 + unsigned int i, has_hi;
126.669 + char *cp;
126.670 +
126.671 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.672 + return 1;
126.673 +
126.674 + has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE &&
126.675 + inode->i_extra_isize >= EXT4_INODE_CSUM_HI_EXTRA_END);
126.676 +
126.677 + provided = ext2fs_le16_to_cpu(inode->i_checksum_lo);
126.678 + retval = ext2fs_inode_csum(fs, inum, inode, &calculated, has_hi);
126.679 + if (retval)
126.680 + return 0;
126.681 + if (has_hi) {
126.682 + __u32 hi = ext2fs_le16_to_cpu(inode->i_checksum_hi);
126.683 + provided |= hi << 16;
126.684 + } else
126.685 + calculated &= 0xFFFF;
126.686 +
126.687 + if (provided == calculated)
126.688 + return 1;
126.689 +
126.690 + /*
126.691 + * If the checksum didn't match, it's possible it was due to
126.692 + * the inode being all zero's. It's unlikely this is the
126.693 + * case, but it can happen. So check for it here. (We only
126.694 + * check the base inode since that's good enough, and it's not
126.695 + * worth the bother to figure out how much of the extended
126.696 + * inode, if any, is present.)
126.697 + */
126.698 + for (cp = (char *) inode, i = 0;
126.699 + i < sizeof(struct ext2_inode);
126.700 + cp++, i++)
126.701 + if (*cp)
126.702 + return 0;
126.703 + return 1; /* Inode must have been all zero's */
126.704 +}
126.705 +
126.706 +errcode_t ext2fs_inode_csum_set(ext2_filsys fs, ext2_ino_t inum,
126.707 + struct ext2_inode_large *inode)
126.708 +{
126.709 + errcode_t retval;
126.710 + __u32 crc;
126.711 + int has_hi;
126.712 +
126.713 + if (!ext2fs_has_feature_metadata_csum(fs->super))
126.714 + return 0;
126.715 +
126.716 + has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE &&
126.717 + inode->i_extra_isize >= EXT4_INODE_CSUM_HI_EXTRA_END);
126.718 +
126.719 + retval = ext2fs_inode_csum(fs, inum, inode, &crc, has_hi);
126.720 + if (retval)
126.721 + return retval;
126.722 + inode->i_checksum_lo = ext2fs_cpu_to_le16(crc & 0xFFFF);
126.723 + if (has_hi)
126.724 + inode->i_checksum_hi = ext2fs_cpu_to_le16(crc >> 16);
126.725 + return 0;
126.726 +}
126.727 +
126.728 +__u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group)
126.729 +{
126.730 + struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc,
126.731 + group);
126.732 + size_t offset, size = EXT2_DESC_SIZE(fs->super);
126.733 + __u16 crc = 0;
126.734 +#ifdef WORDS_BIGENDIAN
126.735 + struct ext4_group_desc swabdesc;
126.736 + size_t save_size = size;
126.737 + const size_t ext4_bg_size = sizeof(struct ext4_group_desc);
126.738 + struct ext2_group_desc *save_desc = desc;
126.739 +
126.740 + /* Have to swab back to little-endian to do the checksum */
126.741 + if (size > ext4_bg_size)
126.742 + size = ext4_bg_size;
126.743 + memcpy(&swabdesc, desc, size);
126.744 + ext2fs_swap_group_desc2(fs, (struct ext2_group_desc *) &swabdesc);
126.745 + desc = (struct ext2_group_desc *) &swabdesc;
126.746 + group = ext2fs_swab32(group);
126.747 +#endif
126.748 +
126.749 + if (ext2fs_has_feature_metadata_csum(fs->super)) {
126.750 + /* new metadata csum code */
126.751 + __u16 old_crc;
126.752 + __u32 crc32;
126.753 +
126.754 + old_crc = desc->bg_checksum;
126.755 + desc->bg_checksum = 0;
126.756 + crc32 = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&group,
126.757 + sizeof(group));
126.758 + crc32 = ext2fs_crc32c_le(crc32, (unsigned char *)desc,
126.759 + size);
126.760 + desc->bg_checksum = old_crc;
126.761 +#ifdef WORDS_BIGENDIAN
126.762 + if (save_size > ext4_bg_size)
126.763 + crc32 = ext2fs_crc32c_le(crc32,
126.764 + (unsigned char *)save_desc + ext4_bg_size,
126.765 + save_size - ext4_bg_size);
126.766 +#endif
126.767 + crc = crc32 & 0xFFFF;
126.768 + goto out;
126.769 + }
126.770 +
126.771 + /* old crc16 code */
126.772 + offset = offsetof(struct ext2_group_desc, bg_checksum);
126.773 + crc = ext2fs_crc16(~0, fs->super->s_uuid,
126.774 + sizeof(fs->super->s_uuid));
126.775 + crc = ext2fs_crc16(crc, &group, sizeof(group));
126.776 + crc = ext2fs_crc16(crc, desc, offset);
126.777 + offset += sizeof(desc->bg_checksum); /* skip checksum */
126.778 + /* for checksum of struct ext4_group_desc do the rest...*/
126.779 + if (offset < size) {
126.780 + crc = ext2fs_crc16(crc, (char *)desc + offset,
126.781 + size - offset);
126.782 + }
126.783 +#ifdef WORDS_BIGENDIAN
126.784 + /*
126.785 + * If the size of the bg descriptor is greater than 64
126.786 + * bytes, which is the size of the traditional ext4 bg
126.787 + * descriptor, checksum the rest of the descriptor here
126.788 + */
126.789 + if (save_size > ext4_bg_size)
126.790 + crc = ext2fs_crc16(crc, (char *)save_desc + ext4_bg_size,
126.791 + save_size - ext4_bg_size);
126.792 +#endif
126.793 +
126.794 +out:
126.795 + return crc;
126.796 +}
126.797 +
126.798 +int ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group)
126.799 +{
126.800 + if (ext2fs_has_group_desc_csum(fs) &&
126.801 + (ext2fs_bg_checksum(fs, group) !=
126.802 + ext2fs_group_desc_csum(fs, group)))
126.803 + return 0;
126.804 +
126.805 + return 1;
126.806 +}
126.807 +
126.808 +void ext2fs_group_desc_csum_set(ext2_filsys fs, dgrp_t group)
126.809 +{
126.810 + if (!ext2fs_has_group_desc_csum(fs))
126.811 + return;
126.812 +
126.813 + /* ext2fs_bg_checksum_set() sets the actual checksum field but
126.814 + * does not calculate the checksum itself. */
126.815 + ext2fs_bg_checksum_set(fs, group, ext2fs_group_desc_csum(fs, group));
126.816 +}
126.817 +
126.818 +static __u32 find_last_inode_ingrp(ext2fs_inode_bitmap bitmap,
126.819 + __u32 inodes_per_grp, dgrp_t grp_no)
126.820 +{
126.821 + ext2_ino_t i, start_ino, end_ino;
126.822 +
126.823 + start_ino = grp_no * inodes_per_grp + 1;
126.824 + end_ino = start_ino + inodes_per_grp - 1;
126.825 +
126.826 + for (i = end_ino; i >= start_ino; i--) {
126.827 + if (ext2fs_fast_test_inode_bitmap2(bitmap, i))
126.828 + return i - start_ino + 1;
126.829 + }
126.830 + return inodes_per_grp;
126.831 +}
126.832 +
126.833 +/* update the bitmap flags, set the itable high watermark, and calculate
126.834 + * checksums for the group descriptors */
126.835 +errcode_t ext2fs_set_gdt_csum(ext2_filsys fs)
126.836 +{
126.837 + struct ext2_super_block *sb = fs->super;
126.838 + int dirty = 0;
126.839 + dgrp_t i;
126.840 +
126.841 + if (!fs->inode_map)
126.842 + return EXT2_ET_NO_INODE_BITMAP;
126.843 +
126.844 + if (!ext2fs_has_group_desc_csum(fs))
126.845 + return 0;
126.846 +
126.847 + for (i = 0; i < fs->group_desc_count; i++) {
126.848 + __u32 old_csum = ext2fs_bg_checksum(fs, i);
126.849 + __u32 old_unused = ext2fs_bg_itable_unused(fs, i);
126.850 + __u32 old_flags = ext2fs_bg_flags(fs, i);
126.851 + __u32 old_free_inodes_count = ext2fs_bg_free_inodes_count(fs, i);
126.852 + __u32 old_free_blocks_count = ext2fs_bg_free_blocks_count(fs, i);
126.853 +
126.854 + if (old_free_blocks_count == sb->s_blocks_per_group &&
126.855 + i != fs->group_desc_count - 1)
126.856 + ext2fs_bg_flags_set(fs, i, EXT2_BG_BLOCK_UNINIT);
126.857 +
126.858 + if (old_free_inodes_count == sb->s_inodes_per_group) {
126.859 + ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
126.860 + ext2fs_bg_itable_unused_set(fs, i, sb->s_inodes_per_group);
126.861 + } else {
126.862 + int unused =
126.863 + sb->s_inodes_per_group -
126.864 + find_last_inode_ingrp(fs->inode_map,
126.865 + sb->s_inodes_per_group, i);
126.866 +
126.867 + ext2fs_bg_flags_clear(fs, i, EXT2_BG_INODE_UNINIT);
126.868 + ext2fs_bg_itable_unused_set(fs, i, unused);
126.869 + }
126.870 +
126.871 + ext2fs_group_desc_csum_set(fs, i);
126.872 + if (old_flags != ext2fs_bg_flags(fs, i))
126.873 + dirty = 1;
126.874 + if (old_unused != ext2fs_bg_itable_unused(fs, i))
126.875 + dirty = 1;
126.876 + if (old_csum != ext2fs_bg_checksum(fs, i))
126.877 + dirty = 1;
126.878 + }
126.879 + if (dirty)
126.880 + ext2fs_mark_super_dirty(fs);
126.881 + return 0;
126.882 +}
126.883 +
126.884 +#ifdef DEBUG
126.885 +#include "e2p/e2p.h"
126.886 +
126.887 +void print_csum(const char *msg, ext2_filsys fs, dgrp_t group)
126.888 +{
126.889 + __u16 crc1, crc2, crc3;
126.890 + dgrp_t swabgroup;
126.891 + struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc,
126.892 + group);
126.893 + size_t size = EXT2_DESC_SIZE(fs->super);
126.894 + struct ext2_super_block *sb = fs->super;
126.895 + int offset = offsetof(struct ext2_group_desc, bg_checksum);
126.896 +#ifdef WORDS_BIGENDIAN
126.897 + struct ext4_group_desc swabdesc;
126.898 + struct ext2_group_desc *save_desc = desc;
126.899 + const size_t ext4_bg_size = sizeof(struct ext4_group_desc);
126.900 + size_t save_size = size;
126.901 +#endif
126.902 +
126.903 +#ifdef WORDS_BIGENDIAN
126.904 + /* Have to swab back to little-endian to do the checksum */
126.905 + if (size > ext4_bg_size)
126.906 + size = ext4_bg_size;
126.907 + memcpy(&swabdesc, desc, size);
126.908 + ext2fs_swap_group_desc2(fs, (struct ext2_group_desc *) &swabdesc);
126.909 + desc = (struct ext2_group_desc *) &swabdesc;
126.910 +
126.911 + swabgroup = ext2fs_swab32(group);
126.912 +#else
126.913 + swabgroup = group;
126.914 +#endif
126.915 +
126.916 + crc1 = ext2fs_crc16(~0, sb->s_uuid, sizeof(fs->super->s_uuid));
126.917 + crc2 = ext2fs_crc16(crc1, &swabgroup, sizeof(swabgroup));
126.918 + crc3 = ext2fs_crc16(crc2, desc, offset);
126.919 + offset += sizeof(desc->bg_checksum); /* skip checksum */
126.920 + /* for checksum of struct ext4_group_desc do the rest...*/
126.921 + if (offset < size)
126.922 + crc3 = ext2fs_crc16(crc3, (char *)desc + offset, size - offset);
126.923 +#ifdef WORDS_BIGENDIAN
126.924 + if (save_size > ext4_bg_size)
126.925 + crc3 = ext2fs_crc16(crc3, (char *)save_desc + ext4_bg_size,
126.926 + save_size - ext4_bg_size);
126.927 +#endif
126.928 +
126.929 + printf("%s UUID %s=%04x, grp %u=%04x: %04x=%04x\n",
126.930 + msg, e2p_uuid2str(sb->s_uuid), crc1, group, crc2, crc3,
126.931 + ext2fs_group_desc_csum(fs, group));
126.932 +}
126.933 +
126.934 +unsigned char sb_uuid[16] = { 0x4f, 0x25, 0xe8, 0xcf, 0xe7, 0x97, 0x48, 0x23,
126.935 + 0xbe, 0xfa, 0xa7, 0x88, 0x4b, 0xae, 0xec, 0xdb };
126.936 +
126.937 +int main(int argc, char **argv)
126.938 +{
126.939 + struct ext2_super_block param;
126.940 + errcode_t retval;
126.941 + ext2_filsys fs;
126.942 + int i;
126.943 + __u16 csum1, csum2, csum_known = 0xd3a4;
126.944 +
126.945 + memset(¶m, 0, sizeof(param));
126.946 + ext2fs_blocks_count_set(¶m, 32768);
126.947 +#if 0
126.948 + param.s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT;
126.949 + param.s_desc_size = 128;
126.950 + csum_known = 0x5b6e;
126.951 +#endif
126.952 +
126.953 + retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m,
126.954 + test_io_manager, &fs);
126.955 + if (retval) {
126.956 + com_err("setup", retval,
126.957 + "While initializing filesystem");
126.958 + exit(1);
126.959 + }
126.960 + memcpy(fs->super->s_uuid, sb_uuid, 16);
126.961 + fs->super->s_feature_ro_compat = EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
126.962 +
126.963 + for (i=0; i < fs->group_desc_count; i++) {
126.964 + ext2fs_block_bitmap_loc_set(fs, i, 124);
126.965 + ext2fs_inode_bitmap_loc_set(fs, i, 125);
126.966 + ext2fs_inode_table_loc_set(fs, i, 126);
126.967 + ext2fs_bg_free_blocks_count_set(fs, i, 31119);
126.968 + ext2fs_bg_free_inodes_count_set(fs, i, 15701);
126.969 + ext2fs_bg_used_dirs_count_set(fs, i, 2);
126.970 + ext2fs_bg_flags_zap(fs, i);
126.971 + };
126.972 +
126.973 + csum1 = ext2fs_group_desc_csum(fs, 0);
126.974 + print_csum("csum0000", fs, 0);
126.975 +
126.976 + if (csum1 != csum_known) {
126.977 + printf("checksum for group 0 should be %04x\n", csum_known);
126.978 + exit(1);
126.979 + }
126.980 + csum2 = ext2fs_group_desc_csum(fs, 1);
126.981 + print_csum("csum0001", fs, 1);
126.982 + if (csum1 == csum2) {
126.983 + printf("checksums for different groups shouldn't match\n");
126.984 + exit(1);
126.985 + }
126.986 + csum2 = ext2fs_group_desc_csum(fs, 2);
126.987 + print_csum("csumffff", fs, 2);
126.988 + if (csum1 == csum2) {
126.989 + printf("checksums for different groups shouldn't match\n");
126.990 + exit(1);
126.991 + }
126.992 + ext2fs_bg_checksum_set(fs, 0, csum1);
126.993 + csum2 = ext2fs_group_desc_csum(fs, 0);
126.994 + print_csum("csum_set", fs, 0);
126.995 + if (csum1 != csum2) {
126.996 + printf("checksums should not depend on checksum field\n");
126.997 + exit(1);
126.998 + }
126.999 + if (!ext2fs_group_desc_csum_verify(fs, 0)) {
126.1000 + printf("checksums should verify against gd_checksum\n");
126.1001 + exit(1);
126.1002 + }
126.1003 + memset(fs->super->s_uuid, 0x30, sizeof(fs->super->s_uuid));
126.1004 + print_csum("new_uuid", fs, 0);
126.1005 + if (ext2fs_group_desc_csum_verify(fs, 0) != 0) {
126.1006 + printf("checksums for different filesystems shouldn't match\n");
126.1007 + exit(1);
126.1008 + }
126.1009 + csum1 = ext2fs_group_desc_csum(fs, 0);
126.1010 + ext2fs_bg_checksum_set(fs, 0, csum1);
126.1011 + print_csum("csum_new", fs, 0);
126.1012 + ext2fs_bg_free_blocks_count_set(fs, 0, 1);
126.1013 + csum2 = ext2fs_group_desc_csum(fs, 0);
126.1014 + print_csum("csum_blk", fs, 0);
126.1015 + if (csum1 == csum2) {
126.1016 + printf("checksums for different data shouldn't match\n");
126.1017 + exit(1);
126.1018 + }
126.1019 + ext2fs_free(fs);
126.1020 +
126.1021 + return 0;
126.1022 +}
126.1023 +#endif
127.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
127.2 +++ b/libext2fs/lib/libext2fs/dblist.c Wed Aug 25 01:28:08 2021 +0200
127.3 @@ -0,0 +1,403 @@
127.4 +/*
127.5 + * dblist.c -- directory block list functions
127.6 + *
127.7 + * Copyright 1997 by Theodore Ts'o
127.8 + *
127.9 + * %Begin-Header%
127.10 + * This file may be redistributed under the terms of the GNU Library
127.11 + * General Public License, version 2.
127.12 + * %End-Header%
127.13 + */
127.14 +
127.15 +#include "config.h"
127.16 +#include <stdio.h>
127.17 +#if HAVE_UNISTD_H
127.18 +#include <unistd.h>
127.19 +#endif
127.20 +#include <string.h>
127.21 +#include <time.h>
127.22 +
127.23 +#include "ext2_fs.h"
127.24 +#include "ext2fsP.h"
127.25 +
127.26 +static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b);
127.27 +static EXT2_QSORT_TYPE dir_block_cmp2(const void *a, const void *b);
127.28 +static EXT2_QSORT_TYPE (*sortfunc32)(const void *a, const void *b);
127.29 +
127.30 +/*
127.31 + * helper function for making a new directory block list (for
127.32 + * initialize and copy).
127.33 + */
127.34 +static errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size,
127.35 + ext2_ino_t count,
127.36 + struct ext2_db_entry2 *list,
127.37 + ext2_dblist *ret_dblist)
127.38 +{
127.39 + ext2_dblist dblist = NULL;
127.40 + errcode_t retval;
127.41 + ext2_ino_t num_dirs;
127.42 + size_t len;
127.43 +
127.44 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
127.45 +
127.46 + if ((ret_dblist == 0) && fs->dblist &&
127.47 + (fs->dblist->magic == EXT2_ET_MAGIC_DBLIST))
127.48 + return 0;
127.49 +
127.50 + retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist);
127.51 + if (retval)
127.52 + goto cleanup;
127.53 + memset(dblist, 0, sizeof(struct ext2_struct_dblist));
127.54 +
127.55 + dblist->magic = EXT2_ET_MAGIC_DBLIST;
127.56 + dblist->fs = fs;
127.57 + if (size)
127.58 + dblist->size = size;
127.59 + else {
127.60 + retval = ext2fs_get_num_dirs(fs, &num_dirs);
127.61 + if (retval)
127.62 + goto cleanup;
127.63 + dblist->size = (num_dirs * 2) + 12;
127.64 + }
127.65 + len = (size_t) sizeof(struct ext2_db_entry2) * dblist->size;
127.66 + dblist->count = count;
127.67 + retval = ext2fs_get_array(dblist->size, sizeof(struct ext2_db_entry2),
127.68 + &dblist->list);
127.69 + if (retval)
127.70 + goto cleanup;
127.71 +
127.72 + if (list)
127.73 + memcpy(dblist->list, list, len);
127.74 + else
127.75 + memset(dblist->list, 0, len);
127.76 + if (ret_dblist)
127.77 + *ret_dblist = dblist;
127.78 + else
127.79 + fs->dblist = dblist;
127.80 + return 0;
127.81 +cleanup:
127.82 + if (dblist)
127.83 + ext2fs_free_mem(&dblist);
127.84 + return retval;
127.85 +}
127.86 +
127.87 +/*
127.88 + * Initialize a directory block list
127.89 + */
127.90 +errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist)
127.91 +{
127.92 + ext2_dblist dblist;
127.93 + errcode_t retval;
127.94 +
127.95 + retval = make_dblist(fs, 0, 0, 0, &dblist);
127.96 + if (retval)
127.97 + return retval;
127.98 +
127.99 + dblist->sorted = 1;
127.100 + if (ret_dblist)
127.101 + *ret_dblist = dblist;
127.102 + else
127.103 + fs->dblist = dblist;
127.104 +
127.105 + return 0;
127.106 +}
127.107 +
127.108 +/*
127.109 + * Copy a directory block list
127.110 + */
127.111 +errcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest)
127.112 +{
127.113 + ext2_dblist dblist;
127.114 + errcode_t retval;
127.115 +
127.116 + retval = make_dblist(src->fs, src->size, src->count, src->list,
127.117 + &dblist);
127.118 + if (retval)
127.119 + return retval;
127.120 + dblist->sorted = src->sorted;
127.121 + *dest = dblist;
127.122 + return 0;
127.123 +}
127.124 +
127.125 +/*
127.126 + * Close a directory block list
127.127 + *
127.128 + * (moved to closefs.c)
127.129 + */
127.130 +
127.131 +
127.132 +/*
127.133 + * Add a directory block to the directory block list
127.134 + */
127.135 +errcode_t ext2fs_add_dir_block2(ext2_dblist dblist, ext2_ino_t ino,
127.136 + blk64_t blk, e2_blkcnt_t blockcnt)
127.137 +{
127.138 + struct ext2_db_entry2 *new_entry;
127.139 + errcode_t retval;
127.140 + unsigned long old_size;
127.141 +
127.142 + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
127.143 +
127.144 + if (dblist->count >= dblist->size) {
127.145 + old_size = dblist->size * sizeof(struct ext2_db_entry2);
127.146 + dblist->size += dblist->size > 200 ? dblist->size / 2 : 100;
127.147 + retval = ext2fs_resize_mem(old_size, (size_t) dblist->size *
127.148 + sizeof(struct ext2_db_entry2),
127.149 + &dblist->list);
127.150 + if (retval) {
127.151 + dblist->size = old_size / sizeof(struct ext2_db_entry2);
127.152 + return retval;
127.153 + }
127.154 + }
127.155 + new_entry = dblist->list + ( dblist->count++);
127.156 + new_entry->blk = blk;
127.157 + new_entry->ino = ino;
127.158 + new_entry->blockcnt = blockcnt;
127.159 +
127.160 + dblist->sorted = 0;
127.161 +
127.162 + return 0;
127.163 +}
127.164 +
127.165 +/*
127.166 + * Change the directory block to the directory block list
127.167 + */
127.168 +errcode_t ext2fs_set_dir_block2(ext2_dblist dblist, ext2_ino_t ino,
127.169 + blk64_t blk, e2_blkcnt_t blockcnt)
127.170 +{
127.171 + dgrp_t i;
127.172 +
127.173 + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
127.174 +
127.175 + for (i=0; i < dblist->count; i++) {
127.176 + if ((dblist->list[i].ino != ino) ||
127.177 + (dblist->list[i].blockcnt != blockcnt))
127.178 + continue;
127.179 + dblist->list[i].blk = blk;
127.180 + dblist->sorted = 0;
127.181 + return 0;
127.182 + }
127.183 + return EXT2_ET_DB_NOT_FOUND;
127.184 +}
127.185 +
127.186 +void ext2fs_dblist_sort2(ext2_dblist dblist,
127.187 + EXT2_QSORT_TYPE (*sortfunc)(const void *,
127.188 + const void *))
127.189 +{
127.190 + if (!sortfunc)
127.191 + sortfunc = dir_block_cmp2;
127.192 + qsort(dblist->list, (size_t) dblist->count,
127.193 + sizeof(struct ext2_db_entry2), sortfunc);
127.194 + dblist->sorted = 1;
127.195 +}
127.196 +
127.197 +/*
127.198 + * This function iterates over the directory block list
127.199 + */
127.200 +errcode_t ext2fs_dblist_iterate3(ext2_dblist dblist,
127.201 + int (*func)(ext2_filsys fs,
127.202 + struct ext2_db_entry2 *db_info,
127.203 + void *priv_data),
127.204 + unsigned long long start,
127.205 + unsigned long long count,
127.206 + void *priv_data)
127.207 +{
127.208 + unsigned long long i, end;
127.209 + int ret;
127.210 +
127.211 + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
127.212 +
127.213 + end = start + count;
127.214 + if (!dblist->sorted)
127.215 + ext2fs_dblist_sort2(dblist, 0);
127.216 + if (end > dblist->count)
127.217 + end = dblist->count;
127.218 + for (i = start; i < end; i++) {
127.219 + ret = (*func)(dblist->fs, &dblist->list[i], priv_data);
127.220 + if (ret & DBLIST_ABORT)
127.221 + return 0;
127.222 + }
127.223 + return 0;
127.224 +}
127.225 +
127.226 +errcode_t ext2fs_dblist_iterate2(ext2_dblist dblist,
127.227 + int (*func)(ext2_filsys fs,
127.228 + struct ext2_db_entry2 *db_info,
127.229 + void *priv_data),
127.230 + void *priv_data)
127.231 +{
127.232 + return ext2fs_dblist_iterate3(dblist, func, 0, dblist->count,
127.233 + priv_data);
127.234 +}
127.235 +
127.236 +static EXT2_QSORT_TYPE dir_block_cmp2(const void *a, const void *b)
127.237 +{
127.238 + const struct ext2_db_entry2 *db_a =
127.239 + (const struct ext2_db_entry2 *) a;
127.240 + const struct ext2_db_entry2 *db_b =
127.241 + (const struct ext2_db_entry2 *) b;
127.242 +
127.243 + if (db_a->blk != db_b->blk)
127.244 + return (int) (db_a->blk - db_b->blk);
127.245 +
127.246 + if (db_a->ino != db_b->ino)
127.247 + return (int) (db_a->ino - db_b->ino);
127.248 +
127.249 + return (db_a->blockcnt - db_b->blockcnt);
127.250 +}
127.251 +
127.252 +blk64_t ext2fs_dblist_count2(ext2_dblist dblist)
127.253 +{
127.254 + return dblist->count;
127.255 +}
127.256 +
127.257 +errcode_t ext2fs_dblist_get_last2(ext2_dblist dblist,
127.258 + struct ext2_db_entry2 **entry)
127.259 +{
127.260 + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
127.261 +
127.262 + if (dblist->count == 0)
127.263 + return EXT2_ET_DBLIST_EMPTY;
127.264 +
127.265 + if (entry)
127.266 + *entry = dblist->list + ( dblist->count-1);
127.267 + return 0;
127.268 +}
127.269 +
127.270 +errcode_t ext2fs_dblist_drop_last(ext2_dblist dblist)
127.271 +{
127.272 + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
127.273 +
127.274 + if (dblist->count == 0)
127.275 + return EXT2_ET_DBLIST_EMPTY;
127.276 +
127.277 + dblist->count--;
127.278 + return 0;
127.279 +}
127.280 +
127.281 +/*
127.282 + * Legacy 32-bit versions
127.283 + */
127.284 +
127.285 +/*
127.286 + * Add a directory block to the directory block list
127.287 + */
127.288 +errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
127.289 + int blockcnt)
127.290 +{
127.291 + return ext2fs_add_dir_block2(dblist, ino, blk, blockcnt);
127.292 +}
127.293 +
127.294 +/*
127.295 + * Change the directory block to the directory block list
127.296 + */
127.297 +errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
127.298 + int blockcnt)
127.299 +{
127.300 + return ext2fs_set_dir_block2(dblist, ino, blk, blockcnt);
127.301 +}
127.302 +
127.303 +void ext2fs_dblist_sort(ext2_dblist dblist,
127.304 + EXT2_QSORT_TYPE (*sortfunc)(const void *,
127.305 + const void *))
127.306 +{
127.307 + if (sortfunc) {
127.308 + sortfunc32 = sortfunc;
127.309 + sortfunc = dir_block_cmp;
127.310 + } else
127.311 + sortfunc = dir_block_cmp2;
127.312 + qsort(dblist->list, (size_t) dblist->count,
127.313 + sizeof(struct ext2_db_entry2), sortfunc);
127.314 + dblist->sorted = 1;
127.315 +}
127.316 +
127.317 +/*
127.318 + * This function iterates over the directory block list
127.319 + */
127.320 +struct iterate_passthrough {
127.321 + int (*func)(ext2_filsys fs,
127.322 + struct ext2_db_entry *db_info,
127.323 + void *priv_data);
127.324 + void *priv_data;
127.325 +};
127.326 +
127.327 +static int passthrough_func(ext2_filsys fs,
127.328 + struct ext2_db_entry2 *db_info,
127.329 + void *priv_data)
127.330 +{
127.331 + struct iterate_passthrough *p = priv_data;
127.332 + struct ext2_db_entry db;
127.333 + int ret;
127.334 +
127.335 + db.ino = db_info->ino;
127.336 + db.blk = (blk_t) db_info->blk;
127.337 + db.blockcnt = (int) db_info->blockcnt;
127.338 + ret = (p->func)(fs, &db, p->priv_data);
127.339 + db_info->ino = db.ino;
127.340 + db_info->blk = db.blk;
127.341 + db_info->blockcnt = db.blockcnt;
127.342 + return ret;
127.343 +}
127.344 +
127.345 +errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
127.346 + int (*func)(ext2_filsys fs,
127.347 + struct ext2_db_entry *db_info,
127.348 + void *priv_data),
127.349 + void *priv_data)
127.350 +{
127.351 + struct iterate_passthrough pass;
127.352 +
127.353 + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
127.354 + pass.func = func;
127.355 + pass.priv_data = priv_data;
127.356 +
127.357 + return ext2fs_dblist_iterate2(dblist, passthrough_func, &pass);
127.358 +}
127.359 +
127.360 +static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b)
127.361 +{
127.362 + const struct ext2_db_entry2 *db_a =
127.363 + (const struct ext2_db_entry2 *) a;
127.364 + const struct ext2_db_entry2 *db_b =
127.365 + (const struct ext2_db_entry2 *) b;
127.366 +
127.367 + struct ext2_db_entry a32, b32;
127.368 +
127.369 + a32.ino = db_a->ino; a32.blk = db_a->blk;
127.370 + a32.blockcnt = db_a->blockcnt;
127.371 +
127.372 + b32.ino = db_b->ino; b32.blk = db_b->blk;
127.373 + b32.blockcnt = db_b->blockcnt;
127.374 +
127.375 + return sortfunc32(&a32, &b32);
127.376 +}
127.377 +
127.378 +int ext2fs_dblist_count(ext2_dblist dblist)
127.379 +{
127.380 + return dblist->count;
127.381 +}
127.382 +
127.383 +errcode_t ext2fs_dblist_get_last(ext2_dblist dblist,
127.384 + struct ext2_db_entry **entry)
127.385 +{
127.386 + static struct ext2_db_entry ret_entry;
127.387 + struct ext2_db_entry2 *last;
127.388 +
127.389 + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
127.390 +
127.391 + if (dblist->count == 0)
127.392 + return EXT2_ET_DBLIST_EMPTY;
127.393 +
127.394 + if (!entry)
127.395 + return 0;
127.396 +
127.397 + last = dblist->list + dblist->count -1;
127.398 +
127.399 + ret_entry.ino = last->ino;
127.400 + ret_entry.blk = last->blk;
127.401 + ret_entry.blockcnt = last->blockcnt;
127.402 + *entry = &ret_entry;
127.403 +
127.404 + return 0;
127.405 +}
127.406 +
128.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
128.2 +++ b/libext2fs/lib/libext2fs/dblist_dir.c Wed Aug 25 01:28:08 2021 +0200
128.3 @@ -0,0 +1,88 @@
128.4 +/*
128.5 + * dblist_dir.c --- iterate by directory entry
128.6 + *
128.7 + * Copyright 1997 by Theodore Ts'o
128.8 + *
128.9 + * %Begin-Header%
128.10 + * This file may be redistributed under the terms of the GNU Library
128.11 + * General Public License, version 2.
128.12 + * %End-Header%
128.13 + */
128.14 +
128.15 +#include "config.h"
128.16 +#include <stdio.h>
128.17 +#if HAVE_UNISTD_H
128.18 +#include <unistd.h>
128.19 +#endif
128.20 +#include <string.h>
128.21 +#include <time.h>
128.22 +
128.23 +#include "ext2_fs.h"
128.24 +#include "ext2fsP.h"
128.25 +
128.26 +static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry2 *db_info,
128.27 + void *priv_data);
128.28 +
128.29 +errcode_t ext2fs_dblist_dir_iterate(ext2_dblist dblist,
128.30 + int flags,
128.31 + char *block_buf,
128.32 + int (*func)(ext2_ino_t dir,
128.33 + int entry,
128.34 + struct ext2_dir_entry *dirent,
128.35 + int offset,
128.36 + int blocksize,
128.37 + char *buf,
128.38 + void *priv_data),
128.39 + void *priv_data)
128.40 +{
128.41 + errcode_t retval;
128.42 + struct dir_context ctx;
128.43 +
128.44 + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
128.45 +
128.46 + ctx.dir = 0;
128.47 + ctx.flags = flags;
128.48 + if (block_buf)
128.49 + ctx.buf = block_buf;
128.50 + else {
128.51 + retval = ext2fs_get_mem(dblist->fs->blocksize, &ctx.buf);
128.52 + if (retval)
128.53 + return retval;
128.54 + }
128.55 + ctx.func = func;
128.56 + ctx.priv_data = priv_data;
128.57 + ctx.errcode = 0;
128.58 +
128.59 + retval = ext2fs_dblist_iterate2(dblist, db_dir_proc, &ctx);
128.60 +
128.61 + if (!block_buf)
128.62 + ext2fs_free_mem(&ctx.buf);
128.63 + if (retval)
128.64 + return retval;
128.65 + return ctx.errcode;
128.66 +}
128.67 +
128.68 +static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry2 *db_info,
128.69 + void *priv_data)
128.70 +{
128.71 + struct ext2_inode inode;
128.72 + struct dir_context *ctx;
128.73 + int ret;
128.74 +
128.75 + ctx = (struct dir_context *) priv_data;
128.76 + ctx->dir = db_info->ino;
128.77 + ctx->errcode = 0;
128.78 +
128.79 + ctx->errcode = ext2fs_read_inode(fs, ctx->dir, &inode);
128.80 + if (ctx->errcode)
128.81 + return DBLIST_ABORT;
128.82 + if (inode.i_flags & EXT4_INLINE_DATA_FL)
128.83 + ret = ext2fs_inline_data_dir_iterate(fs, ctx->dir, ctx);
128.84 + else
128.85 + ret = ext2fs_process_dir_block(fs, &db_info->blk,
128.86 + db_info->blockcnt, 0, 0,
128.87 + priv_data);
128.88 + if ((ret & BLOCK_ABORT) && !ctx->errcode)
128.89 + return DBLIST_ABORT;
128.90 + return 0;
128.91 +}
129.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
129.2 +++ b/libext2fs/lib/libext2fs/digest_encode.c Wed Aug 25 01:28:08 2021 +0200
129.3 @@ -0,0 +1,187 @@
129.4 +/*
129.5 + * lib/ext2fs/digest_encode.c
129.6 + *
129.7 + * A function to encode a digest using 64 characters that are valid in a
129.8 + * filename per ext2fs rules.
129.9 + *
129.10 + * Written by Uday Savagaonkar, 2014.
129.11 + *
129.12 + * Copyright 2014 Google Inc. All Rights Reserved.
129.13 + *
129.14 + * %Begin-Header%
129.15 + * This file may be redistributed under the terms of the GNU Library
129.16 + * General Public License, version 2.
129.17 + * %End-Header%
129.18 + */
129.19 +
129.20 +#include "config.h"
129.21 +#if HAVE_SYS_TYPES_H
129.22 +#include <sys/types.h>
129.23 +#endif
129.24 +#include "ext2fs.h"
129.25 +
129.26 +static const char *lookup_table =
129.27 + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
129.28 +
129.29 +/**
129.30 + * ext2fs_digest_encode() -
129.31 + *
129.32 + * Encodes the input digest using characters from the set [a-zA-Z0-9_+].
129.33 + * The encoded string is roughly 4/3 times the size of the input string.
129.34 + */
129.35 +int ext2fs_digest_encode(const char *src, int len, char *dst)
129.36 +{
129.37 + int i = 0, bits = 0, ac = 0;
129.38 + char *cp = dst;
129.39 +
129.40 + while (i < len) {
129.41 + ac += (((unsigned char) src[i]) << bits);
129.42 + bits += 8;
129.43 + do {
129.44 + *cp++ = lookup_table[ac & 0x3f];
129.45 + ac >>= 6;
129.46 + bits -= 6;
129.47 + } while (bits >= 6);
129.48 + i++;
129.49 + }
129.50 + if (bits)
129.51 + *cp++ = lookup_table[ac & 0x3f];
129.52 + return cp - dst;
129.53 +}
129.54 +
129.55 +int ext2fs_digest_decode(const char *src, int len, char *dst)
129.56 +{
129.57 + int i = 0, bits = 0, ac = 0;
129.58 + const char *p;
129.59 + char *cp = dst;
129.60 +
129.61 + while (i < len) {
129.62 + p = strchr(lookup_table, src[i]);
129.63 + if (p == NULL || src[i] == 0)
129.64 + return -1;
129.65 + ac += (p - lookup_table) << bits;
129.66 + bits += 6;
129.67 + if (bits >= 8) {
129.68 + *cp++ = ac & 0xff;
129.69 + ac >>= 8;
129.70 + bits -= 8;
129.71 + }
129.72 + i++;
129.73 + }
129.74 + if (ac)
129.75 + return -1;
129.76 + return cp - dst;
129.77 +}
129.78 +
129.79 +
129.80 +#ifdef UNITTEST
129.81 +static const struct {
129.82 + unsigned char d[32];
129.83 + unsigned int len;
129.84 + const char *ed;
129.85 +} tests[] = {
129.86 + { { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
129.87 + 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
129.88 + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
129.89 + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 }, 32,
129.90 + "jDLxChJ,cQhm7TPyZ+WukcirBROZbOJTkWZmbgnU4WF"
129.91 + },
129.92 + { { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
129.93 + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
129.94 + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
129.95 + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }, 32,
129.96 + "6inF,+YAPreQBBk3d5qIjA7AhNqlXoHn0Cx,hJPAV0K"
129.97 + },
129.98 + { { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
129.99 + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
129.100 + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
129.101 + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }, 32,
129.102 + "k0oahJtB4gb5AbykM4DY5MKPknFZ,HyZ2ze7Unx2GEM"
129.103 + },
129.104 + { { 0x00, }, 1,
129.105 + "AA"
129.106 + },
129.107 + { { 0x01, }, 1,
129.108 + "BA"
129.109 + },
129.110 + { { 0x01, 0x02 }, 2,
129.111 + "BIA"
129.112 + },
129.113 + { { 0x01, 0x02, 0x03 }, 3,
129.114 + "BIwA"
129.115 + },
129.116 + { { 0x01, 0x02, 0x03, 0x04 }, 4,
129.117 + "BIwAEA"
129.118 + },
129.119 + { { 0x01, 0x02, 0x03, 0x04, 0xff }, 5,
129.120 + "BIwAE8P"
129.121 + },
129.122 + { { 0x01, 0x02, 0x03, 0x04, 0xff, 0xfe }, 6,
129.123 + "BIwAE8v,"
129.124 + },
129.125 + { { 0x01, 0x02, 0x03, 0x04, 0xff, 0xfe, 0xfd }, 7,
129.126 + "BIwAE8v,9D"
129.127 + },
129.128 +};
129.129 +
129.130 +int main(int argc, char **argv)
129.131 +{
129.132 + int i, ret, len;
129.133 + int errors = 0;
129.134 + char tmp[1024], tmp2[1024];
129.135 +
129.136 + if (argc == 3 && !strcmp(argv[1], "encode")) {
129.137 + memset(tmp, 0, sizeof(tmp));
129.138 + ext2fs_digest_encode(argv[2], strlen(argv[2]), tmp);
129.139 + puts(tmp);
129.140 + exit(0);
129.141 + }
129.142 + if (argc == 3 && !strcmp(argv[1], "decode")) {
129.143 + memset(tmp, 0, sizeof(tmp));
129.144 + ret = ext2fs_digest_decode(argv[2], strlen(argv[2]), tmp);
129.145 + puts(tmp);
129.146 + fprintf(stderr, "returned %d\n", ret);
129.147 + exit(0);
129.148 + }
129.149 + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
129.150 + memset(tmp, 0, sizeof(tmp));
129.151 + ret = ext2fs_digest_encode((const char *) tests[i].d,
129.152 + tests[i].len, tmp);
129.153 + len = strlen(tmp);
129.154 + printf("Test Digest %d (returned %d): ", i, ret);
129.155 + if (ret != len) {
129.156 + printf("FAILED returned %d, string length was %d\n",
129.157 + ret, len);
129.158 + errors++;
129.159 + continue;
129.160 + } else if (strcmp(tmp, tests[i].ed) != 0) {
129.161 + printf("FAILED: got %s, expected %s\n", tmp,
129.162 + tests[i].ed);
129.163 + errors++;
129.164 + continue;
129.165 + }
129.166 + ret = ext2fs_digest_decode(tmp, len, tmp2);
129.167 + if (ret != tests[i].len) {
129.168 + printf("FAILED decode returned %d, expected %d\n",
129.169 + ret, tests[i].len);
129.170 + errors++;
129.171 + continue;
129.172 + }
129.173 + if (memcmp(tmp2, tests[i].d, ret) != 0) {
129.174 + puts("FAILED: decode mismatched");
129.175 + errors++;
129.176 + continue;
129.177 + }
129.178 + printf("OK\n");
129.179 + }
129.180 + for (i = 1; i < argc; i++) {
129.181 + memset(tmp, 0, sizeof(tmp));
129.182 + ret = ext2fs_digest_encode(argv[i], strlen(argv[i]), tmp);
129.183 + len = strlen(tmp);
129.184 + printf("Digest of '%s' is '%s' (returned %d, length %d)\n",
129.185 + argv[i], tmp, ret, len);
129.186 + }
129.187 + return errors;
129.188 +}
129.189 +
129.190 +#endif /* UNITTEST */
130.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
130.2 +++ b/libext2fs/lib/libext2fs/dir_iterate.c Wed Aug 25 01:28:08 2021 +0200
130.3 @@ -0,0 +1,311 @@
130.4 +/*
130.5 + * dir_iterate.c --- ext2fs directory iteration operations
130.6 + *
130.7 + * Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o.
130.8 + *
130.9 + * %Begin-Header%
130.10 + * This file may be redistributed under the terms of the GNU Library
130.11 + * General Public License, version 2.
130.12 + * %End-Header%
130.13 + */
130.14 +
130.15 +#include "config.h"
130.16 +#include <stdio.h>
130.17 +#include <string.h>
130.18 +#if HAVE_UNISTD_H
130.19 +#include <unistd.h>
130.20 +#endif
130.21 +#if HAVE_ERRNO_H
130.22 +#include <errno.h>
130.23 +#endif
130.24 +
130.25 +#include "ext2_fs.h"
130.26 +#include "ext2fsP.h"
130.27 +
130.28 +#define EXT4_MAX_REC_LEN ((1<<16)-1)
130.29 +
130.30 +errcode_t ext2fs_get_rec_len(ext2_filsys fs,
130.31 + struct ext2_dir_entry *dirent,
130.32 + unsigned int *rec_len)
130.33 +{
130.34 + unsigned int len = dirent->rec_len;
130.35 +
130.36 + if (fs->blocksize < 65536)
130.37 + *rec_len = len;
130.38 + else if (len == EXT4_MAX_REC_LEN || len == 0)
130.39 + *rec_len = fs->blocksize;
130.40 + else
130.41 + *rec_len = (len & 65532) | ((len & 3) << 16);
130.42 + return 0;
130.43 +}
130.44 +
130.45 +errcode_t ext2fs_set_rec_len(ext2_filsys fs,
130.46 + unsigned int len,
130.47 + struct ext2_dir_entry *dirent)
130.48 +{
130.49 + if ((len > fs->blocksize) || (fs->blocksize > (1 << 18)) || (len & 3))
130.50 + return EINVAL;
130.51 + if (len < 65536) {
130.52 + dirent->rec_len = len;
130.53 + return 0;
130.54 + }
130.55 + if (len == fs->blocksize) {
130.56 + if (fs->blocksize == 65536)
130.57 + dirent->rec_len = EXT4_MAX_REC_LEN;
130.58 + else
130.59 + dirent->rec_len = 0;
130.60 + } else
130.61 + dirent->rec_len = (len & 65532) | ((len >> 16) & 3);
130.62 + return 0;
130.63 +}
130.64 +
130.65 +/*
130.66 + * This function checks to see whether or not a potential deleted
130.67 + * directory entry looks valid. What we do is check the deleted entry
130.68 + * and each successive entry to make sure that they all look valid and
130.69 + * that the last deleted entry ends at the beginning of the next
130.70 + * undeleted entry. Returns 1 if the deleted entry looks valid, zero
130.71 + * if not valid.
130.72 + */
130.73 +static int ext2fs_validate_entry(ext2_filsys fs, char *buf,
130.74 + unsigned int offset,
130.75 + unsigned int final_offset)
130.76 +{
130.77 + struct ext2_dir_entry *dirent;
130.78 + unsigned int rec_len;
130.79 +#define DIRENT_MIN_LENGTH 12
130.80 +
130.81 + while ((offset < final_offset) &&
130.82 + (offset <= fs->blocksize - DIRENT_MIN_LENGTH)) {
130.83 + dirent = (struct ext2_dir_entry *)(buf + offset);
130.84 + if (ext2fs_get_rec_len(fs, dirent, &rec_len))
130.85 + return 0;
130.86 + offset += rec_len;
130.87 + if ((rec_len < 8) ||
130.88 + ((rec_len % 4) != 0) ||
130.89 + ((ext2fs_dirent_name_len(dirent)+8) > (int) rec_len))
130.90 + return 0;
130.91 + }
130.92 + return (offset == final_offset);
130.93 +}
130.94 +
130.95 +errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
130.96 + ext2_ino_t dir,
130.97 + int flags,
130.98 + char *block_buf,
130.99 + int (*func)(ext2_ino_t dir,
130.100 + int entry,
130.101 + struct ext2_dir_entry *dirent,
130.102 + int offset,
130.103 + int blocksize,
130.104 + char *buf,
130.105 + void *priv_data),
130.106 + void *priv_data)
130.107 +{
130.108 + struct dir_context ctx;
130.109 + errcode_t retval;
130.110 +
130.111 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
130.112 +
130.113 + retval = ext2fs_check_directory(fs, dir);
130.114 + if (retval)
130.115 + return retval;
130.116 +
130.117 + ctx.dir = dir;
130.118 + ctx.flags = flags;
130.119 + if (block_buf)
130.120 + ctx.buf = block_buf;
130.121 + else {
130.122 + retval = ext2fs_get_mem(fs->blocksize, &ctx.buf);
130.123 + if (retval)
130.124 + return retval;
130.125 + }
130.126 + ctx.func = func;
130.127 + ctx.priv_data = priv_data;
130.128 + ctx.errcode = 0;
130.129 + retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_READ_ONLY, 0,
130.130 + ext2fs_process_dir_block, &ctx);
130.131 + if (!block_buf)
130.132 + ext2fs_free_mem(&ctx.buf);
130.133 + if (retval == EXT2_ET_INLINE_DATA_CANT_ITERATE) {
130.134 + (void) ext2fs_inline_data_dir_iterate(fs, dir, &ctx);
130.135 + retval = 0;
130.136 + }
130.137 + if (retval)
130.138 + return retval;
130.139 + return ctx.errcode;
130.140 +}
130.141 +
130.142 +struct xlate {
130.143 + int (*func)(struct ext2_dir_entry *dirent,
130.144 + int offset,
130.145 + int blocksize,
130.146 + char *buf,
130.147 + void *priv_data);
130.148 + void *real_private;
130.149 +};
130.150 +
130.151 +static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)),
130.152 + int entry EXT2FS_ATTR((unused)),
130.153 + struct ext2_dir_entry *dirent, int offset,
130.154 + int blocksize, char *buf, void *priv_data)
130.155 +{
130.156 + struct xlate *xl = (struct xlate *) priv_data;
130.157 +
130.158 + return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private);
130.159 +}
130.160 +
130.161 +errcode_t ext2fs_dir_iterate(ext2_filsys fs,
130.162 + ext2_ino_t dir,
130.163 + int flags,
130.164 + char *block_buf,
130.165 + int (*func)(struct ext2_dir_entry *dirent,
130.166 + int offset,
130.167 + int blocksize,
130.168 + char *buf,
130.169 + void *priv_data),
130.170 + void *priv_data)
130.171 +{
130.172 + struct xlate xl;
130.173 +
130.174 + xl.real_private = priv_data;
130.175 + xl.func = func;
130.176 +
130.177 + return ext2fs_dir_iterate2(fs, dir, flags, block_buf,
130.178 + xlate_func, &xl);
130.179 +}
130.180 +
130.181 +
130.182 +/*
130.183 + * Helper function which is private to this module. Used by
130.184 + * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
130.185 + */
130.186 +int ext2fs_process_dir_block(ext2_filsys fs,
130.187 + blk64_t *blocknr,
130.188 + e2_blkcnt_t blockcnt,
130.189 + blk64_t ref_block EXT2FS_ATTR((unused)),
130.190 + int ref_offset EXT2FS_ATTR((unused)),
130.191 + void *priv_data)
130.192 +{
130.193 + struct dir_context *ctx = (struct dir_context *) priv_data;
130.194 + unsigned int offset = 0;
130.195 + unsigned int next_real_entry = 0;
130.196 + int ret = 0;
130.197 + int changed = 0;
130.198 + int do_abort = 0;
130.199 + unsigned int rec_len, size, buflen;
130.200 + int entry;
130.201 + struct ext2_dir_entry *dirent;
130.202 + int csum_size = 0;
130.203 + int inline_data;
130.204 + errcode_t retval = 0;
130.205 +
130.206 + if (blockcnt < 0)
130.207 + return 0;
130.208 +
130.209 + entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
130.210 +
130.211 + /* If a dir has inline data, we don't need to read block */
130.212 + inline_data = !!(ctx->flags & DIRENT_FLAG_INCLUDE_INLINE_DATA);
130.213 + if (!inline_data) {
130.214 + ctx->errcode = ext2fs_read_dir_block4(fs, *blocknr, ctx->buf, 0,
130.215 + ctx->dir);
130.216 + if (ctx->errcode)
130.217 + return BLOCK_ABORT;
130.218 + /* If we handle a normal dir, we traverse the entire block */
130.219 + buflen = fs->blocksize;
130.220 + } else {
130.221 + buflen = ctx->buflen;
130.222 + }
130.223 +
130.224 + if (ext2fs_has_feature_metadata_csum(fs->super))
130.225 + csum_size = sizeof(struct ext2_dir_entry_tail);
130.226 +
130.227 + while (offset < buflen - 8) {
130.228 + dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
130.229 + if (ext2fs_get_rec_len(fs, dirent, &rec_len))
130.230 + return BLOCK_ABORT;
130.231 + if (((offset + rec_len) > buflen) ||
130.232 + (rec_len < 8) ||
130.233 + ((rec_len % 4) != 0) ||
130.234 + ((ext2fs_dirent_name_len(dirent)+8) > (int) rec_len)) {
130.235 + ctx->errcode = EXT2_ET_DIR_CORRUPTED;
130.236 + return BLOCK_ABORT;
130.237 + }
130.238 + if (!dirent->inode) {
130.239 + /*
130.240 + * We just need to check metadata_csum when this
130.241 + * dir hasn't inline data. That means that 'buflen'
130.242 + * should be blocksize.
130.243 + */
130.244 + if (!inline_data &&
130.245 + (offset == buflen - csum_size) &&
130.246 + (dirent->rec_len == csum_size) &&
130.247 + (dirent->name_len == EXT2_DIR_NAME_LEN_CSUM)) {
130.248 + if (!(ctx->flags & DIRENT_FLAG_INCLUDE_CSUM))
130.249 + goto next;
130.250 + entry = DIRENT_CHECKSUM;
130.251 + } else if (!(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
130.252 + goto next;
130.253 + }
130.254 +
130.255 + ret = (ctx->func)(ctx->dir,
130.256 + (next_real_entry > offset) ?
130.257 + DIRENT_DELETED_FILE : entry,
130.258 + dirent, offset,
130.259 + buflen, ctx->buf,
130.260 + ctx->priv_data);
130.261 + if (entry < DIRENT_OTHER_FILE)
130.262 + entry++;
130.263 +
130.264 + if (ret & DIRENT_CHANGED) {
130.265 + if (ext2fs_get_rec_len(fs, dirent, &rec_len))
130.266 + return BLOCK_ABORT;
130.267 + changed++;
130.268 + }
130.269 + if (ret & DIRENT_ABORT) {
130.270 + do_abort++;
130.271 + break;
130.272 + }
130.273 +next:
130.274 + if (next_real_entry == offset)
130.275 + next_real_entry += rec_len;
130.276 +
130.277 + if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) {
130.278 + size = (ext2fs_dirent_name_len(dirent) + 11) & ~3;
130.279 +
130.280 + if (rec_len != size) {
130.281 + unsigned int final_offset;
130.282 +
130.283 + final_offset = offset + rec_len;
130.284 + offset += size;
130.285 + while (offset < final_offset &&
130.286 + !ext2fs_validate_entry(fs, ctx->buf,
130.287 + offset,
130.288 + final_offset))
130.289 + offset += 4;
130.290 + continue;
130.291 + }
130.292 + }
130.293 + offset += rec_len;
130.294 + }
130.295 +
130.296 + if (changed) {
130.297 + if (!inline_data) {
130.298 + ctx->errcode = ext2fs_write_dir_block4(fs, *blocknr,
130.299 + ctx->buf,
130.300 + 0, ctx->dir);
130.301 + if (ctx->errcode)
130.302 + return BLOCK_ABORT;
130.303 + } else {
130.304 + /*
130.305 + * return BLOCK_INLINE_DATA_CHANGED to notify caller
130.306 + * that inline data has been changed.
130.307 + */
130.308 + retval = BLOCK_INLINE_DATA_CHANGED;
130.309 + }
130.310 + }
130.311 + if (do_abort)
130.312 + return retval | BLOCK_ABORT;
130.313 + return retval;
130.314 +}
131.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
131.2 +++ b/libext2fs/lib/libext2fs/dirblock.c Wed Aug 25 01:28:08 2021 +0200
131.3 @@ -0,0 +1,113 @@
131.4 +/*
131.5 + * dirblock.c --- directory block routines.
131.6 + *
131.7 + * Copyright (C) 1995, 1996 Theodore Ts'o.
131.8 + *
131.9 + * %Begin-Header%
131.10 + * This file may be redistributed under the terms of the GNU Library
131.11 + * General Public License, version 2.
131.12 + * %End-Header%
131.13 + */
131.14 +
131.15 +#include "config.h"
131.16 +#include <stdio.h>
131.17 +#if HAVE_UNISTD_H
131.18 +#include <unistd.h>
131.19 +#endif
131.20 +#include <string.h>
131.21 +#include <time.h>
131.22 +
131.23 +#include "ext2_fs.h"
131.24 +#include "ext2fs.h"
131.25 +
131.26 +errcode_t ext2fs_read_dir_block4(ext2_filsys fs, blk64_t block,
131.27 + void *buf, int flags EXT2FS_ATTR((unused)),
131.28 + ext2_ino_t ino)
131.29 +{
131.30 + errcode_t retval;
131.31 + int corrupt = 0;
131.32 +
131.33 + retval = io_channel_read_blk64(fs->io, block, 1, buf);
131.34 + if (retval)
131.35 + return retval;
131.36 +
131.37 + if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
131.38 + !ext2fs_dir_block_csum_verify(fs, ino,
131.39 + (struct ext2_dir_entry *)buf))
131.40 + corrupt = 1;
131.41 +
131.42 +#ifdef WORDS_BIGENDIAN
131.43 + retval = ext2fs_dirent_swab_in(fs, buf, flags);
131.44 +#endif
131.45 + if (!retval && corrupt)
131.46 + retval = EXT2_ET_DIR_CSUM_INVALID;
131.47 + return retval;
131.48 +}
131.49 +
131.50 +errcode_t ext2fs_read_dir_block3(ext2_filsys fs, blk64_t block,
131.51 + void *buf, int flags EXT2FS_ATTR((unused)))
131.52 +{
131.53 + return ext2fs_read_dir_block4(fs, block, buf, flags, 0);
131.54 +}
131.55 +
131.56 +errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
131.57 + void *buf, int flags EXT2FS_ATTR((unused)))
131.58 +{
131.59 + return ext2fs_read_dir_block3(fs, block, buf, flags);
131.60 +}
131.61 +
131.62 +errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
131.63 + void *buf)
131.64 +{
131.65 + return ext2fs_read_dir_block3(fs, block, buf, 0);
131.66 +}
131.67 +
131.68 +
131.69 +errcode_t ext2fs_write_dir_block4(ext2_filsys fs, blk64_t block,
131.70 + void *inbuf, int flags EXT2FS_ATTR((unused)),
131.71 + ext2_ino_t ino)
131.72 +{
131.73 + errcode_t retval;
131.74 + char *buf = inbuf;
131.75 +
131.76 +#ifdef WORDS_BIGENDIAN
131.77 + retval = ext2fs_get_mem(fs->blocksize, &buf);
131.78 + if (retval)
131.79 + return retval;
131.80 + memcpy(buf, inbuf, fs->blocksize);
131.81 + retval = ext2fs_dirent_swab_out(fs, buf, flags);
131.82 + if (retval)
131.83 + return retval;
131.84 +#endif
131.85 + retval = ext2fs_dir_block_csum_set(fs, ino,
131.86 + (struct ext2_dir_entry *)buf);
131.87 + if (retval)
131.88 + goto out;
131.89 +
131.90 + retval = io_channel_write_blk64(fs->io, block, 1, buf);
131.91 +
131.92 +out:
131.93 +#ifdef WORDS_BIGENDIAN
131.94 + ext2fs_free_mem(&buf);
131.95 +#endif
131.96 + return retval;
131.97 +}
131.98 +
131.99 +errcode_t ext2fs_write_dir_block3(ext2_filsys fs, blk64_t block,
131.100 + void *inbuf, int flags EXT2FS_ATTR((unused)))
131.101 +{
131.102 + return ext2fs_write_dir_block4(fs, block, inbuf, flags, 0);
131.103 +}
131.104 +
131.105 +errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
131.106 + void *inbuf, int flags EXT2FS_ATTR((unused)))
131.107 +{
131.108 + return ext2fs_write_dir_block3(fs, block, inbuf, flags);
131.109 +}
131.110 +
131.111 +errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
131.112 + void *inbuf)
131.113 +{
131.114 + return ext2fs_write_dir_block3(fs, block, inbuf, 0);
131.115 +}
131.116 +
132.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
132.2 +++ b/libext2fs/lib/libext2fs/dirhash.c Wed Aug 25 01:28:08 2021 +0200
132.3 @@ -0,0 +1,259 @@
132.4 +/*
132.5 + * dirhash.c -- Calculate the hash of a directory entry
132.6 + *
132.7 + * Copyright (c) 2001 Daniel Phillips
132.8 + *
132.9 + * Copyright (c) 2002 Theodore Ts'o.
132.10 + *
132.11 + * %Begin-Header%
132.12 + * This file may be redistributed under the terms of the GNU Library
132.13 + * General Public License, version 2.
132.14 + * %End-Header%
132.15 + */
132.16 +
132.17 +#include "config.h"
132.18 +#include <stdio.h>
132.19 +#include <string.h>
132.20 +
132.21 +#include "ext2_fs.h"
132.22 +#include "ext2fs.h"
132.23 +
132.24 +/*
132.25 + * Keyed 32-bit hash function using TEA in a Davis-Meyer function
132.26 + * H0 = Key
132.27 + * Hi = E Mi(Hi-1) + Hi-1
132.28 + *
132.29 + * (see Applied Cryptography, 2nd edition, p448).
132.30 + *
132.31 + * Jeremy Fitzhardinge <jeremy@zip.com.au> 1998
132.32 + *
132.33 + * This code is made available under the terms of the GPL
132.34 + */
132.35 +#define DELTA 0x9E3779B9
132.36 +
132.37 +static void TEA_transform(__u32 buf[4], __u32 const in[])
132.38 +{
132.39 + __u32 sum = 0;
132.40 + __u32 b0 = buf[0], b1 = buf[1];
132.41 + __u32 a = in[0], b = in[1], c = in[2], d = in[3];
132.42 + int n = 16;
132.43 +
132.44 + do {
132.45 + sum += DELTA;
132.46 + b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
132.47 + b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
132.48 + } while(--n);
132.49 +
132.50 + buf[0] += b0;
132.51 + buf[1] += b1;
132.52 +}
132.53 +
132.54 +/* F, G and H are basic MD4 functions: selection, majority, parity */
132.55 +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
132.56 +#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
132.57 +#define H(x, y, z) ((x) ^ (y) ^ (z))
132.58 +
132.59 +/*
132.60 + * The generic round function. The application is so specific that
132.61 + * we don't bother protecting all the arguments with parens, as is generally
132.62 + * good macro practice, in favor of extra legibility.
132.63 + * Rotation is separate from addition to prevent recomputation
132.64 + */
132.65 +#define ROUND(f, a, b, c, d, x, s) \
132.66 + (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
132.67 +#define K1 0
132.68 +#define K2 013240474631UL
132.69 +#define K3 015666365641UL
132.70 +
132.71 +/*
132.72 + * Basic cut-down MD4 transform. Returns only 32 bits of result.
132.73 + */
132.74 +static void halfMD4Transform (__u32 buf[4], __u32 const in[])
132.75 +{
132.76 + __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
132.77 +
132.78 + /* Round 1 */
132.79 + ROUND(F, a, b, c, d, in[0] + K1, 3);
132.80 + ROUND(F, d, a, b, c, in[1] + K1, 7);
132.81 + ROUND(F, c, d, a, b, in[2] + K1, 11);
132.82 + ROUND(F, b, c, d, a, in[3] + K1, 19);
132.83 + ROUND(F, a, b, c, d, in[4] + K1, 3);
132.84 + ROUND(F, d, a, b, c, in[5] + K1, 7);
132.85 + ROUND(F, c, d, a, b, in[6] + K1, 11);
132.86 + ROUND(F, b, c, d, a, in[7] + K1, 19);
132.87 +
132.88 + /* Round 2 */
132.89 + ROUND(G, a, b, c, d, in[1] + K2, 3);
132.90 + ROUND(G, d, a, b, c, in[3] + K2, 5);
132.91 + ROUND(G, c, d, a, b, in[5] + K2, 9);
132.92 + ROUND(G, b, c, d, a, in[7] + K2, 13);
132.93 + ROUND(G, a, b, c, d, in[0] + K2, 3);
132.94 + ROUND(G, d, a, b, c, in[2] + K2, 5);
132.95 + ROUND(G, c, d, a, b, in[4] + K2, 9);
132.96 + ROUND(G, b, c, d, a, in[6] + K2, 13);
132.97 +
132.98 + /* Round 3 */
132.99 + ROUND(H, a, b, c, d, in[3] + K3, 3);
132.100 + ROUND(H, d, a, b, c, in[7] + K3, 9);
132.101 + ROUND(H, c, d, a, b, in[2] + K3, 11);
132.102 + ROUND(H, b, c, d, a, in[6] + K3, 15);
132.103 + ROUND(H, a, b, c, d, in[1] + K3, 3);
132.104 + ROUND(H, d, a, b, c, in[5] + K3, 9);
132.105 + ROUND(H, c, d, a, b, in[0] + K3, 11);
132.106 + ROUND(H, b, c, d, a, in[4] + K3, 15);
132.107 +
132.108 + buf[0] += a;
132.109 + buf[1] += b;
132.110 + buf[2] += c;
132.111 + buf[3] += d;
132.112 +}
132.113 +
132.114 +#undef ROUND
132.115 +#undef F
132.116 +#undef G
132.117 +#undef H
132.118 +#undef K1
132.119 +#undef K2
132.120 +#undef K3
132.121 +
132.122 +/* The old legacy hash */
132.123 +static ext2_dirhash_t dx_hack_hash (const char *name, int len,
132.124 + int unsigned_flag)
132.125 +{
132.126 + __u32 hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
132.127 + const unsigned char *ucp = (const unsigned char *) name;
132.128 + const signed char *scp = (const signed char *) name;
132.129 + int c;
132.130 +
132.131 + while (len--) {
132.132 + if (unsigned_flag)
132.133 + c = (int) *ucp++;
132.134 + else
132.135 + c = (int) *scp++;
132.136 + hash = hash1 + (hash0 ^ (c * 7152373));
132.137 +
132.138 + if (hash & 0x80000000) hash -= 0x7fffffff;
132.139 + hash1 = hash0;
132.140 + hash0 = hash;
132.141 + }
132.142 + return (hash0 << 1);
132.143 +}
132.144 +
132.145 +static void str2hashbuf(const char *msg, int len, __u32 *buf, int num,
132.146 + int unsigned_flag)
132.147 +{
132.148 + __u32 pad, val;
132.149 + int i, c;
132.150 + const unsigned char *ucp = (const unsigned char *) msg;
132.151 + const signed char *scp = (const signed char *) msg;
132.152 +
132.153 + pad = (__u32)len | ((__u32)len << 8);
132.154 + pad |= pad << 16;
132.155 +
132.156 + val = pad;
132.157 + if (len > num*4)
132.158 + len = num * 4;
132.159 + for (i=0; i < len; i++) {
132.160 + if (unsigned_flag)
132.161 + c = (int) ucp[i];
132.162 + else
132.163 + c = (int) scp[i];
132.164 +
132.165 + val = c + (val << 8);
132.166 + if ((i % 4) == 3) {
132.167 + *buf++ = val;
132.168 + val = pad;
132.169 + num--;
132.170 + }
132.171 + }
132.172 + if (--num >= 0)
132.173 + *buf++ = val;
132.174 + while (--num >= 0)
132.175 + *buf++ = pad;
132.176 +}
132.177 +
132.178 +/*
132.179 + * Returns the hash of a filename. If len is 0 and name is NULL, then
132.180 + * this function can be used to test whether or not a hash version is
132.181 + * supported.
132.182 + *
132.183 + * The seed is an 4 longword (32 bits) "secret" which can be used to
132.184 + * uniquify a hash. If the seed is all zero's, then some default seed
132.185 + * may be used.
132.186 + *
132.187 + * A particular hash version specifies whether or not the seed is
132.188 + * represented, and whether or not the returned hash is 32 bits or 64
132.189 + * bits. 32 bit hashes will return 0 for the minor hash.
132.190 + */
132.191 +errcode_t ext2fs_dirhash(int version, const char *name, int len,
132.192 + const __u32 *seed,
132.193 + ext2_dirhash_t *ret_hash,
132.194 + ext2_dirhash_t *ret_minor_hash)
132.195 +{
132.196 + __u32 hash;
132.197 + __u32 minor_hash = 0;
132.198 + const char *p;
132.199 + int i;
132.200 + __u32 in[8], buf[4];
132.201 + int unsigned_flag = 0;
132.202 +
132.203 + /* Initialize the default seed for the hash checksum functions */
132.204 + buf[0] = 0x67452301;
132.205 + buf[1] = 0xefcdab89;
132.206 + buf[2] = 0x98badcfe;
132.207 + buf[3] = 0x10325476;
132.208 +
132.209 + /* Check to see if the seed is all zero's */
132.210 + if (seed) {
132.211 + for (i=0; i < 4; i++) {
132.212 + if (seed[i])
132.213 + break;
132.214 + }
132.215 + if (i < 4)
132.216 + memcpy(buf, seed, sizeof(buf));
132.217 + }
132.218 +
132.219 + switch (version) {
132.220 + case EXT2_HASH_LEGACY_UNSIGNED:
132.221 + unsigned_flag++;
132.222 + /* fallthrough */
132.223 + case EXT2_HASH_LEGACY:
132.224 + hash = dx_hack_hash(name, len, unsigned_flag);
132.225 + break;
132.226 + case EXT2_HASH_HALF_MD4_UNSIGNED:
132.227 + unsigned_flag++;
132.228 + /* fallthrough */
132.229 + case EXT2_HASH_HALF_MD4:
132.230 + p = name;
132.231 + while (len > 0) {
132.232 + str2hashbuf(p, len, in, 8, unsigned_flag);
132.233 + halfMD4Transform(buf, in);
132.234 + len -= 32;
132.235 + p += 32;
132.236 + }
132.237 + minor_hash = buf[2];
132.238 + hash = buf[1];
132.239 + break;
132.240 + case EXT2_HASH_TEA_UNSIGNED:
132.241 + unsigned_flag++;
132.242 + /* fallthrough */
132.243 + case EXT2_HASH_TEA:
132.244 + p = name;
132.245 + while (len > 0) {
132.246 + str2hashbuf(p, len, in, 4, unsigned_flag);
132.247 + TEA_transform(buf, in);
132.248 + len -= 16;
132.249 + p += 16;
132.250 + }
132.251 + hash = buf[0];
132.252 + minor_hash = buf[1];
132.253 + break;
132.254 + default:
132.255 + *ret_hash = 0;
132.256 + return EXT2_ET_DIRHASH_UNSUPP;
132.257 + }
132.258 + *ret_hash = hash & ~1;
132.259 + if (ret_minor_hash)
132.260 + *ret_minor_hash = minor_hash;
132.261 + return 0;
132.262 +}
133.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
133.2 +++ b/libext2fs/lib/libext2fs/dupfs.c Wed Aug 25 01:28:08 2021 +0200
133.3 @@ -0,0 +1,122 @@
133.4 +/*
133.5 + * dupfs.c --- duplicate a ext2 filesystem handle
133.6 + *
133.7 + * Copyright (C) 1997, 1998, 2001, 2003, 2005 by Theodore Ts'o.
133.8 + *
133.9 + * %Begin-Header%
133.10 + * This file may be redistributed under the terms of the GNU Library
133.11 + * General Public License, version 2.
133.12 + * %End-Header%
133.13 + */
133.14 +
133.15 +#include "config.h"
133.16 +#include <stdio.h>
133.17 +#if HAVE_UNISTD_H
133.18 +#include <unistd.h>
133.19 +#endif
133.20 +#include <time.h>
133.21 +#include <string.h>
133.22 +
133.23 +#include "ext2_fs.h"
133.24 +#include "ext2fsP.h"
133.25 +
133.26 +errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest)
133.27 +{
133.28 + ext2_filsys fs;
133.29 + errcode_t retval;
133.30 +
133.31 + EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS);
133.32 +
133.33 + retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
133.34 + if (retval)
133.35 + return retval;
133.36 +
133.37 + *fs = *src;
133.38 + fs->device_name = 0;
133.39 + fs->super = 0;
133.40 + fs->orig_super = 0;
133.41 + fs->group_desc = 0;
133.42 + fs->inode_map = 0;
133.43 + fs->block_map = 0;
133.44 + fs->badblocks = 0;
133.45 + fs->dblist = 0;
133.46 + fs->mmp_buf = 0;
133.47 + fs->mmp_cmp = 0;
133.48 + fs->mmp_fd = -1;
133.49 +
133.50 + io_channel_bumpcount(fs->io);
133.51 + if (fs->icache)
133.52 + fs->icache->refcount++;
133.53 +
133.54 + retval = ext2fs_get_mem(strlen(src->device_name)+1, &fs->device_name);
133.55 + if (retval)
133.56 + goto errout;
133.57 + strcpy(fs->device_name, src->device_name);
133.58 +
133.59 + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super);
133.60 + if (retval)
133.61 + goto errout;
133.62 + memcpy(fs->super, src->super, SUPERBLOCK_SIZE);
133.63 +
133.64 + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
133.65 + if (retval)
133.66 + goto errout;
133.67 + memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE);
133.68 +
133.69 + retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
133.70 + &fs->group_desc);
133.71 + if (retval)
133.72 + goto errout;
133.73 + memcpy(fs->group_desc, src->group_desc,
133.74 + (size_t) fs->desc_blocks * fs->blocksize);
133.75 +
133.76 + if (src->inode_map) {
133.77 + retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map);
133.78 + if (retval)
133.79 + goto errout;
133.80 + }
133.81 + if (src->block_map) {
133.82 + retval = ext2fs_copy_bitmap(src->block_map, &fs->block_map);
133.83 + if (retval)
133.84 + goto errout;
133.85 + }
133.86 + if (src->badblocks) {
133.87 + retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks);
133.88 + if (retval)
133.89 + goto errout;
133.90 + }
133.91 + if (src->dblist) {
133.92 + retval = ext2fs_copy_dblist(src->dblist, &fs->dblist);
133.93 + if (retval)
133.94 + goto errout;
133.95 + }
133.96 + if (src->mmp_buf) {
133.97 + retval = ext2fs_get_mem(src->blocksize, &fs->mmp_buf);
133.98 + if (retval)
133.99 + goto errout;
133.100 + memcpy(fs->mmp_buf, src->mmp_buf, src->blocksize);
133.101 + }
133.102 + if (src->mmp_fd >= 0) {
133.103 + fs->mmp_fd = dup(src->mmp_fd);
133.104 + if (fs->mmp_fd < 0) {
133.105 + retval = EXT2_ET_MMP_OPEN_DIRECT;
133.106 + goto errout;
133.107 + }
133.108 + }
133.109 + if (src->mmp_cmp) {
133.110 + int align = ext2fs_get_dio_alignment(src->mmp_fd);
133.111 +
133.112 + retval = ext2fs_get_memalign(src->blocksize, align,
133.113 + &fs->mmp_cmp);
133.114 + if (retval)
133.115 + goto errout;
133.116 + memcpy(fs->mmp_cmp, src->mmp_cmp, src->blocksize);
133.117 + }
133.118 + *dest = fs;
133.119 + return 0;
133.120 +errout:
133.121 + ext2fs_free(fs);
133.122 + return retval;
133.123 +
133.124 +}
133.125 +
134.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
134.2 +++ b/libext2fs/lib/libext2fs/e2image.h Wed Aug 25 01:28:08 2021 +0200
134.3 @@ -0,0 +1,37 @@
134.4 +/*
134.5 + * e2image.h --- header file describing the ext2 image format
134.6 + *
134.7 + * Copyright (C) 2000 Theodore Ts'o.
134.8 + *
134.9 + * Note: this uses the POSIX IO interfaces, unlike most of the other
134.10 + * functions in this library. So sue me.
134.11 + *
134.12 + * %Begin-Header%
134.13 + * This file may be redistributed under the terms of the GNU Library
134.14 + * General Public License, version 2.
134.15 + * %End-Header%
134.16 + */
134.17 +
134.18 +struct ext2_image_hdr {
134.19 + __u32 magic_number; /* This must be EXT2_ET_MAGIC_E2IMAGE */
134.20 + char magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */
134.21 + char fs_hostname[64];/* Hostname of machine of image */
134.22 + char fs_netaddr[32]; /* Network address */
134.23 + __u32 fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */
134.24 + __u32 fs_device; /* Device number of image */
134.25 + char fs_device_name[64]; /* Device name */
134.26 + char fs_uuid[16]; /* UUID of filesystem */
134.27 + __u32 fs_blocksize; /* Block size of the filesystem */
134.28 + __u32 fs_reserved[8];
134.29 +
134.30 + __u32 image_device; /* Device number of image file */
134.31 + __u32 image_inode; /* Inode number of image file */
134.32 + __u32 image_time; /* Time of image creation */
134.33 + __u32 image_reserved[8];
134.34 +
134.35 + __u32 offset_super; /* Byte offset of the sb and descriptors */
134.36 + __u32 offset_inode; /* Byte offset of the inode table */
134.37 + __u32 offset_inodemap; /* Byte offset of the inode bitmaps */
134.38 + __u32 offset_blockmap; /* Byte offset of the inode bitmaps */
134.39 + __u32 offset_reserved[8];
134.40 +};
135.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
135.2 +++ b/libext2fs/lib/libext2fs/expanddir.c Wed Aug 25 01:28:08 2021 +0200
135.3 @@ -0,0 +1,140 @@
135.4 +/*
135.5 + * expand.c --- expand an ext2fs directory
135.6 + *
135.7 + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o.
135.8 + *
135.9 + * %Begin-Header%
135.10 + * This file may be redistributed under the terms of the GNU Library
135.11 + * General Public License, version 2.
135.12 + * %End-Header%
135.13 + */
135.14 +
135.15 +#include "config.h"
135.16 +#include <stdio.h>
135.17 +#include <string.h>
135.18 +#if HAVE_UNISTD_H
135.19 +#include <unistd.h>
135.20 +#endif
135.21 +
135.22 +#include "ext2_fs.h"
135.23 +#include "ext2fs.h"
135.24 +#include "ext2fsP.h"
135.25 +
135.26 +struct expand_dir_struct {
135.27 + int done;
135.28 + int newblocks;
135.29 + blk64_t goal;
135.30 + errcode_t err;
135.31 + ext2_ino_t dir;
135.32 +};
135.33 +
135.34 +static int expand_dir_proc(ext2_filsys fs,
135.35 + blk64_t *blocknr,
135.36 + e2_blkcnt_t blockcnt,
135.37 + blk64_t ref_block EXT2FS_ATTR((unused)),
135.38 + int ref_offset EXT2FS_ATTR((unused)),
135.39 + void *priv_data)
135.40 +{
135.41 + struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
135.42 + blk64_t new_blk;
135.43 + char *block;
135.44 + errcode_t retval;
135.45 +
135.46 + if (*blocknr) {
135.47 + if (blockcnt >= 0)
135.48 + es->goal = *blocknr;
135.49 + return 0;
135.50 + }
135.51 + if (blockcnt &&
135.52 + (EXT2FS_B2C(fs, es->goal) == EXT2FS_B2C(fs, es->goal+1)))
135.53 + new_blk = es->goal+1;
135.54 + else {
135.55 + es->goal &= ~EXT2FS_CLUSTER_MASK(fs);
135.56 + retval = ext2fs_new_block2(fs, es->goal, 0, &new_blk);
135.57 + if (retval) {
135.58 + es->err = retval;
135.59 + return BLOCK_ABORT;
135.60 + }
135.61 + es->newblocks++;
135.62 + ext2fs_block_alloc_stats2(fs, new_blk, +1);
135.63 + }
135.64 + if (blockcnt > 0) {
135.65 + retval = ext2fs_new_dir_block(fs, 0, 0, &block);
135.66 + if (retval) {
135.67 + es->err = retval;
135.68 + return BLOCK_ABORT;
135.69 + }
135.70 + es->done = 1;
135.71 + retval = ext2fs_write_dir_block4(fs, new_blk, block, 0,
135.72 + es->dir);
135.73 + ext2fs_free_mem(&block);
135.74 + } else
135.75 + retval = ext2fs_zero_blocks2(fs, new_blk, 1, NULL, NULL);
135.76 + if (blockcnt >= 0)
135.77 + es->goal = new_blk;
135.78 + if (retval) {
135.79 + es->err = retval;
135.80 + return BLOCK_ABORT;
135.81 + }
135.82 + *blocknr = new_blk;
135.83 +
135.84 + if (es->done)
135.85 + return (BLOCK_CHANGED | BLOCK_ABORT);
135.86 + else
135.87 + return BLOCK_CHANGED;
135.88 +}
135.89 +
135.90 +errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir)
135.91 +{
135.92 + errcode_t retval;
135.93 + struct expand_dir_struct es;
135.94 + struct ext2_inode inode;
135.95 +
135.96 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
135.97 +
135.98 + if (!(fs->flags & EXT2_FLAG_RW))
135.99 + return EXT2_ET_RO_FILSYS;
135.100 +
135.101 + if (!fs->block_map)
135.102 + return EXT2_ET_NO_BLOCK_BITMAP;
135.103 +
135.104 + retval = ext2fs_check_directory(fs, dir);
135.105 + if (retval)
135.106 + return retval;
135.107 +
135.108 + retval = ext2fs_read_inode(fs, dir, &inode);
135.109 + if (retval)
135.110 + return retval;
135.111 +
135.112 + es.done = 0;
135.113 + es.err = 0;
135.114 + es.goal = ext2fs_find_inode_goal(fs, dir, &inode, 0);
135.115 + es.newblocks = 0;
135.116 + es.dir = dir;
135.117 +
135.118 + retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_APPEND,
135.119 + 0, expand_dir_proc, &es);
135.120 + if (retval == EXT2_ET_INLINE_DATA_CANT_ITERATE)
135.121 + return ext2fs_inline_data_expand(fs, dir);
135.122 +
135.123 + if (es.err)
135.124 + return es.err;
135.125 + if (!es.done)
135.126 + return EXT2_ET_EXPAND_DIR_ERR;
135.127 +
135.128 + /*
135.129 + * Update the size and block count fields in the inode.
135.130 + */
135.131 + retval = ext2fs_read_inode(fs, dir, &inode);
135.132 + if (retval)
135.133 + return retval;
135.134 +
135.135 + inode.i_size += fs->blocksize;
135.136 + ext2fs_iblk_add_blocks(fs, &inode, es.newblocks);
135.137 +
135.138 + retval = ext2fs_write_inode(fs, dir, &inode);
135.139 + if (retval)
135.140 + return retval;
135.141 +
135.142 + return 0;
135.143 +}
136.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
136.2 +++ b/libext2fs/lib/libext2fs/ext2_err.et.in Wed Aug 25 01:28:08 2021 +0200
136.3 @@ -0,0 +1,548 @@
136.4 +#
136.5 +# Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
136.6 +#
136.7 +# %Begin-Header%
136.8 +# This file may be redistributed under the terms of the GNU Public
136.9 +# License.
136.10 +# %End-Header%
136.11 +#
136.12 + error_table ext2
136.13 +
136.14 +ec EXT2_ET_BASE,
136.15 + "EXT2FS Library version @E2FSPROGS_VERSION@"
136.16 +
136.17 +ec EXT2_ET_MAGIC_EXT2FS_FILSYS,
136.18 + "Wrong magic number for ext2_filsys structure"
136.19 +
136.20 +ec EXT2_ET_MAGIC_BADBLOCKS_LIST,
136.21 + "Wrong magic number for badblocks_list structure"
136.22 +
136.23 +ec EXT2_ET_MAGIC_BADBLOCKS_ITERATE,
136.24 + "Wrong magic number for badblocks_iterate structure"
136.25 +
136.26 +ec EXT2_ET_MAGIC_INODE_SCAN,
136.27 + "Wrong magic number for inode_scan structure"
136.28 +
136.29 +ec EXT2_ET_MAGIC_IO_CHANNEL,
136.30 + "Wrong magic number for io_channel structure"
136.31 +
136.32 +ec EXT2_ET_MAGIC_UNIX_IO_CHANNEL,
136.33 + "Wrong magic number for unix io_channel structure"
136.34 +
136.35 +ec EXT2_ET_MAGIC_IO_MANAGER,
136.36 + "Wrong magic number for io_manager structure"
136.37 +
136.38 +ec EXT2_ET_MAGIC_BLOCK_BITMAP,
136.39 + "Wrong magic number for block_bitmap structure"
136.40 +
136.41 +ec EXT2_ET_MAGIC_INODE_BITMAP,
136.42 + "Wrong magic number for inode_bitmap structure"
136.43 +
136.44 +ec EXT2_ET_MAGIC_GENERIC_BITMAP,
136.45 + "Wrong magic number for generic_bitmap structure"
136.46 +
136.47 +ec EXT2_ET_MAGIC_TEST_IO_CHANNEL,
136.48 + "Wrong magic number for test io_channel structure"
136.49 +
136.50 +ec EXT2_ET_MAGIC_DBLIST,
136.51 + "Wrong magic number for directory block list structure"
136.52 +
136.53 +ec EXT2_ET_MAGIC_ICOUNT,
136.54 + "Wrong magic number for icount structure"
136.55 +
136.56 +ec EXT2_ET_MAGIC_PQ_IO_CHANNEL,
136.57 + "Wrong magic number for Powerquest io_channel structure"
136.58 +
136.59 +ec EXT2_ET_MAGIC_EXT2_FILE,
136.60 + "Wrong magic number for ext2 file structure"
136.61 +
136.62 +ec EXT2_ET_MAGIC_E2IMAGE,
136.63 + "Wrong magic number for Ext2 Image Header"
136.64 +
136.65 +ec EXT2_ET_MAGIC_INODE_IO_CHANNEL,
136.66 + "Wrong magic number for inode io_channel structure"
136.67 +
136.68 +ec EXT2_ET_MAGIC_EXTENT_HANDLE,
136.69 + "Wrong magic number for ext4 extent handle"
136.70 +
136.71 +ec EXT2_ET_BAD_MAGIC,
136.72 + "Bad magic number in super-block"
136.73 +
136.74 +ec EXT2_ET_REV_TOO_HIGH,
136.75 + "Filesystem revision too high"
136.76 +
136.77 +ec EXT2_ET_RO_FILSYS,
136.78 + "Attempt to write to filesystem opened read-only"
136.79 +
136.80 +ec EXT2_ET_GDESC_READ,
136.81 + "Can't read group descriptors"
136.82 +
136.83 +ec EXT2_ET_GDESC_WRITE,
136.84 + "Can't write group descriptors"
136.85 +
136.86 +ec EXT2_ET_GDESC_BAD_BLOCK_MAP,
136.87 + "Corrupt group descriptor: bad block for block bitmap"
136.88 +
136.89 +ec EXT2_ET_GDESC_BAD_INODE_MAP,
136.90 + "Corrupt group descriptor: bad block for inode bitmap"
136.91 +
136.92 +ec EXT2_ET_GDESC_BAD_INODE_TABLE,
136.93 + "Corrupt group descriptor: bad block for inode table"
136.94 +
136.95 +ec EXT2_ET_INODE_BITMAP_WRITE,
136.96 + "Can't write an inode bitmap"
136.97 +
136.98 +ec EXT2_ET_INODE_BITMAP_READ,
136.99 + "Can't read an inode bitmap"
136.100 +
136.101 +ec EXT2_ET_BLOCK_BITMAP_WRITE,
136.102 + "Can't write a block bitmap"
136.103 +
136.104 +ec EXT2_ET_BLOCK_BITMAP_READ,
136.105 + "Can't read a block bitmap"
136.106 +
136.107 +ec EXT2_ET_INODE_TABLE_WRITE,
136.108 + "Can't write an inode table"
136.109 +
136.110 +ec EXT2_ET_INODE_TABLE_READ,
136.111 + "Can't read an inode table"
136.112 +
136.113 +ec EXT2_ET_NEXT_INODE_READ,
136.114 + "Can't read next inode"
136.115 +
136.116 +ec EXT2_ET_UNEXPECTED_BLOCK_SIZE,
136.117 + "Filesystem has unexpected block size"
136.118 +
136.119 +ec EXT2_ET_DIR_CORRUPTED,
136.120 + "EXT2 directory corrupted"
136.121 +
136.122 +ec EXT2_ET_SHORT_READ,
136.123 + "Attempt to read block from filesystem resulted in short read"
136.124 +
136.125 +ec EXT2_ET_SHORT_WRITE,
136.126 + "Attempt to write block to filesystem resulted in short write"
136.127 +
136.128 +ec EXT2_ET_DIR_NO_SPACE,
136.129 + "No free space in the directory"
136.130 +
136.131 +ec EXT2_ET_NO_INODE_BITMAP,
136.132 + "Inode bitmap not loaded"
136.133 +
136.134 +ec EXT2_ET_NO_BLOCK_BITMAP,
136.135 + "Block bitmap not loaded"
136.136 +
136.137 +ec EXT2_ET_BAD_INODE_NUM,
136.138 + "Illegal inode number"
136.139 +
136.140 +ec EXT2_ET_BAD_BLOCK_NUM,
136.141 + "Illegal block number"
136.142 +
136.143 +ec EXT2_ET_EXPAND_DIR_ERR,
136.144 + "Internal error in ext2fs_expand_dir"
136.145 +
136.146 +ec EXT2_ET_TOOSMALL,
136.147 + "Not enough space to build proposed filesystem"
136.148 +
136.149 +ec EXT2_ET_BAD_BLOCK_MARK,
136.150 + "Illegal block number passed to ext2fs_mark_block_bitmap"
136.151 +
136.152 +ec EXT2_ET_BAD_BLOCK_UNMARK,
136.153 + "Illegal block number passed to ext2fs_unmark_block_bitmap"
136.154 +
136.155 +ec EXT2_ET_BAD_BLOCK_TEST,
136.156 + "Illegal block number passed to ext2fs_test_block_bitmap"
136.157 +
136.158 +ec EXT2_ET_BAD_INODE_MARK,
136.159 + "Illegal inode number passed to ext2fs_mark_inode_bitmap"
136.160 +
136.161 +ec EXT2_ET_BAD_INODE_UNMARK,
136.162 + "Illegal inode number passed to ext2fs_unmark_inode_bitmap"
136.163 +
136.164 +ec EXT2_ET_BAD_INODE_TEST,
136.165 + "Illegal inode number passed to ext2fs_test_inode_bitmap"
136.166 +
136.167 +ec EXT2_ET_FUDGE_BLOCK_BITMAP_END,
136.168 + "Attempt to fudge end of block bitmap past the real end"
136.169 +
136.170 +ec EXT2_ET_FUDGE_INODE_BITMAP_END,
136.171 + "Attempt to fudge end of inode bitmap past the real end"
136.172 +
136.173 +ec EXT2_ET_BAD_IND_BLOCK,
136.174 + "Illegal indirect block found"
136.175 +
136.176 +ec EXT2_ET_BAD_DIND_BLOCK,
136.177 + "Illegal doubly indirect block found"
136.178 +
136.179 +ec EXT2_ET_BAD_TIND_BLOCK,
136.180 + "Illegal triply indirect block found"
136.181 +
136.182 +ec EXT2_ET_NEQ_BLOCK_BITMAP,
136.183 + "Block bitmaps are not the same"
136.184 +
136.185 +ec EXT2_ET_NEQ_INODE_BITMAP,
136.186 + "Inode bitmaps are not the same"
136.187 +
136.188 +ec EXT2_ET_BAD_DEVICE_NAME,
136.189 + "Illegal or malformed device name"
136.190 +
136.191 +ec EXT2_ET_MISSING_INODE_TABLE,
136.192 + "A block group is missing an inode table"
136.193 +
136.194 +ec EXT2_ET_CORRUPT_SUPERBLOCK,
136.195 + "The ext2 superblock is corrupt"
136.196 +
136.197 +ec EXT2_ET_BAD_GENERIC_MARK,
136.198 + "Illegal generic bit number passed to ext2fs_mark_generic_bitmap"
136.199 +
136.200 +ec EXT2_ET_BAD_GENERIC_UNMARK,
136.201 + "Illegal generic bit number passed to ext2fs_unmark_generic_bitmap"
136.202 +
136.203 +ec EXT2_ET_BAD_GENERIC_TEST,
136.204 + "Illegal generic bit number passed to ext2fs_test_generic_bitmap"
136.205 +
136.206 +ec EXT2_ET_SYMLINK_LOOP,
136.207 + "Too many symbolic links encountered."
136.208 +
136.209 +ec EXT2_ET_CALLBACK_NOTHANDLED,
136.210 + "The callback function will not handle this case"
136.211 +
136.212 +ec EXT2_ET_BAD_BLOCK_IN_INODE_TABLE,
136.213 + "The inode is from a bad block in the inode table"
136.214 +
136.215 +ec EXT2_ET_UNSUPP_FEATURE,
136.216 + "Filesystem has unsupported feature(s)"
136.217 +
136.218 +ec EXT2_ET_RO_UNSUPP_FEATURE,
136.219 + "Filesystem has unsupported read-only feature(s)"
136.220 +
136.221 +ec EXT2_ET_LLSEEK_FAILED,
136.222 + "IO Channel failed to seek on read or write"
136.223 +
136.224 +ec EXT2_ET_NO_MEMORY,
136.225 + "Memory allocation failed"
136.226 +
136.227 +ec EXT2_ET_INVALID_ARGUMENT,
136.228 + "Invalid argument passed to ext2 library"
136.229 +
136.230 +ec EXT2_ET_BLOCK_ALLOC_FAIL,
136.231 + "Could not allocate block in ext2 filesystem"
136.232 +
136.233 +ec EXT2_ET_INODE_ALLOC_FAIL,
136.234 + "Could not allocate inode in ext2 filesystem"
136.235 +
136.236 +ec EXT2_ET_NO_DIRECTORY,
136.237 + "Ext2 inode is not a directory"
136.238 +
136.239 +ec EXT2_ET_TOO_MANY_REFS,
136.240 + "Too many references in table"
136.241 +
136.242 +ec EXT2_ET_FILE_NOT_FOUND,
136.243 + "File not found by ext2_lookup"
136.244 +
136.245 +ec EXT2_ET_FILE_RO,
136.246 + "File open read-only"
136.247 +
136.248 +ec EXT2_ET_DB_NOT_FOUND,
136.249 + "Ext2 directory block not found"
136.250 +
136.251 +ec EXT2_ET_DIR_EXISTS,
136.252 + "Ext2 directory already exists"
136.253 +
136.254 +ec EXT2_ET_UNIMPLEMENTED,
136.255 + "Unimplemented ext2 library function"
136.256 +
136.257 +ec EXT2_ET_CANCEL_REQUESTED,
136.258 + "User cancel requested"
136.259 +
136.260 +ec EXT2_ET_FILE_TOO_BIG,
136.261 + "Ext2 file too big"
136.262 +
136.263 +ec EXT2_ET_JOURNAL_NOT_BLOCK,
136.264 + "Supplied journal device not a block device"
136.265 +
136.266 +ec EXT2_ET_NO_JOURNAL_SB,
136.267 + "Journal superblock not found"
136.268 +
136.269 +ec EXT2_ET_JOURNAL_TOO_SMALL,
136.270 + "Journal must be at least 1024 blocks"
136.271 +
136.272 +ec EXT2_ET_JOURNAL_UNSUPP_VERSION,
136.273 + "Unsupported journal version"
136.274 +
136.275 +ec EXT2_ET_LOAD_EXT_JOURNAL,
136.276 + "Error loading external journal"
136.277 +
136.278 +ec EXT2_ET_NO_JOURNAL,
136.279 + "Journal not found"
136.280 +
136.281 +ec EXT2_ET_DIRHASH_UNSUPP,
136.282 + "Directory hash unsupported"
136.283 +
136.284 +ec EXT2_ET_BAD_EA_BLOCK_NUM,
136.285 + "Illegal extended attribute block number"
136.286 +
136.287 +ec EXT2_ET_TOO_MANY_INODES,
136.288 + "Cannot create filesystem with requested number of inodes"
136.289 +
136.290 +ec EXT2_ET_NOT_IMAGE_FILE,
136.291 + "E2image snapshot not in use"
136.292 +
136.293 +ec EXT2_ET_RES_GDT_BLOCKS,
136.294 + "Too many reserved group descriptor blocks"
136.295 +
136.296 +ec EXT2_ET_RESIZE_INODE_CORRUPT,
136.297 + "Resize inode is corrupt"
136.298 +
136.299 +ec EXT2_ET_SET_BMAP_NO_IND,
136.300 + "Tried to set block bmap with missing indirect block"
136.301 +
136.302 +ec EXT2_ET_TDB_SUCCESS,
136.303 + "TDB: Success"
136.304 +
136.305 +ec EXT2_ET_TDB_ERR_CORRUPT,
136.306 + "TDB: Corrupt database"
136.307 +
136.308 +ec EXT2_ET_TDB_ERR_IO,
136.309 + "TDB: IO Error"
136.310 +
136.311 +ec EXT2_ET_TDB_ERR_LOCK,
136.312 + "TDB: Locking error"
136.313 +
136.314 +ec EXT2_ET_TDB_ERR_OOM,
136.315 + "TDB: Out of memory"
136.316 +
136.317 +ec EXT2_ET_TDB_ERR_EXISTS,
136.318 + "TDB: Record exists"
136.319 +
136.320 +ec EXT2_ET_TDB_ERR_NOLOCK,
136.321 + "TDB: Lock exists on other keys"
136.322 +
136.323 +ec EXT2_ET_TDB_ERR_EINVAL,
136.324 + "TDB: Invalid parameter"
136.325 +
136.326 +ec EXT2_ET_TDB_ERR_NOEXIST,
136.327 + "TDB: Record does not exist"
136.328 +
136.329 +ec EXT2_ET_TDB_ERR_RDONLY,
136.330 + "TDB: Write not permitted"
136.331 +
136.332 +ec EXT2_ET_DBLIST_EMPTY,
136.333 + "Ext2fs directory block list is empty"
136.334 +
136.335 +ec EXT2_ET_RO_BLOCK_ITERATE,
136.336 + "Attempt to modify a block mapping via a read-only block iterator"
136.337 +
136.338 +ec EXT2_ET_MAGIC_EXTENT_PATH,
136.339 + "Wrong magic number for ext4 extent saved path"
136.340 +
136.341 +ec EXT2_ET_MAGIC_GENERIC_BITMAP64,
136.342 + "Wrong magic number for 64-bit generic bitmap"
136.343 +
136.344 +ec EXT2_ET_MAGIC_BLOCK_BITMAP64,
136.345 + "Wrong magic number for 64-bit block bitmap"
136.346 +
136.347 +ec EXT2_ET_MAGIC_INODE_BITMAP64,
136.348 + "Wrong magic number for 64-bit inode bitmap"
136.349 +
136.350 +ec EXT2_ET_MAGIC_RESERVED_13,
136.351 + "Wrong magic number --- RESERVED_13"
136.352 +
136.353 +ec EXT2_ET_MAGIC_RESERVED_14,
136.354 + "Wrong magic number --- RESERVED_14"
136.355 +
136.356 +ec EXT2_ET_MAGIC_RESERVED_15,
136.357 + "Wrong magic number --- RESERVED_15"
136.358 +
136.359 +ec EXT2_ET_MAGIC_RESERVED_16,
136.360 + "Wrong magic number --- RESERVED_16"
136.361 +
136.362 +ec EXT2_ET_MAGIC_RESERVED_17,
136.363 + "Wrong magic number --- RESERVED_17"
136.364 +
136.365 +ec EXT2_ET_MAGIC_RESERVED_18,
136.366 + "Wrong magic number --- RESERVED_18"
136.367 +
136.368 +ec EXT2_ET_MAGIC_RESERVED_19,
136.369 + "Wrong magic number --- RESERVED_19"
136.370 +
136.371 +ec EXT2_ET_EXTENT_HEADER_BAD,
136.372 + "Corrupt extent header"
136.373 +
136.374 +ec EXT2_ET_EXTENT_INDEX_BAD,
136.375 + "Corrupt extent index"
136.376 +
136.377 +ec EXT2_ET_EXTENT_LEAF_BAD,
136.378 + "Corrupt extent"
136.379 +
136.380 +ec EXT2_ET_EXTENT_NO_SPACE,
136.381 + "No free space in extent map"
136.382 +
136.383 +ec EXT2_ET_INODE_NOT_EXTENT,
136.384 + "Inode does not use extents"
136.385 +
136.386 +ec EXT2_ET_EXTENT_NO_NEXT,
136.387 + "No 'next' extent"
136.388 +
136.389 +ec EXT2_ET_EXTENT_NO_PREV,
136.390 + "No 'previous' extent"
136.391 +
136.392 +ec EXT2_ET_EXTENT_NO_UP,
136.393 + "No 'up' extent"
136.394 +
136.395 +ec EXT2_ET_EXTENT_NO_DOWN,
136.396 + "No 'down' extent"
136.397 +
136.398 +ec EXT2_ET_NO_CURRENT_NODE,
136.399 + "No current node"
136.400 +
136.401 +ec EXT2_ET_OP_NOT_SUPPORTED,
136.402 + "Ext2fs operation not supported"
136.403 +
136.404 +ec EXT2_ET_CANT_INSERT_EXTENT,
136.405 + "No room to insert extent in node"
136.406 +
136.407 +ec EXT2_ET_CANT_SPLIT_EXTENT,
136.408 + "Splitting would result in empty node"
136.409 +
136.410 +ec EXT2_ET_EXTENT_NOT_FOUND,
136.411 + "Extent not found"
136.412 +
136.413 +ec EXT2_ET_EXTENT_NOT_SUPPORTED,
136.414 + "Operation not supported for inodes containing extents"
136.415 +
136.416 +ec EXT2_ET_EXTENT_INVALID_LENGTH,
136.417 + "Extent length is invalid"
136.418 +
136.419 +ec EXT2_ET_IO_CHANNEL_NO_SUPPORT_64,
136.420 + "I/O Channel does not support 64-bit block numbers"
136.421 +
136.422 +ec EXT2_ET_NO_MTAB_FILE,
136.423 + "Can't check if filesystem is mounted due to missing mtab file"
136.424 +
136.425 +ec EXT2_ET_CANT_USE_LEGACY_BITMAPS,
136.426 + "Filesystem too large to use legacy bitmaps"
136.427 +
136.428 +ec EXT2_ET_MMP_MAGIC_INVALID,
136.429 + "MMP: invalid magic number"
136.430 +
136.431 +ec EXT2_ET_MMP_FAILED,
136.432 + "MMP: device currently active"
136.433 +
136.434 +ec EXT2_ET_MMP_FSCK_ON,
136.435 + "MMP: e2fsck being run"
136.436 +
136.437 +ec EXT2_ET_MMP_BAD_BLOCK,
136.438 + "MMP: block number beyond filesystem range"
136.439 +
136.440 +ec EXT2_ET_MMP_UNKNOWN_SEQ,
136.441 + "MMP: undergoing an unknown operation"
136.442 +
136.443 +ec EXT2_ET_MMP_CHANGE_ABORT,
136.444 + "MMP: filesystem still in use"
136.445 +
136.446 +ec EXT2_ET_MMP_OPEN_DIRECT,
136.447 + "MMP: open with O_DIRECT failed"
136.448 +
136.449 +ec EXT2_ET_BAD_DESC_SIZE,
136.450 + "Block group descriptor size incorrect"
136.451 +
136.452 +ec EXT2_ET_INODE_CSUM_INVALID,
136.453 + "Inode checksum does not match inode"
136.454 +
136.455 +ec EXT2_ET_INODE_BITMAP_CSUM_INVALID,
136.456 + "Inode bitmap checksum does not match bitmap"
136.457 +
136.458 +ec EXT2_ET_EXTENT_CSUM_INVALID,
136.459 + "Extent block checksum does not match extent block"
136.460 +
136.461 +ec EXT2_ET_DIR_NO_SPACE_FOR_CSUM,
136.462 + "Directory block does not have space for checksum"
136.463 +
136.464 +ec EXT2_ET_DIR_CSUM_INVALID,
136.465 + "Directory block checksum does not match directory block"
136.466 +
136.467 +ec EXT2_ET_EXT_ATTR_CSUM_INVALID,
136.468 + "Extended attribute block checksum does not match block"
136.469 +
136.470 +ec EXT2_ET_SB_CSUM_INVALID,
136.471 + "Superblock checksum does not match superblock"
136.472 +
136.473 +ec EXT2_ET_UNKNOWN_CSUM,
136.474 + "Unknown checksum algorithm"
136.475 +
136.476 +ec EXT2_ET_MMP_CSUM_INVALID,
136.477 + "MMP block checksum does not match"
136.478 +
136.479 +ec EXT2_ET_FILE_EXISTS,
136.480 + "Ext2 file already exists"
136.481 +
136.482 +ec EXT2_ET_BLOCK_BITMAP_CSUM_INVALID,
136.483 + "Block bitmap checksum does not match bitmap"
136.484 +
136.485 +ec EXT2_ET_INLINE_DATA_CANT_ITERATE,
136.486 + "Cannot iterate data blocks of an inode containing inline data"
136.487 +
136.488 +ec EXT2_ET_EA_BAD_NAME_LEN,
136.489 + "Extended attribute has an invalid name length"
136.490 +
136.491 +ec EXT2_ET_EA_BAD_VALUE_SIZE,
136.492 + "Extended attribute has an invalid value length"
136.493 +
136.494 +ec EXT2_ET_BAD_EA_HASH,
136.495 + "Extended attribute has an incorrect hash"
136.496 +
136.497 +ec EXT2_ET_BAD_EA_HEADER,
136.498 + "Extended attribute block has a bad header"
136.499 +
136.500 +ec EXT2_ET_EA_KEY_NOT_FOUND,
136.501 + "Extended attribute key not found"
136.502 +
136.503 +ec EXT2_ET_EA_NO_SPACE,
136.504 + "Insufficient space to store extended attribute data"
136.505 +
136.506 +ec EXT2_ET_MISSING_EA_FEATURE,
136.507 + "Filesystem is missing ext_attr or inline_data feature"
136.508 +
136.509 +ec EXT2_ET_NO_INLINE_DATA,
136.510 + "Inode doesn't have inline data"
136.511 +
136.512 +ec EXT2_ET_INLINE_DATA_NO_BLOCK,
136.513 + "No block for an inode with inline data"
136.514 +
136.515 +ec EXT2_ET_INLINE_DATA_NO_SPACE,
136.516 + "No free space in inline data"
136.517 +
136.518 +ec EXT2_ET_MAGIC_EA_HANDLE,
136.519 + "Wrong magic number for extended attribute structure"
136.520 +
136.521 +ec EXT2_ET_INODE_IS_GARBAGE,
136.522 + "Inode seems to contain garbage"
136.523 +
136.524 +ec EXT2_ET_EA_BAD_VALUE_OFFSET,
136.525 + "Extended attribute has an invalid value offset"
136.526 +
136.527 +ec EXT2_ET_JOURNAL_FLAGS_WRONG,
136.528 + "Journal flags inconsistent"
136.529 +
136.530 +ec EXT2_ET_UNDO_FILE_CORRUPT,
136.531 + "Undo file corrupt"
136.532 +
136.533 +ec EXT2_ET_UNDO_FILE_WRONG,
136.534 + "Wrong undo file for this filesystem"
136.535 +
136.536 +ec EXT2_ET_FILESYSTEM_CORRUPTED,
136.537 + "File system is corrupted"
136.538 +
136.539 +ec EXT2_ET_BAD_CRC,
136.540 + "Bad CRC detected in file system"
136.541 +
136.542 +ec EXT2_ET_CORRUPT_JOURNAL_SB,
136.543 + "The journal superblock is corrupt"
136.544 +
136.545 +ec EXT2_ET_INODE_CORRUPTED,
136.546 + "Inode is corrupted"
136.547 +
136.548 +ec EXT2_ET_EA_INODE_CORRUPTED,
136.549 + "Inode containing extended attribute value is corrupted"
136.550 +
136.551 + end
138.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
138.2 +++ b/libext2fs/lib/libext2fs/ext2fs.pc.in Wed Aug 25 01:28:08 2021 +0200
138.3 @@ -0,0 +1,11 @@
138.4 +prefix=@prefix@
138.5 +exec_prefix=@exec_prefix@
138.6 +libdir=@libdir@
138.7 +includedir=@includedir@
138.8 +
138.9 +Name: ext2fs
138.10 +Description: Ext2fs library
138.11 +Version: @E2FSPROGS_VERSION@
138.12 +Requires.private: com_err
138.13 +Cflags: -I${includedir}/ext2fs -I${includedir}
138.14 +Libs: -L${libdir} -lext2fs
139.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
139.2 +++ b/libext2fs/lib/libext2fs/ext_attr.c Wed Aug 25 01:28:08 2021 +0200
139.3 @@ -0,0 +1,1718 @@
139.4 +/*
139.5 + * ext_attr.c --- extended attribute blocks
139.6 + *
139.7 + * Copyright (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
139.8 + *
139.9 + * Copyright (C) 2002 Theodore Ts'o.
139.10 + *
139.11 + * %Begin-Header%
139.12 + * This file may be redistributed under the terms of the GNU Library
139.13 + * General Public License, version 2.
139.14 + * %End-Header%
139.15 + */
139.16 +
139.17 +#include "config.h"
139.18 +#include <stdio.h>
139.19 +#if HAVE_UNISTD_H
139.20 +#include <unistd.h>
139.21 +#endif
139.22 +#include <string.h>
139.23 +#include <time.h>
139.24 +
139.25 +#include "ext2_fs.h"
139.26 +#include "ext2_ext_attr.h"
139.27 +#include "ext4_acl.h"
139.28 +
139.29 +#include "ext2fs.h"
139.30 +
139.31 +static errcode_t read_ea_inode_hash(ext2_filsys fs, ext2_ino_t ino, __u32 *hash)
139.32 +{
139.33 + struct ext2_inode inode;
139.34 + errcode_t retval;
139.35 +
139.36 + retval = ext2fs_read_inode(fs, ino, &inode);
139.37 + if (retval)
139.38 + return retval;
139.39 + *hash = ext2fs_get_ea_inode_hash(&inode);
139.40 + return 0;
139.41 +}
139.42 +
139.43 +#define NAME_HASH_SHIFT 5
139.44 +#define VALUE_HASH_SHIFT 16
139.45 +
139.46 +/*
139.47 + * ext2_xattr_hash_entry()
139.48 + *
139.49 + * Compute the hash of an extended attribute.
139.50 + */
139.51 +__u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, void *data)
139.52 +{
139.53 + __u32 hash = 0;
139.54 + char *name = ((char *) entry) + sizeof(struct ext2_ext_attr_entry);
139.55 + int n;
139.56 +
139.57 + for (n = 0; n < entry->e_name_len; n++) {
139.58 + hash = (hash << NAME_HASH_SHIFT) ^
139.59 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
139.60 + *name++;
139.61 + }
139.62 +
139.63 + /* The hash needs to be calculated on the data in little-endian. */
139.64 + if (entry->e_value_inum == 0 && entry->e_value_size != 0) {
139.65 + __u32 *value = (__u32 *)data;
139.66 + for (n = (entry->e_value_size + EXT2_EXT_ATTR_ROUND) >>
139.67 + EXT2_EXT_ATTR_PAD_BITS; n; n--) {
139.68 + hash = (hash << VALUE_HASH_SHIFT) ^
139.69 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
139.70 + ext2fs_le32_to_cpu(*value++);
139.71 + }
139.72 + }
139.73 +
139.74 + return hash;
139.75 +}
139.76 +
139.77 +/*
139.78 + * ext2fs_ext_attr_hash_entry2()
139.79 + *
139.80 + * Compute the hash of an extended attribute.
139.81 + * This version of the function supports hashing entries that reference
139.82 + * external inodes (ea_inode feature).
139.83 + */
139.84 +errcode_t ext2fs_ext_attr_hash_entry2(ext2_filsys fs,
139.85 + struct ext2_ext_attr_entry *entry,
139.86 + void *data, __u32 *hash)
139.87 +{
139.88 + *hash = ext2fs_ext_attr_hash_entry(entry, data);
139.89 +
139.90 + if (entry->e_value_inum) {
139.91 + __u32 ea_inode_hash;
139.92 + errcode_t retval;
139.93 +
139.94 + retval = read_ea_inode_hash(fs, entry->e_value_inum,
139.95 + &ea_inode_hash);
139.96 + if (retval)
139.97 + return retval;
139.98 +
139.99 + *hash = (*hash << VALUE_HASH_SHIFT) ^
139.100 + (*hash >> (8*sizeof(*hash) - VALUE_HASH_SHIFT)) ^
139.101 + ea_inode_hash;
139.102 + }
139.103 + return 0;
139.104 +}
139.105 +
139.106 +#undef NAME_HASH_SHIFT
139.107 +#undef VALUE_HASH_SHIFT
139.108 +
139.109 +#define BLOCK_HASH_SHIFT 16
139.110 +
139.111 +/* Mirrors ext4_xattr_rehash() implementation in kernel. */
139.112 +void ext2fs_ext_attr_block_rehash(struct ext2_ext_attr_header *header,
139.113 + struct ext2_ext_attr_entry *end)
139.114 +{
139.115 + struct ext2_ext_attr_entry *here;
139.116 + __u32 hash = 0;
139.117 +
139.118 + here = (struct ext2_ext_attr_entry *)(header+1);
139.119 + while (here < end && !EXT2_EXT_IS_LAST_ENTRY(here)) {
139.120 + if (!here->e_hash) {
139.121 + /* Block is not shared if an entry's hash value == 0 */
139.122 + hash = 0;
139.123 + break;
139.124 + }
139.125 + hash = (hash << BLOCK_HASH_SHIFT) ^
139.126 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
139.127 + here->e_hash;
139.128 + here = EXT2_EXT_ATTR_NEXT(here);
139.129 + }
139.130 + header->h_hash = hash;
139.131 +}
139.132 +
139.133 +#undef BLOCK_HASH_SHIFT
139.134 +
139.135 +__u32 ext2fs_get_ea_inode_hash(struct ext2_inode *inode)
139.136 +{
139.137 + return inode->i_atime;
139.138 +}
139.139 +
139.140 +void ext2fs_set_ea_inode_hash(struct ext2_inode *inode, __u32 hash)
139.141 +{
139.142 + inode->i_atime = hash;
139.143 +}
139.144 +
139.145 +__u64 ext2fs_get_ea_inode_ref(struct ext2_inode *inode)
139.146 +{
139.147 + return ((__u64)inode->i_ctime << 32) | inode->osd1.linux1.l_i_version;
139.148 +}
139.149 +
139.150 +void ext2fs_set_ea_inode_ref(struct ext2_inode *inode, __u64 ref_count)
139.151 +{
139.152 + inode->i_ctime = (__u32)(ref_count >> 32);
139.153 + inode->osd1.linux1.l_i_version = (__u32)ref_count;
139.154 +}
139.155 +
139.156 +static errcode_t check_ext_attr_header(struct ext2_ext_attr_header *header)
139.157 +{
139.158 + if ((header->h_magic != EXT2_EXT_ATTR_MAGIC_v1 &&
139.159 + header->h_magic != EXT2_EXT_ATTR_MAGIC) ||
139.160 + header->h_blocks != 1)
139.161 + return EXT2_ET_BAD_EA_HEADER;
139.162 +
139.163 + return 0;
139.164 +}
139.165 +
139.166 +errcode_t ext2fs_read_ext_attr3(ext2_filsys fs, blk64_t block, void *buf,
139.167 + ext2_ino_t inum)
139.168 +{
139.169 + int csum_failed = 0;
139.170 + errcode_t retval;
139.171 +
139.172 + retval = io_channel_read_blk64(fs->io, block, 1, buf);
139.173 + if (retval)
139.174 + return retval;
139.175 +
139.176 + if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
139.177 + !ext2fs_ext_attr_block_csum_verify(fs, inum, block, buf))
139.178 + csum_failed = 1;
139.179 +
139.180 +#ifdef WORDS_BIGENDIAN
139.181 + ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1);
139.182 +#endif
139.183 +
139.184 + retval = check_ext_attr_header(buf);
139.185 + if (retval == 0 && csum_failed)
139.186 + retval = EXT2_ET_EXT_ATTR_CSUM_INVALID;
139.187 +
139.188 + return retval;
139.189 +}
139.190 +
139.191 +errcode_t ext2fs_read_ext_attr2(ext2_filsys fs, blk64_t block, void *buf)
139.192 +{
139.193 + return ext2fs_read_ext_attr3(fs, block, buf, 0);
139.194 +}
139.195 +
139.196 +errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
139.197 +{
139.198 + return ext2fs_read_ext_attr2(fs, block, buf);
139.199 +}
139.200 +
139.201 +errcode_t ext2fs_write_ext_attr3(ext2_filsys fs, blk64_t block, void *inbuf,
139.202 + ext2_ino_t inum)
139.203 +{
139.204 + errcode_t retval;
139.205 + char *write_buf;
139.206 +
139.207 +#ifdef WORDS_BIGENDIAN
139.208 + retval = ext2fs_get_mem(fs->blocksize, &write_buf);
139.209 + if (retval)
139.210 + return retval;
139.211 + ext2fs_swap_ext_attr(write_buf, inbuf, fs->blocksize, 1);
139.212 +#else
139.213 + write_buf = (char *) inbuf;
139.214 +#endif
139.215 +
139.216 + retval = ext2fs_ext_attr_block_csum_set(fs, inum, block,
139.217 + (struct ext2_ext_attr_header *)write_buf);
139.218 + if (retval)
139.219 + return retval;
139.220 +
139.221 + retval = io_channel_write_blk64(fs->io, block, 1, write_buf);
139.222 +#ifdef WORDS_BIGENDIAN
139.223 + ext2fs_free_mem(&write_buf);
139.224 +#endif
139.225 + if (!retval)
139.226 + ext2fs_mark_changed(fs);
139.227 + return retval;
139.228 +}
139.229 +
139.230 +errcode_t ext2fs_write_ext_attr2(ext2_filsys fs, blk64_t block, void *inbuf)
139.231 +{
139.232 + return ext2fs_write_ext_attr3(fs, block, inbuf, 0);
139.233 +}
139.234 +
139.235 +errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
139.236 +{
139.237 + return ext2fs_write_ext_attr2(fs, block, inbuf);
139.238 +}
139.239 +
139.240 +/*
139.241 + * This function adjusts the reference count of the EA block.
139.242 + */
139.243 +errcode_t ext2fs_adjust_ea_refcount3(ext2_filsys fs, blk64_t blk,
139.244 + char *block_buf, int adjust,
139.245 + __u32 *newcount, ext2_ino_t inum)
139.246 +{
139.247 + errcode_t retval;
139.248 + struct ext2_ext_attr_header *header;
139.249 + char *buf = 0;
139.250 +
139.251 + if ((blk >= ext2fs_blocks_count(fs->super)) ||
139.252 + (blk < fs->super->s_first_data_block))
139.253 + return EXT2_ET_BAD_EA_BLOCK_NUM;
139.254 +
139.255 + if (!block_buf) {
139.256 + retval = ext2fs_get_mem(fs->blocksize, &buf);
139.257 + if (retval)
139.258 + return retval;
139.259 + block_buf = buf;
139.260 + }
139.261 +
139.262 + retval = ext2fs_read_ext_attr3(fs, blk, block_buf, inum);
139.263 + if (retval)
139.264 + goto errout;
139.265 +
139.266 + header = (struct ext2_ext_attr_header *) block_buf;
139.267 + header->h_refcount += adjust;
139.268 + if (newcount)
139.269 + *newcount = header->h_refcount;
139.270 +
139.271 + retval = ext2fs_write_ext_attr3(fs, blk, block_buf, inum);
139.272 + if (retval)
139.273 + goto errout;
139.274 +
139.275 +errout:
139.276 + if (buf)
139.277 + ext2fs_free_mem(&buf);
139.278 + return retval;
139.279 +}
139.280 +
139.281 +errcode_t ext2fs_adjust_ea_refcount2(ext2_filsys fs, blk64_t blk,
139.282 + char *block_buf, int adjust,
139.283 + __u32 *newcount)
139.284 +{
139.285 + return ext2fs_adjust_ea_refcount3(fs, blk, block_buf, adjust,
139.286 + newcount, 0);
139.287 +}
139.288 +
139.289 +errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
139.290 + char *block_buf, int adjust,
139.291 + __u32 *newcount)
139.292 +{
139.293 + return ext2fs_adjust_ea_refcount2(fs, blk, block_buf, adjust,
139.294 + newcount);
139.295 +}
139.296 +
139.297 +/* Manipulate the contents of extended attribute regions */
139.298 +struct ext2_xattr {
139.299 + char *name;
139.300 + void *value;
139.301 + unsigned int value_len;
139.302 + ext2_ino_t ea_ino;
139.303 +};
139.304 +
139.305 +struct ext2_xattr_handle {
139.306 + errcode_t magic;
139.307 + ext2_filsys fs;
139.308 + struct ext2_xattr *attrs;
139.309 + int capacity;
139.310 + int count;
139.311 + int ibody_count;
139.312 + ext2_ino_t ino;
139.313 + unsigned int flags;
139.314 +};
139.315 +
139.316 +static errcode_t ext2fs_xattrs_expand(struct ext2_xattr_handle *h,
139.317 + unsigned int expandby)
139.318 +{
139.319 + struct ext2_xattr *new_attrs;
139.320 + errcode_t err;
139.321 +
139.322 + err = ext2fs_get_arrayzero(h->capacity + expandby,
139.323 + sizeof(struct ext2_xattr), &new_attrs);
139.324 + if (err)
139.325 + return err;
139.326 +
139.327 + memcpy(new_attrs, h->attrs, h->capacity * sizeof(struct ext2_xattr));
139.328 + ext2fs_free_mem(&h->attrs);
139.329 + h->capacity += expandby;
139.330 + h->attrs = new_attrs;
139.331 +
139.332 + return 0;
139.333 +}
139.334 +
139.335 +struct ea_name_index {
139.336 + int index;
139.337 + const char *name;
139.338 +};
139.339 +
139.340 +/* Keep these names sorted in order of decreasing specificity. */
139.341 +static struct ea_name_index ea_names[] = {
139.342 + {3, "system.posix_acl_default"},
139.343 + {2, "system.posix_acl_access"},
139.344 + {8, "system.richacl"},
139.345 + {6, "security."},
139.346 + {4, "trusted."},
139.347 + {7, "system."},
139.348 + {1, "user."},
139.349 + {0, NULL},
139.350 +};
139.351 +
139.352 +static const char *find_ea_prefix(int index)
139.353 +{
139.354 + struct ea_name_index *e;
139.355 +
139.356 + for (e = ea_names; e->name; e++)
139.357 + if (e->index == index)
139.358 + return e->name;
139.359 +
139.360 + return NULL;
139.361 +}
139.362 +
139.363 +static int find_ea_index(const char *fullname, const char **name, int *index)
139.364 +{
139.365 + struct ea_name_index *e;
139.366 +
139.367 + for (e = ea_names; e->name; e++) {
139.368 + if (strncmp(fullname, e->name, strlen(e->name)) == 0) {
139.369 + *name = fullname + strlen(e->name);
139.370 + *index = e->index;
139.371 + return 1;
139.372 + }
139.373 + }
139.374 + return 0;
139.375 +}
139.376 +
139.377 +errcode_t ext2fs_free_ext_attr(ext2_filsys fs, ext2_ino_t ino,
139.378 + struct ext2_inode_large *inode)
139.379 +{
139.380 + struct ext2_ext_attr_header *header;
139.381 + void *block_buf = NULL;
139.382 + blk64_t blk;
139.383 + errcode_t err;
139.384 + struct ext2_inode_large i;
139.385 +
139.386 + /* Read inode? */
139.387 + if (inode == NULL) {
139.388 + err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&i,
139.389 + sizeof(struct ext2_inode_large));
139.390 + if (err)
139.391 + return err;
139.392 + inode = &i;
139.393 + }
139.394 +
139.395 + /* Do we already have an EA block? */
139.396 + blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode);
139.397 + if (blk == 0)
139.398 + return 0;
139.399 +
139.400 + /* Find block, zero it, write back */
139.401 + if ((blk < fs->super->s_first_data_block) ||
139.402 + (blk >= ext2fs_blocks_count(fs->super))) {
139.403 + err = EXT2_ET_BAD_EA_BLOCK_NUM;
139.404 + goto out;
139.405 + }
139.406 +
139.407 + err = ext2fs_get_mem(fs->blocksize, &block_buf);
139.408 + if (err)
139.409 + goto out;
139.410 +
139.411 + err = ext2fs_read_ext_attr3(fs, blk, block_buf, ino);
139.412 + if (err)
139.413 + goto out2;
139.414 +
139.415 + /* We only know how to deal with v2 EA blocks */
139.416 + header = (struct ext2_ext_attr_header *) block_buf;
139.417 + if (header->h_magic != EXT2_EXT_ATTR_MAGIC) {
139.418 + err = EXT2_ET_BAD_EA_HEADER;
139.419 + goto out2;
139.420 + }
139.421 +
139.422 + header->h_refcount--;
139.423 + err = ext2fs_write_ext_attr3(fs, blk, block_buf, ino);
139.424 + if (err)
139.425 + goto out2;
139.426 +
139.427 + /* Erase link to block */
139.428 + ext2fs_file_acl_block_set(fs, (struct ext2_inode *)inode, 0);
139.429 + if (header->h_refcount == 0)
139.430 + ext2fs_block_alloc_stats2(fs, blk, -1);
139.431 + err = ext2fs_iblk_sub_blocks(fs, (struct ext2_inode *)inode, 1);
139.432 + if (err)
139.433 + goto out2;
139.434 +
139.435 + /* Write inode? */
139.436 + if (inode == &i) {
139.437 + err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&i,
139.438 + sizeof(struct ext2_inode_large));
139.439 + if (err)
139.440 + goto out2;
139.441 + }
139.442 +
139.443 +out2:
139.444 + ext2fs_free_mem(&block_buf);
139.445 +out:
139.446 + return err;
139.447 +}
139.448 +
139.449 +static errcode_t prep_ea_block_for_write(ext2_filsys fs, ext2_ino_t ino,
139.450 + struct ext2_inode_large *inode)
139.451 +{
139.452 + struct ext2_ext_attr_header *header;
139.453 + void *block_buf = NULL;
139.454 + blk64_t blk, goal;
139.455 + errcode_t err;
139.456 +
139.457 + /* Do we already have an EA block? */
139.458 + blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode);
139.459 + if (blk != 0) {
139.460 + if ((blk < fs->super->s_first_data_block) ||
139.461 + (blk >= ext2fs_blocks_count(fs->super))) {
139.462 + err = EXT2_ET_BAD_EA_BLOCK_NUM;
139.463 + goto out;
139.464 + }
139.465 +
139.466 + err = ext2fs_get_mem(fs->blocksize, &block_buf);
139.467 + if (err)
139.468 + goto out;
139.469 +
139.470 + err = ext2fs_read_ext_attr3(fs, blk, block_buf, ino);
139.471 + if (err)
139.472 + goto out2;
139.473 +
139.474 + /* We only know how to deal with v2 EA blocks */
139.475 + header = (struct ext2_ext_attr_header *) block_buf;
139.476 + if (header->h_magic != EXT2_EXT_ATTR_MAGIC) {
139.477 + err = EXT2_ET_BAD_EA_HEADER;
139.478 + goto out2;
139.479 + }
139.480 +
139.481 + /* Single-user block. We're done here. */
139.482 + if (header->h_refcount == 1)
139.483 + goto out2;
139.484 +
139.485 + /* We need to CoW the block. */
139.486 + header->h_refcount--;
139.487 + err = ext2fs_write_ext_attr3(fs, blk, block_buf, ino);
139.488 + if (err)
139.489 + goto out2;
139.490 + } else {
139.491 + /* No block, we must increment i_blocks */
139.492 + err = ext2fs_iblk_add_blocks(fs, (struct ext2_inode *)inode,
139.493 + 1);
139.494 + if (err)
139.495 + goto out;
139.496 + }
139.497 +
139.498 + /* Allocate a block */
139.499 + goal = ext2fs_find_inode_goal(fs, ino, (struct ext2_inode *)inode, 0);
139.500 + err = ext2fs_alloc_block2(fs, goal, NULL, &blk);
139.501 + if (err)
139.502 + goto out2;
139.503 + ext2fs_file_acl_block_set(fs, (struct ext2_inode *)inode, blk);
139.504 +out2:
139.505 + if (block_buf)
139.506 + ext2fs_free_mem(&block_buf);
139.507 +out:
139.508 + return err;
139.509 +}
139.510 +
139.511 +
139.512 +static inline int
139.513 +posix_acl_xattr_count(size_t size)
139.514 +{
139.515 + if (size < sizeof(posix_acl_xattr_header))
139.516 + return -1;
139.517 + size -= sizeof(posix_acl_xattr_header);
139.518 + if (size % sizeof(posix_acl_xattr_entry))
139.519 + return -1;
139.520 + return size / sizeof(posix_acl_xattr_entry);
139.521 +}
139.522 +
139.523 +/*
139.524 + * The lgetxattr function returns data formatted in the POSIX extended
139.525 + * attribute format. The on-disk format uses a more compact encoding.
139.526 + * See the ext4_acl_to_disk in fs/ext4/acl.c.
139.527 + */
139.528 +static errcode_t convert_posix_acl_to_disk_buffer(const void *value, size_t size,
139.529 + void *out_buf, size_t *size_out)
139.530 +{
139.531 + const posix_acl_xattr_header *header =
139.532 + (const posix_acl_xattr_header*) value;
139.533 + const posix_acl_xattr_entry *end, *entry =
139.534 + (const posix_acl_xattr_entry *)(header+1);
139.535 + ext4_acl_header *ext_acl;
139.536 + size_t s;
139.537 + char *e;
139.538 +
139.539 + int count;
139.540 +
139.541 + if (!value)
139.542 + return EINVAL;
139.543 + if (size < sizeof(posix_acl_xattr_header))
139.544 + return ENOMEM;
139.545 + if (header->a_version != ext2fs_cpu_to_le32(POSIX_ACL_XATTR_VERSION))
139.546 + return EINVAL;
139.547 +
139.548 + count = posix_acl_xattr_count(size);
139.549 + ext_acl = out_buf;
139.550 + ext_acl->a_version = ext2fs_cpu_to_le32(EXT4_ACL_VERSION);
139.551 +
139.552 + if (count <= 0)
139.553 + return EINVAL;
139.554 +
139.555 + e = (char *) out_buf + sizeof(ext4_acl_header);
139.556 + s = sizeof(ext4_acl_header);
139.557 + for (end = entry + count; entry != end;entry++) {
139.558 + ext4_acl_entry *disk_entry = (ext4_acl_entry*) e;
139.559 + disk_entry->e_tag = ext2fs_cpu_to_le16(entry->e_tag);
139.560 + disk_entry->e_perm = ext2fs_cpu_to_le16(entry->e_perm);
139.561 +
139.562 + switch(entry->e_tag) {
139.563 + case ACL_USER_OBJ:
139.564 + case ACL_GROUP_OBJ:
139.565 + case ACL_MASK:
139.566 + case ACL_OTHER:
139.567 + e += sizeof(ext4_acl_entry_short);
139.568 + s += sizeof(ext4_acl_entry_short);
139.569 + break;
139.570 + case ACL_USER:
139.571 + case ACL_GROUP:
139.572 + disk_entry->e_id = ext2fs_cpu_to_le32(entry->e_id);
139.573 + e += sizeof(ext4_acl_entry);
139.574 + s += sizeof(ext4_acl_entry);
139.575 + break;
139.576 + }
139.577 + }
139.578 + *size_out = s;
139.579 + return 0;
139.580 +}
139.581 +
139.582 +static errcode_t convert_disk_buffer_to_posix_acl(const void *value, size_t size,
139.583 + void **out_buf, size_t *size_out)
139.584 +{
139.585 + posix_acl_xattr_header *header;
139.586 + posix_acl_xattr_entry *entry;
139.587 + const ext4_acl_header *ext_acl = (const ext4_acl_header *) value;
139.588 + errcode_t err;
139.589 + const char *cp;
139.590 + char *out;
139.591 +
139.592 + if ((!value) ||
139.593 + (size < sizeof(ext4_acl_header)) ||
139.594 + (ext_acl->a_version != ext2fs_cpu_to_le32(EXT4_ACL_VERSION)))
139.595 + return EINVAL;
139.596 +
139.597 + err = ext2fs_get_mem(size * 2, &out);
139.598 + if (err)
139.599 + return err;
139.600 +
139.601 + header = (posix_acl_xattr_header *) out;
139.602 + header->a_version = ext2fs_cpu_to_le32(POSIX_ACL_XATTR_VERSION);
139.603 + entry = (posix_acl_xattr_entry *) (out + sizeof(posix_acl_xattr_header));
139.604 +
139.605 + cp = (const char *) value + sizeof(ext4_acl_header);
139.606 + size -= sizeof(ext4_acl_header);
139.607 +
139.608 + while (size > 0) {
139.609 + const ext4_acl_entry *disk_entry = (const ext4_acl_entry *) cp;
139.610 +
139.611 + entry->e_tag = ext2fs_le16_to_cpu(disk_entry->e_tag);
139.612 + entry->e_perm = ext2fs_le16_to_cpu(disk_entry->e_perm);
139.613 +
139.614 + switch(entry->e_tag) {
139.615 + case ACL_USER_OBJ:
139.616 + case ACL_GROUP_OBJ:
139.617 + case ACL_MASK:
139.618 + case ACL_OTHER:
139.619 + entry->e_id = 0;
139.620 + cp += sizeof(ext4_acl_entry_short);
139.621 + size -= sizeof(ext4_acl_entry_short);
139.622 + break;
139.623 + case ACL_USER:
139.624 + case ACL_GROUP:
139.625 + entry->e_id = ext2fs_le32_to_cpu(disk_entry->e_id);
139.626 + cp += sizeof(ext4_acl_entry);
139.627 + size -= sizeof(ext4_acl_entry);
139.628 + break;
139.629 + default:
139.630 + ext2fs_free_mem(&out);
139.631 + return EINVAL;
139.632 + break;
139.633 + }
139.634 + entry++;
139.635 + }
139.636 + *out_buf = out;
139.637 + *size_out = ((char *) entry - out);
139.638 + return 0;
139.639 +}
139.640 +
139.641 +static errcode_t
139.642 +write_xattrs_to_buffer(ext2_filsys fs, struct ext2_xattr *attrs, int count,
139.643 + void *entries_start, unsigned int storage_size,
139.644 + unsigned int value_offset_correction, int write_hash)
139.645 +{
139.646 + struct ext2_xattr *x;
139.647 + struct ext2_ext_attr_entry *e = entries_start;
139.648 + char *end = (char *) entries_start + storage_size;
139.649 + const char *shortname;
139.650 + unsigned int value_size;
139.651 + int idx, ret;
139.652 + errcode_t err;
139.653 +
139.654 + memset(entries_start, 0, storage_size);
139.655 + for (x = attrs; x < attrs + count; x++) {
139.656 + /* Calculate index and shortname position */
139.657 + shortname = x->name;
139.658 + ret = find_ea_index(x->name, &shortname, &idx);
139.659 +
139.660 + value_size = ((x->value_len + EXT2_EXT_ATTR_PAD - 1) /
139.661 + EXT2_EXT_ATTR_PAD) * EXT2_EXT_ATTR_PAD;
139.662 +
139.663 + /* Fill out e appropriately */
139.664 + e->e_name_len = strlen(shortname);
139.665 + e->e_name_index = (ret ? idx : 0);
139.666 +
139.667 + e->e_value_size = x->value_len;
139.668 + e->e_value_inum = x->ea_ino;
139.669 +
139.670 + /* Store name */
139.671 + memcpy((char *)e + sizeof(*e), shortname, e->e_name_len);
139.672 + if (x->ea_ino) {
139.673 + e->e_value_offs = 0;
139.674 + } else {
139.675 + end -= value_size;
139.676 + e->e_value_offs = end - (char *) entries_start +
139.677 + value_offset_correction;
139.678 + memcpy(end, x->value, e->e_value_size);
139.679 + }
139.680 +
139.681 + if (write_hash || x->ea_ino) {
139.682 + err = ext2fs_ext_attr_hash_entry2(fs, e,
139.683 + x->ea_ino ? 0 : end,
139.684 + &e->e_hash);
139.685 + if (err)
139.686 + return err;
139.687 + } else
139.688 + e->e_hash = 0;
139.689 +
139.690 + e = EXT2_EXT_ATTR_NEXT(e);
139.691 + *(__u32 *)e = 0;
139.692 + }
139.693 + return 0;
139.694 +}
139.695 +
139.696 +errcode_t ext2fs_xattrs_write(struct ext2_xattr_handle *handle)
139.697 +{
139.698 + ext2_filsys fs = handle->fs;
139.699 + const unsigned int inode_size = EXT2_INODE_SIZE(fs->super);
139.700 + struct ext2_inode_large *inode;
139.701 + char *start, *block_buf = NULL;
139.702 + struct ext2_ext_attr_header *header;
139.703 + __u32 ea_inode_magic;
139.704 + blk64_t blk;
139.705 + unsigned int storage_size;
139.706 + unsigned int i;
139.707 + errcode_t err;
139.708 +
139.709 + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
139.710 + i = inode_size;
139.711 + if (i < sizeof(*inode))
139.712 + i = sizeof(*inode);
139.713 + err = ext2fs_get_memzero(i, &inode);
139.714 + if (err)
139.715 + return err;
139.716 +
139.717 + err = ext2fs_read_inode_full(fs, handle->ino, EXT2_INODE(inode),
139.718 + inode_size);
139.719 + if (err)
139.720 + goto out;
139.721 +
139.722 + /* If extra_isize isn't set, we need to set it now */
139.723 + if (inode->i_extra_isize == 0 &&
139.724 + inode_size > EXT2_GOOD_OLD_INODE_SIZE) {
139.725 + char *p = (char *)inode;
139.726 + size_t extra = fs->super->s_want_extra_isize;
139.727 +
139.728 + if (extra == 0)
139.729 + extra = sizeof(__u32);
139.730 + memset(p + EXT2_GOOD_OLD_INODE_SIZE, 0, extra);
139.731 + inode->i_extra_isize = extra;
139.732 + }
139.733 + if (inode->i_extra_isize & 3) {
139.734 + err = EXT2_ET_INODE_CORRUPTED;
139.735 + goto out;
139.736 + }
139.737 +
139.738 + /* Does the inode have space for EA? */
139.739 + if (inode->i_extra_isize < sizeof(inode->i_extra_isize) ||
139.740 + inode_size <= EXT2_GOOD_OLD_INODE_SIZE + inode->i_extra_isize +
139.741 + sizeof(__u32))
139.742 + goto write_ea_block;
139.743 +
139.744 + /* Write the inode EA */
139.745 + ea_inode_magic = EXT2_EXT_ATTR_MAGIC;
139.746 + memcpy(((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
139.747 + inode->i_extra_isize, &ea_inode_magic, sizeof(__u32));
139.748 + storage_size = inode_size - EXT2_GOOD_OLD_INODE_SIZE -
139.749 + inode->i_extra_isize - sizeof(__u32);
139.750 + start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
139.751 + inode->i_extra_isize + sizeof(__u32);
139.752 +
139.753 + err = write_xattrs_to_buffer(fs, handle->attrs, handle->ibody_count,
139.754 + start, storage_size, 0, 0);
139.755 + if (err)
139.756 + goto out;
139.757 +write_ea_block:
139.758 + /* Are we done? */
139.759 + if (handle->ibody_count == handle->count &&
139.760 + !ext2fs_file_acl_block(fs, EXT2_INODE(inode)))
139.761 + goto skip_ea_block;
139.762 +
139.763 + /* Write the EA block */
139.764 + err = ext2fs_get_memzero(fs->blocksize, &block_buf);
139.765 + if (err)
139.766 + goto out;
139.767 +
139.768 + storage_size = fs->blocksize - sizeof(struct ext2_ext_attr_header);
139.769 + start = block_buf + sizeof(struct ext2_ext_attr_header);
139.770 +
139.771 + err = write_xattrs_to_buffer(fs, handle->attrs + handle->ibody_count,
139.772 + handle->count - handle->ibody_count, start,
139.773 + storage_size, start - block_buf, 1);
139.774 + if (err)
139.775 + goto out2;
139.776 +
139.777 + /* Write a header on the EA block */
139.778 + header = (struct ext2_ext_attr_header *) block_buf;
139.779 + header->h_magic = EXT2_EXT_ATTR_MAGIC;
139.780 + header->h_refcount = 1;
139.781 + header->h_blocks = 1;
139.782 +
139.783 + /* Get a new block for writing */
139.784 + err = prep_ea_block_for_write(fs, handle->ino, inode);
139.785 + if (err)
139.786 + goto out2;
139.787 +
139.788 + /* Finally, write the new EA block */
139.789 + blk = ext2fs_file_acl_block(fs, EXT2_INODE(inode));
139.790 + err = ext2fs_write_ext_attr3(fs, blk, block_buf, handle->ino);
139.791 + if (err)
139.792 + goto out2;
139.793 +
139.794 +skip_ea_block:
139.795 + blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode);
139.796 + if (!block_buf && blk) {
139.797 + /* xattrs shrunk, free the block */
139.798 + err = ext2fs_free_ext_attr(fs, handle->ino, inode);
139.799 + if (err)
139.800 + goto out;
139.801 + }
139.802 +
139.803 + /* Write the inode */
139.804 + err = ext2fs_write_inode_full(fs, handle->ino, EXT2_INODE(inode),
139.805 + inode_size);
139.806 + if (err)
139.807 + goto out2;
139.808 +
139.809 +out2:
139.810 + ext2fs_free_mem(&block_buf);
139.811 +out:
139.812 + ext2fs_free_mem(&inode);
139.813 + return err;
139.814 +}
139.815 +
139.816 +static errcode_t read_xattrs_from_buffer(struct ext2_xattr_handle *handle,
139.817 + struct ext2_inode_large *inode,
139.818 + struct ext2_ext_attr_entry *entries,
139.819 + unsigned int storage_size,
139.820 + char *value_start)
139.821 +{
139.822 + struct ext2_xattr *x;
139.823 + struct ext2_ext_attr_entry *entry, *end;
139.824 + const char *prefix;
139.825 + unsigned int remain, prefix_len;
139.826 + errcode_t err;
139.827 + unsigned int values_size = storage_size +
139.828 + ((char *)entries - value_start);
139.829 +
139.830 + /* find the end */
139.831 + end = entries;
139.832 + remain = storage_size;
139.833 + while (remain >= sizeof(struct ext2_ext_attr_entry) &&
139.834 + !EXT2_EXT_IS_LAST_ENTRY(end)) {
139.835 +
139.836 + /* header eats this space */
139.837 + remain -= sizeof(struct ext2_ext_attr_entry);
139.838 +
139.839 + /* is attribute name valid? */
139.840 + if (EXT2_EXT_ATTR_SIZE(end->e_name_len) > remain)
139.841 + return EXT2_ET_EA_BAD_NAME_LEN;
139.842 +
139.843 + /* attribute len eats this space */
139.844 + remain -= EXT2_EXT_ATTR_SIZE(end->e_name_len);
139.845 + end = EXT2_EXT_ATTR_NEXT(end);
139.846 + }
139.847 +
139.848 + entry = entries;
139.849 + remain = storage_size;
139.850 + while (remain >= sizeof(struct ext2_ext_attr_entry) &&
139.851 + !EXT2_EXT_IS_LAST_ENTRY(entry)) {
139.852 +
139.853 + /* Allocate space for more attrs? */
139.854 + if (handle->count == handle->capacity) {
139.855 + err = ext2fs_xattrs_expand(handle, 4);
139.856 + if (err)
139.857 + return err;
139.858 + }
139.859 +
139.860 + x = handle->attrs + handle->count;
139.861 +
139.862 + /* header eats this space */
139.863 + remain -= sizeof(struct ext2_ext_attr_entry);
139.864 +
139.865 + /* attribute len eats this space */
139.866 + remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
139.867 +
139.868 + /* Extract name */
139.869 + prefix = find_ea_prefix(entry->e_name_index);
139.870 + prefix_len = (prefix ? strlen(prefix) : 0);
139.871 + err = ext2fs_get_memzero(entry->e_name_len + prefix_len + 1,
139.872 + &x->name);
139.873 + if (err)
139.874 + return err;
139.875 + if (prefix)
139.876 + memcpy(x->name, prefix, prefix_len);
139.877 + if (entry->e_name_len)
139.878 + memcpy(x->name + prefix_len,
139.879 + (char *)entry + sizeof(*entry),
139.880 + entry->e_name_len);
139.881 +
139.882 + /* Check & copy value */
139.883 + if (!ext2fs_has_feature_ea_inode(handle->fs->super) &&
139.884 + entry->e_value_inum != 0)
139.885 + return EXT2_ET_BAD_EA_BLOCK_NUM;
139.886 +
139.887 + if (entry->e_value_inum == 0) {
139.888 + if (entry->e_value_size > remain)
139.889 + return EXT2_ET_EA_BAD_VALUE_SIZE;
139.890 +
139.891 + if (entry->e_value_offs + entry->e_value_size > values_size)
139.892 + return EXT2_ET_EA_BAD_VALUE_OFFSET;
139.893 +
139.894 + if (entry->e_value_size > 0 &&
139.895 + value_start + entry->e_value_offs <
139.896 + (char *)end + sizeof(__u32))
139.897 + return EXT2_ET_EA_BAD_VALUE_OFFSET;
139.898 +
139.899 + remain -= entry->e_value_size;
139.900 +
139.901 + err = ext2fs_get_mem(entry->e_value_size, &x->value);
139.902 + if (err)
139.903 + return err;
139.904 + memcpy(x->value, value_start + entry->e_value_offs,
139.905 + entry->e_value_size);
139.906 + } else {
139.907 + struct ext2_inode *ea_inode;
139.908 + ext2_file_t ea_file;
139.909 +
139.910 + if (entry->e_value_offs != 0)
139.911 + return EXT2_ET_EA_BAD_VALUE_OFFSET;
139.912 +
139.913 + if (entry->e_value_size > (64 * 1024))
139.914 + return EXT2_ET_EA_BAD_VALUE_SIZE;
139.915 +
139.916 + err = ext2fs_get_mem(entry->e_value_size, &x->value);
139.917 + if (err)
139.918 + return err;
139.919 +
139.920 + err = ext2fs_file_open(handle->fs, entry->e_value_inum,
139.921 + 0, &ea_file);
139.922 + if (err)
139.923 + return err;
139.924 +
139.925 + ea_inode = ext2fs_file_get_inode(ea_file);
139.926 + if ((ea_inode->i_flags & EXT4_INLINE_DATA_FL) ||
139.927 + !(ea_inode->i_flags & EXT4_EA_INODE_FL) ||
139.928 + ea_inode->i_links_count == 0)
139.929 + err = EXT2_ET_EA_INODE_CORRUPTED;
139.930 + else if (ext2fs_file_get_size(ea_file) !=
139.931 + entry->e_value_size)
139.932 + err = EXT2_ET_EA_BAD_VALUE_SIZE;
139.933 + else
139.934 + err = ext2fs_file_read(ea_file, x->value,
139.935 + entry->e_value_size, 0);
139.936 + ext2fs_file_close(ea_file);
139.937 + if (err)
139.938 + return err;
139.939 + }
139.940 +
139.941 + x->ea_ino = entry->e_value_inum;
139.942 + x->value_len = entry->e_value_size;
139.943 +
139.944 + /* e_hash may be 0 in older inode's ea */
139.945 + if (entry->e_hash != 0) {
139.946 + __u32 hash;
139.947 + void *data = (entry->e_value_inum != 0) ?
139.948 + 0 : value_start + entry->e_value_offs;
139.949 +
139.950 + err = ext2fs_ext_attr_hash_entry2(handle->fs, entry,
139.951 + data, &hash);
139.952 + if (err)
139.953 + return err;
139.954 + if (entry->e_hash != hash) {
139.955 + struct ext2_inode child;
139.956 +
139.957 + /* Check whether this is an old Lustre-style
139.958 + * ea_inode reference.
139.959 + */
139.960 + err = ext2fs_read_inode(handle->fs,
139.961 + entry->e_value_inum,
139.962 + &child);
139.963 + if (err)
139.964 + return err;
139.965 + if (child.i_mtime != handle->ino ||
139.966 + child.i_generation != inode->i_generation)
139.967 + return EXT2_ET_BAD_EA_HASH;
139.968 + }
139.969 + }
139.970 +
139.971 + handle->count++;
139.972 + entry = EXT2_EXT_ATTR_NEXT(entry);
139.973 + }
139.974 +
139.975 + return 0;
139.976 +}
139.977 +
139.978 +static void xattrs_free_keys(struct ext2_xattr_handle *h)
139.979 +{
139.980 + struct ext2_xattr *a = h->attrs;
139.981 + int i;
139.982 +
139.983 + for (i = 0; i < h->capacity; i++) {
139.984 + if (a[i].name)
139.985 + ext2fs_free_mem(&a[i].name);
139.986 + if (a[i].value)
139.987 + ext2fs_free_mem(&a[i].value);
139.988 + }
139.989 + h->count = 0;
139.990 + h->ibody_count = 0;
139.991 +}
139.992 +
139.993 +errcode_t ext2fs_xattrs_read(struct ext2_xattr_handle *handle)
139.994 +{
139.995 + struct ext2_inode_large *inode;
139.996 + struct ext2_ext_attr_header *header;
139.997 + __u32 ea_inode_magic;
139.998 + unsigned int storage_size;
139.999 + char *start, *block_buf = NULL;
139.1000 + blk64_t blk;
139.1001 + size_t i;
139.1002 + errcode_t err;
139.1003 +
139.1004 + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
139.1005 + i = EXT2_INODE_SIZE(handle->fs->super);
139.1006 + if (i < sizeof(*inode))
139.1007 + i = sizeof(*inode);
139.1008 + err = ext2fs_get_memzero(i, &inode);
139.1009 + if (err)
139.1010 + return err;
139.1011 +
139.1012 + err = ext2fs_read_inode_full(handle->fs, handle->ino,
139.1013 + (struct ext2_inode *)inode,
139.1014 + EXT2_INODE_SIZE(handle->fs->super));
139.1015 + if (err)
139.1016 + goto out;
139.1017 +
139.1018 + xattrs_free_keys(handle);
139.1019 +
139.1020 + /* Does the inode have space for EA? */
139.1021 + if (inode->i_extra_isize < sizeof(inode->i_extra_isize) ||
139.1022 + EXT2_INODE_SIZE(handle->fs->super) <= EXT2_GOOD_OLD_INODE_SIZE +
139.1023 + inode->i_extra_isize +
139.1024 + sizeof(__u32))
139.1025 + goto read_ea_block;
139.1026 + if (inode->i_extra_isize & 3) {
139.1027 + err = EXT2_ET_INODE_CORRUPTED;
139.1028 + goto out;
139.1029 + }
139.1030 +
139.1031 + /* Look for EA in the inode */
139.1032 + memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
139.1033 + inode->i_extra_isize, sizeof(__u32));
139.1034 + if (ea_inode_magic == EXT2_EXT_ATTR_MAGIC) {
139.1035 + storage_size = EXT2_INODE_SIZE(handle->fs->super) -
139.1036 + EXT2_GOOD_OLD_INODE_SIZE - inode->i_extra_isize -
139.1037 + sizeof(__u32);
139.1038 + start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
139.1039 + inode->i_extra_isize + sizeof(__u32);
139.1040 +
139.1041 + err = read_xattrs_from_buffer(handle, inode,
139.1042 + (struct ext2_ext_attr_entry *) start,
139.1043 + storage_size, start);
139.1044 + if (err)
139.1045 + goto out;
139.1046 +
139.1047 + handle->ibody_count = handle->count;
139.1048 + }
139.1049 +
139.1050 +read_ea_block:
139.1051 + /* Look for EA in a separate EA block */
139.1052 + blk = ext2fs_file_acl_block(handle->fs, (struct ext2_inode *)inode);
139.1053 + if (blk != 0) {
139.1054 + if ((blk < handle->fs->super->s_first_data_block) ||
139.1055 + (blk >= ext2fs_blocks_count(handle->fs->super))) {
139.1056 + err = EXT2_ET_BAD_EA_BLOCK_NUM;
139.1057 + goto out;
139.1058 + }
139.1059 +
139.1060 + err = ext2fs_get_mem(handle->fs->blocksize, &block_buf);
139.1061 + if (err)
139.1062 + goto out;
139.1063 +
139.1064 + err = ext2fs_read_ext_attr3(handle->fs, blk, block_buf,
139.1065 + handle->ino);
139.1066 + if (err)
139.1067 + goto out3;
139.1068 +
139.1069 + /* We only know how to deal with v2 EA blocks */
139.1070 + header = (struct ext2_ext_attr_header *) block_buf;
139.1071 + if (header->h_magic != EXT2_EXT_ATTR_MAGIC) {
139.1072 + err = EXT2_ET_BAD_EA_HEADER;
139.1073 + goto out3;
139.1074 + }
139.1075 +
139.1076 + /* Read EAs */
139.1077 + storage_size = handle->fs->blocksize -
139.1078 + sizeof(struct ext2_ext_attr_header);
139.1079 + start = block_buf + sizeof(struct ext2_ext_attr_header);
139.1080 + err = read_xattrs_from_buffer(handle, inode,
139.1081 + (struct ext2_ext_attr_entry *) start,
139.1082 + storage_size, block_buf);
139.1083 + if (err)
139.1084 + goto out3;
139.1085 +
139.1086 + ext2fs_free_mem(&block_buf);
139.1087 + }
139.1088 +
139.1089 + ext2fs_free_mem(&block_buf);
139.1090 + ext2fs_free_mem(&inode);
139.1091 + return 0;
139.1092 +
139.1093 +out3:
139.1094 + ext2fs_free_mem(&block_buf);
139.1095 +out:
139.1096 + ext2fs_free_mem(&inode);
139.1097 + return err;
139.1098 +}
139.1099 +
139.1100 +errcode_t ext2fs_xattrs_iterate(struct ext2_xattr_handle *h,
139.1101 + int (*func)(char *name, char *value,
139.1102 + size_t value_len, void *data),
139.1103 + void *data)
139.1104 +{
139.1105 + struct ext2_xattr *x;
139.1106 + int dirty = 0;
139.1107 + int ret;
139.1108 +
139.1109 + EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE);
139.1110 + for (x = h->attrs; x < h->attrs + h->count; x++) {
139.1111 + ret = func(x->name, x->value, x->value_len, data);
139.1112 + if (ret & XATTR_CHANGED)
139.1113 + dirty = 1;
139.1114 + if (ret & XATTR_ABORT)
139.1115 + break;
139.1116 + }
139.1117 +
139.1118 + if (dirty)
139.1119 + return ext2fs_xattrs_write(h);
139.1120 + return 0;
139.1121 +}
139.1122 +
139.1123 +errcode_t ext2fs_xattr_get(struct ext2_xattr_handle *h, const char *key,
139.1124 + void **value, size_t *value_len)
139.1125 +{
139.1126 + struct ext2_xattr *x;
139.1127 + char *val;
139.1128 + errcode_t err;
139.1129 +
139.1130 + EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE);
139.1131 + for (x = h->attrs; x < h->attrs + h->count; x++) {
139.1132 + if (strcmp(x->name, key))
139.1133 + continue;
139.1134 +
139.1135 + if (!(h->flags & XATTR_HANDLE_FLAG_RAW) &&
139.1136 + ((strcmp(key, "system.posix_acl_default") == 0) ||
139.1137 + (strcmp(key, "system.posix_acl_access") == 0))) {
139.1138 + err = convert_disk_buffer_to_posix_acl(x->value, x->value_len,
139.1139 + value, value_len);
139.1140 + return err;
139.1141 + } else {
139.1142 + err = ext2fs_get_mem(x->value_len, &val);
139.1143 + if (err)
139.1144 + return err;
139.1145 + memcpy(val, x->value, x->value_len);
139.1146 + *value = val;
139.1147 + *value_len = x->value_len;
139.1148 + return 0;
139.1149 + }
139.1150 + }
139.1151 +
139.1152 + return EXT2_ET_EA_KEY_NOT_FOUND;
139.1153 +}
139.1154 +
139.1155 +errcode_t ext2fs_xattr_inode_max_size(ext2_filsys fs, ext2_ino_t ino,
139.1156 + size_t *size)
139.1157 +{
139.1158 + struct ext2_ext_attr_entry *entry;
139.1159 + struct ext2_inode_large *inode;
139.1160 + __u32 ea_inode_magic;
139.1161 + unsigned int minoff;
139.1162 + char *start;
139.1163 + size_t i;
139.1164 + errcode_t err;
139.1165 +
139.1166 + i = EXT2_INODE_SIZE(fs->super);
139.1167 + if (i < sizeof(*inode))
139.1168 + i = sizeof(*inode);
139.1169 + err = ext2fs_get_memzero(i, &inode);
139.1170 + if (err)
139.1171 + return err;
139.1172 +
139.1173 + err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)inode,
139.1174 + EXT2_INODE_SIZE(fs->super));
139.1175 + if (err)
139.1176 + goto out;
139.1177 +
139.1178 + /* Does the inode have size for EA? */
139.1179 + if (EXT2_INODE_SIZE(fs->super) <= EXT2_GOOD_OLD_INODE_SIZE +
139.1180 + inode->i_extra_isize +
139.1181 + sizeof(__u32)) {
139.1182 + err = EXT2_ET_INLINE_DATA_NO_SPACE;
139.1183 + goto out;
139.1184 + }
139.1185 +
139.1186 + minoff = EXT2_INODE_SIZE(fs->super) - sizeof(*inode) - sizeof(__u32);
139.1187 + memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
139.1188 + inode->i_extra_isize, sizeof(__u32));
139.1189 + if (ea_inode_magic == EXT2_EXT_ATTR_MAGIC) {
139.1190 + /* has xattrs. calculate the size */
139.1191 + start= ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
139.1192 + inode->i_extra_isize + sizeof(__u32);
139.1193 + entry = (struct ext2_ext_attr_entry *) start;
139.1194 + while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
139.1195 + if (!entry->e_value_inum && entry->e_value_size) {
139.1196 + unsigned int offs = entry->e_value_offs;
139.1197 + if (offs < minoff)
139.1198 + minoff = offs;
139.1199 + }
139.1200 + entry = EXT2_EXT_ATTR_NEXT(entry);
139.1201 + }
139.1202 + *size = minoff - ((char *)entry - (char *)start) - sizeof(__u32);
139.1203 + } else {
139.1204 + /* no xattr. return a maximum size */
139.1205 + *size = EXT2_EXT_ATTR_SIZE(minoff -
139.1206 + EXT2_EXT_ATTR_LEN(strlen("data")) -
139.1207 + EXT2_EXT_ATTR_ROUND - sizeof(__u32));
139.1208 + }
139.1209 +
139.1210 +out:
139.1211 + ext2fs_free_mem(&inode);
139.1212 + return err;
139.1213 +}
139.1214 +
139.1215 +static errcode_t xattr_create_ea_inode(ext2_filsys fs, const void *value,
139.1216 + size_t value_len, ext2_ino_t *ea_ino)
139.1217 +{
139.1218 + struct ext2_inode inode;
139.1219 + ext2_ino_t ino;
139.1220 + ext2_file_t file;
139.1221 + __u32 hash;
139.1222 + errcode_t ret;
139.1223 +
139.1224 + ret = ext2fs_new_inode(fs, 0, 0, 0, &ino);
139.1225 + if (ret)
139.1226 + return ret;
139.1227 +
139.1228 + memset(&inode, 0, sizeof(inode));
139.1229 + inode.i_flags |= EXT4_EA_INODE_FL;
139.1230 + if (ext2fs_has_feature_extents(fs->super))
139.1231 + inode.i_flags |= EXT4_EXTENTS_FL;
139.1232 + inode.i_size = 0;
139.1233 + inode.i_mode = LINUX_S_IFREG | 0600;
139.1234 + inode.i_links_count = 1;
139.1235 + ret = ext2fs_write_new_inode(fs, ino, &inode);
139.1236 + if (ret)
139.1237 + return ret;
139.1238 + /*
139.1239 + * ref_count and hash utilize inode's i_*time fields.
139.1240 + * ext2fs_write_new_inode() call above initializes these fields with
139.1241 + * current time. That's why ref count and hash updates are done
139.1242 + * separately below.
139.1243 + */
139.1244 + ext2fs_set_ea_inode_ref(&inode, 1);
139.1245 + hash = ext2fs_crc32c_le(fs->csum_seed, value, value_len);
139.1246 + ext2fs_set_ea_inode_hash(&inode, hash);
139.1247 +
139.1248 + ret = ext2fs_write_inode(fs, ino, &inode);
139.1249 + if (ret)
139.1250 + return ret;
139.1251 +
139.1252 + ret = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &file);
139.1253 + if (ret)
139.1254 + return ret;
139.1255 + ret = ext2fs_file_write(file, value, value_len, NULL);
139.1256 + ext2fs_file_close(file);
139.1257 + if (ret)
139.1258 + return ret;
139.1259 +
139.1260 + ext2fs_inode_alloc_stats2(fs, ino, 1 /* inuse */, 0 /* isdir */);
139.1261 +
139.1262 + *ea_ino = ino;
139.1263 + return 0;
139.1264 +}
139.1265 +
139.1266 +static errcode_t xattr_inode_dec_ref(ext2_filsys fs, ext2_ino_t ino)
139.1267 +{
139.1268 + struct ext2_inode_large inode;
139.1269 + __u64 ref_count;
139.1270 + errcode_t ret;
139.1271 +
139.1272 + ret = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
139.1273 + sizeof(inode));
139.1274 + if (ret)
139.1275 + goto out;
139.1276 +
139.1277 + ref_count = ext2fs_get_ea_inode_ref(EXT2_INODE(&inode));
139.1278 + ref_count--;
139.1279 + ext2fs_set_ea_inode_ref(EXT2_INODE(&inode), ref_count);
139.1280 +
139.1281 + if (ref_count)
139.1282 + goto write_out;
139.1283 +
139.1284 + inode.i_links_count = 0;
139.1285 + inode.i_dtime = fs->now ? fs->now : time(0);
139.1286 +
139.1287 + ret = ext2fs_free_ext_attr(fs, ino, &inode);
139.1288 + if (ret)
139.1289 + goto write_out;
139.1290 +
139.1291 + if (ext2fs_inode_has_valid_blocks2(fs, (struct ext2_inode *)&inode)) {
139.1292 + ret = ext2fs_punch(fs, ino, (struct ext2_inode *)&inode, NULL,
139.1293 + 0, ~0ULL);
139.1294 + if (ret)
139.1295 + goto out;
139.1296 + }
139.1297 +
139.1298 + ext2fs_inode_alloc_stats2(fs, ino, -1 /* inuse */, 0 /* is_dir */);
139.1299 +
139.1300 +write_out:
139.1301 + ret = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
139.1302 + sizeof(inode));
139.1303 +out:
139.1304 + return ret;
139.1305 +}
139.1306 +
139.1307 +static errcode_t xattr_update_entry(ext2_filsys fs, struct ext2_xattr *x,
139.1308 + const char *name, const void *value,
139.1309 + size_t value_len, int in_inode)
139.1310 +{
139.1311 + ext2_ino_t ea_ino = 0;
139.1312 + void *new_value = NULL;
139.1313 + char *new_name = NULL;
139.1314 + int name_len;
139.1315 + errcode_t ret;
139.1316 +
139.1317 + if (!x->name) {
139.1318 + name_len = strlen(name);
139.1319 + ret = ext2fs_get_mem(name_len + 1, &new_name);
139.1320 + if (ret)
139.1321 + goto fail;
139.1322 + memcpy(new_name, name, name_len + 1);
139.1323 + }
139.1324 +
139.1325 + ret = ext2fs_get_mem(value_len, &new_value);
139.1326 + if (ret)
139.1327 + goto fail;
139.1328 + memcpy(new_value, value, value_len);
139.1329 +
139.1330 + if (in_inode) {
139.1331 + ret = xattr_create_ea_inode(fs, value, value_len, &ea_ino);
139.1332 + if (ret)
139.1333 + goto fail;
139.1334 + }
139.1335 +
139.1336 + if (x->ea_ino) {
139.1337 + ret = xattr_inode_dec_ref(fs, x->ea_ino);
139.1338 + if (ret)
139.1339 + goto fail;
139.1340 + }
139.1341 +
139.1342 + if (!x->name)
139.1343 + x->name = new_name;
139.1344 +
139.1345 + if (x->value)
139.1346 + ext2fs_free_mem(&x->value);
139.1347 + x->value = new_value;
139.1348 + x->value_len = value_len;
139.1349 + x->ea_ino = ea_ino;
139.1350 + return 0;
139.1351 +fail:
139.1352 + if (new_name)
139.1353 + ext2fs_free_mem(&new_name);
139.1354 + if (new_value)
139.1355 + ext2fs_free_mem(&new_value);
139.1356 + if (ea_ino)
139.1357 + xattr_inode_dec_ref(fs, ea_ino);
139.1358 + return ret;
139.1359 +}
139.1360 +
139.1361 +static int xattr_find_position(struct ext2_xattr *attrs, int count,
139.1362 + const char *name)
139.1363 +{
139.1364 + struct ext2_xattr *x;
139.1365 + int i;
139.1366 + const char *shortname, *x_shortname;
139.1367 + int name_idx, x_name_idx;
139.1368 + int shortname_len, x_shortname_len;
139.1369 +
139.1370 + find_ea_index(name, &shortname, &name_idx);
139.1371 + shortname_len = strlen(shortname);
139.1372 +
139.1373 + for (i = 0, x = attrs; i < count; i++, x++) {
139.1374 + find_ea_index(x->name, &x_shortname, &x_name_idx);
139.1375 + if (name_idx < x_name_idx)
139.1376 + break;
139.1377 + if (name_idx > x_name_idx)
139.1378 + continue;
139.1379 +
139.1380 + x_shortname_len = strlen(x_shortname);
139.1381 + if (shortname_len < x_shortname_len)
139.1382 + break;
139.1383 + if (shortname_len > x_shortname_len)
139.1384 + continue;
139.1385 +
139.1386 + if (memcmp(shortname, x_shortname, shortname_len) <= 0)
139.1387 + break;
139.1388 + }
139.1389 + return i;
139.1390 +}
139.1391 +
139.1392 +static errcode_t xattr_array_update(struct ext2_xattr_handle *h,
139.1393 + const char *name,
139.1394 + const void *value, size_t value_len,
139.1395 + int ibody_free, int block_free,
139.1396 + int old_idx, int in_inode)
139.1397 +{
139.1398 + struct ext2_xattr tmp;
139.1399 + int add_to_ibody;
139.1400 + int needed;
139.1401 + int name_len, name_idx;
139.1402 + const char *shortname;
139.1403 + int new_idx;
139.1404 + int ret;
139.1405 +
139.1406 + find_ea_index(name, &shortname, &name_idx);
139.1407 + name_len = strlen(shortname);
139.1408 +
139.1409 + needed = EXT2_EXT_ATTR_LEN(name_len);
139.1410 + if (!in_inode)
139.1411 + needed += EXT2_EXT_ATTR_SIZE(value_len);
139.1412 +
139.1413 + if (old_idx >= 0 && old_idx < h->ibody_count) {
139.1414 + ibody_free += EXT2_EXT_ATTR_LEN(name_len);
139.1415 + if (!h->attrs[old_idx].ea_ino)
139.1416 + ibody_free += EXT2_EXT_ATTR_SIZE(
139.1417 + h->attrs[old_idx].value_len);
139.1418 + }
139.1419 +
139.1420 + if (needed <= ibody_free) {
139.1421 + if (old_idx < 0) {
139.1422 + new_idx = h->ibody_count;
139.1423 + add_to_ibody = 1;
139.1424 + goto add_new;
139.1425 + }
139.1426 +
139.1427 + /* Update the existing entry. */
139.1428 + ret = xattr_update_entry(h->fs, &h->attrs[old_idx], name,
139.1429 + value, value_len, in_inode);
139.1430 + if (ret)
139.1431 + return ret;
139.1432 + if (h->ibody_count <= old_idx) {
139.1433 + /* Move entry from block to the end of ibody. */
139.1434 + tmp = h->attrs[old_idx];
139.1435 + memmove(h->attrs + h->ibody_count + 1,
139.1436 + h->attrs + h->ibody_count,
139.1437 + (old_idx - h->ibody_count) * sizeof(*h->attrs));
139.1438 + h->attrs[h->ibody_count] = tmp;
139.1439 + h->ibody_count++;
139.1440 + }
139.1441 + return 0;
139.1442 + }
139.1443 +
139.1444 + if (h->ibody_count <= old_idx) {
139.1445 + block_free += EXT2_EXT_ATTR_LEN(name_len);
139.1446 + if (!h->attrs[old_idx].ea_ino)
139.1447 + block_free +=
139.1448 + EXT2_EXT_ATTR_SIZE(h->attrs[old_idx].value_len);
139.1449 + }
139.1450 +
139.1451 + if (needed > block_free)
139.1452 + return EXT2_ET_EA_NO_SPACE;
139.1453 +
139.1454 + if (old_idx >= 0) {
139.1455 + /* Update the existing entry. */
139.1456 + ret = xattr_update_entry(h->fs, &h->attrs[old_idx], name,
139.1457 + value, value_len, in_inode);
139.1458 + if (ret)
139.1459 + return ret;
139.1460 + if (old_idx < h->ibody_count) {
139.1461 + /*
139.1462 + * Move entry from ibody to the block. Note that
139.1463 + * entries in the block are sorted.
139.1464 + */
139.1465 + new_idx = xattr_find_position(h->attrs + h->ibody_count,
139.1466 + h->count - h->ibody_count, name);
139.1467 + new_idx += h->ibody_count - 1;
139.1468 + tmp = h->attrs[old_idx];
139.1469 + memmove(h->attrs + old_idx, h->attrs + old_idx + 1,
139.1470 + (new_idx - old_idx) * sizeof(*h->attrs));
139.1471 + h->attrs[new_idx] = tmp;
139.1472 + h->ibody_count--;
139.1473 + }
139.1474 + return 0;
139.1475 + }
139.1476 +
139.1477 + new_idx = xattr_find_position(h->attrs + h->ibody_count,
139.1478 + h->count - h->ibody_count, name);
139.1479 + new_idx += h->ibody_count;
139.1480 + add_to_ibody = 0;
139.1481 +
139.1482 +add_new:
139.1483 + if (h->count == h->capacity) {
139.1484 + ret = ext2fs_xattrs_expand(h, 4);
139.1485 + if (ret)
139.1486 + return ret;
139.1487 + }
139.1488 +
139.1489 + ret = xattr_update_entry(h->fs, &h->attrs[h->count], name, value,
139.1490 + value_len, in_inode);
139.1491 + if (ret)
139.1492 + return ret;
139.1493 +
139.1494 + tmp = h->attrs[h->count];
139.1495 + memmove(h->attrs + new_idx + 1, h->attrs + new_idx,
139.1496 + (h->count - new_idx)*sizeof(*h->attrs));
139.1497 + h->attrs[new_idx] = tmp;
139.1498 + if (add_to_ibody)
139.1499 + h->ibody_count++;
139.1500 + h->count++;
139.1501 + return 0;
139.1502 +}
139.1503 +
139.1504 +static int space_used(struct ext2_xattr *attrs, int count)
139.1505 +{
139.1506 + int total = 0;
139.1507 + struct ext2_xattr *x;
139.1508 + const char *shortname;
139.1509 + int i, len, name_idx;
139.1510 +
139.1511 + for (i = 0, x = attrs; i < count; i++, x++) {
139.1512 + find_ea_index(x->name, &shortname, &name_idx);
139.1513 + len = strlen(shortname);
139.1514 + total += EXT2_EXT_ATTR_LEN(len);
139.1515 + if (!x->ea_ino)
139.1516 + total += EXT2_EXT_ATTR_SIZE(x->value_len);
139.1517 + }
139.1518 + return total;
139.1519 +}
139.1520 +
139.1521 +/*
139.1522 + * The minimum size of EA value when you start storing it in an external inode
139.1523 + * size of block - size of header - size of 1 entry - 4 null bytes
139.1524 + */
139.1525 +#define EXT4_XATTR_MIN_LARGE_EA_SIZE(b) \
139.1526 + ((b) - EXT2_EXT_ATTR_LEN(3) - sizeof(struct ext2_ext_attr_header) - 4)
139.1527 +
139.1528 +errcode_t ext2fs_xattr_set(struct ext2_xattr_handle *h,
139.1529 + const char *name,
139.1530 + const void *value,
139.1531 + size_t value_len)
139.1532 +{
139.1533 + ext2_filsys fs = h->fs;
139.1534 + const int inode_size = EXT2_INODE_SIZE(fs->super);
139.1535 + struct ext2_inode_large *inode = NULL;
139.1536 + struct ext2_xattr *x;
139.1537 + char *new_value;
139.1538 + int ibody_free, block_free;
139.1539 + int in_inode = 0;
139.1540 + int old_idx = -1;
139.1541 + int extra_isize;
139.1542 + errcode_t ret;
139.1543 +
139.1544 + EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE);
139.1545 +
139.1546 + ret = ext2fs_get_mem(value_len, &new_value);
139.1547 + if (ret)
139.1548 + return ret;
139.1549 + if (!(h->flags & XATTR_HANDLE_FLAG_RAW) &&
139.1550 + ((strcmp(name, "system.posix_acl_default") == 0) ||
139.1551 + (strcmp(name, "system.posix_acl_access") == 0))) {
139.1552 + ret = convert_posix_acl_to_disk_buffer(value, value_len,
139.1553 + new_value, &value_len);
139.1554 + if (ret)
139.1555 + goto out;
139.1556 + } else
139.1557 + memcpy(new_value, value, value_len);
139.1558 +
139.1559 + /* Imitate kernel behavior by skipping update if value is the same. */
139.1560 + for (x = h->attrs; x < h->attrs + h->count; x++) {
139.1561 + if (!strcmp(x->name, name)) {
139.1562 + if (!x->ea_ino && x->value_len == value_len &&
139.1563 + !memcmp(x->value, new_value, value_len)) {
139.1564 + ret = 0;
139.1565 + goto out;
139.1566 + }
139.1567 + old_idx = x - h->attrs;
139.1568 + break;
139.1569 + }
139.1570 + }
139.1571 +
139.1572 + ret = ext2fs_get_memzero(inode_size, &inode);
139.1573 + if (ret)
139.1574 + goto out;
139.1575 + ret = ext2fs_read_inode_full(fs, h->ino,
139.1576 + (struct ext2_inode *)inode,
139.1577 + inode_size);
139.1578 + if (ret)
139.1579 + goto out;
139.1580 + if (inode_size > EXT2_GOOD_OLD_INODE_SIZE) {
139.1581 + extra_isize = inode->i_extra_isize;
139.1582 + if (extra_isize == 0) {
139.1583 + extra_isize = fs->super->s_want_extra_isize;
139.1584 + if (extra_isize == 0)
139.1585 + extra_isize = sizeof(__u32);
139.1586 + }
139.1587 + ibody_free = inode_size - EXT2_GOOD_OLD_INODE_SIZE;
139.1588 + ibody_free -= extra_isize;
139.1589 + /* Extended attribute magic and final null entry. */
139.1590 + ibody_free -= sizeof(__u32) * 2;
139.1591 + ibody_free -= space_used(h->attrs, h->ibody_count);
139.1592 + } else
139.1593 + ibody_free = 0;
139.1594 +
139.1595 + /* Inline data can only go to ibody. */
139.1596 + if (strcmp(name, "system.data") == 0) {
139.1597 + if (h->ibody_count <= old_idx) {
139.1598 + ret = EXT2_ET_FILESYSTEM_CORRUPTED;
139.1599 + goto out;
139.1600 + }
139.1601 + ret = xattr_array_update(h, name, new_value, value_len,
139.1602 + ibody_free,
139.1603 + 0 /* block_free */, old_idx,
139.1604 + 0 /* in_inode */);
139.1605 + if (ret)
139.1606 + goto out;
139.1607 + goto write_out;
139.1608 + }
139.1609 +
139.1610 + block_free = fs->blocksize;
139.1611 + block_free -= sizeof(struct ext2_ext_attr_header);
139.1612 + /* Final null entry. */
139.1613 + block_free -= sizeof(__u32);
139.1614 + block_free -= space_used(h->attrs + h->ibody_count,
139.1615 + h->count - h->ibody_count);
139.1616 +
139.1617 + if (ext2fs_has_feature_ea_inode(fs->super) &&
139.1618 + value_len > EXT4_XATTR_MIN_LARGE_EA_SIZE(fs->blocksize))
139.1619 + in_inode = 1;
139.1620 +
139.1621 + ret = xattr_array_update(h, name, new_value, value_len, ibody_free,
139.1622 + block_free, old_idx, in_inode);
139.1623 + if (ret == EXT2_ET_EA_NO_SPACE && !in_inode &&
139.1624 + ext2fs_has_feature_ea_inode(fs->super))
139.1625 + ret = xattr_array_update(h, name, new_value, value_len,
139.1626 + ibody_free, block_free, old_idx, 1 /* in_inode */);
139.1627 + if (ret)
139.1628 + goto out;
139.1629 +
139.1630 +write_out:
139.1631 + ret = ext2fs_xattrs_write(h);
139.1632 +out:
139.1633 + if (inode)
139.1634 + ext2fs_free_mem(&inode);
139.1635 + ext2fs_free_mem(&new_value);
139.1636 + return ret;
139.1637 +}
139.1638 +
139.1639 +errcode_t ext2fs_xattr_remove(struct ext2_xattr_handle *handle,
139.1640 + const char *key)
139.1641 +{
139.1642 + struct ext2_xattr *x;
139.1643 + struct ext2_xattr *end = handle->attrs + handle->count;
139.1644 +
139.1645 + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
139.1646 + for (x = handle->attrs; x < end; x++) {
139.1647 + if (strcmp(x->name, key) == 0) {
139.1648 + ext2fs_free_mem(&x->name);
139.1649 + ext2fs_free_mem(&x->value);
139.1650 + if (x->ea_ino)
139.1651 + xattr_inode_dec_ref(handle->fs, x->ea_ino);
139.1652 + memmove(x, x + 1, (end - x - 1)*sizeof(*x));
139.1653 + memset(end - 1, 0, sizeof(*end));
139.1654 + if (x < handle->attrs + handle->ibody_count)
139.1655 + handle->ibody_count--;
139.1656 + handle->count--;
139.1657 + return ext2fs_xattrs_write(handle);
139.1658 + }
139.1659 + }
139.1660 +
139.1661 + /* no key found, success! */
139.1662 + return 0;
139.1663 +}
139.1664 +
139.1665 +errcode_t ext2fs_xattrs_open(ext2_filsys fs, ext2_ino_t ino,
139.1666 + struct ext2_xattr_handle **handle)
139.1667 +{
139.1668 + struct ext2_xattr_handle *h;
139.1669 + errcode_t err;
139.1670 +
139.1671 + if (!ext2fs_has_feature_xattr(fs->super) &&
139.1672 + !ext2fs_has_feature_inline_data(fs->super))
139.1673 + return EXT2_ET_MISSING_EA_FEATURE;
139.1674 +
139.1675 + err = ext2fs_get_memzero(sizeof(*h), &h);
139.1676 + if (err)
139.1677 + return err;
139.1678 +
139.1679 + h->magic = EXT2_ET_MAGIC_EA_HANDLE;
139.1680 + h->capacity = 4;
139.1681 + err = ext2fs_get_arrayzero(h->capacity, sizeof(struct ext2_xattr),
139.1682 + &h->attrs);
139.1683 + if (err) {
139.1684 + ext2fs_free_mem(&h);
139.1685 + return err;
139.1686 + }
139.1687 + h->count = 0;
139.1688 + h->ino = ino;
139.1689 + h->fs = fs;
139.1690 + *handle = h;
139.1691 + return 0;
139.1692 +}
139.1693 +
139.1694 +errcode_t ext2fs_xattrs_close(struct ext2_xattr_handle **handle)
139.1695 +{
139.1696 + struct ext2_xattr_handle *h = *handle;
139.1697 +
139.1698 + EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE);
139.1699 + xattrs_free_keys(h);
139.1700 + ext2fs_free_mem(&h->attrs);
139.1701 + ext2fs_free_mem(handle);
139.1702 + return 0;
139.1703 +}
139.1704 +
139.1705 +errcode_t ext2fs_xattrs_count(struct ext2_xattr_handle *handle, size_t *count)
139.1706 +{
139.1707 + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
139.1708 + *count = handle->count;
139.1709 + return 0;
139.1710 +}
139.1711 +
139.1712 +errcode_t ext2fs_xattrs_flags(struct ext2_xattr_handle *handle,
139.1713 + unsigned int *new_flags, unsigned int *old_flags)
139.1714 +{
139.1715 + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
139.1716 + if (old_flags)
139.1717 + *old_flags = handle->flags;
139.1718 + if (new_flags)
139.1719 + handle->flags = *new_flags;
139.1720 + return 0;
139.1721 +}
140.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
140.2 +++ b/libext2fs/lib/libext2fs/extent.c Wed Aug 25 01:28:08 2021 +0200
140.3 @@ -0,0 +1,1747 @@
140.4 +/*
140.5 + * extent.c --- routines to implement extents support
140.6 + *
140.7 + * Copyright (C) 2007 Theodore Ts'o.
140.8 + *
140.9 + * %Begin-Header%
140.10 + * This file may be redistributed under the terms of the GNU Library
140.11 + * General Public License, version 2.
140.12 + * %End-Header%
140.13 + */
140.14 +
140.15 +#include "config.h"
140.16 +#include <stdio.h>
140.17 +#include <string.h>
140.18 +#if HAVE_UNISTD_H
140.19 +#include <unistd.h>
140.20 +#endif
140.21 +#if HAVE_ERRNO_H
140.22 +#include <errno.h>
140.23 +#endif
140.24 +#if HAVE_SYS_STAT_H
140.25 +#include <sys/stat.h>
140.26 +#endif
140.27 +#if HAVE_SYS_TYPES_H
140.28 +#include <sys/types.h>
140.29 +#endif
140.30 +
140.31 +#include "ext2_fs.h"
140.32 +#include "ext2fsP.h"
140.33 +#include "e2image.h"
140.34 +
140.35 +#undef DEBUG
140.36 +
140.37 +/*
140.38 + * Definitions to be dropped in lib/ext2fs/ext2fs.h
140.39 + */
140.40 +
140.41 +/*
140.42 + * Private definitions
140.43 + */
140.44 +
140.45 +struct extent_path {
140.46 + char *buf;
140.47 + int entries;
140.48 + int max_entries;
140.49 + int left;
140.50 + int visit_num;
140.51 + int flags;
140.52 + blk64_t end_blk;
140.53 + void *curr;
140.54 +};
140.55 +
140.56 +
140.57 +struct ext2_extent_handle {
140.58 + errcode_t magic;
140.59 + ext2_filsys fs;
140.60 + ext2_ino_t ino;
140.61 + struct ext2_inode *inode;
140.62 + struct ext2_inode inodebuf;
140.63 + int type;
140.64 + int level;
140.65 + int max_depth;
140.66 + int max_paths;
140.67 + struct extent_path *path;
140.68 +};
140.69 +
140.70 +struct ext2_extent_path {
140.71 + errcode_t magic;
140.72 + int leaf_height;
140.73 + blk64_t lblk;
140.74 +};
140.75 +
140.76 +/*
140.77 + * Useful Debugging stuff
140.78 + */
140.79 +
140.80 +#ifdef DEBUG
140.81 +static void dbg_show_header(struct ext3_extent_header *eh)
140.82 +{
140.83 + printf("header: magic=%x entries=%u max=%u depth=%u generation=%u\n",
140.84 + ext2fs_le16_to_cpu(eh->eh_magic),
140.85 + ext2fs_le16_to_cpu(eh->eh_entries),
140.86 + ext2fs_le16_to_cpu(eh->eh_max),
140.87 + ext2fs_le16_to_cpu(eh->eh_depth),
140.88 + ext2fs_le32_to_cpu(eh->eh_generation));
140.89 +}
140.90 +
140.91 +static void dbg_show_index(struct ext3_extent_idx *ix)
140.92 +{
140.93 + printf("index: block=%u leaf=%u leaf_hi=%u unused=%u\n",
140.94 + ext2fs_le32_to_cpu(ix->ei_block),
140.95 + ext2fs_le32_to_cpu(ix->ei_leaf),
140.96 + ext2fs_le16_to_cpu(ix->ei_leaf_hi),
140.97 + ext2fs_le16_to_cpu(ix->ei_unused));
140.98 +}
140.99 +
140.100 +static void dbg_show_extent(struct ext3_extent *ex)
140.101 +{
140.102 + printf("extent: block=%u-%u len=%u start=%u start_hi=%u\n",
140.103 + ext2fs_le32_to_cpu(ex->ee_block),
140.104 + ext2fs_le32_to_cpu(ex->ee_block) +
140.105 + ext2fs_le16_to_cpu(ex->ee_len) - 1,
140.106 + ext2fs_le16_to_cpu(ex->ee_len),
140.107 + ext2fs_le32_to_cpu(ex->ee_start),
140.108 + ext2fs_le16_to_cpu(ex->ee_start_hi));
140.109 +}
140.110 +
140.111 +static void dbg_print_extent(char *desc, struct ext2fs_extent *extent)
140.112 +{
140.113 + if (desc)
140.114 + printf("%s: ", desc);
140.115 + printf("extent: lblk %llu--%llu, len %u, pblk %llu, flags: ",
140.116 + extent->e_lblk, extent->e_lblk + extent->e_len - 1,
140.117 + extent->e_len, extent->e_pblk);
140.118 + if (extent->e_flags & EXT2_EXTENT_FLAGS_LEAF)
140.119 + fputs("LEAF ", stdout);
140.120 + if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
140.121 + fputs("UNINIT ", stdout);
140.122 + if (extent->e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)
140.123 + fputs("2ND_VISIT ", stdout);
140.124 + if (!extent->e_flags)
140.125 + fputs("(none)", stdout);
140.126 + fputc('\n', stdout);
140.127 +
140.128 +}
140.129 +
140.130 +static void dump_path(const char *tag, struct ext2_extent_handle *handle,
140.131 + struct extent_path *path)
140.132 +{
140.133 + struct extent_path *ppp = path;
140.134 + printf("%s: level=%d\n", tag, handle->level);
140.135 +
140.136 + do {
140.137 + printf("%s: path=%ld buf=%p entries=%d max_entries=%d left=%d "
140.138 + "visit_num=%d flags=0x%x end_blk=%llu curr=%p(%ld)\n",
140.139 + tag, (ppp - handle->path), ppp->buf, ppp->entries,
140.140 + ppp->max_entries, ppp->left, ppp->visit_num, ppp->flags,
140.141 + ppp->end_blk, ppp->curr, ppp->curr - (void *)ppp->buf);
140.142 + printf(" ");
140.143 + dbg_show_header((struct ext3_extent_header *)ppp->buf);
140.144 + if (ppp->curr) {
140.145 + printf(" ");
140.146 + dbg_show_index(ppp->curr);
140.147 + printf(" ");
140.148 + dbg_show_extent(ppp->curr);
140.149 + }
140.150 + ppp--;
140.151 + } while (ppp >= handle->path);
140.152 + fflush(stdout);
140.153 +
140.154 + return;
140.155 +}
140.156 +
140.157 +#else
140.158 +#define dbg_show_header(eh) do { } while (0)
140.159 +#define dbg_show_index(ix) do { } while (0)
140.160 +#define dbg_show_extent(ex) do { } while (0)
140.161 +#define dbg_print_extent(desc, ex) do { } while (0)
140.162 +#define dump_path(tag, handle, path) do { } while (0)
140.163 +#endif
140.164 +
140.165 +/*
140.166 + * Verify the extent header as being sane
140.167 + */
140.168 +errcode_t ext2fs_extent_header_verify(void *ptr, int size)
140.169 +{
140.170 + int eh_max, entry_size;
140.171 + struct ext3_extent_header *eh = ptr;
140.172 +
140.173 + dbg_show_header(eh);
140.174 + if (ext2fs_le16_to_cpu(eh->eh_magic) != EXT3_EXT_MAGIC)
140.175 + return EXT2_ET_EXTENT_HEADER_BAD;
140.176 + if (ext2fs_le16_to_cpu(eh->eh_entries) > ext2fs_le16_to_cpu(eh->eh_max))
140.177 + return EXT2_ET_EXTENT_HEADER_BAD;
140.178 + if (eh->eh_depth == 0)
140.179 + entry_size = sizeof(struct ext3_extent);
140.180 + else
140.181 + entry_size = sizeof(struct ext3_extent_idx);
140.182 +
140.183 + eh_max = (size - sizeof(*eh)) / entry_size;
140.184 + /* Allow two extent-sized items at the end of the block, for
140.185 + * ext4_extent_tail with checksum in the future. */
140.186 + if ((ext2fs_le16_to_cpu(eh->eh_max) > eh_max) ||
140.187 + (ext2fs_le16_to_cpu(eh->eh_max) < (eh_max - 2)))
140.188 + return EXT2_ET_EXTENT_HEADER_BAD;
140.189 +
140.190 + return 0;
140.191 +}
140.192 +
140.193 +
140.194 +/*
140.195 + * Begin functions to handle an inode's extent information
140.196 + */
140.197 +void ext2fs_extent_free(ext2_extent_handle_t handle)
140.198 +{
140.199 + int i;
140.200 +
140.201 + if (!handle)
140.202 + return;
140.203 +
140.204 + if (handle->path) {
140.205 + for (i = 1; i < handle->max_paths; i++) {
140.206 + if (handle->path[i].buf)
140.207 + ext2fs_free_mem(&handle->path[i].buf);
140.208 + }
140.209 + ext2fs_free_mem(&handle->path);
140.210 + }
140.211 + ext2fs_free_mem(&handle);
140.212 +}
140.213 +
140.214 +errcode_t ext2fs_extent_open(ext2_filsys fs, ext2_ino_t ino,
140.215 + ext2_extent_handle_t *ret_handle)
140.216 +{
140.217 + return ext2fs_extent_open2(fs, ino, NULL, ret_handle);
140.218 +}
140.219 +
140.220 +errcode_t ext2fs_extent_open2(ext2_filsys fs, ext2_ino_t ino,
140.221 + struct ext2_inode *inode,
140.222 + ext2_extent_handle_t *ret_handle)
140.223 +{
140.224 + struct ext2_extent_handle *handle;
140.225 + errcode_t retval;
140.226 + int i;
140.227 + struct ext3_extent_header *eh;
140.228 +
140.229 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
140.230 +
140.231 + if (!inode)
140.232 + if ((ino == 0) || (ino > fs->super->s_inodes_count))
140.233 + return EXT2_ET_BAD_INODE_NUM;
140.234 +
140.235 + retval = ext2fs_get_mem(sizeof(struct ext2_extent_handle), &handle);
140.236 + if (retval)
140.237 + return retval;
140.238 + memset(handle, 0, sizeof(struct ext2_extent_handle));
140.239 +
140.240 + handle->ino = ino;
140.241 + handle->fs = fs;
140.242 +
140.243 + if (inode) {
140.244 + handle->inode = inode;
140.245 + } else {
140.246 + handle->inode = &handle->inodebuf;
140.247 + retval = ext2fs_read_inode(fs, ino, handle->inode);
140.248 + if (retval)
140.249 + goto errout;
140.250 + }
140.251 +
140.252 + eh = (struct ext3_extent_header *) &handle->inode->i_block[0];
140.253 +
140.254 + for (i=0; i < EXT2_N_BLOCKS; i++)
140.255 + if (handle->inode->i_block[i])
140.256 + break;
140.257 + if (i >= EXT2_N_BLOCKS) {
140.258 + eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC);
140.259 + eh->eh_depth = 0;
140.260 + eh->eh_entries = 0;
140.261 + i = (sizeof(handle->inode->i_block) - sizeof(*eh)) /
140.262 + sizeof(struct ext3_extent);
140.263 + eh->eh_max = ext2fs_cpu_to_le16(i);
140.264 + handle->inode->i_flags |= EXT4_EXTENTS_FL;
140.265 + }
140.266 +
140.267 + if (!(handle->inode->i_flags & EXT4_EXTENTS_FL)) {
140.268 + retval = EXT2_ET_INODE_NOT_EXTENT;
140.269 + goto errout;
140.270 + }
140.271 +
140.272 + retval = ext2fs_extent_header_verify(eh, sizeof(handle->inode->i_block));
140.273 + if (retval)
140.274 + goto errout;
140.275 +
140.276 + handle->max_depth = ext2fs_le16_to_cpu(eh->eh_depth);
140.277 + handle->type = ext2fs_le16_to_cpu(eh->eh_magic);
140.278 +
140.279 + handle->max_paths = handle->max_depth + 1;
140.280 + retval = ext2fs_get_memzero(handle->max_paths *
140.281 + sizeof(struct extent_path),
140.282 + &handle->path);
140.283 + handle->path[0].buf = (char *) handle->inode->i_block;
140.284 +
140.285 + handle->path[0].left = handle->path[0].entries =
140.286 + ext2fs_le16_to_cpu(eh->eh_entries);
140.287 + handle->path[0].max_entries = ext2fs_le16_to_cpu(eh->eh_max);
140.288 + handle->path[0].curr = 0;
140.289 + handle->path[0].end_blk =
140.290 + (EXT2_I_SIZE(handle->inode) + fs->blocksize - 1) >>
140.291 + EXT2_BLOCK_SIZE_BITS(fs->super);
140.292 + handle->path[0].visit_num = 1;
140.293 + handle->level = 0;
140.294 + handle->magic = EXT2_ET_MAGIC_EXTENT_HANDLE;
140.295 +
140.296 + *ret_handle = handle;
140.297 + return 0;
140.298 +
140.299 +errout:
140.300 + ext2fs_extent_free(handle);
140.301 + return retval;
140.302 +}
140.303 +
140.304 +/*
140.305 + * This function is responsible for (optionally) moving through the
140.306 + * extent tree and then returning the current extent
140.307 + */
140.308 +errcode_t ext2fs_extent_get(ext2_extent_handle_t handle,
140.309 + int flags, struct ext2fs_extent *extent)
140.310 +{
140.311 + struct extent_path *path, *newpath;
140.312 + struct ext3_extent_header *eh;
140.313 + struct ext3_extent_idx *ix = 0;
140.314 + struct ext3_extent *ex;
140.315 + errcode_t retval;
140.316 + blk64_t blk;
140.317 + blk64_t end_blk;
140.318 + int orig_op, op;
140.319 + int failed_csum = 0;
140.320 +
140.321 + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
140.322 +
140.323 + if (!handle->path)
140.324 + return EXT2_ET_NO_CURRENT_NODE;
140.325 +
140.326 + orig_op = op = flags & EXT2_EXTENT_MOVE_MASK;
140.327 +
140.328 +retry:
140.329 + path = handle->path + handle->level;
140.330 + if ((orig_op == EXT2_EXTENT_NEXT) ||
140.331 + (orig_op == EXT2_EXTENT_NEXT_LEAF)) {
140.332 + if (handle->level < handle->max_depth) {
140.333 + /* interior node */
140.334 + if (path->visit_num == 0) {
140.335 + path->visit_num++;
140.336 + op = EXT2_EXTENT_DOWN;
140.337 + } else if (path->left > 0)
140.338 + op = EXT2_EXTENT_NEXT_SIB;
140.339 + else if (handle->level > 0)
140.340 + op = EXT2_EXTENT_UP;
140.341 + else
140.342 + return EXT2_ET_EXTENT_NO_NEXT;
140.343 + } else {
140.344 + /* leaf node */
140.345 + if (path->left > 0)
140.346 + op = EXT2_EXTENT_NEXT_SIB;
140.347 + else if (handle->level > 0)
140.348 + op = EXT2_EXTENT_UP;
140.349 + else
140.350 + return EXT2_ET_EXTENT_NO_NEXT;
140.351 + }
140.352 + if (op != EXT2_EXTENT_NEXT_SIB) {
140.353 +#ifdef DEBUG_GET_EXTENT
140.354 + printf("<<<< OP = %s\n",
140.355 + (op == EXT2_EXTENT_DOWN) ? "down" :
140.356 + ((op == EXT2_EXTENT_UP) ? "up" : "unknown"));
140.357 +#endif
140.358 + }
140.359 + }
140.360 +
140.361 + if ((orig_op == EXT2_EXTENT_PREV) ||
140.362 + (orig_op == EXT2_EXTENT_PREV_LEAF)) {
140.363 + if (handle->level < handle->max_depth) {
140.364 + /* interior node */
140.365 + if (path->visit_num > 0 ) {
140.366 + /* path->visit_num = 0; */
140.367 + op = EXT2_EXTENT_DOWN_AND_LAST;
140.368 + } else if (path->left < path->entries-1)
140.369 + op = EXT2_EXTENT_PREV_SIB;
140.370 + else if (handle->level > 0)
140.371 + op = EXT2_EXTENT_UP;
140.372 + else
140.373 + return EXT2_ET_EXTENT_NO_PREV;
140.374 + } else {
140.375 + /* leaf node */
140.376 + if (path->left < path->entries-1)
140.377 + op = EXT2_EXTENT_PREV_SIB;
140.378 + else if (handle->level > 0)
140.379 + op = EXT2_EXTENT_UP;
140.380 + else
140.381 + return EXT2_ET_EXTENT_NO_PREV;
140.382 + }
140.383 + if (op != EXT2_EXTENT_PREV_SIB) {
140.384 +#ifdef DEBUG_GET_EXTENT
140.385 + printf("<<<< OP = %s\n",
140.386 + (op == EXT2_EXTENT_DOWN_AND_LAST) ? "down/last" :
140.387 + ((op == EXT2_EXTENT_UP) ? "up" : "unknown"));
140.388 +#endif
140.389 + }
140.390 + }
140.391 +
140.392 + if (orig_op == EXT2_EXTENT_LAST_LEAF) {
140.393 + if ((handle->level < handle->max_depth) &&
140.394 + (path->left == 0))
140.395 + op = EXT2_EXTENT_DOWN;
140.396 + else
140.397 + op = EXT2_EXTENT_LAST_SIB;
140.398 +#ifdef DEBUG_GET_EXTENT
140.399 + printf("<<<< OP = %s\n",
140.400 + (op == EXT2_EXTENT_DOWN) ? "down" : "last_sib");
140.401 +#endif
140.402 + }
140.403 +
140.404 + switch (op) {
140.405 + case EXT2_EXTENT_CURRENT:
140.406 + ix = path->curr;
140.407 + break;
140.408 + case EXT2_EXTENT_ROOT:
140.409 + handle->level = 0;
140.410 + path = handle->path + handle->level;
140.411 + /* fallthrough */
140.412 + case EXT2_EXTENT_FIRST_SIB:
140.413 + path->left = path->entries;
140.414 + path->curr = 0;
140.415 + /* fallthrough */
140.416 + case EXT2_EXTENT_NEXT_SIB:
140.417 + if (path->left <= 0)
140.418 + return EXT2_ET_EXTENT_NO_NEXT;
140.419 + if (path->curr) {
140.420 + ix = path->curr;
140.421 + ix++;
140.422 + } else {
140.423 + eh = (struct ext3_extent_header *) path->buf;
140.424 + ix = EXT_FIRST_INDEX(eh);
140.425 + }
140.426 + path->left--;
140.427 + path->curr = ix;
140.428 + path->visit_num = 0;
140.429 + break;
140.430 + case EXT2_EXTENT_PREV_SIB:
140.431 + if (!path->curr ||
140.432 + path->left+1 >= path->entries)
140.433 + return EXT2_ET_EXTENT_NO_PREV;
140.434 + ix = path->curr;
140.435 + ix--;
140.436 + path->curr = ix;
140.437 + path->left++;
140.438 + if (handle->level < handle->max_depth)
140.439 + path->visit_num = 1;
140.440 + break;
140.441 + case EXT2_EXTENT_LAST_SIB:
140.442 + eh = (struct ext3_extent_header *) path->buf;
140.443 + path->curr = EXT_LAST_EXTENT(eh);
140.444 + ix = path->curr;
140.445 + path->left = 0;
140.446 + path->visit_num = 0;
140.447 + break;
140.448 + case EXT2_EXTENT_UP:
140.449 + if (handle->level <= 0)
140.450 + return EXT2_ET_EXTENT_NO_UP;
140.451 + handle->level--;
140.452 + path--;
140.453 + ix = path->curr;
140.454 + if ((orig_op == EXT2_EXTENT_PREV) ||
140.455 + (orig_op == EXT2_EXTENT_PREV_LEAF))
140.456 + path->visit_num = 0;
140.457 + break;
140.458 + case EXT2_EXTENT_DOWN:
140.459 + case EXT2_EXTENT_DOWN_AND_LAST:
140.460 + if (!path->curr ||(handle->level >= handle->max_depth))
140.461 + return EXT2_ET_EXTENT_NO_DOWN;
140.462 +
140.463 + ix = path->curr;
140.464 + newpath = path + 1;
140.465 + if (!newpath->buf) {
140.466 + retval = ext2fs_get_mem(handle->fs->blocksize,
140.467 + &newpath->buf);
140.468 + if (retval)
140.469 + return retval;
140.470 + }
140.471 + blk = ext2fs_le32_to_cpu(ix->ei_leaf) +
140.472 + ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32);
140.473 + if ((handle->fs->flags & EXT2_FLAG_IMAGE_FILE) &&
140.474 + (handle->fs->io != handle->fs->image_io))
140.475 + memset(newpath->buf, 0, handle->fs->blocksize);
140.476 + else {
140.477 + retval = io_channel_read_blk64(handle->fs->io,
140.478 + blk, 1, newpath->buf);
140.479 + if (retval)
140.480 + return retval;
140.481 + }
140.482 + handle->level++;
140.483 +
140.484 + eh = (struct ext3_extent_header *) newpath->buf;
140.485 +
140.486 + retval = ext2fs_extent_header_verify(eh, handle->fs->blocksize);
140.487 + if (retval) {
140.488 + handle->level--;
140.489 + return retval;
140.490 + }
140.491 +
140.492 + if (!(handle->fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
140.493 + !ext2fs_extent_block_csum_verify(handle->fs, handle->ino,
140.494 + eh))
140.495 + failed_csum = 1;
140.496 +
140.497 + newpath->left = newpath->entries =
140.498 + ext2fs_le16_to_cpu(eh->eh_entries);
140.499 + newpath->max_entries = ext2fs_le16_to_cpu(eh->eh_max);
140.500 +
140.501 + if (path->left > 0) {
140.502 + ix++;
140.503 + newpath->end_blk = ext2fs_le32_to_cpu(ix->ei_block);
140.504 + } else
140.505 + newpath->end_blk = path->end_blk;
140.506 +
140.507 + path = newpath;
140.508 + if (op == EXT2_EXTENT_DOWN) {
140.509 + ix = EXT_FIRST_INDEX((struct ext3_extent_header *) eh);
140.510 + path->curr = ix;
140.511 + path->left = path->entries - 1;
140.512 + path->visit_num = 0;
140.513 + } else {
140.514 + ix = EXT_LAST_INDEX((struct ext3_extent_header *) eh);
140.515 + path->curr = ix;
140.516 + path->left = 0;
140.517 + if (handle->level < handle->max_depth)
140.518 + path->visit_num = 1;
140.519 + }
140.520 +#ifdef DEBUG_GET_EXTENT
140.521 + printf("Down to level %d/%d, end_blk=%llu\n",
140.522 + handle->level, handle->max_depth,
140.523 + path->end_blk);
140.524 +#endif
140.525 + break;
140.526 + default:
140.527 + return EXT2_ET_OP_NOT_SUPPORTED;
140.528 + }
140.529 +
140.530 + if (!ix)
140.531 + return EXT2_ET_NO_CURRENT_NODE;
140.532 +
140.533 + extent->e_flags = 0;
140.534 +#ifdef DEBUG_GET_EXTENT
140.535 + printf("(Left %d)\n", path->left);
140.536 +#endif
140.537 +
140.538 + if (handle->level == handle->max_depth) {
140.539 + ex = (struct ext3_extent *) ix;
140.540 +
140.541 + extent->e_pblk = ext2fs_le32_to_cpu(ex->ee_start) +
140.542 + ((__u64) ext2fs_le16_to_cpu(ex->ee_start_hi) << 32);
140.543 + extent->e_lblk = ext2fs_le32_to_cpu(ex->ee_block);
140.544 + extent->e_len = ext2fs_le16_to_cpu(ex->ee_len);
140.545 + extent->e_flags |= EXT2_EXTENT_FLAGS_LEAF;
140.546 + if (extent->e_len > EXT_INIT_MAX_LEN) {
140.547 + extent->e_len -= EXT_INIT_MAX_LEN;
140.548 + extent->e_flags |= EXT2_EXTENT_FLAGS_UNINIT;
140.549 + }
140.550 + } else {
140.551 + extent->e_pblk = ext2fs_le32_to_cpu(ix->ei_leaf) +
140.552 + ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32);
140.553 + extent->e_lblk = ext2fs_le32_to_cpu(ix->ei_block);
140.554 + if (path->left > 0) {
140.555 + ix++;
140.556 + end_blk = ext2fs_le32_to_cpu(ix->ei_block);
140.557 + } else
140.558 + end_blk = path->end_blk;
140.559 +
140.560 + extent->e_len = end_blk - extent->e_lblk;
140.561 + }
140.562 + if (path->visit_num)
140.563 + extent->e_flags |= EXT2_EXTENT_FLAGS_SECOND_VISIT;
140.564 +
140.565 + if (((orig_op == EXT2_EXTENT_NEXT_LEAF) ||
140.566 + (orig_op == EXT2_EXTENT_PREV_LEAF)) &&
140.567 + (handle->level != handle->max_depth))
140.568 + goto retry;
140.569 +
140.570 + if ((orig_op == EXT2_EXTENT_LAST_LEAF) &&
140.571 + ((handle->level != handle->max_depth) ||
140.572 + (path->left != 0)))
140.573 + goto retry;
140.574 +
140.575 + if (failed_csum)
140.576 + return EXT2_ET_EXTENT_CSUM_INVALID;
140.577 +
140.578 + return 0;
140.579 +}
140.580 +
140.581 +static errcode_t update_path(ext2_extent_handle_t handle)
140.582 +{
140.583 + blk64_t blk;
140.584 + errcode_t retval;
140.585 + struct ext3_extent_idx *ix;
140.586 + struct ext3_extent_header *eh;
140.587 +
140.588 + if (handle->level == 0) {
140.589 + retval = ext2fs_write_inode(handle->fs, handle->ino,
140.590 + handle->inode);
140.591 + } else {
140.592 + ix = handle->path[handle->level - 1].curr;
140.593 + blk = ext2fs_le32_to_cpu(ix->ei_leaf) +
140.594 + ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32);
140.595 +
140.596 + /* then update the checksum */
140.597 + eh = (struct ext3_extent_header *)
140.598 + handle->path[handle->level].buf;
140.599 + retval = ext2fs_extent_block_csum_set(handle->fs, handle->ino,
140.600 + eh);
140.601 + if (retval)
140.602 + return retval;
140.603 +
140.604 + retval = io_channel_write_blk64(handle->fs->io,
140.605 + blk, 1, handle->path[handle->level].buf);
140.606 + }
140.607 + return retval;
140.608 +}
140.609 +
140.610 +#if 0
140.611 +errcode_t ext2fs_extent_save_path(ext2_extent_handle_t handle,
140.612 + ext2_extent_path_t *ret_path)
140.613 +{
140.614 + ext2_extent_path_t save_path;
140.615 + struct ext2fs_extent extent;
140.616 + struct ext2_extent_info info;
140.617 + errcode_t retval;
140.618 +
140.619 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
140.620 + if (retval)
140.621 + return retval;
140.622 +
140.623 + retval = ext2fs_extent_get_info(handle, &info);
140.624 + if (retval)
140.625 + return retval;
140.626 +
140.627 + retval = ext2fs_get_mem(sizeof(struct ext2_extent_path), &save_path);
140.628 + if (retval)
140.629 + return retval;
140.630 + memset(save_path, 0, sizeof(struct ext2_extent_path));
140.631 +
140.632 + save_path->magic = EXT2_ET_MAGIC_EXTENT_PATH;
140.633 + save_path->leaf_height = info.max_depth - info.curr_level - 1;
140.634 + save_path->lblk = extent.e_lblk;
140.635 +
140.636 + *ret_path = save_path;
140.637 + return 0;
140.638 +}
140.639 +
140.640 +errcode_t ext2fs_extent_free_path(ext2_extent_path_t path)
140.641 +{
140.642 + EXT2_CHECK_MAGIC(path, EXT2_ET_MAGIC_EXTENT_PATH);
140.643 +
140.644 + ext2fs_free_mem(&path);
140.645 + return 0;
140.646 +}
140.647 +#endif
140.648 +
140.649 +/*
140.650 + * Go to the node at leaf_level which contains logical block blk.
140.651 + *
140.652 + * leaf_level is height from the leaf node level, i.e.
140.653 + * leaf_level 0 is at leaf node, leaf_level 1 is 1 above etc.
140.654 + *
140.655 + * If "blk" has no mapping (hole) then handle is left at last
140.656 + * extent before blk.
140.657 + */
140.658 +errcode_t ext2fs_extent_goto2(ext2_extent_handle_t handle,
140.659 + int leaf_level, blk64_t blk)
140.660 +{
140.661 + struct ext2fs_extent extent;
140.662 + errcode_t retval;
140.663 +
140.664 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent);
140.665 + if (retval) {
140.666 + if (retval == EXT2_ET_EXTENT_NO_NEXT)
140.667 + retval = EXT2_ET_EXTENT_NOT_FOUND;
140.668 + return retval;
140.669 + }
140.670 +
140.671 + if (leaf_level > handle->max_depth) {
140.672 +#ifdef DEBUG
140.673 + printf("leaf level %d greater than tree depth %d\n",
140.674 + leaf_level, handle->max_depth);
140.675 +#endif
140.676 + return EXT2_ET_OP_NOT_SUPPORTED;
140.677 + }
140.678 +
140.679 +#ifdef DEBUG
140.680 + printf("goto extent ino %u, level %d, %llu\n", handle->ino,
140.681 + leaf_level, blk);
140.682 +#endif
140.683 +
140.684 +#ifdef DEBUG_GOTO_EXTENTS
140.685 + dbg_print_extent("root", &extent);
140.686 +#endif
140.687 + while (1) {
140.688 + if (handle->max_depth - handle->level == leaf_level) {
140.689 + /* block is in this &extent */
140.690 + if ((blk >= extent.e_lblk) &&
140.691 + (blk < extent.e_lblk + extent.e_len))
140.692 + return 0;
140.693 + if (blk < extent.e_lblk) {
140.694 + retval = ext2fs_extent_get(handle,
140.695 + EXT2_EXTENT_PREV_SIB,
140.696 + &extent);
140.697 + return EXT2_ET_EXTENT_NOT_FOUND;
140.698 + }
140.699 + retval = ext2fs_extent_get(handle,
140.700 + EXT2_EXTENT_NEXT_SIB,
140.701 + &extent);
140.702 + if (retval == EXT2_ET_EXTENT_NO_NEXT)
140.703 + return EXT2_ET_EXTENT_NOT_FOUND;
140.704 + if (retval)
140.705 + return retval;
140.706 + continue;
140.707 + }
140.708 +
140.709 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_SIB,
140.710 + &extent);
140.711 + if (retval == EXT2_ET_EXTENT_NO_NEXT)
140.712 + goto go_down;
140.713 + if (retval)
140.714 + return retval;
140.715 +
140.716 +#ifdef DEBUG_GOTO_EXTENTS
140.717 + dbg_print_extent("next", &extent);
140.718 +#endif
140.719 + if (blk == extent.e_lblk)
140.720 + goto go_down;
140.721 + if (blk > extent.e_lblk)
140.722 + continue;
140.723 +
140.724 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_PREV_SIB,
140.725 + &extent);
140.726 + if (retval)
140.727 + return retval;
140.728 +
140.729 +#ifdef DEBUG_GOTO_EXTENTS
140.730 + dbg_print_extent("prev", &extent);
140.731 +#endif
140.732 +
140.733 + go_down:
140.734 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_DOWN,
140.735 + &extent);
140.736 + if (retval)
140.737 + return retval;
140.738 +
140.739 +#ifdef DEBUG_GOTO_EXTENTS
140.740 + dbg_print_extent("down", &extent);
140.741 +#endif
140.742 + }
140.743 +}
140.744 +
140.745 +errcode_t ext2fs_extent_goto(ext2_extent_handle_t handle,
140.746 + blk64_t blk)
140.747 +{
140.748 + return ext2fs_extent_goto2(handle, 0, blk);
140.749 +}
140.750 +
140.751 +/*
140.752 + * Traverse back up to root fixing parents of current node as needed.
140.753 + *
140.754 + * If we changed start of first entry in a node, fix parent index start
140.755 + * and so on.
140.756 + *
140.757 + * Safe to call for any position in node; if not at the first entry,
140.758 + * it will simply return.
140.759 + *
140.760 + * Note a subtlety of this function -- if there happen to be two extents
140.761 + * mapping the same lblk and someone calls fix_parents on the second of the two
140.762 + * extents, the position of the extent handle after the call will be the second
140.763 + * extent if nothing happened, or the first extent if something did. A caller
140.764 + * in this situation must use ext2fs_extent_goto() after calling this function.
140.765 + * Or simply don't map the same lblk with two extents, ever.
140.766 + */
140.767 +errcode_t ext2fs_extent_fix_parents(ext2_extent_handle_t handle)
140.768 +{
140.769 + int retval = 0;
140.770 + int orig_height;
140.771 + blk64_t start;
140.772 + struct extent_path *path;
140.773 + struct ext2fs_extent extent;
140.774 + struct ext2_extent_info info;
140.775 +
140.776 + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
140.777 +
140.778 + if (!(handle->fs->flags & EXT2_FLAG_RW))
140.779 + return EXT2_ET_RO_FILSYS;
140.780 +
140.781 + if (!handle->path)
140.782 + return EXT2_ET_NO_CURRENT_NODE;
140.783 +
140.784 + path = handle->path + handle->level;
140.785 + if (!path->curr)
140.786 + return EXT2_ET_NO_CURRENT_NODE;
140.787 +
140.788 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
140.789 + if (retval)
140.790 + goto done;
140.791 +
140.792 + /* modified node's start block */
140.793 + start = extent.e_lblk;
140.794 +
140.795 + if ((retval = ext2fs_extent_get_info(handle, &info)))
140.796 + return retval;
140.797 + orig_height = info.max_depth - info.curr_level;
140.798 +
140.799 + /* traverse up until index not first, or startblk matches, or top */
140.800 + while (handle->level > 0 &&
140.801 + (path->left == path->entries - 1)) {
140.802 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent);
140.803 + if (retval)
140.804 + goto done;
140.805 + if (extent.e_lblk == start)
140.806 + break;
140.807 + path = handle->path + handle->level;
140.808 + extent.e_len += (extent.e_lblk - start);
140.809 + extent.e_lblk = start;
140.810 + retval = ext2fs_extent_replace(handle, 0, &extent);
140.811 + if (retval)
140.812 + goto done;
140.813 + update_path(handle);
140.814 + }
140.815 +
140.816 + /* put handle back to where we started */
140.817 + retval = ext2fs_extent_goto2(handle, orig_height, start);
140.818 +done:
140.819 + return retval;
140.820 +}
140.821 +
140.822 +errcode_t ext2fs_extent_replace(ext2_extent_handle_t handle,
140.823 + int flags EXT2FS_ATTR((unused)),
140.824 + struct ext2fs_extent *extent)
140.825 +{
140.826 + struct extent_path *path;
140.827 + struct ext3_extent_idx *ix;
140.828 + struct ext3_extent *ex;
140.829 +
140.830 + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
140.831 +
140.832 + if (!(handle->fs->flags & EXT2_FLAG_RW))
140.833 + return EXT2_ET_RO_FILSYS;
140.834 +
140.835 + if (!handle->path)
140.836 + return EXT2_ET_NO_CURRENT_NODE;
140.837 +
140.838 + path = handle->path + handle->level;
140.839 + if (!path->curr)
140.840 + return EXT2_ET_NO_CURRENT_NODE;
140.841 +
140.842 +#ifdef DEBUG
140.843 + printf("extent replace: %u ", handle->ino);
140.844 + dbg_print_extent(0, extent);
140.845 +#endif
140.846 +
140.847 + if (handle->level == handle->max_depth) {
140.848 + ex = path->curr;
140.849 +
140.850 + ex->ee_block = ext2fs_cpu_to_le32(extent->e_lblk);
140.851 + ex->ee_start = ext2fs_cpu_to_le32(extent->e_pblk & 0xFFFFFFFF);
140.852 + ex->ee_start_hi = ext2fs_cpu_to_le16(extent->e_pblk >> 32);
140.853 + if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT) {
140.854 + if (extent->e_len > EXT_UNINIT_MAX_LEN)
140.855 + return EXT2_ET_EXTENT_INVALID_LENGTH;
140.856 + ex->ee_len = ext2fs_cpu_to_le16(extent->e_len +
140.857 + EXT_INIT_MAX_LEN);
140.858 + } else {
140.859 + if (extent->e_len > EXT_INIT_MAX_LEN)
140.860 + return EXT2_ET_EXTENT_INVALID_LENGTH;
140.861 + ex->ee_len = ext2fs_cpu_to_le16(extent->e_len);
140.862 + }
140.863 + } else {
140.864 + ix = path->curr;
140.865 +
140.866 + ix->ei_leaf = ext2fs_cpu_to_le32(extent->e_pblk & 0xFFFFFFFF);
140.867 + ix->ei_leaf_hi = ext2fs_cpu_to_le16(extent->e_pblk >> 32);
140.868 + ix->ei_block = ext2fs_cpu_to_le32(extent->e_lblk);
140.869 + ix->ei_unused = 0;
140.870 + }
140.871 + update_path(handle);
140.872 + return 0;
140.873 +}
140.874 +
140.875 +static int splitting_at_eof(struct ext2_extent_handle *handle,
140.876 + struct extent_path *path)
140.877 +{
140.878 + struct extent_path *ppp = path;
140.879 + dump_path(__func__, handle, path);
140.880 +
140.881 + if (handle->level == 0)
140.882 + return 0;
140.883 +
140.884 + do {
140.885 + if (ppp->left)
140.886 + return 0;
140.887 + ppp--;
140.888 + } while (ppp >= handle->path);
140.889 +
140.890 + return 1;
140.891 +}
140.892 +
140.893 +/*
140.894 + * allocate a new block, move half the current node to it, and update parent
140.895 + *
140.896 + * handle will be left pointing at original record.
140.897 + */
140.898 +static errcode_t extent_node_split(ext2_extent_handle_t handle,
140.899 + int expand_allowed)
140.900 +{
140.901 + errcode_t retval = 0;
140.902 + blk64_t new_node_pblk;
140.903 + blk64_t new_node_start;
140.904 + blk64_t orig_lblk;
140.905 + blk64_t goal_blk = 0;
140.906 + int orig_height;
140.907 + char *block_buf = NULL;
140.908 + struct ext2fs_extent extent;
140.909 + struct extent_path *path, *newpath = 0;
140.910 + struct ext3_extent_header *eh, *neweh;
140.911 + int tocopy;
140.912 + int new_root = 0;
140.913 + struct ext2_extent_info info;
140.914 + int no_balance;
140.915 +
140.916 + /* basic sanity */
140.917 + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
140.918 +
140.919 + if (!(handle->fs->flags & EXT2_FLAG_RW))
140.920 + return EXT2_ET_RO_FILSYS;
140.921 +
140.922 + if (!handle->path)
140.923 + return EXT2_ET_NO_CURRENT_NODE;
140.924 +
140.925 +#ifdef DEBUG
140.926 + printf("splitting node at level %d\n", handle->level);
140.927 +#endif
140.928 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
140.929 + if (retval)
140.930 + goto done;
140.931 +
140.932 + retval = ext2fs_extent_get_info(handle, &info);
140.933 + if (retval)
140.934 + goto done;
140.935 +
140.936 + /* save the position we were originally splitting... */
140.937 + orig_height = info.max_depth - info.curr_level;
140.938 + orig_lblk = extent.e_lblk;
140.939 +
140.940 + /* Try to put the index block before the first extent */
140.941 + path = handle->path + handle->level;
140.942 + eh = (struct ext3_extent_header *) path->buf;
140.943 + if (handle->level == handle->max_depth) {
140.944 + struct ext3_extent *ex;
140.945 +
140.946 + ex = EXT_FIRST_EXTENT(eh);
140.947 + goal_blk = ext2fs_le32_to_cpu(ex->ee_start) +
140.948 + ((__u64) ext2fs_le16_to_cpu(ex->ee_start_hi) << 32);
140.949 + } else {
140.950 + struct ext3_extent_idx *ix;
140.951 +
140.952 + ix = EXT_FIRST_INDEX(eh);
140.953 + goal_blk = ext2fs_le32_to_cpu(ix->ei_leaf) +
140.954 + ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32);
140.955 + }
140.956 + goal_blk -= EXT2FS_CLUSTER_RATIO(handle->fs);
140.957 + goal_blk &= ~EXT2FS_CLUSTER_MASK(handle->fs);
140.958 +
140.959 + /* Is there room in the parent for a new entry? */
140.960 + if (handle->level &&
140.961 + (handle->path[handle->level - 1].entries >=
140.962 + handle->path[handle->level - 1].max_entries)) {
140.963 +
140.964 +#ifdef DEBUG
140.965 + printf("parent level %d full; splitting it too\n",
140.966 + handle->level - 1);
140.967 +#endif
140.968 + /* split the parent */
140.969 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent);
140.970 + if (retval)
140.971 + goto done;
140.972 +
140.973 + retval = extent_node_split(handle, expand_allowed);
140.974 + if (retval)
140.975 + goto done;
140.976 +
140.977 + /* get handle back to our original split position */
140.978 + retval = ext2fs_extent_goto2(handle, orig_height, orig_lblk);
140.979 + if (retval)
140.980 + goto done;
140.981 + }
140.982 +
140.983 + /* At this point, parent should have room for this split */
140.984 + path = handle->path + handle->level;
140.985 + if (!path->curr)
140.986 + return EXT2_ET_NO_CURRENT_NODE;
140.987 +
140.988 + /*
140.989 + * Normally, we try to split a full node in half. This doesn't turn
140.990 + * out so well if we're tacking extents on the end of the file because
140.991 + * then we're stuck with a tree of half-full extent blocks. This of
140.992 + * course doesn't apply to the root level.
140.993 + */
140.994 + no_balance = expand_allowed ? splitting_at_eof(handle, path) : 0;
140.995 +
140.996 + /* extent header of the current node we'll split */
140.997 + eh = (struct ext3_extent_header *)path->buf;
140.998 +
140.999 + /* splitting root level means moving them all out */
140.1000 + if (handle->level == 0) {
140.1001 + new_root = 1;
140.1002 + tocopy = ext2fs_le16_to_cpu(eh->eh_entries);
140.1003 + retval = ext2fs_get_memzero((handle->max_paths + 1) *
140.1004 + sizeof(struct extent_path),
140.1005 + &newpath);
140.1006 + if (retval)
140.1007 + goto done;
140.1008 + } else {
140.1009 + if (no_balance)
140.1010 + tocopy = 1;
140.1011 + else
140.1012 + tocopy = ext2fs_le16_to_cpu(eh->eh_entries) / 2;
140.1013 + }
140.1014 +
140.1015 +#ifdef DEBUG
140.1016 + printf("will copy out %d of %d entries at level %d\n",
140.1017 + tocopy, ext2fs_le16_to_cpu(eh->eh_entries),
140.1018 + handle->level);
140.1019 +#endif
140.1020 +
140.1021 + if (!tocopy && !no_balance) {
140.1022 +#ifdef DEBUG
140.1023 + printf("Nothing to copy to new block!\n");
140.1024 +#endif
140.1025 + retval = EXT2_ET_CANT_SPLIT_EXTENT;
140.1026 + goto done;
140.1027 + }
140.1028 +
140.1029 + /* first we need a new block, or can do nothing. */
140.1030 + block_buf = malloc(handle->fs->blocksize);
140.1031 + if (!block_buf) {
140.1032 + retval = ENOMEM;
140.1033 + goto done;
140.1034 + }
140.1035 +
140.1036 + if (!goal_blk)
140.1037 + goal_blk = ext2fs_find_inode_goal(handle->fs, handle->ino,
140.1038 + handle->inode, 0);
140.1039 + retval = ext2fs_alloc_block2(handle->fs, goal_blk, block_buf,
140.1040 + &new_node_pblk);
140.1041 + if (retval)
140.1042 + goto done;
140.1043 +
140.1044 +#ifdef DEBUG
140.1045 + printf("will copy to new node at block %lu\n",
140.1046 + (unsigned long) new_node_pblk);
140.1047 +#endif
140.1048 +
140.1049 + /* Copy data into new block buffer */
140.1050 + /* First the header for the new block... */
140.1051 + neweh = (struct ext3_extent_header *) block_buf;
140.1052 + memcpy(neweh, eh, sizeof(struct ext3_extent_header));
140.1053 + neweh->eh_entries = ext2fs_cpu_to_le16(tocopy);
140.1054 + neweh->eh_max = ext2fs_cpu_to_le16((handle->fs->blocksize -
140.1055 + sizeof(struct ext3_extent_header)) /
140.1056 + sizeof(struct ext3_extent));
140.1057 +
140.1058 + /* then the entries for the new block... */
140.1059 + memcpy(EXT_FIRST_INDEX(neweh),
140.1060 + EXT_FIRST_INDEX(eh) +
140.1061 + (ext2fs_le16_to_cpu(eh->eh_entries) - tocopy),
140.1062 + sizeof(struct ext3_extent_idx) * tocopy);
140.1063 +
140.1064 + new_node_start = ext2fs_le32_to_cpu(EXT_FIRST_INDEX(neweh)->ei_block);
140.1065 +
140.1066 + /* then update the checksum */
140.1067 + retval = ext2fs_extent_block_csum_set(handle->fs, handle->ino, neweh);
140.1068 + if (retval)
140.1069 + goto done;
140.1070 +
140.1071 + /* ...and write the new node block out to disk. */
140.1072 + retval = io_channel_write_blk64(handle->fs->io, new_node_pblk, 1,
140.1073 + block_buf);
140.1074 +
140.1075 + if (retval)
140.1076 + goto done;
140.1077 +
140.1078 + /* OK! we've created the new node; now adjust the tree */
140.1079 +
140.1080 + /* current path now has fewer active entries, we copied some out */
140.1081 + if (handle->level == 0) {
140.1082 + memcpy(newpath, path,
140.1083 + sizeof(struct extent_path) * handle->max_paths);
140.1084 + handle->path = newpath;
140.1085 + newpath = path;
140.1086 + path = handle->path;
140.1087 + path->entries = 1;
140.1088 + path->left = path->max_entries - 1;
140.1089 + handle->max_depth++;
140.1090 + handle->max_paths++;
140.1091 + eh->eh_depth = ext2fs_cpu_to_le16(handle->max_depth);
140.1092 + } else {
140.1093 + path->entries -= tocopy;
140.1094 + path->left -= tocopy;
140.1095 + }
140.1096 +
140.1097 + eh->eh_entries = ext2fs_cpu_to_le16(path->entries);
140.1098 + /* this writes out the node, incl. the modified header */
140.1099 + retval = update_path(handle);
140.1100 + if (retval)
140.1101 + goto done;
140.1102 +
140.1103 + /* now go up and insert/replace index for new node we created */
140.1104 + if (new_root) {
140.1105 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_FIRST_SIB, &extent);
140.1106 + if (retval)
140.1107 + goto done;
140.1108 +
140.1109 + extent.e_lblk = new_node_start;
140.1110 + extent.e_pblk = new_node_pblk;
140.1111 + extent.e_len = handle->path[0].end_blk - extent.e_lblk;
140.1112 + retval = ext2fs_extent_replace(handle, 0, &extent);
140.1113 + if (retval)
140.1114 + goto done;
140.1115 + } else {
140.1116 + __u32 new_node_length;
140.1117 +
140.1118 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent);
140.1119 + /* will insert after this one; it's length is shorter now */
140.1120 + new_node_length = new_node_start - extent.e_lblk;
140.1121 + extent.e_len -= new_node_length;
140.1122 + retval = ext2fs_extent_replace(handle, 0, &extent);
140.1123 + if (retval)
140.1124 + goto done;
140.1125 +
140.1126 + /* now set up the new extent and insert it */
140.1127 + extent.e_lblk = new_node_start;
140.1128 + extent.e_pblk = new_node_pblk;
140.1129 + extent.e_len = new_node_length;
140.1130 + retval = ext2fs_extent_insert(handle, EXT2_EXTENT_INSERT_AFTER, &extent);
140.1131 + if (retval)
140.1132 + goto done;
140.1133 + }
140.1134 +
140.1135 + /* get handle back to our original position */
140.1136 + retval = ext2fs_extent_goto2(handle, orig_height, orig_lblk);
140.1137 + if (retval)
140.1138 + goto done;
140.1139 +
140.1140 + /* new node hooked in, so update inode block count (do this here?) */
140.1141 + ext2fs_iblk_add_blocks(handle->fs, handle->inode, 1);
140.1142 + retval = ext2fs_write_inode(handle->fs, handle->ino,
140.1143 + handle->inode);
140.1144 + if (retval)
140.1145 + goto done;
140.1146 +
140.1147 +done:
140.1148 + if (newpath)
140.1149 + ext2fs_free_mem(&newpath);
140.1150 + free(block_buf);
140.1151 +
140.1152 + return retval;
140.1153 +}
140.1154 +
140.1155 +errcode_t ext2fs_extent_node_split(ext2_extent_handle_t handle)
140.1156 +{
140.1157 + return extent_node_split(handle, 0);
140.1158 +}
140.1159 +
140.1160 +errcode_t ext2fs_extent_insert(ext2_extent_handle_t handle, int flags,
140.1161 + struct ext2fs_extent *extent)
140.1162 +{
140.1163 + struct extent_path *path;
140.1164 + struct ext3_extent_idx *ix;
140.1165 + struct ext3_extent_header *eh;
140.1166 + errcode_t retval;
140.1167 +
140.1168 + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
140.1169 +
140.1170 + if (!(handle->fs->flags & EXT2_FLAG_RW))
140.1171 + return EXT2_ET_RO_FILSYS;
140.1172 +
140.1173 + if (!handle->path)
140.1174 + return EXT2_ET_NO_CURRENT_NODE;
140.1175 +
140.1176 +#ifdef DEBUG
140.1177 + printf("extent insert: %u ", handle->ino);
140.1178 + dbg_print_extent(0, extent);
140.1179 +#endif
140.1180 +
140.1181 + path = handle->path + handle->level;
140.1182 +
140.1183 + if (path->entries >= path->max_entries) {
140.1184 + if (flags & EXT2_EXTENT_INSERT_NOSPLIT) {
140.1185 + return EXT2_ET_CANT_INSERT_EXTENT;
140.1186 + } else {
140.1187 +#ifdef DEBUG
140.1188 + printf("node full (level %d) - splitting\n",
140.1189 + handle->level);
140.1190 +#endif
140.1191 + retval = extent_node_split(handle, 1);
140.1192 + if (retval)
140.1193 + return retval;
140.1194 + path = handle->path + handle->level;
140.1195 + }
140.1196 + }
140.1197 +
140.1198 + eh = (struct ext3_extent_header *) path->buf;
140.1199 + if (path->curr) {
140.1200 + ix = path->curr;
140.1201 + if (flags & EXT2_EXTENT_INSERT_AFTER) {
140.1202 + ix++;
140.1203 + path->left--;
140.1204 + }
140.1205 + } else {
140.1206 + ix = EXT_FIRST_INDEX(eh);
140.1207 + path->left = -1;
140.1208 + }
140.1209 +
140.1210 + path->curr = ix;
140.1211 +
140.1212 + if (path->left >= 0)
140.1213 + memmove(ix + 1, ix,
140.1214 + (path->left+1) * sizeof(struct ext3_extent_idx));
140.1215 + path->left++;
140.1216 + path->entries++;
140.1217 +
140.1218 + eh = (struct ext3_extent_header *) path->buf;
140.1219 + eh->eh_entries = ext2fs_cpu_to_le16(path->entries);
140.1220 +
140.1221 + retval = ext2fs_extent_replace(handle, 0, extent);
140.1222 + if (retval)
140.1223 + goto errout;
140.1224 +
140.1225 + retval = update_path(handle);
140.1226 + if (retval)
140.1227 + goto errout;
140.1228 +
140.1229 + return 0;
140.1230 +
140.1231 +errout:
140.1232 + ext2fs_extent_delete(handle, 0);
140.1233 + return retval;
140.1234 +}
140.1235 +
140.1236 +/*
140.1237 + * Sets the physical block for a logical file block in the extent tree.
140.1238 + *
140.1239 + * May: map unmapped, unmap mapped, or remap mapped blocks.
140.1240 + *
140.1241 + * Mapping an unmapped block adds a single-block extent.
140.1242 + *
140.1243 + * Unmapping first or last block modifies extent in-place
140.1244 + * - But may need to fix parent's starts too in first-block case
140.1245 + *
140.1246 + * Mapping any unmapped block requires adding a (single-block) extent
140.1247 + * and inserting into proper point in tree.
140.1248 + *
140.1249 + * Modifying (unmapping or remapping) a block in the middle
140.1250 + * of an extent requires splitting the extent.
140.1251 + * - Remapping case requires new single-block extent.
140.1252 + *
140.1253 + * Remapping first or last block adds an extent.
140.1254 + *
140.1255 + * We really need extent adding to be smart about merging.
140.1256 + */
140.1257 +
140.1258 +errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,
140.1259 + blk64_t logical, blk64_t physical, int flags)
140.1260 +{
140.1261 + errcode_t ec, retval = 0;
140.1262 + int mapped = 1; /* logical is mapped? */
140.1263 + int orig_height;
140.1264 + int extent_uninit = 0;
140.1265 + int prev_uninit = 0;
140.1266 + int next_uninit = 0;
140.1267 + int new_uninit = 0;
140.1268 + int max_len = EXT_INIT_MAX_LEN;
140.1269 + int has_prev, has_next;
140.1270 + blk64_t orig_lblk;
140.1271 + struct extent_path *path;
140.1272 + struct ext2fs_extent extent, next_extent, prev_extent;
140.1273 + struct ext2fs_extent newextent;
140.1274 + struct ext2_extent_info info;
140.1275 +
140.1276 + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
140.1277 +
140.1278 +#ifdef DEBUG
140.1279 + printf("set_bmap ino %u log %lld phys %lld flags %d\n",
140.1280 + handle->ino, logical, physical, flags);
140.1281 +#endif
140.1282 +
140.1283 + if (!(handle->fs->flags & EXT2_FLAG_RW))
140.1284 + return EXT2_ET_RO_FILSYS;
140.1285 +
140.1286 + if (!handle->path)
140.1287 + return EXT2_ET_NO_CURRENT_NODE;
140.1288 +
140.1289 + path = handle->path + handle->level;
140.1290 +
140.1291 + if (flags & EXT2_EXTENT_SET_BMAP_UNINIT) {
140.1292 + new_uninit = 1;
140.1293 + max_len = EXT_UNINIT_MAX_LEN;
140.1294 + }
140.1295 +
140.1296 + /* if (re)mapping, set up new extent to insert */
140.1297 + if (physical) {
140.1298 + newextent.e_len = 1;
140.1299 + newextent.e_pblk = physical;
140.1300 + newextent.e_lblk = logical;
140.1301 + newextent.e_flags = EXT2_EXTENT_FLAGS_LEAF;
140.1302 + if (new_uninit)
140.1303 + newextent.e_flags |= EXT2_EXTENT_FLAGS_UNINIT;
140.1304 + }
140.1305 +
140.1306 + /* special case if the extent tree is completely empty */
140.1307 + if ((handle->max_depth == 0) && (path->entries == 0)) {
140.1308 + retval = ext2fs_extent_insert(handle, 0, &newextent);
140.1309 + return retval;
140.1310 + }
140.1311 +
140.1312 + /* save our original location in the extent tree */
140.1313 + if ((retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT,
140.1314 + &extent))) {
140.1315 + if (retval != EXT2_ET_NO_CURRENT_NODE)
140.1316 + return retval;
140.1317 + memset(&extent, 0, sizeof(extent));
140.1318 + }
140.1319 + if ((retval = ext2fs_extent_get_info(handle, &info)))
140.1320 + return retval;
140.1321 + orig_height = info.max_depth - info.curr_level;
140.1322 + orig_lblk = extent.e_lblk;
140.1323 +
140.1324 + /* go to the logical spot we want to (re/un)map */
140.1325 + retval = ext2fs_extent_goto(handle, logical);
140.1326 + if (retval) {
140.1327 + if (retval == EXT2_ET_EXTENT_NOT_FOUND) {
140.1328 + retval = 0;
140.1329 + mapped = 0;
140.1330 + if (!physical) {
140.1331 +#ifdef DEBUG
140.1332 + printf("block %llu already unmapped\n",
140.1333 + logical);
140.1334 +#endif
140.1335 + goto done;
140.1336 + }
140.1337 + } else
140.1338 + goto done;
140.1339 + }
140.1340 +
140.1341 + /*
140.1342 + * This may be the extent *before* the requested logical,
140.1343 + * if it's currently unmapped.
140.1344 + *
140.1345 + * Get the previous and next leaf extents, if they are present.
140.1346 + */
140.1347 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
140.1348 + if (retval)
140.1349 + goto done;
140.1350 + if (extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
140.1351 + extent_uninit = 1;
140.1352 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_LEAF, &next_extent);
140.1353 + if (retval) {
140.1354 + has_next = 0;
140.1355 + if (retval != EXT2_ET_EXTENT_NO_NEXT)
140.1356 + goto done;
140.1357 + } else {
140.1358 + dbg_print_extent("set_bmap: next_extent",
140.1359 + &next_extent);
140.1360 + has_next = 1;
140.1361 + if (next_extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
140.1362 + next_uninit = 1;
140.1363 + }
140.1364 + retval = ext2fs_extent_goto(handle, logical);
140.1365 + if (retval && retval != EXT2_ET_EXTENT_NOT_FOUND)
140.1366 + goto done;
140.1367 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_PREV_LEAF, &prev_extent);
140.1368 + if (retval) {
140.1369 + has_prev = 0;
140.1370 + if (retval != EXT2_ET_EXTENT_NO_PREV)
140.1371 + goto done;
140.1372 + } else {
140.1373 + has_prev = 1;
140.1374 + dbg_print_extent("set_bmap: prev_extent",
140.1375 + &prev_extent);
140.1376 + if (prev_extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
140.1377 + prev_uninit = 1;
140.1378 + }
140.1379 + retval = ext2fs_extent_goto(handle, logical);
140.1380 + if (retval && retval != EXT2_ET_EXTENT_NOT_FOUND)
140.1381 + goto done;
140.1382 +
140.1383 + /* check if already pointing to the requested physical */
140.1384 + if (mapped && (new_uninit == extent_uninit) &&
140.1385 + (extent.e_pblk + (logical - extent.e_lblk) == physical)) {
140.1386 +#ifdef DEBUG
140.1387 + printf("physical block (at %llu) unchanged\n", logical);
140.1388 +#endif
140.1389 + goto done;
140.1390 + }
140.1391 +
140.1392 + if (!mapped) {
140.1393 +#ifdef DEBUG
140.1394 + printf("mapping unmapped logical block %llu\n", logical);
140.1395 +#endif
140.1396 + if ((logical == extent.e_lblk + extent.e_len) &&
140.1397 + (physical == extent.e_pblk + extent.e_len) &&
140.1398 + (new_uninit == extent_uninit) &&
140.1399 + ((int) extent.e_len < max_len-1)) {
140.1400 + extent.e_len++;
140.1401 + retval = ext2fs_extent_replace(handle, 0, &extent);
140.1402 + } else if ((logical == extent.e_lblk - 1) &&
140.1403 + (physical == extent.e_pblk - 1) &&
140.1404 + (new_uninit == extent_uninit) &&
140.1405 + ((int) extent.e_len < max_len - 1)) {
140.1406 + extent.e_len++;
140.1407 + extent.e_lblk--;
140.1408 + extent.e_pblk--;
140.1409 + retval = ext2fs_extent_replace(handle, 0, &extent);
140.1410 + } else if (has_next &&
140.1411 + (logical == next_extent.e_lblk - 1) &&
140.1412 + (physical == next_extent.e_pblk - 1) &&
140.1413 + (new_uninit == next_uninit) &&
140.1414 + ((int) next_extent.e_len < max_len - 1)) {
140.1415 + retval = ext2fs_extent_get(handle,
140.1416 + EXT2_EXTENT_NEXT_LEAF,
140.1417 + &next_extent);
140.1418 + if (retval)
140.1419 + goto done;
140.1420 + next_extent.e_len++;
140.1421 + next_extent.e_lblk--;
140.1422 + next_extent.e_pblk--;
140.1423 + retval = ext2fs_extent_replace(handle, 0, &next_extent);
140.1424 + } else if (logical < extent.e_lblk)
140.1425 + retval = ext2fs_extent_insert(handle, 0, &newextent);
140.1426 + else
140.1427 + retval = ext2fs_extent_insert(handle,
140.1428 + EXT2_EXTENT_INSERT_AFTER, &newextent);
140.1429 + if (retval)
140.1430 + goto done;
140.1431 + retval = ext2fs_extent_fix_parents(handle);
140.1432 + if (retval)
140.1433 + goto done;
140.1434 + } else if ((logical == extent.e_lblk) && (extent.e_len == 1)) {
140.1435 +#ifdef DEBUG
140.1436 + printf("(re/un)mapping only block in extent\n");
140.1437 +#endif
140.1438 + if (physical) {
140.1439 + retval = ext2fs_extent_replace(handle, 0, &newextent);
140.1440 + } else {
140.1441 + retval = ext2fs_extent_delete(handle, 0);
140.1442 + if (retval)
140.1443 + goto done;
140.1444 + ec = ext2fs_extent_fix_parents(handle);
140.1445 + if (ec != EXT2_ET_NO_CURRENT_NODE)
140.1446 + retval = ec;
140.1447 + }
140.1448 +
140.1449 + if (retval)
140.1450 + goto done;
140.1451 + } else if (logical == extent.e_lblk + extent.e_len - 1) {
140.1452 +#ifdef DEBUG
140.1453 + printf("(re/un)mapping last block in extent\n");
140.1454 +#endif
140.1455 + if (physical) {
140.1456 + if (has_next &&
140.1457 + (logical == (next_extent.e_lblk - 1)) &&
140.1458 + (physical == (next_extent.e_pblk - 1)) &&
140.1459 + (new_uninit == next_uninit) &&
140.1460 + ((int) next_extent.e_len < max_len - 1)) {
140.1461 + retval = ext2fs_extent_get(handle,
140.1462 + EXT2_EXTENT_NEXT_LEAF, &next_extent);
140.1463 + if (retval)
140.1464 + goto done;
140.1465 + next_extent.e_len++;
140.1466 + next_extent.e_lblk--;
140.1467 + next_extent.e_pblk--;
140.1468 + retval = ext2fs_extent_replace(handle, 0,
140.1469 + &next_extent);
140.1470 + if (retval)
140.1471 + goto done;
140.1472 + } else
140.1473 + retval = ext2fs_extent_insert(handle,
140.1474 + EXT2_EXTENT_INSERT_AFTER, &newextent);
140.1475 + if (retval)
140.1476 + goto done;
140.1477 + retval = ext2fs_extent_fix_parents(handle);
140.1478 + if (retval)
140.1479 + goto done;
140.1480 + /*
140.1481 + * Now pointing at inserted extent; move back to prev.
140.1482 + *
140.1483 + * We cannot use EXT2_EXTENT_PREV to go back; note the
140.1484 + * subtlety in the comment for fix_parents().
140.1485 + */
140.1486 + retval = ext2fs_extent_goto(handle, logical);
140.1487 + if (retval)
140.1488 + goto done;
140.1489 + retval = ext2fs_extent_get(handle,
140.1490 + EXT2_EXTENT_CURRENT,
140.1491 + &extent);
140.1492 + if (retval)
140.1493 + goto done;
140.1494 + }
140.1495 + extent.e_len--;
140.1496 + retval = ext2fs_extent_replace(handle, 0, &extent);
140.1497 + if (retval)
140.1498 + goto done;
140.1499 + } else if (logical == extent.e_lblk) {
140.1500 +#ifdef DEBUG
140.1501 + printf("(re/un)mapping first block in extent\n");
140.1502 +#endif
140.1503 + if (physical) {
140.1504 + if (has_prev &&
140.1505 + (logical == (prev_extent.e_lblk +
140.1506 + prev_extent.e_len)) &&
140.1507 + (physical == (prev_extent.e_pblk +
140.1508 + prev_extent.e_len)) &&
140.1509 + (new_uninit == prev_uninit) &&
140.1510 + ((int) prev_extent.e_len < max_len-1)) {
140.1511 + retval = ext2fs_extent_get(handle,
140.1512 + EXT2_EXTENT_PREV_LEAF, &prev_extent);
140.1513 + if (retval)
140.1514 + goto done;
140.1515 + prev_extent.e_len++;
140.1516 + retval = ext2fs_extent_replace(handle, 0,
140.1517 + &prev_extent);
140.1518 + } else
140.1519 + retval = ext2fs_extent_insert(handle,
140.1520 + 0, &newextent);
140.1521 + if (retval)
140.1522 + goto done;
140.1523 + retval = ext2fs_extent_fix_parents(handle);
140.1524 + if (retval)
140.1525 + goto done;
140.1526 + retval = ext2fs_extent_get(handle,
140.1527 + EXT2_EXTENT_NEXT_LEAF,
140.1528 + &extent);
140.1529 + if (retval)
140.1530 + goto done;
140.1531 + }
140.1532 + extent.e_pblk++;
140.1533 + extent.e_lblk++;
140.1534 + extent.e_len--;
140.1535 + retval = ext2fs_extent_replace(handle, 0, &extent);
140.1536 + if (retval)
140.1537 + goto done;
140.1538 + retval = ext2fs_extent_fix_parents(handle);
140.1539 + if (retval)
140.1540 + goto done;
140.1541 + } else {
140.1542 + __u32 save_length;
140.1543 + blk64_t save_lblk;
140.1544 + struct ext2fs_extent save_extent;
140.1545 + errcode_t r2;
140.1546 +
140.1547 +#ifdef DEBUG
140.1548 + printf("(re/un)mapping in middle of extent\n");
140.1549 +#endif
140.1550 + /* need to split this extent; later */
140.1551 + save_lblk = extent.e_lblk;
140.1552 + save_length = extent.e_len;
140.1553 + save_extent = extent;
140.1554 +
140.1555 + /* shorten pre-split extent */
140.1556 + extent.e_len = (logical - extent.e_lblk);
140.1557 + retval = ext2fs_extent_replace(handle, 0, &extent);
140.1558 + if (retval)
140.1559 + goto done;
140.1560 + /* insert our new extent, if any */
140.1561 + if (physical) {
140.1562 + /* insert new extent after current */
140.1563 + retval = ext2fs_extent_insert(handle,
140.1564 + EXT2_EXTENT_INSERT_AFTER, &newextent);
140.1565 + if (retval) {
140.1566 + r2 = ext2fs_extent_goto(handle, save_lblk);
140.1567 + if (r2 == 0)
140.1568 + (void)ext2fs_extent_replace(handle, 0,
140.1569 + &save_extent);
140.1570 + goto done;
140.1571 + }
140.1572 + }
140.1573 + /* add post-split extent */
140.1574 + extent.e_pblk += extent.e_len + 1;
140.1575 + extent.e_lblk += extent.e_len + 1;
140.1576 + extent.e_len = save_length - extent.e_len - 1;
140.1577 + retval = ext2fs_extent_insert(handle,
140.1578 + EXT2_EXTENT_INSERT_AFTER, &extent);
140.1579 + if (retval) {
140.1580 + if (physical) {
140.1581 + r2 = ext2fs_extent_goto(handle,
140.1582 + newextent.e_lblk);
140.1583 + if (r2 == 0)
140.1584 + (void)ext2fs_extent_delete(handle, 0);
140.1585 + }
140.1586 + r2 = ext2fs_extent_goto(handle, save_lblk);
140.1587 + if (r2 == 0)
140.1588 + (void)ext2fs_extent_replace(handle, 0,
140.1589 + &save_extent);
140.1590 + goto done;
140.1591 + }
140.1592 + }
140.1593 +
140.1594 +done:
140.1595 + /* get handle back to its position */
140.1596 + if (orig_height > handle->max_depth)
140.1597 + orig_height = handle->max_depth; /* In case we shortened the tree */
140.1598 + ext2fs_extent_goto2(handle, orig_height, orig_lblk);
140.1599 + return retval;
140.1600 +}
140.1601 +
140.1602 +errcode_t ext2fs_extent_delete(ext2_extent_handle_t handle, int flags)
140.1603 +{
140.1604 + struct extent_path *path;
140.1605 + char *cp;
140.1606 + struct ext3_extent_header *eh;
140.1607 + errcode_t retval = 0;
140.1608 +
140.1609 + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
140.1610 +
140.1611 + if (!(handle->fs->flags & EXT2_FLAG_RW))
140.1612 + return EXT2_ET_RO_FILSYS;
140.1613 +
140.1614 + if (!handle->path)
140.1615 + return EXT2_ET_NO_CURRENT_NODE;
140.1616 +
140.1617 +#ifdef DEBUG
140.1618 + {
140.1619 + struct ext2fs_extent extent;
140.1620 +
140.1621 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT,
140.1622 + &extent);
140.1623 + if (retval == 0) {
140.1624 + printf("extent delete %u ", handle->ino);
140.1625 + dbg_print_extent(0, &extent);
140.1626 + }
140.1627 + }
140.1628 +#endif
140.1629 +
140.1630 + path = handle->path + handle->level;
140.1631 + if (!path->curr)
140.1632 + return EXT2_ET_NO_CURRENT_NODE;
140.1633 +
140.1634 + cp = path->curr;
140.1635 +
140.1636 + if (path->left) {
140.1637 + memmove(cp, cp + sizeof(struct ext3_extent_idx),
140.1638 + path->left * sizeof(struct ext3_extent_idx));
140.1639 + path->left--;
140.1640 + } else {
140.1641 + struct ext3_extent_idx *ix = path->curr;
140.1642 + ix--;
140.1643 + path->curr = ix;
140.1644 + }
140.1645 + if (--path->entries == 0)
140.1646 + path->curr = 0;
140.1647 +
140.1648 + /* if non-root node has no entries left, remove it & parent ptr to it */
140.1649 + if (path->entries == 0 && handle->level) {
140.1650 + if (!(flags & EXT2_EXTENT_DELETE_KEEP_EMPTY)) {
140.1651 + struct ext2fs_extent extent;
140.1652 +
140.1653 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP,
140.1654 + &extent);
140.1655 + if (retval)
140.1656 + return retval;
140.1657 +
140.1658 + retval = ext2fs_extent_delete(handle, flags);
140.1659 + handle->inode->i_blocks -=
140.1660 + (handle->fs->blocksize *
140.1661 + EXT2FS_CLUSTER_RATIO(handle->fs)) / 512;
140.1662 + retval = ext2fs_write_inode(handle->fs, handle->ino,
140.1663 + handle->inode);
140.1664 + ext2fs_block_alloc_stats2(handle->fs,
140.1665 + extent.e_pblk, -1);
140.1666 + }
140.1667 + } else {
140.1668 + eh = (struct ext3_extent_header *) path->buf;
140.1669 + eh->eh_entries = ext2fs_cpu_to_le16(path->entries);
140.1670 + if ((path->entries == 0) && (handle->level == 0)) {
140.1671 + eh->eh_depth = 0;
140.1672 + handle->max_depth = 0;
140.1673 + }
140.1674 + retval = update_path(handle);
140.1675 + }
140.1676 + return retval;
140.1677 +}
140.1678 +
140.1679 +errcode_t ext2fs_extent_get_info(ext2_extent_handle_t handle,
140.1680 + struct ext2_extent_info *info)
140.1681 +{
140.1682 + struct extent_path *path;
140.1683 +
140.1684 + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
140.1685 +
140.1686 + memset(info, 0, sizeof(struct ext2_extent_info));
140.1687 +
140.1688 + path = handle->path + handle->level;
140.1689 + if (path) {
140.1690 + if (path->curr)
140.1691 + info->curr_entry = ((char *) path->curr - path->buf) /
140.1692 + sizeof(struct ext3_extent_idx);
140.1693 + else
140.1694 + info->curr_entry = 0;
140.1695 + info->num_entries = path->entries;
140.1696 + info->max_entries = path->max_entries;
140.1697 + info->bytes_avail = (path->max_entries - path->entries) *
140.1698 + sizeof(struct ext3_extent);
140.1699 + }
140.1700 +
140.1701 + info->curr_level = handle->level;
140.1702 + info->max_depth = handle->max_depth;
140.1703 + info->max_lblk = EXT_MAX_EXTENT_LBLK;
140.1704 + info->max_pblk = EXT_MAX_EXTENT_PBLK;
140.1705 + info->max_len = EXT_INIT_MAX_LEN;
140.1706 + info->max_uninit_len = EXT_UNINIT_MAX_LEN;
140.1707 +
140.1708 + return 0;
140.1709 +}
140.1710 +
140.1711 +static int ul_log2(unsigned long arg)
140.1712 +{
140.1713 + int l = 0;
140.1714 +
140.1715 + arg >>= 1;
140.1716 + while (arg) {
140.1717 + l++;
140.1718 + arg >>= 1;
140.1719 + }
140.1720 + return l;
140.1721 +}
140.1722 +
140.1723 +size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle)
140.1724 +{
140.1725 + size_t iblock_sz = sizeof(((struct ext2_inode *)NULL)->i_block);
140.1726 + size_t iblock_extents = (iblock_sz - sizeof(struct ext3_extent_header)) /
140.1727 + sizeof(struct ext3_extent);
140.1728 + size_t extents_per_block = (handle->fs->blocksize -
140.1729 + sizeof(struct ext3_extent_header)) /
140.1730 + sizeof(struct ext3_extent);
140.1731 + static unsigned int last_blocksize = 0;
140.1732 + static size_t last_result = 0;
140.1733 +
140.1734 + if (last_blocksize && last_blocksize == handle->fs->blocksize)
140.1735 + return last_result;
140.1736 +
140.1737 + last_result = 1 + ((ul_log2(EXT_MAX_EXTENT_LBLK) - ul_log2(iblock_extents)) /
140.1738 + ul_log2(extents_per_block));
140.1739 + last_blocksize = handle->fs->blocksize;
140.1740 + return last_result;
140.1741 +}
140.1742 +
140.1743 +#ifdef DEBUG
140.1744 +/*
140.1745 + * Override debugfs's prompt
140.1746 + */
140.1747 +const char *debug_prog_name = "tst_extents";
140.1748 +
140.1749 +#endif
140.1750 +
141.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
141.2 +++ b/libext2fs/lib/libext2fs/fallocate.c Wed Aug 25 01:28:08 2021 +0200
141.3 @@ -0,0 +1,855 @@
141.4 +/*
141.5 + * fallocate.c -- Allocate large chunks of file.
141.6 + *
141.7 + * Copyright (C) 2014 Oracle.
141.8 + *
141.9 + * %Begin-Header%
141.10 + * This file may be redistributed under the terms of the GNU Library
141.11 + * General Public License, version 2.
141.12 + * %End-Header%
141.13 + */
141.14 +
141.15 +#include "config.h"
141.16 +
141.17 +#if HAVE_SYS_TYPES_H
141.18 +#include <sys/types.h>
141.19 +#endif
141.20 +
141.21 +#include "ext2_fs.h"
141.22 +#include "ext2fs.h"
141.23 +#define min(a, b) ((a) < (b) ? (a) : (b))
141.24 +
141.25 +#undef DEBUG
141.26 +
141.27 +#ifdef DEBUG
141.28 +# define dbg_printf(f, a...) do {printf(f, ## a); fflush(stdout); } while (0)
141.29 +#else
141.30 +# define dbg_printf(f, a...)
141.31 +#endif
141.32 +
141.33 +/*
141.34 + * Extent-based fallocate code.
141.35 + *
141.36 + * Find runs of unmapped logical blocks by starting at start and walking the
141.37 + * extents until we reach the end of the range we want.
141.38 + *
141.39 + * For each run of unmapped blocks, try to find the extents on either side of
141.40 + * the range. If there's a left extent that can grow by at least a cluster and
141.41 + * there are lblocks between start and the next lcluster after start, see if
141.42 + * there's an implied cluster allocation; if so, zero the blocks (if the left
141.43 + * extent is initialized) and adjust the extent. Ditto for the blocks between
141.44 + * the end of the last full lcluster and end, if there's a right extent.
141.45 + *
141.46 + * Try to attach as much as we can to the left extent, then try to attach as
141.47 + * much as we can to the right extent. For the remainder, try to allocate the
141.48 + * whole range; map in whatever we get; and repeat until we're done.
141.49 + *
141.50 + * To attach to a left extent, figure out the maximum amount we can add to the
141.51 + * extent and try to allocate that much, and append if successful. To attach
141.52 + * to a right extent, figure out the max we can add to the extent, try to
141.53 + * allocate that much, and prepend if successful.
141.54 + *
141.55 + * We need an alloc_range function that tells us how much we can allocate given
141.56 + * a maximum length and one of a suggested start, a fixed start, or a fixed end
141.57 + * point.
141.58 + *
141.59 + * Every time we modify the extent tree we also need to update the block stats.
141.60 + *
141.61 + * At the end, update i_blocks and i_size appropriately.
141.62 + */
141.63 +
141.64 +static void dbg_print_extent(const char *desc EXT2FS_ATTR((unused)),
141.65 + const struct ext2fs_extent *extent EXT2FS_ATTR((unused)))
141.66 +{
141.67 +#ifdef DEBUG
141.68 + if (desc)
141.69 + printf("%s: ", desc);
141.70 + printf("extent: lblk %llu--%llu, len %u, pblk %llu, flags: ",
141.71 + extent->e_lblk, extent->e_lblk + extent->e_len - 1,
141.72 + extent->e_len, extent->e_pblk);
141.73 + if (extent->e_flags & EXT2_EXTENT_FLAGS_LEAF)
141.74 + fputs("LEAF ", stdout);
141.75 + if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
141.76 + fputs("UNINIT ", stdout);
141.77 + if (extent->e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)
141.78 + fputs("2ND_VISIT ", stdout);
141.79 + if (!extent->e_flags)
141.80 + fputs("(none)", stdout);
141.81 + fputc('\n', stdout);
141.82 + fflush(stdout);
141.83 +#endif
141.84 +}
141.85 +
141.86 +static errcode_t claim_range(ext2_filsys fs, struct ext2_inode *inode,
141.87 + blk64_t blk, blk64_t len)
141.88 +{
141.89 + blk64_t clusters;
141.90 +
141.91 + clusters = (len + EXT2FS_CLUSTER_RATIO(fs) - 1) /
141.92 + EXT2FS_CLUSTER_RATIO(fs);
141.93 + ext2fs_block_alloc_stats_range(fs, blk,
141.94 + clusters * EXT2FS_CLUSTER_RATIO(fs), +1);
141.95 + return ext2fs_iblk_add_blocks(fs, inode, clusters);
141.96 +}
141.97 +
141.98 +static errcode_t ext_falloc_helper(ext2_filsys fs,
141.99 + int flags,
141.100 + ext2_ino_t ino,
141.101 + struct ext2_inode *inode,
141.102 + ext2_extent_handle_t handle,
141.103 + struct ext2fs_extent *left_ext,
141.104 + struct ext2fs_extent *right_ext,
141.105 + blk64_t range_start, blk64_t range_len,
141.106 + blk64_t alloc_goal)
141.107 +{
141.108 + struct ext2fs_extent newex, ex;
141.109 + int op;
141.110 + blk64_t fillable, pblk, plen, x, y;
141.111 + blk64_t eof_blk = 0, cluster_fill = 0;
141.112 + errcode_t err;
141.113 + blk_t max_extent_len, max_uninit_len, max_init_len;
141.114 +
141.115 +#ifdef DEBUG
141.116 + printf("%s: ", __func__);
141.117 + if (left_ext)
141.118 + printf("left_ext=%llu--%llu, ", left_ext->e_lblk,
141.119 + left_ext->e_lblk + left_ext->e_len - 1);
141.120 + if (right_ext)
141.121 + printf("right_ext=%llu--%llu, ", right_ext->e_lblk,
141.122 + right_ext->e_lblk + right_ext->e_len - 1);
141.123 + printf("start=%llu len=%llu, goal=%llu\n", range_start, range_len,
141.124 + alloc_goal);
141.125 + fflush(stdout);
141.126 +#endif
141.127 + /* Can't create initialized extents past EOF? */
141.128 + if (!(flags & EXT2_FALLOCATE_INIT_BEYOND_EOF))
141.129 + eof_blk = EXT2_I_SIZE(inode) / fs->blocksize;
141.130 +
141.131 + /* The allocation goal must be as far into a cluster as range_start. */
141.132 + alloc_goal = (alloc_goal & ~EXT2FS_CLUSTER_MASK(fs)) |
141.133 + (range_start & EXT2FS_CLUSTER_MASK(fs));
141.134 +
141.135 + max_uninit_len = EXT_UNINIT_MAX_LEN & ~EXT2FS_CLUSTER_MASK(fs);
141.136 + max_init_len = EXT_INIT_MAX_LEN & ~EXT2FS_CLUSTER_MASK(fs);
141.137 +
141.138 + /* We must lengthen the left extent to the end of the cluster */
141.139 + if (left_ext && EXT2FS_CLUSTER_RATIO(fs) > 1) {
141.140 + /* How many more blocks can be attached to left_ext? */
141.141 + if (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
141.142 + fillable = max_uninit_len - left_ext->e_len;
141.143 + else
141.144 + fillable = max_init_len - left_ext->e_len;
141.145 +
141.146 + if (fillable > range_len)
141.147 + fillable = range_len;
141.148 + if (fillable == 0)
141.149 + goto expand_right;
141.150 +
141.151 + /*
141.152 + * If range_start isn't on a cluster boundary, try an
141.153 + * implied cluster allocation for left_ext.
141.154 + */
141.155 + cluster_fill = EXT2FS_CLUSTER_RATIO(fs) -
141.156 + (range_start & EXT2FS_CLUSTER_MASK(fs));
141.157 + cluster_fill &= EXT2FS_CLUSTER_MASK(fs);
141.158 + if (cluster_fill == 0)
141.159 + goto expand_right;
141.160 +
141.161 + if (cluster_fill > fillable)
141.162 + cluster_fill = fillable;
141.163 +
141.164 + /* Don't expand an initialized left_ext beyond EOF */
141.165 + if (!(flags & EXT2_FALLOCATE_INIT_BEYOND_EOF)) {
141.166 + x = left_ext->e_lblk + left_ext->e_len - 1;
141.167 + dbg_printf("%s: lend=%llu newlend=%llu eofblk=%llu\n",
141.168 + __func__, x, x + cluster_fill, eof_blk);
141.169 + if (eof_blk >= x && eof_blk <= x + cluster_fill)
141.170 + cluster_fill = eof_blk - x;
141.171 + if (cluster_fill == 0)
141.172 + goto expand_right;
141.173 + }
141.174 +
141.175 + err = ext2fs_extent_goto(handle, left_ext->e_lblk);
141.176 + if (err)
141.177 + goto expand_right;
141.178 + left_ext->e_len += cluster_fill;
141.179 + range_start += cluster_fill;
141.180 + range_len -= cluster_fill;
141.181 + alloc_goal += cluster_fill;
141.182 +
141.183 + dbg_print_extent("ext_falloc clus left+", left_ext);
141.184 + err = ext2fs_extent_replace(handle, 0, left_ext);
141.185 + if (err)
141.186 + goto out;
141.187 + err = ext2fs_extent_fix_parents(handle);
141.188 + if (err)
141.189 + goto out;
141.190 +
141.191 + /* Zero blocks */
141.192 + if (!(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) {
141.193 + err = ext2fs_zero_blocks2(fs, left_ext->e_pblk +
141.194 + left_ext->e_len -
141.195 + cluster_fill, cluster_fill,
141.196 + NULL, NULL);
141.197 + if (err)
141.198 + goto out;
141.199 + }
141.200 + }
141.201 +
141.202 +expand_right:
141.203 + /* We must lengthen the right extent to the beginning of the cluster */
141.204 + if (right_ext && EXT2FS_CLUSTER_RATIO(fs) > 1) {
141.205 + /* How much can we attach to right_ext? */
141.206 + if (right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
141.207 + fillable = max_uninit_len - right_ext->e_len;
141.208 + else
141.209 + fillable = max_init_len - right_ext->e_len;
141.210 +
141.211 + if (fillable > range_len)
141.212 + fillable = range_len;
141.213 + if (fillable == 0)
141.214 + goto try_merge;
141.215 +
141.216 + /*
141.217 + * If range_end isn't on a cluster boundary, try an implied
141.218 + * cluster allocation for right_ext.
141.219 + */
141.220 + cluster_fill = right_ext->e_lblk & EXT2FS_CLUSTER_MASK(fs);
141.221 + if (cluster_fill == 0)
141.222 + goto try_merge;
141.223 +
141.224 + err = ext2fs_extent_goto(handle, right_ext->e_lblk);
141.225 + if (err)
141.226 + goto out;
141.227 +
141.228 + if (cluster_fill > fillable)
141.229 + cluster_fill = fillable;
141.230 + right_ext->e_lblk -= cluster_fill;
141.231 + right_ext->e_pblk -= cluster_fill;
141.232 + right_ext->e_len += cluster_fill;
141.233 + range_len -= cluster_fill;
141.234 +
141.235 + dbg_print_extent("ext_falloc clus right+", right_ext);
141.236 + err = ext2fs_extent_replace(handle, 0, right_ext);
141.237 + if (err)
141.238 + goto out;
141.239 + err = ext2fs_extent_fix_parents(handle);
141.240 + if (err)
141.241 + goto out;
141.242 +
141.243 + /* Zero blocks if necessary */
141.244 + if (!(right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) {
141.245 + err = ext2fs_zero_blocks2(fs, right_ext->e_pblk,
141.246 + cluster_fill, NULL, NULL);
141.247 + if (err)
141.248 + goto out;
141.249 + }
141.250 + }
141.251 +
141.252 +try_merge:
141.253 + /* Merge both extents together, perhaps? */
141.254 + if (left_ext && right_ext) {
141.255 + /* Are the two extents mergeable? */
141.256 + if ((left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) !=
141.257 + (right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT))
141.258 + goto try_left;
141.259 +
141.260 + /* User requires init/uninit but extent is uninit/init. */
141.261 + if (((flags & EXT2_FALLOCATE_FORCE_INIT) &&
141.262 + (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) ||
141.263 + ((flags & EXT2_FALLOCATE_FORCE_UNINIT) &&
141.264 + !(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)))
141.265 + goto try_left;
141.266 +
141.267 + /*
141.268 + * Skip initialized extent unless user wants to zero blocks
141.269 + * or requires init extent.
141.270 + */
141.271 + if (!(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
141.272 + (!(flags & EXT2_FALLOCATE_ZERO_BLOCKS) ||
141.273 + !(flags & EXT2_FALLOCATE_FORCE_INIT)))
141.274 + goto try_left;
141.275 +
141.276 + /* Will it even fit? */
141.277 + x = left_ext->e_len + range_len + right_ext->e_len;
141.278 + if (x > (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT ?
141.279 + max_uninit_len : max_init_len))
141.280 + goto try_left;
141.281 +
141.282 + err = ext2fs_extent_goto(handle, left_ext->e_lblk);
141.283 + if (err)
141.284 + goto try_left;
141.285 +
141.286 + /* Allocate blocks */
141.287 + y = left_ext->e_pblk + left_ext->e_len;
141.288 + err = ext2fs_new_range(fs, EXT2_NEWRANGE_FIXED_GOAL |
141.289 + EXT2_NEWRANGE_MIN_LENGTH, y,
141.290 + right_ext->e_pblk - y + 1, NULL,
141.291 + &pblk, &plen);
141.292 + if (err)
141.293 + goto try_left;
141.294 + if (pblk + plen != right_ext->e_pblk)
141.295 + goto try_left;
141.296 + err = claim_range(fs, inode, pblk, plen);
141.297 + if (err)
141.298 + goto out;
141.299 +
141.300 + /* Modify extents */
141.301 + left_ext->e_len = x;
141.302 + dbg_print_extent("ext_falloc merge", left_ext);
141.303 + err = ext2fs_extent_replace(handle, 0, left_ext);
141.304 + if (err)
141.305 + goto out;
141.306 + err = ext2fs_extent_fix_parents(handle);
141.307 + if (err)
141.308 + goto out;
141.309 + err = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_LEAF, &newex);
141.310 + if (err)
141.311 + goto out;
141.312 + err = ext2fs_extent_delete(handle, 0);
141.313 + if (err)
141.314 + goto out;
141.315 + err = ext2fs_extent_fix_parents(handle);
141.316 + if (err)
141.317 + goto out;
141.318 + *right_ext = *left_ext;
141.319 +
141.320 + /* Zero blocks */
141.321 + if (!(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
141.322 + (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) {
141.323 + err = ext2fs_zero_blocks2(fs, range_start, range_len,
141.324 + NULL, NULL);
141.325 + if (err)
141.326 + goto out;
141.327 + }
141.328 +
141.329 + return 0;
141.330 + }
141.331 +
141.332 +try_left:
141.333 + /* Extend the left extent */
141.334 + if (left_ext) {
141.335 + /* How many more blocks can be attached to left_ext? */
141.336 + if (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
141.337 + fillable = max_uninit_len - left_ext->e_len;
141.338 + else if (flags & EXT2_FALLOCATE_ZERO_BLOCKS)
141.339 + fillable = max_init_len - left_ext->e_len;
141.340 + else
141.341 + fillable = 0;
141.342 +
141.343 + /* User requires init/uninit but extent is uninit/init. */
141.344 + if (((flags & EXT2_FALLOCATE_FORCE_INIT) &&
141.345 + (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) ||
141.346 + ((flags & EXT2_FALLOCATE_FORCE_UNINIT) &&
141.347 + !(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)))
141.348 + goto try_right;
141.349 +
141.350 + if (fillable > range_len)
141.351 + fillable = range_len;
141.352 +
141.353 + /* Don't expand an initialized left_ext beyond EOF */
141.354 + x = left_ext->e_lblk + left_ext->e_len - 1;
141.355 + if (!(flags & EXT2_FALLOCATE_INIT_BEYOND_EOF)) {
141.356 + dbg_printf("%s: lend=%llu newlend=%llu eofblk=%llu\n",
141.357 + __func__, x, x + fillable, eof_blk);
141.358 + if (eof_blk >= x && eof_blk <= x + fillable)
141.359 + fillable = eof_blk - x;
141.360 + }
141.361 +
141.362 + if (fillable == 0)
141.363 + goto try_right;
141.364 +
141.365 + /* Test if the right edge of the range is already mapped? */
141.366 + if (EXT2FS_CLUSTER_RATIO(fs) > 1) {
141.367 + err = ext2fs_map_cluster_block(fs, ino, inode,
141.368 + x + fillable, &pblk);
141.369 + if (err)
141.370 + goto out;
141.371 + if (pblk)
141.372 + fillable -= 1 + ((x + fillable)
141.373 + & EXT2FS_CLUSTER_MASK(fs));
141.374 + if (fillable == 0)
141.375 + goto try_right;
141.376 + }
141.377 +
141.378 + /* Allocate range of blocks */
141.379 + x = left_ext->e_pblk + left_ext->e_len;
141.380 + err = ext2fs_new_range(fs, EXT2_NEWRANGE_FIXED_GOAL |
141.381 + EXT2_NEWRANGE_MIN_LENGTH,
141.382 + x, fillable, NULL, &pblk, &plen);
141.383 + if (err)
141.384 + goto try_right;
141.385 + err = claim_range(fs, inode, pblk, plen);
141.386 + if (err)
141.387 + goto out;
141.388 +
141.389 + /* Modify left_ext */
141.390 + err = ext2fs_extent_goto(handle, left_ext->e_lblk);
141.391 + if (err)
141.392 + goto out;
141.393 + range_start += plen;
141.394 + range_len -= plen;
141.395 + left_ext->e_len += plen;
141.396 + dbg_print_extent("ext_falloc left+", left_ext);
141.397 + err = ext2fs_extent_replace(handle, 0, left_ext);
141.398 + if (err)
141.399 + goto out;
141.400 + err = ext2fs_extent_fix_parents(handle);
141.401 + if (err)
141.402 + goto out;
141.403 +
141.404 + /* Zero blocks if necessary */
141.405 + if (!(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
141.406 + (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) {
141.407 + err = ext2fs_zero_blocks2(fs, pblk, plen, NULL, NULL);
141.408 + if (err)
141.409 + goto out;
141.410 + }
141.411 + }
141.412 +
141.413 +try_right:
141.414 + /* Extend the right extent */
141.415 + if (right_ext) {
141.416 + /* How much can we attach to right_ext? */
141.417 + if (right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
141.418 + fillable = max_uninit_len - right_ext->e_len;
141.419 + else if (flags & EXT2_FALLOCATE_ZERO_BLOCKS)
141.420 + fillable = max_init_len - right_ext->e_len;
141.421 + else
141.422 + fillable = 0;
141.423 +
141.424 + /* User requires init/uninit but extent is uninit/init. */
141.425 + if (((flags & EXT2_FALLOCATE_FORCE_INIT) &&
141.426 + (right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) ||
141.427 + ((flags & EXT2_FALLOCATE_FORCE_UNINIT) &&
141.428 + !(right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)))
141.429 + goto try_anywhere;
141.430 +
141.431 + if (fillable > range_len)
141.432 + fillable = range_len;
141.433 + if (fillable == 0)
141.434 + goto try_anywhere;
141.435 +
141.436 + /* Test if the left edge of the range is already mapped? */
141.437 + if (EXT2FS_CLUSTER_RATIO(fs) > 1) {
141.438 + err = ext2fs_map_cluster_block(fs, ino, inode,
141.439 + right_ext->e_lblk - fillable, &pblk);
141.440 + if (err)
141.441 + goto out;
141.442 + if (pblk)
141.443 + fillable -= EXT2FS_CLUSTER_RATIO(fs) -
141.444 + ((right_ext->e_lblk - fillable)
141.445 + & EXT2FS_CLUSTER_MASK(fs));
141.446 + if (fillable == 0)
141.447 + goto try_anywhere;
141.448 + }
141.449 +
141.450 + /*
141.451 + * FIXME: It would be nice if we could handle allocating a
141.452 + * variable range from a fixed end point instead of just
141.453 + * skipping to the general allocator if the whole range is
141.454 + * unavailable.
141.455 + */
141.456 + err = ext2fs_new_range(fs, EXT2_NEWRANGE_FIXED_GOAL |
141.457 + EXT2_NEWRANGE_MIN_LENGTH,
141.458 + right_ext->e_pblk - fillable,
141.459 + fillable, NULL, &pblk, &plen);
141.460 + if (err)
141.461 + goto try_anywhere;
141.462 + err = claim_range(fs, inode,
141.463 + pblk & ~EXT2FS_CLUSTER_MASK(fs),
141.464 + plen + (pblk & EXT2FS_CLUSTER_MASK(fs)));
141.465 + if (err)
141.466 + goto out;
141.467 +
141.468 + /* Modify right_ext */
141.469 + err = ext2fs_extent_goto(handle, right_ext->e_lblk);
141.470 + if (err)
141.471 + goto out;
141.472 + range_len -= plen;
141.473 + right_ext->e_lblk -= plen;
141.474 + right_ext->e_pblk -= plen;
141.475 + right_ext->e_len += plen;
141.476 + dbg_print_extent("ext_falloc right+", right_ext);
141.477 + err = ext2fs_extent_replace(handle, 0, right_ext);
141.478 + if (err)
141.479 + goto out;
141.480 + err = ext2fs_extent_fix_parents(handle);
141.481 + if (err)
141.482 + goto out;
141.483 +
141.484 + /* Zero blocks if necessary */
141.485 + if (!(right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
141.486 + (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) {
141.487 + err = ext2fs_zero_blocks2(fs, pblk,
141.488 + plen + cluster_fill, NULL, NULL);
141.489 + if (err)
141.490 + goto out;
141.491 + }
141.492 + }
141.493 +
141.494 +try_anywhere:
141.495 + /* Try implied cluster alloc on the left and right ends */
141.496 + if (range_len > 0 && (range_start & EXT2FS_CLUSTER_MASK(fs))) {
141.497 + cluster_fill = EXT2FS_CLUSTER_RATIO(fs) -
141.498 + (range_start & EXT2FS_CLUSTER_MASK(fs));
141.499 + cluster_fill &= EXT2FS_CLUSTER_MASK(fs);
141.500 + if (cluster_fill > range_len)
141.501 + cluster_fill = range_len;
141.502 + newex.e_lblk = range_start;
141.503 + err = ext2fs_map_cluster_block(fs, ino, inode, newex.e_lblk,
141.504 + &pblk);
141.505 + if (err)
141.506 + goto out;
141.507 + if (pblk == 0)
141.508 + goto try_right_implied;
141.509 + newex.e_pblk = pblk;
141.510 + newex.e_len = cluster_fill;
141.511 + newex.e_flags = (flags & EXT2_FALLOCATE_FORCE_INIT ? 0 :
141.512 + EXT2_EXTENT_FLAGS_UNINIT);
141.513 + dbg_print_extent("ext_falloc iclus left+", &newex);
141.514 + ext2fs_extent_goto(handle, newex.e_lblk);
141.515 + err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT,
141.516 + &ex);
141.517 + if (err == EXT2_ET_NO_CURRENT_NODE)
141.518 + ex.e_lblk = 0;
141.519 + else if (err)
141.520 + goto out;
141.521 +
141.522 + if (ex.e_lblk > newex.e_lblk)
141.523 + op = 0; /* insert before */
141.524 + else
141.525 + op = EXT2_EXTENT_INSERT_AFTER;
141.526 + dbg_printf("%s: inserting %s lblk %llu newex=%llu\n",
141.527 + __func__, op ? "after" : "before", ex.e_lblk,
141.528 + newex.e_lblk);
141.529 + err = ext2fs_extent_insert(handle, op, &newex);
141.530 + if (err)
141.531 + goto out;
141.532 + err = ext2fs_extent_fix_parents(handle);
141.533 + if (err)
141.534 + goto out;
141.535 +
141.536 + if (!(newex.e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
141.537 + (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) {
141.538 + err = ext2fs_zero_blocks2(fs, newex.e_pblk,
141.539 + newex.e_len, NULL, NULL);
141.540 + if (err)
141.541 + goto out;
141.542 + }
141.543 +
141.544 + range_start += cluster_fill;
141.545 + range_len -= cluster_fill;
141.546 + }
141.547 +
141.548 +try_right_implied:
141.549 + y = range_start + range_len;
141.550 + if (range_len > 0 && (y & EXT2FS_CLUSTER_MASK(fs))) {
141.551 + cluster_fill = y & EXT2FS_CLUSTER_MASK(fs);
141.552 + if (cluster_fill > range_len)
141.553 + cluster_fill = range_len;
141.554 + newex.e_lblk = y & ~EXT2FS_CLUSTER_MASK(fs);
141.555 + err = ext2fs_map_cluster_block(fs, ino, inode, newex.e_lblk,
141.556 + &pblk);
141.557 + if (err)
141.558 + goto out;
141.559 + if (pblk == 0)
141.560 + goto no_implied;
141.561 + newex.e_pblk = pblk;
141.562 + newex.e_len = cluster_fill;
141.563 + newex.e_flags = (flags & EXT2_FALLOCATE_FORCE_INIT ? 0 :
141.564 + EXT2_EXTENT_FLAGS_UNINIT);
141.565 + dbg_print_extent("ext_falloc iclus right+", &newex);
141.566 + ext2fs_extent_goto(handle, newex.e_lblk);
141.567 + err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT,
141.568 + &ex);
141.569 + if (err == EXT2_ET_NO_CURRENT_NODE)
141.570 + ex.e_lblk = 0;
141.571 + else if (err)
141.572 + goto out;
141.573 +
141.574 + if (ex.e_lblk > newex.e_lblk)
141.575 + op = 0; /* insert before */
141.576 + else
141.577 + op = EXT2_EXTENT_INSERT_AFTER;
141.578 + dbg_printf("%s: inserting %s lblk %llu newex=%llu\n",
141.579 + __func__, op ? "after" : "before", ex.e_lblk,
141.580 + newex.e_lblk);
141.581 + err = ext2fs_extent_insert(handle, op, &newex);
141.582 + if (err)
141.583 + goto out;
141.584 + err = ext2fs_extent_fix_parents(handle);
141.585 + if (err)
141.586 + goto out;
141.587 +
141.588 + if (!(newex.e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
141.589 + (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) {
141.590 + err = ext2fs_zero_blocks2(fs, newex.e_pblk,
141.591 + newex.e_len, NULL, NULL);
141.592 + if (err)
141.593 + goto out;
141.594 + }
141.595 +
141.596 + range_len -= cluster_fill;
141.597 + }
141.598 +
141.599 +no_implied:
141.600 + if (range_len == 0)
141.601 + return 0;
141.602 +
141.603 + newex.e_lblk = range_start;
141.604 + if (flags & EXT2_FALLOCATE_FORCE_INIT) {
141.605 + max_extent_len = max_init_len;
141.606 + newex.e_flags = 0;
141.607 + } else {
141.608 + max_extent_len = max_uninit_len;
141.609 + newex.e_flags = EXT2_EXTENT_FLAGS_UNINIT;
141.610 + }
141.611 + pblk = alloc_goal;
141.612 + y = range_len;
141.613 + for (x = 0; x < y;) {
141.614 + cluster_fill = newex.e_lblk & EXT2FS_CLUSTER_MASK(fs);
141.615 + fillable = min(range_len + cluster_fill, max_extent_len);
141.616 + err = ext2fs_new_range(fs, 0, pblk & ~EXT2FS_CLUSTER_MASK(fs),
141.617 + fillable,
141.618 + NULL, &pblk, &plen);
141.619 + if (err)
141.620 + goto out;
141.621 + err = claim_range(fs, inode, pblk, plen);
141.622 + if (err)
141.623 + goto out;
141.624 +
141.625 + /* Create extent */
141.626 + newex.e_pblk = pblk + cluster_fill;
141.627 + newex.e_len = plen - cluster_fill;
141.628 + dbg_print_extent("ext_falloc create", &newex);
141.629 + ext2fs_extent_goto(handle, newex.e_lblk);
141.630 + err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT,
141.631 + &ex);
141.632 + if (err == EXT2_ET_NO_CURRENT_NODE)
141.633 + ex.e_lblk = 0;
141.634 + else if (err)
141.635 + goto out;
141.636 +
141.637 + if (ex.e_lblk > newex.e_lblk)
141.638 + op = 0; /* insert before */
141.639 + else
141.640 + op = EXT2_EXTENT_INSERT_AFTER;
141.641 + dbg_printf("%s: inserting %s lblk %llu newex=%llu\n",
141.642 + __func__, op ? "after" : "before", ex.e_lblk,
141.643 + newex.e_lblk);
141.644 + err = ext2fs_extent_insert(handle, op, &newex);
141.645 + if (err)
141.646 + goto out;
141.647 + err = ext2fs_extent_fix_parents(handle);
141.648 + if (err)
141.649 + goto out;
141.650 +
141.651 + if (!(newex.e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
141.652 + (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) {
141.653 + err = ext2fs_zero_blocks2(fs, pblk, plen, NULL, NULL);
141.654 + if (err)
141.655 + goto out;
141.656 + }
141.657 +
141.658 + /* Update variables at end of loop */
141.659 + x += plen - cluster_fill;
141.660 + range_len -= plen - cluster_fill;
141.661 + newex.e_lblk += plen - cluster_fill;
141.662 + pblk += plen - cluster_fill;
141.663 + if (pblk >= ext2fs_blocks_count(fs->super))
141.664 + pblk = fs->super->s_first_data_block;
141.665 + }
141.666 +
141.667 +out:
141.668 + return err;
141.669 +}
141.670 +
141.671 +static errcode_t extent_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino,
141.672 + struct ext2_inode *inode, blk64_t goal,
141.673 + blk64_t start, blk64_t len)
141.674 +{
141.675 + ext2_extent_handle_t handle;
141.676 + struct ext2fs_extent left_extent, right_extent;
141.677 + struct ext2fs_extent *left_adjacent, *right_adjacent;
141.678 + errcode_t err;
141.679 + blk64_t range_start, range_end = 0, end, next;
141.680 + blk64_t count, goal_distance;
141.681 +
141.682 + end = start + len - 1;
141.683 + err = ext2fs_extent_open2(fs, ino, inode, &handle);
141.684 + if (err)
141.685 + return err;
141.686 +
141.687 + /*
141.688 + * Find the extent closest to the start of the alloc range. We don't
141.689 + * check the return value because _goto() sets the current node to the
141.690 + * next-lowest extent if 'start' is in a hole; or the next-highest
141.691 + * extent if there aren't any lower ones; or doesn't set a current node
141.692 + * if there was a real error reading the extent tree. In that case,
141.693 + * _get() will error out.
141.694 + */
141.695 +start_again:
141.696 + ext2fs_extent_goto(handle, start);
141.697 + err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &left_extent);
141.698 + if (err == EXT2_ET_NO_CURRENT_NODE) {
141.699 + blk64_t max_blocks = ext2fs_blocks_count(fs->super);
141.700 +
141.701 + if (goal == ~0ULL)
141.702 + goal = ext2fs_find_inode_goal(fs, ino, inode, start);
141.703 + err = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
141.704 + goal, max_blocks - 1, &goal);
141.705 + goal += start;
141.706 + err = ext_falloc_helper(fs, flags, ino, inode, handle, NULL,
141.707 + NULL, start, len, goal);
141.708 + goto errout;
141.709 + } else if (err)
141.710 + goto errout;
141.711 +
141.712 + dbg_print_extent("ext_falloc initial", &left_extent);
141.713 + next = left_extent.e_lblk + left_extent.e_len;
141.714 + if (left_extent.e_lblk > start) {
141.715 + /* The nearest extent we found was beyond start??? */
141.716 + goal = left_extent.e_pblk - (left_extent.e_lblk - start);
141.717 + err = ext_falloc_helper(fs, flags, ino, inode, handle, NULL,
141.718 + &left_extent, start,
141.719 + left_extent.e_lblk - start, goal);
141.720 + if (err)
141.721 + goto errout;
141.722 +
141.723 + goto start_again;
141.724 + } else if (next >= start) {
141.725 + range_start = next;
141.726 + left_adjacent = &left_extent;
141.727 + } else {
141.728 + range_start = start;
141.729 + left_adjacent = NULL;
141.730 + }
141.731 + goal = left_extent.e_pblk + (range_start - left_extent.e_lblk);
141.732 +
141.733 + do {
141.734 + err = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_LEAF,
141.735 + &right_extent);
141.736 + dbg_printf("%s: ino=%d get next =%d\n", __func__, ino,
141.737 + (int)err);
141.738 + dbg_print_extent("ext_falloc next", &right_extent);
141.739 + /* Stop if we've seen this extent before */
141.740 + if (!err && right_extent.e_lblk <= left_extent.e_lblk)
141.741 + err = EXT2_ET_EXTENT_NO_NEXT;
141.742 +
141.743 + if (err && err != EXT2_ET_EXTENT_NO_NEXT)
141.744 + goto errout;
141.745 + if (err == EXT2_ET_EXTENT_NO_NEXT ||
141.746 + right_extent.e_lblk > end + 1) {
141.747 + range_end = end;
141.748 + right_adjacent = NULL;
141.749 + } else {
141.750 + /* Handle right_extent.e_lblk <= end */
141.751 + range_end = right_extent.e_lblk - 1;
141.752 + right_adjacent = &right_extent;
141.753 + }
141.754 + goal_distance = range_start - next;
141.755 + if (err != EXT2_ET_EXTENT_NO_NEXT &&
141.756 + goal_distance > (range_end - right_extent.e_lblk))
141.757 + goal = right_extent.e_pblk -
141.758 + (right_extent.e_lblk - range_start);
141.759 +
141.760 + dbg_printf("%s: ino=%d rstart=%llu rend=%llu\n", __func__, ino,
141.761 + range_start, range_end);
141.762 + err = 0;
141.763 + if (range_start <= range_end) {
141.764 + count = range_end - range_start + 1;
141.765 + err = ext_falloc_helper(fs, flags, ino, inode, handle,
141.766 + left_adjacent, right_adjacent,
141.767 + range_start, count, goal);
141.768 + if (err)
141.769 + goto errout;
141.770 + }
141.771 +
141.772 + if (range_end == end)
141.773 + break;
141.774 +
141.775 + err = ext2fs_extent_goto(handle, right_extent.e_lblk);
141.776 + if (err)
141.777 + goto errout;
141.778 + next = right_extent.e_lblk + right_extent.e_len;
141.779 + left_extent = right_extent;
141.780 + left_adjacent = &left_extent;
141.781 + range_start = next;
141.782 + goal = left_extent.e_pblk + (range_start - left_extent.e_lblk);
141.783 + } while (range_end < end);
141.784 +
141.785 +errout:
141.786 + ext2fs_extent_free(handle);
141.787 + return err;
141.788 +}
141.789 +
141.790 +/*
141.791 + * Map physical blocks to a range of logical blocks within a file. The range
141.792 + * of logical blocks are (start, start + len). If there are already extents,
141.793 + * the mappings will try to extend the mappings; otherwise, it will try to map
141.794 + * start as if logical block 0 points to goal. If goal is ~0ULL, then the goal
141.795 + * is calculated based on the inode group.
141.796 + *
141.797 + * Flags:
141.798 + * - EXT2_FALLOCATE_ZERO_BLOCKS: Zero the blocks that are allocated.
141.799 + * - EXT2_FALLOCATE_FORCE_INIT: Create only initialized extents.
141.800 + * - EXT2_FALLOCATE_FORCE_UNINIT: Create only uninitialized extents.
141.801 + * - EXT2_FALLOCATE_INIT_BEYOND_EOF: Create extents beyond EOF.
141.802 + *
141.803 + * If neither FORCE_INIT nor FORCE_UNINIT are specified, this function will
141.804 + * try to expand any extents it finds, zeroing blocks as necessary.
141.805 + */
141.806 +errcode_t ext2fs_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino,
141.807 + struct ext2_inode *inode, blk64_t goal,
141.808 + blk64_t start, blk64_t len)
141.809 +{
141.810 + struct ext2_inode inode_buf;
141.811 + blk64_t blk, x;
141.812 + errcode_t err;
141.813 +
141.814 + if (((flags & EXT2_FALLOCATE_FORCE_INIT) &&
141.815 + (flags & EXT2_FALLOCATE_FORCE_UNINIT)) ||
141.816 + (flags & ~EXT2_FALLOCATE_ALL_FLAGS))
141.817 + return EXT2_ET_INVALID_ARGUMENT;
141.818 +
141.819 + if (len > ext2fs_blocks_count(fs->super))
141.820 + return EXT2_ET_BLOCK_ALLOC_FAIL;
141.821 + else if (len == 0)
141.822 + return 0;
141.823 +
141.824 + /* Read inode structure if necessary */
141.825 + if (!inode) {
141.826 + err = ext2fs_read_inode(fs, ino, &inode_buf);
141.827 + if (err)
141.828 + return err;
141.829 + inode = &inode_buf;
141.830 + }
141.831 + dbg_printf("%s: ino=%d start=%llu len=%llu goal=%llu\n", __func__, ino,
141.832 + start, len, goal);
141.833 +
141.834 + if (inode->i_flags & EXT4_EXTENTS_FL) {
141.835 + err = extent_fallocate(fs, flags, ino, inode, goal, start, len);
141.836 + goto out;
141.837 + }
141.838 +
141.839 + /* XXX: Allocate a bunch of blocks the slow way */
141.840 + for (blk = start; blk < start + len; blk++) {
141.841 + err = ext2fs_bmap2(fs, ino, inode, NULL, 0, blk, 0, &x);
141.842 + if (err)
141.843 + return err;
141.844 + if (x)
141.845 + continue;
141.846 +
141.847 + err = ext2fs_bmap2(fs, ino, inode, NULL,
141.848 + BMAP_ALLOC | BMAP_UNINIT | BMAP_ZERO, blk,
141.849 + 0, &x);
141.850 + if (err)
141.851 + return err;
141.852 + }
141.853 +
141.854 +out:
141.855 + if (inode == &inode_buf)
141.856 + ext2fs_write_inode(fs, ino, inode);
141.857 + return err;
141.858 +}
142.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
142.2 +++ b/libext2fs/lib/libext2fs/fiemap.h Wed Aug 25 01:28:08 2021 +0200
142.3 @@ -0,0 +1,77 @@
142.4 +/*
142.5 + * FS_IOC_FIEMAP ioctl infrastructure.
142.6 + *
142.7 + * Some portions copyright (C) 2007 Cluster File Systems, Inc
142.8 + *
142.9 + * Authors: Mark Fasheh <mfasheh@suse.com>
142.10 + * Kalpak Shah <kalpak.shah@sun.com>
142.11 + * Andreas Dilger <adilger@sun.com>
142.12 + */
142.13 +
142.14 +#ifndef _LINUX_FIEMAP_H
142.15 +#define _LINUX_FIEMAP_H
142.16 +
142.17 +struct fiemap_extent {
142.18 + __u64 fe_logical; /* logical offset in bytes for the start of
142.19 + * the extent from the beginning of the file */
142.20 + __u64 fe_physical; /* physical offset in bytes for the start
142.21 + * of the extent from the beginning of the disk */
142.22 + __u64 fe_length; /* length in bytes for this extent */
142.23 + __u64 fe_reserved64[2];
142.24 + __u32 fe_flags; /* FIEMAP_EXTENT_* flags for this extent */
142.25 + __u32 fe_reserved[3];
142.26 +};
142.27 +
142.28 +struct fiemap {
142.29 + __u64 fm_start; /* logical offset (inclusive) at
142.30 + * which to start mapping (in) */
142.31 + __u64 fm_length; /* logical length of mapping which
142.32 + * userspace wants (in) */
142.33 + __u32 fm_flags; /* FIEMAP_FLAG_* flags for request (in/out) */
142.34 + __u32 fm_mapped_extents;/* number of extents that were mapped (out) */
142.35 + __u32 fm_extent_count; /* size of fm_extents array (in) */
142.36 + __u32 fm_reserved;
142.37 +#if __GNUC_PREREQ (4, 8)
142.38 +#pragma GCC diagnostic push
142.39 +#pragma GCC diagnostic ignored "-Wpedantic"
142.40 +#endif
142.41 + struct fiemap_extent fm_extents[0]; /* array of mapped extents (out) */
142.42 +#if __GNUC_PREREQ (4, 8)
142.43 +#pragma GCC diagnostic pop
142.44 +#endif
142.45 +};
142.46 +
142.47 +#if defined(__linux__) && !defined(FS_IOC_FIEMAP)
142.48 +#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap)
142.49 +#endif
142.50 +
142.51 +#define FIEMAP_MAX_OFFSET (~0ULL)
142.52 +
142.53 +#define FIEMAP_FLAG_SYNC 0x00000001 /* sync file data before map */
142.54 +#define FIEMAP_FLAG_XATTR 0x00000002 /* map extended attribute tree */
142.55 +
142.56 +#define FIEMAP_FLAGS_COMPAT (FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR)
142.57 +
142.58 +#define FIEMAP_EXTENT_LAST 0x00000001 /* Last extent in file. */
142.59 +#define FIEMAP_EXTENT_UNKNOWN 0x00000002 /* Data location unknown. */
142.60 +#define FIEMAP_EXTENT_DELALLOC 0x00000004 /* Location still pending.
142.61 + * Sets EXTENT_UNKNOWN. */
142.62 +#define FIEMAP_EXTENT_ENCODED 0x00000008 /* Data can not be read
142.63 + * while fs is unmounted */
142.64 +#define FIEMAP_EXTENT_DATA_ENCRYPTED 0x00000080 /* Data is encrypted by fs.
142.65 + * Sets EXTENT_NO_BYPASS. */
142.66 +#define FIEMAP_EXTENT_NOT_ALIGNED 0x00000100 /* Extent offsets may not be
142.67 + * block aligned. */
142.68 +#define FIEMAP_EXTENT_DATA_INLINE 0x00000200 /* Data mixed with metadata.
142.69 + * Sets EXTENT_NOT_ALIGNED.*/
142.70 +#define FIEMAP_EXTENT_DATA_TAIL 0x00000400 /* Multiple files in block.
142.71 + * Sets EXTENT_NOT_ALIGNED.*/
142.72 +#define FIEMAP_EXTENT_UNWRITTEN 0x00000800 /* Space allocated, but
142.73 + * no data (i.e. zero). */
142.74 +#define FIEMAP_EXTENT_MERGED 0x00001000 /* File does not natively
142.75 + * support extents. Result
142.76 + * merged for efficiency. */
142.77 +#define FIEMAP_EXTENT_SHARED 0x00002000 /* Space shared with other
142.78 + * files. */
142.79 +
142.80 +#endif /* _LINUX_FIEMAP_H */
143.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
143.2 +++ b/libext2fs/lib/libext2fs/fileio.c Wed Aug 25 01:28:08 2021 +0200
143.3 @@ -0,0 +1,660 @@
143.4 +/*
143.5 + * fileio.c --- Simple file I/O routines
143.6 + *
143.7 + * Copyright (C) 1997 Theodore Ts'o.
143.8 + *
143.9 + * %Begin-Header%
143.10 + * This file may be redistributed under the terms of the GNU Library
143.11 + * General Public License, version 2.
143.12 + * %End-Header%
143.13 + */
143.14 +
143.15 +#include "config.h"
143.16 +#include <stdio.h>
143.17 +#include <string.h>
143.18 +#if HAVE_UNISTD_H
143.19 +#include <unistd.h>
143.20 +#endif
143.21 +
143.22 +#include "ext2_fs.h"
143.23 +#include "ext2fs.h"
143.24 +#include "ext2fsP.h"
143.25 +
143.26 +struct ext2_file {
143.27 + errcode_t magic;
143.28 + ext2_filsys fs;
143.29 + ext2_ino_t ino;
143.30 + struct ext2_inode inode;
143.31 + int flags;
143.32 + __u64 pos;
143.33 + blk64_t blockno;
143.34 + blk64_t physblock;
143.35 + char *buf;
143.36 +};
143.37 +
143.38 +struct block_entry {
143.39 + blk64_t physblock;
143.40 + unsigned char sha[EXT2FS_SHA512_LENGTH];
143.41 +};
143.42 +typedef struct block_entry *block_entry_t;
143.43 +
143.44 +#define BMAP_BUFFER (file->buf + fs->blocksize)
143.45 +
143.46 +errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
143.47 + struct ext2_inode *inode,
143.48 + int flags, ext2_file_t *ret)
143.49 +{
143.50 + ext2_file_t file;
143.51 + errcode_t retval;
143.52 +
143.53 + /*
143.54 + * Don't let caller create or open a file for writing if the
143.55 + * filesystem is read-only.
143.56 + */
143.57 + if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) &&
143.58 + !(fs->flags & EXT2_FLAG_RW))
143.59 + return EXT2_ET_RO_FILSYS;
143.60 +
143.61 + retval = ext2fs_get_mem(sizeof(struct ext2_file), &file);
143.62 + if (retval)
143.63 + return retval;
143.64 +
143.65 + memset(file, 0, sizeof(struct ext2_file));
143.66 + file->magic = EXT2_ET_MAGIC_EXT2_FILE;
143.67 + file->fs = fs;
143.68 + file->ino = ino;
143.69 + file->flags = flags & EXT2_FILE_MASK;
143.70 +
143.71 + if (inode) {
143.72 + memcpy(&file->inode, inode, sizeof(struct ext2_inode));
143.73 + } else {
143.74 + retval = ext2fs_read_inode(fs, ino, &file->inode);
143.75 + if (retval)
143.76 + goto fail;
143.77 + }
143.78 +
143.79 + retval = ext2fs_get_array(3, fs->blocksize, &file->buf);
143.80 + if (retval)
143.81 + goto fail;
143.82 +
143.83 + *ret = file;
143.84 + return 0;
143.85 +
143.86 +fail:
143.87 + if (file->buf)
143.88 + ext2fs_free_mem(&file->buf);
143.89 + ext2fs_free_mem(&file);
143.90 + return retval;
143.91 +}
143.92 +
143.93 +errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
143.94 + int flags, ext2_file_t *ret)
143.95 +{
143.96 + return ext2fs_file_open2(fs, ino, NULL, flags, ret);
143.97 +}
143.98 +
143.99 +/*
143.100 + * This function returns the filesystem handle of a file from the structure
143.101 + */
143.102 +ext2_filsys ext2fs_file_get_fs(ext2_file_t file)
143.103 +{
143.104 + if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
143.105 + return 0;
143.106 + return file->fs;
143.107 +}
143.108 +
143.109 +/*
143.110 + * This function returns the pointer to the inode of a file from the structure
143.111 + */
143.112 +struct ext2_inode *ext2fs_file_get_inode(ext2_file_t file)
143.113 +{
143.114 + if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
143.115 + return NULL;
143.116 + return &file->inode;
143.117 +}
143.118 +
143.119 +/* This function returns the inode number from the structure */
143.120 +ext2_ino_t ext2fs_file_get_inode_num(ext2_file_t file)
143.121 +{
143.122 + if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
143.123 + return 0;
143.124 + return file->ino;
143.125 +}
143.126 +
143.127 +/*
143.128 + * This function flushes the dirty block buffer out to disk if
143.129 + * necessary.
143.130 + */
143.131 +errcode_t ext2fs_file_flush(ext2_file_t file)
143.132 +{
143.133 + errcode_t retval;
143.134 + ext2_filsys fs;
143.135 + int ret_flags;
143.136 + blk64_t dontcare;
143.137 +
143.138 + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
143.139 + fs = file->fs;
143.140 +
143.141 + if (!(file->flags & EXT2_FILE_BUF_VALID) ||
143.142 + !(file->flags & EXT2_FILE_BUF_DIRTY))
143.143 + return 0;
143.144 +
143.145 + /* Is this an uninit block? */
143.146 + if (file->physblock && file->inode.i_flags & EXT4_EXTENTS_FL) {
143.147 + retval = ext2fs_bmap2(fs, file->ino, &file->inode, BMAP_BUFFER,
143.148 + 0, file->blockno, &ret_flags, &dontcare);
143.149 + if (retval)
143.150 + return retval;
143.151 + if (ret_flags & BMAP_RET_UNINIT) {
143.152 + retval = ext2fs_bmap2(fs, file->ino, &file->inode,
143.153 + BMAP_BUFFER, BMAP_SET,
143.154 + file->blockno, 0,
143.155 + &file->physblock);
143.156 + if (retval)
143.157 + return retval;
143.158 + }
143.159 + }
143.160 +
143.161 + /*
143.162 + * OK, the physical block hasn't been allocated yet.
143.163 + * Allocate it.
143.164 + */
143.165 + if (!file->physblock) {
143.166 + retval = ext2fs_bmap2(fs, file->ino, &file->inode,
143.167 + BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0,
143.168 + file->blockno, 0, &file->physblock);
143.169 + if (retval)
143.170 + return retval;
143.171 + }
143.172 +
143.173 + retval = io_channel_write_blk64(fs->io, file->physblock, 1, file->buf);
143.174 + if (retval)
143.175 + return retval;
143.176 +
143.177 + file->flags &= ~EXT2_FILE_BUF_DIRTY;
143.178 +
143.179 + return retval;
143.180 +}
143.181 +
143.182 +/*
143.183 + * This function synchronizes the file's block buffer and the current
143.184 + * file position, possibly invalidating block buffer if necessary
143.185 + */
143.186 +static errcode_t sync_buffer_position(ext2_file_t file)
143.187 +{
143.188 + blk64_t b;
143.189 + errcode_t retval;
143.190 +
143.191 + b = file->pos / file->fs->blocksize;
143.192 + if (b != file->blockno) {
143.193 + retval = ext2fs_file_flush(file);
143.194 + if (retval)
143.195 + return retval;
143.196 + file->flags &= ~EXT2_FILE_BUF_VALID;
143.197 + }
143.198 + file->blockno = b;
143.199 + return 0;
143.200 +}
143.201 +
143.202 +/*
143.203 + * This function loads the file's block buffer with valid data from
143.204 + * the disk as necessary.
143.205 + *
143.206 + * If dontfill is true, then skip initializing the buffer since we're
143.207 + * going to be replacing its entire contents anyway. If set, then the
143.208 + * function basically only sets file->physblock and EXT2_FILE_BUF_VALID
143.209 + */
143.210 +#define DONTFILL 1
143.211 +static errcode_t load_buffer(ext2_file_t file, int dontfill)
143.212 +{
143.213 + ext2_filsys fs = file->fs;
143.214 + errcode_t retval;
143.215 + int ret_flags;
143.216 +
143.217 + if (!(file->flags & EXT2_FILE_BUF_VALID)) {
143.218 + retval = ext2fs_bmap2(fs, file->ino, &file->inode,
143.219 + BMAP_BUFFER, 0, file->blockno, &ret_flags,
143.220 + &file->physblock);
143.221 + if (retval)
143.222 + return retval;
143.223 + if (!dontfill) {
143.224 + if (file->physblock &&
143.225 + !(ret_flags & BMAP_RET_UNINIT)) {
143.226 + retval = io_channel_read_blk64(fs->io,
143.227 + file->physblock,
143.228 + 1, file->buf);
143.229 + if (retval)
143.230 + return retval;
143.231 + } else
143.232 + memset(file->buf, 0, fs->blocksize);
143.233 + }
143.234 + file->flags |= EXT2_FILE_BUF_VALID;
143.235 + }
143.236 + return 0;
143.237 +}
143.238 +
143.239 +
143.240 +errcode_t ext2fs_file_close(ext2_file_t file)
143.241 +{
143.242 + errcode_t retval;
143.243 +
143.244 + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
143.245 +
143.246 + retval = ext2fs_file_flush(file);
143.247 +
143.248 + if (file->buf)
143.249 + ext2fs_free_mem(&file->buf);
143.250 + ext2fs_free_mem(&file);
143.251 +
143.252 + return retval;
143.253 +}
143.254 +
143.255 +
143.256 +static errcode_t
143.257 +ext2fs_file_read_inline_data(ext2_file_t file, void *buf,
143.258 + unsigned int wanted, unsigned int *got)
143.259 +{
143.260 + ext2_filsys fs;
143.261 + errcode_t retval;
143.262 + unsigned int count = 0;
143.263 + size_t size;
143.264 +
143.265 + fs = file->fs;
143.266 + retval = ext2fs_inline_data_get(fs, file->ino, &file->inode,
143.267 + file->buf, &size);
143.268 + if (retval)
143.269 + return retval;
143.270 +
143.271 + if (file->pos >= size)
143.272 + goto out;
143.273 +
143.274 + count = size - file->pos;
143.275 + if (count > wanted)
143.276 + count = wanted;
143.277 + memcpy(buf, file->buf + file->pos, count);
143.278 + file->pos += count;
143.279 + buf = (char *) buf + count;
143.280 +
143.281 +out:
143.282 + if (got)
143.283 + *got = count;
143.284 + return retval;
143.285 +}
143.286 +
143.287 +
143.288 +errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
143.289 + unsigned int wanted, unsigned int *got)
143.290 +{
143.291 + ext2_filsys fs;
143.292 + errcode_t retval = 0;
143.293 + unsigned int start, c, count = 0;
143.294 + __u64 left;
143.295 + char *ptr = (char *) buf;
143.296 +
143.297 + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
143.298 + fs = file->fs;
143.299 +
143.300 + /* If an inode has inline data, things get complicated. */
143.301 + if (file->inode.i_flags & EXT4_INLINE_DATA_FL)
143.302 + return ext2fs_file_read_inline_data(file, buf, wanted, got);
143.303 +
143.304 + while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) {
143.305 + retval = sync_buffer_position(file);
143.306 + if (retval)
143.307 + goto fail;
143.308 + retval = load_buffer(file, 0);
143.309 + if (retval)
143.310 + goto fail;
143.311 +
143.312 + start = file->pos % fs->blocksize;
143.313 + c = fs->blocksize - start;
143.314 + if (c > wanted)
143.315 + c = wanted;
143.316 + left = EXT2_I_SIZE(&file->inode) - file->pos ;
143.317 + if (c > left)
143.318 + c = left;
143.319 +
143.320 + memcpy(ptr, file->buf+start, c);
143.321 + file->pos += c;
143.322 + ptr += c;
143.323 + count += c;
143.324 + wanted -= c;
143.325 + }
143.326 +
143.327 +fail:
143.328 + if (got)
143.329 + *got = count;
143.330 + return retval;
143.331 +}
143.332 +
143.333 +
143.334 +static errcode_t
143.335 +ext2fs_file_write_inline_data(ext2_file_t file, const void *buf,
143.336 + unsigned int nbytes, unsigned int *written)
143.337 +{
143.338 + ext2_filsys fs;
143.339 + errcode_t retval;
143.340 + unsigned int count = 0;
143.341 + size_t size;
143.342 +
143.343 + fs = file->fs;
143.344 + retval = ext2fs_inline_data_get(fs, file->ino, &file->inode,
143.345 + file->buf, &size);
143.346 + if (retval)
143.347 + return retval;
143.348 +
143.349 + if (file->pos < size) {
143.350 + count = nbytes - file->pos;
143.351 + memcpy(file->buf + file->pos, buf, count);
143.352 +
143.353 + retval = ext2fs_inline_data_set(fs, file->ino, &file->inode,
143.354 + file->buf, count);
143.355 + if (retval == EXT2_ET_INLINE_DATA_NO_SPACE)
143.356 + goto expand;
143.357 + if (retval)
143.358 + return retval;
143.359 +
143.360 + file->pos += count;
143.361 +
143.362 + /* Update inode size */
143.363 + if (count != 0 && EXT2_I_SIZE(&file->inode) < file->pos) {
143.364 + errcode_t rc;
143.365 +
143.366 + rc = ext2fs_file_set_size2(file, file->pos);
143.367 + if (retval == 0)
143.368 + retval = rc;
143.369 + }
143.370 +
143.371 + if (written)
143.372 + *written = count;
143.373 + return 0;
143.374 + }
143.375 +
143.376 +expand:
143.377 + retval = ext2fs_inline_data_expand(fs, file->ino);
143.378 + if (retval)
143.379 + return retval;
143.380 + /*
143.381 + * reload inode and return no space error
143.382 + *
143.383 + * XXX: file->inode could be copied from the outside
143.384 + * in ext2fs_file_open2(). We have no way to modify
143.385 + * the outside inode.
143.386 + */
143.387 + retval = ext2fs_read_inode(fs, file->ino, &file->inode);
143.388 + if (retval)
143.389 + return retval;
143.390 + return EXT2_ET_INLINE_DATA_NO_SPACE;
143.391 +}
143.392 +
143.393 +
143.394 +errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
143.395 + unsigned int nbytes, unsigned int *written)
143.396 +{
143.397 + ext2_filsys fs;
143.398 + errcode_t retval = 0;
143.399 + unsigned int start, c, count = 0;
143.400 + const char *ptr = (const char *) buf;
143.401 + block_entry_t new_block = NULL, old_block = NULL;
143.402 + int bmap_flags = 0;
143.403 +
143.404 + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
143.405 + fs = file->fs;
143.406 +
143.407 + if (!(file->flags & EXT2_FILE_WRITE))
143.408 + return EXT2_ET_FILE_RO;
143.409 +
143.410 + /* If an inode has inline data, things get complicated. */
143.411 + if (file->inode.i_flags & EXT4_INLINE_DATA_FL) {
143.412 + retval = ext2fs_file_write_inline_data(file, buf, nbytes,
143.413 + written);
143.414 + if (retval != EXT2_ET_INLINE_DATA_NO_SPACE)
143.415 + return retval;
143.416 + /* fall through to read data from the block */
143.417 + retval = 0;
143.418 + }
143.419 +
143.420 + while (nbytes > 0) {
143.421 + retval = sync_buffer_position(file);
143.422 + if (retval)
143.423 + goto fail;
143.424 +
143.425 + start = file->pos % fs->blocksize;
143.426 + c = fs->blocksize - start;
143.427 + if (c > nbytes)
143.428 + c = nbytes;
143.429 +
143.430 + /*
143.431 + * We only need to do a read-modify-update cycle if
143.432 + * we're doing a partial write.
143.433 + */
143.434 + retval = load_buffer(file, (c == fs->blocksize));
143.435 + if (retval)
143.436 + goto fail;
143.437 +
143.438 + file->flags |= EXT2_FILE_BUF_DIRTY;
143.439 + memcpy(file->buf+start, ptr, c);
143.440 +
143.441 + /*
143.442 + * OK, the physical block hasn't been allocated yet.
143.443 + * Allocate it.
143.444 + */
143.445 + if (!file->physblock) {
143.446 + bmap_flags = (file->ino ? BMAP_ALLOC : 0);
143.447 + if (fs->flags & EXT2_FLAG_SHARE_DUP) {
143.448 + new_block = calloc(1, sizeof(*new_block));
143.449 + if (!new_block) {
143.450 + retval = EXT2_ET_NO_MEMORY;
143.451 + goto fail;
143.452 + }
143.453 + ext2fs_sha512((const unsigned char*)file->buf,
143.454 + fs->blocksize, new_block->sha);
143.455 + old_block = ext2fs_hashmap_lookup(
143.456 + fs->block_sha_map,
143.457 + new_block->sha,
143.458 + sizeof(new_block->sha));
143.459 + }
143.460 +
143.461 + if (old_block) {
143.462 + file->physblock = old_block->physblock;
143.463 + bmap_flags |= BMAP_SET;
143.464 + free(new_block);
143.465 + new_block = NULL;
143.466 + }
143.467 +
143.468 + retval = ext2fs_bmap2(fs, file->ino, &file->inode,
143.469 + BMAP_BUFFER,
143.470 + bmap_flags,
143.471 + file->blockno, 0,
143.472 + &file->physblock);
143.473 + if (retval) {
143.474 + free(new_block);
143.475 + new_block = NULL;
143.476 + goto fail;
143.477 + }
143.478 +
143.479 + if (new_block) {
143.480 + new_block->physblock = file->physblock;
143.481 + ext2fs_hashmap_add(fs->block_sha_map, new_block,
143.482 + new_block->sha, sizeof(new_block->sha));
143.483 + }
143.484 +
143.485 + if (bmap_flags & BMAP_SET) {
143.486 + ext2fs_iblk_add_blocks(fs, &file->inode, 1);
143.487 + ext2fs_write_inode(fs, file->ino, &file->inode);
143.488 + }
143.489 + }
143.490 +
143.491 + file->pos += c;
143.492 + ptr += c;
143.493 + count += c;
143.494 + nbytes -= c;
143.495 + }
143.496 +
143.497 +fail:
143.498 + /* Update inode size */
143.499 + if (count != 0 && EXT2_I_SIZE(&file->inode) < file->pos) {
143.500 + errcode_t rc;
143.501 +
143.502 + rc = ext2fs_file_set_size2(file, file->pos);
143.503 + if (retval == 0)
143.504 + retval = rc;
143.505 + }
143.506 +
143.507 + if (written)
143.508 + *written = count;
143.509 + return retval;
143.510 +}
143.511 +
143.512 +errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
143.513 + int whence, __u64 *ret_pos)
143.514 +{
143.515 + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
143.516 +
143.517 + if (whence == EXT2_SEEK_SET)
143.518 + file->pos = offset;
143.519 + else if (whence == EXT2_SEEK_CUR)
143.520 + file->pos += offset;
143.521 + else if (whence == EXT2_SEEK_END)
143.522 + file->pos = EXT2_I_SIZE(&file->inode) + offset;
143.523 + else
143.524 + return EXT2_ET_INVALID_ARGUMENT;
143.525 +
143.526 + if (ret_pos)
143.527 + *ret_pos = file->pos;
143.528 +
143.529 + return 0;
143.530 +}
143.531 +
143.532 +errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
143.533 + int whence, ext2_off_t *ret_pos)
143.534 +{
143.535 + __u64 loffset, ret_loffset = 0;
143.536 + errcode_t retval;
143.537 +
143.538 + loffset = offset;
143.539 + retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset);
143.540 + if (ret_pos)
143.541 + *ret_pos = (ext2_off_t) ret_loffset;
143.542 + return retval;
143.543 +}
143.544 +
143.545 +
143.546 +/*
143.547 + * This function returns the size of the file, according to the inode
143.548 + */
143.549 +errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size)
143.550 +{
143.551 + if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
143.552 + return EXT2_ET_MAGIC_EXT2_FILE;
143.553 + *ret_size = EXT2_I_SIZE(&file->inode);
143.554 + return 0;
143.555 +}
143.556 +
143.557 +/*
143.558 + * This function returns the size of the file, according to the inode
143.559 + */
143.560 +ext2_off_t ext2fs_file_get_size(ext2_file_t file)
143.561 +{
143.562 + __u64 size;
143.563 +
143.564 + if (ext2fs_file_get_lsize(file, &size))
143.565 + return 0;
143.566 + if ((size >> 32) != 0)
143.567 + return 0;
143.568 + return size;
143.569 +}
143.570 +
143.571 +/* Zero the parts of the last block that are past EOF. */
143.572 +static errcode_t ext2fs_file_zero_past_offset(ext2_file_t file,
143.573 + ext2_off64_t offset)
143.574 +{
143.575 + ext2_filsys fs = file->fs;
143.576 + char *b = NULL;
143.577 + ext2_off64_t off = offset % fs->blocksize;
143.578 + blk64_t blk;
143.579 + int ret_flags;
143.580 + errcode_t retval;
143.581 +
143.582 + if (off == 0)
143.583 + return 0;
143.584 +
143.585 + retval = sync_buffer_position(file);
143.586 + if (retval)
143.587 + return retval;
143.588 +
143.589 + /* Is there an initialized block at the end? */
143.590 + retval = ext2fs_bmap2(fs, file->ino, NULL, NULL, 0,
143.591 + offset / fs->blocksize, &ret_flags, &blk);
143.592 + if (retval)
143.593 + return retval;
143.594 + if ((blk == 0) || (ret_flags & BMAP_RET_UNINIT))
143.595 + return 0;
143.596 +
143.597 + /* Zero to the end of the block */
143.598 + retval = ext2fs_get_mem(fs->blocksize, &b);
143.599 + if (retval)
143.600 + return retval;
143.601 +
143.602 + /* Read/zero/write block */
143.603 + retval = io_channel_read_blk64(fs->io, blk, 1, b);
143.604 + if (retval)
143.605 + goto out;
143.606 +
143.607 + memset(b + off, 0, fs->blocksize - off);
143.608 +
143.609 + retval = io_channel_write_blk64(fs->io, blk, 1, b);
143.610 + if (retval)
143.611 + goto out;
143.612 +
143.613 +out:
143.614 + ext2fs_free_mem(&b);
143.615 + return retval;
143.616 +}
143.617 +
143.618 +/*
143.619 + * This function sets the size of the file, truncating it if necessary
143.620 + *
143.621 + */
143.622 +errcode_t ext2fs_file_set_size2(ext2_file_t file, ext2_off64_t size)
143.623 +{
143.624 + ext2_off64_t old_size;
143.625 + errcode_t retval;
143.626 + blk64_t old_truncate, truncate_block;
143.627 +
143.628 + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
143.629 +
143.630 + if (size && ext2fs_file_block_offset_too_big(file->fs, &file->inode,
143.631 + (size - 1) / file->fs->blocksize))
143.632 + return EXT2_ET_FILE_TOO_BIG;
143.633 + truncate_block = ((size + file->fs->blocksize - 1) >>
143.634 + EXT2_BLOCK_SIZE_BITS(file->fs->super));
143.635 + old_size = EXT2_I_SIZE(&file->inode);
143.636 + old_truncate = ((old_size + file->fs->blocksize - 1) >>
143.637 + EXT2_BLOCK_SIZE_BITS(file->fs->super));
143.638 +
143.639 + retval = ext2fs_inode_size_set(file->fs, &file->inode, size);
143.640 + if (retval)
143.641 + return retval;
143.642 +
143.643 + if (file->ino) {
143.644 + retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
143.645 + if (retval)
143.646 + return retval;
143.647 + }
143.648 +
143.649 + retval = ext2fs_file_zero_past_offset(file, size);
143.650 + if (retval)
143.651 + return retval;
143.652 +
143.653 + if (truncate_block >= old_truncate)
143.654 + return 0;
143.655 +
143.656 + return ext2fs_punch(file->fs, file->ino, &file->inode, 0,
143.657 + truncate_block, ~0ULL);
143.658 +}
143.659 +
143.660 +errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size)
143.661 +{
143.662 + return ext2fs_file_set_size2(file, size);
143.663 +}
144.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
144.2 +++ b/libext2fs/lib/libext2fs/finddev.c Wed Aug 25 01:28:08 2021 +0200
144.3 @@ -0,0 +1,218 @@
144.4 +/*
144.5 + * finddev.c -- this routine attempts to find a particular device in
144.6 + * /dev
144.7 + *
144.8 + * Copyright (C) 2000 Theodore Ts'o.
144.9 + *
144.10 + * %Begin-Header%
144.11 + * This file may be redistributed under the terms of the GNU Library
144.12 + * General Public License, version 2.
144.13 + * %End-Header%
144.14 + */
144.15 +
144.16 +#include "config.h"
144.17 +#include <stdio.h>
144.18 +#include <string.h>
144.19 +#if HAVE_UNISTD_H
144.20 +#include <unistd.h>
144.21 +#endif
144.22 +#include <stdlib.h>
144.23 +#include <string.h>
144.24 +#if HAVE_SYS_TYPES_H
144.25 +#include <sys/types.h>
144.26 +#endif
144.27 +#if HAVE_SYS_STAT_H
144.28 +#include <sys/stat.h>
144.29 +#endif
144.30 +#include <dirent.h>
144.31 +#if HAVE_ERRNO_H
144.32 +#include <errno.h>
144.33 +#endif
144.34 +#if HAVE_SYS_MKDEV_H
144.35 +#include <sys/mkdev.h>
144.36 +#endif
144.37 +#ifdef HAVE_SYS_SYSMACROS_H
144.38 +#include <sys/sysmacros.h>
144.39 +#endif
144.40 +
144.41 +#include "ext2_fs.h"
144.42 +#include "ext2fs.h"
144.43 +#include "ext2fsP.h"
144.44 +
144.45 +struct dir_list {
144.46 + char *name;
144.47 + struct dir_list *next;
144.48 +};
144.49 +
144.50 +/*
144.51 + * This function adds an entry to the directory list
144.52 + */
144.53 +static void add_to_dirlist(const char *name, struct dir_list **list)
144.54 +{
144.55 + struct dir_list *dp;
144.56 +
144.57 + dp = malloc(sizeof(struct dir_list));
144.58 + if (!dp)
144.59 + return;
144.60 + dp->name = malloc(strlen(name)+1);
144.61 + if (!dp->name) {
144.62 + free(dp);
144.63 + return;
144.64 + }
144.65 + strcpy(dp->name, name);
144.66 + dp->next = *list;
144.67 + *list = dp;
144.68 +}
144.69 +
144.70 +/*
144.71 + * This function frees a directory list
144.72 + */
144.73 +static void free_dirlist(struct dir_list **list)
144.74 +{
144.75 + struct dir_list *dp, *next;
144.76 +
144.77 + for (dp = *list; dp; dp = next) {
144.78 + next = dp->next;
144.79 + free(dp->name);
144.80 + free(dp);
144.81 + }
144.82 + *list = 0;
144.83 +}
144.84 +
144.85 +static int scan_dir(char *dirname, dev_t device, struct dir_list **list,
144.86 + char **ret_path)
144.87 +{
144.88 + DIR *dir;
144.89 + struct dirent *dp;
144.90 + char path[1024], *cp;
144.91 + int dirlen;
144.92 + struct stat st;
144.93 +
144.94 + dirlen = strlen(dirname);
144.95 + if ((dir = opendir(dirname)) == NULL)
144.96 + return errno;
144.97 + dp = readdir(dir);
144.98 + while (dp) {
144.99 + if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path))
144.100 + goto skip_to_next;
144.101 + if (dp->d_name[0] == '.' &&
144.102 + ((dp->d_name[1] == 0) ||
144.103 + ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
144.104 + goto skip_to_next;
144.105 + sprintf(path, "%s/%s", dirname, dp->d_name);
144.106 + if (stat(path, &st) < 0)
144.107 + goto skip_to_next;
144.108 + if (S_ISDIR(st.st_mode))
144.109 + add_to_dirlist(path, list);
144.110 + if (ext2fsP_is_disk_device(st.st_mode) &&
144.111 + st.st_rdev == device) {
144.112 + cp = malloc(strlen(path)+1);
144.113 + if (!cp) {
144.114 + closedir(dir);
144.115 + return ENOMEM;
144.116 + }
144.117 + strcpy(cp, path);
144.118 + *ret_path = cp;
144.119 + goto success;
144.120 + }
144.121 + skip_to_next:
144.122 + dp = readdir(dir);
144.123 + }
144.124 +success:
144.125 + closedir(dir);
144.126 + return 0;
144.127 +}
144.128 +
144.129 +/*
144.130 + * This function finds the pathname to a block device with a given
144.131 + * device number. It returns a pointer to allocated memory to the
144.132 + * pathname on success, and NULL on failure.
144.133 + */
144.134 +char *ext2fs_find_block_device(dev_t device)
144.135 +{
144.136 + struct dir_list *list = 0, *new_list = 0;
144.137 + struct dir_list *current;
144.138 + char *ret_path = 0;
144.139 + int level = 0;
144.140 +
144.141 + /*
144.142 + * Add the starting directories to search...
144.143 + */
144.144 + add_to_dirlist("/devices", &list);
144.145 + add_to_dirlist("/devfs", &list);
144.146 + add_to_dirlist("/dev", &list);
144.147 +
144.148 + while (list) {
144.149 + current = list;
144.150 + list = list->next;
144.151 +#ifdef DEBUG
144.152 + printf("Scanning directory %s\n", current->name);
144.153 +#endif
144.154 + scan_dir(current->name, device, &new_list, &ret_path);
144.155 + free(current->name);
144.156 + free(current);
144.157 + if (ret_path)
144.158 + break;
144.159 + /*
144.160 + * If we're done checking at this level, descend to
144.161 + * the next level of subdirectories. (breadth-first)
144.162 + */
144.163 + if (list == 0) {
144.164 + list = new_list;
144.165 + new_list = 0;
144.166 + /* Avoid infinite loop */
144.167 + if (++level >= EXT2FS_MAX_NESTED_LINKS)
144.168 + break;
144.169 + }
144.170 + }
144.171 + free_dirlist(&list);
144.172 + free_dirlist(&new_list);
144.173 + return ret_path;
144.174 +}
144.175 +
144.176 +
144.177 +#ifdef DEBUG
144.178 +int main(int argc, char** argv)
144.179 +{
144.180 + char *devname, *tmp;
144.181 + int major, minor;
144.182 + dev_t device;
144.183 + const char *errmsg = "Couldn't parse %s: %s\n";
144.184 +
144.185 + if ((argc != 2) && (argc != 3)) {
144.186 + fprintf(stderr, "Usage: %s device_number\n", argv[0]);
144.187 + fprintf(stderr, "\t: %s major minor\n", argv[0]);
144.188 + exit(1);
144.189 + }
144.190 + if (argc == 2) {
144.191 + device = strtoul(argv[1], &tmp, 0);
144.192 + if (*tmp) {
144.193 + fprintf(stderr, errmsg, "device number", argv[1]);
144.194 + exit(1);
144.195 + }
144.196 + } else {
144.197 + major = strtoul(argv[1], &tmp, 0);
144.198 + if (*tmp) {
144.199 + fprintf(stderr, errmsg, "major number", argv[1]);
144.200 + exit(1);
144.201 + }
144.202 + minor = strtoul(argv[2], &tmp, 0);
144.203 + if (*tmp) {
144.204 + fprintf(stderr, errmsg, "minor number", argv[2]);
144.205 + exit(1);
144.206 + }
144.207 + device = makedev(major, minor);
144.208 + printf("Looking for device 0x%04x (%d:%d)\n", device,
144.209 + major, minor);
144.210 + }
144.211 + devname = ext2fs_find_block_device(device);
144.212 + if (devname) {
144.213 + printf("Found device! %s\n", devname);
144.214 + free(devname);
144.215 + } else {
144.216 + printf("Couldn't find device.\n");
144.217 + }
144.218 + return 0;
144.219 +}
144.220 +
144.221 +#endif
145.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
145.2 +++ b/libext2fs/lib/libext2fs/flushb.c Wed Aug 25 01:28:08 2021 +0200
145.3 @@ -0,0 +1,88 @@
145.4 +/*
145.5 + * flushb.c --- Hides system-dependent information for both syncing a
145.6 + * device to disk and to flush any buffers from disk cache.
145.7 + *
145.8 + * Copyright (C) 2000 Theodore Ts'o.
145.9 + *
145.10 + * %Begin-Header%
145.11 + * This file may be redistributed under the terms of the GNU Library
145.12 + * General Public License, version 2.
145.13 + * %End-Header%
145.14 + */
145.15 +
145.16 +#include "config.h"
145.17 +#include <stdio.h>
145.18 +#if HAVE_ERRNO_H
145.19 +#include <errno.h>
145.20 +#endif
145.21 +#if HAVE_UNISTD_H
145.22 +#include <unistd.h>
145.23 +#endif
145.24 +#if HAVE_SYS_IOCTL_H
145.25 +#include <sys/ioctl.h>
145.26 +#endif
145.27 +#if HAVE_SYS_MOUNT_H
145.28 +#include <sys/param.h>
145.29 +#include <sys/mount.h> /* This may define BLKFLSBUF */
145.30 +#endif
145.31 +
145.32 +#include "ext2_fs.h"
145.33 +#include "ext2fs.h"
145.34 +
145.35 +/*
145.36 + * For Linux, define BLKFLSBUF and FDFLUSH if necessary, since
145.37 + * not all portable header file does so for us. This really should be
145.38 + * fixed in the glibc header files. (Recent glibcs appear to define
145.39 + * BLKFLSBUF in sys/mount.h, but FDFLUSH still doesn't seem to be
145.40 + * defined anywhere portable.) Until then....
145.41 + */
145.42 +#ifdef __linux__
145.43 +#ifndef BLKFLSBUF
145.44 +#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
145.45 +#endif
145.46 +#ifndef FDFLUSH
145.47 +#define FDFLUSH _IO(2,0x4b) /* flush floppy disk */
145.48 +#endif
145.49 +#endif
145.50 +
145.51 +/*
145.52 + * This function will sync a device/file, and optionally attempt to
145.53 + * flush the buffer cache. The latter is basically only useful for
145.54 + * system benchmarks and for torturing systems in burn-in tests. :)
145.55 + */
145.56 +errcode_t ext2fs_sync_device(int fd, int flushb)
145.57 +{
145.58 + /*
145.59 + * We always sync the device in case we're running on old
145.60 + * kernels for which we can lose data if we don't. (There
145.61 + * still is a race condition for those kernels, but this
145.62 + * reduces it greatly.)
145.63 + */
145.64 +#if defined(HAVE_FSYNC)
145.65 + if (fsync (fd) == -1)
145.66 + return errno;
145.67 +#endif
145.68 +
145.69 + if (flushb) {
145.70 + errcode_t retval = 0;
145.71 +
145.72 +#ifdef BLKFLSBUF
145.73 + if (ioctl (fd, BLKFLSBUF, 0) == 0)
145.74 + return 0;
145.75 + retval = errno;
145.76 +#elif defined(__linux__)
145.77 +#warning BLKFLSBUF not defined
145.78 +#endif
145.79 +#ifdef FDFLUSH
145.80 + /* In case this is a floppy */
145.81 + if (ioctl(fd, FDFLUSH, 0) == 0)
145.82 + return 0;
145.83 + if (retval == 0)
145.84 + retval = errno;
145.85 +#elif defined(__linux__)
145.86 +#warning FDFLUSH not defined
145.87 +#endif
145.88 + return retval;
145.89 + }
145.90 + return 0;
145.91 +}
146.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
146.2 +++ b/libext2fs/lib/libext2fs/freefs.c Wed Aug 25 01:28:08 2021 +0200
146.3 @@ -0,0 +1,108 @@
146.4 +/*
146.5 + * freefs.c --- free an ext2 filesystem
146.6 + *
146.7 + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
146.8 + *
146.9 + * %Begin-Header%
146.10 + * This file may be redistributed under the terms of the GNU Library
146.11 + * General Public License, version 2.
146.12 + * %End-Header%
146.13 + */
146.14 +
146.15 +#include "config.h"
146.16 +#include <stdio.h>
146.17 +#if HAVE_UNISTD_H
146.18 +#include <unistd.h>
146.19 +#endif
146.20 +
146.21 +#include "ext2_fs.h"
146.22 +#include "ext2fsP.h"
146.23 +#include "hashmap.h"
146.24 +
146.25 +void ext2fs_free(ext2_filsys fs)
146.26 +{
146.27 + if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS))
146.28 + return;
146.29 + if (fs->image_io != fs->io) {
146.30 + if (fs->image_io)
146.31 + io_channel_close(fs->image_io);
146.32 + }
146.33 + if (fs->io) {
146.34 + io_channel_close(fs->io);
146.35 + }
146.36 + if (fs->device_name)
146.37 + ext2fs_free_mem(&fs->device_name);
146.38 + if (fs->super)
146.39 + ext2fs_free_mem(&fs->super);
146.40 + if (fs->orig_super)
146.41 + ext2fs_free_mem(&fs->orig_super);
146.42 + if (fs->group_desc)
146.43 + ext2fs_free_mem(&fs->group_desc);
146.44 + if (fs->block_map)
146.45 + ext2fs_free_block_bitmap(fs->block_map);
146.46 + if (fs->inode_map)
146.47 + ext2fs_free_inode_bitmap(fs->inode_map);
146.48 + if (fs->image_header)
146.49 + ext2fs_free_mem(&fs->image_header);
146.50 +
146.51 + if (fs->badblocks)
146.52 + ext2fs_badblocks_list_free(fs->badblocks);
146.53 + fs->badblocks = 0;
146.54 +
146.55 + if (fs->dblist)
146.56 + ext2fs_free_dblist(fs->dblist);
146.57 +
146.58 + if (fs->icache)
146.59 + ext2fs_free_inode_cache(fs->icache);
146.60 +
146.61 + if (fs->mmp_buf)
146.62 + ext2fs_free_mem(&fs->mmp_buf);
146.63 + if (fs->mmp_cmp)
146.64 + ext2fs_free_mem(&fs->mmp_cmp);
146.65 +
146.66 + if (fs->block_sha_map)
146.67 + ext2fs_hashmap_free(fs->block_sha_map);
146.68 +
146.69 + fs->magic = 0;
146.70 +
146.71 + ext2fs_zero_blocks2(NULL, 0, 0, NULL, NULL);
146.72 + ext2fs_free_mem(&fs);
146.73 +}
146.74 +
146.75 +/*
146.76 + * This procedure frees a badblocks list.
146.77 + */
146.78 +void ext2fs_u32_list_free(ext2_u32_list bb)
146.79 +{
146.80 + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
146.81 + return;
146.82 +
146.83 + if (bb->list)
146.84 + ext2fs_free_mem(&bb->list);
146.85 + bb->list = 0;
146.86 + ext2fs_free_mem(&bb);
146.87 +}
146.88 +
146.89 +void ext2fs_badblocks_list_free(ext2_badblocks_list bb)
146.90 +{
146.91 + ext2fs_u32_list_free((ext2_u32_list) bb);
146.92 +}
146.93 +
146.94 +
146.95 +/*
146.96 + * Free a directory block list
146.97 + */
146.98 +void ext2fs_free_dblist(ext2_dblist dblist)
146.99 +{
146.100 + if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST))
146.101 + return;
146.102 +
146.103 + if (dblist->list)
146.104 + ext2fs_free_mem(&dblist->list);
146.105 + dblist->list = 0;
146.106 + if (dblist->fs && dblist->fs->dblist == dblist)
146.107 + dblist->fs->dblist = 0;
146.108 + dblist->magic = 0;
146.109 + ext2fs_free_mem(&dblist);
146.110 +}
146.111 +
147.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
147.2 +++ b/libext2fs/lib/libext2fs/gen_bitmap.c Wed Aug 25 01:28:08 2021 +0200
147.3 @@ -0,0 +1,607 @@
147.4 +/*
147.5 + * gen_bitmap.c --- Generic (32-bit) bitmap routines
147.6 + *
147.7 + * Copyright (C) 2001 Theodore Ts'o.
147.8 + *
147.9 + * %Begin-Header%
147.10 + * This file may be redistributed under the terms of the GNU Library
147.11 + * General Public License, version 2.
147.12 + * %End-Header%
147.13 + */
147.14 +
147.15 +
147.16 +#include "config.h"
147.17 +#include <stdio.h>
147.18 +#include <string.h>
147.19 +#if HAVE_UNISTD_H
147.20 +#include <unistd.h>
147.21 +#endif
147.22 +#include <fcntl.h>
147.23 +#include <time.h>
147.24 +#if HAVE_SYS_STAT_H
147.25 +#include <sys/stat.h>
147.26 +#endif
147.27 +#if HAVE_SYS_TYPES_H
147.28 +#include <sys/types.h>
147.29 +#endif
147.30 +
147.31 +#include "ext2_fs.h"
147.32 +#include "ext2fsP.h"
147.33 +
147.34 +struct ext2fs_struct_generic_bitmap {
147.35 + errcode_t magic;
147.36 + ext2_filsys fs;
147.37 + __u32 start, end;
147.38 + __u32 real_end;
147.39 + char * description;
147.40 + char * bitmap;
147.41 + errcode_t base_error_code;
147.42 + __u32 reserved[7];
147.43 +};
147.44 +
147.45 +#define EXT2FS_IS_32_BITMAP(bmap) \
147.46 + (((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) || \
147.47 + ((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP) || \
147.48 + ((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP))
147.49 +
147.50 +#define EXT2FS_IS_64_BITMAP(bmap) \
147.51 + (((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP64) || \
147.52 + ((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP64) || \
147.53 + ((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP64))
147.54 +
147.55 +/*
147.56 + * Used by previously inlined function, so we have to export this and
147.57 + * not change the function signature
147.58 + */
147.59 +void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
147.60 + int code, unsigned long arg)
147.61 +{
147.62 +#ifndef OMIT_COM_ERR
147.63 + if (bitmap->description)
147.64 + com_err(0, bitmap->base_error_code+code,
147.65 + "#%lu for %s", arg, bitmap->description);
147.66 + else
147.67 + com_err(0, bitmap->base_error_code + code, "#%lu", arg);
147.68 +#endif
147.69 +}
147.70 +
147.71 +static errcode_t check_magic(ext2fs_generic_bitmap bitmap)
147.72 +{
147.73 + if (!bitmap || !((bitmap->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) ||
147.74 + (bitmap->magic == EXT2_ET_MAGIC_INODE_BITMAP) ||
147.75 + (bitmap->magic == EXT2_ET_MAGIC_BLOCK_BITMAP)))
147.76 + return EXT2_ET_MAGIC_GENERIC_BITMAP;
147.77 + return 0;
147.78 +}
147.79 +
147.80 +errcode_t ext2fs_make_generic_bitmap(errcode_t magic, ext2_filsys fs,
147.81 + __u32 start, __u32 end, __u32 real_end,
147.82 + const char *descr, char *init_map,
147.83 + ext2fs_generic_bitmap *ret)
147.84 +{
147.85 + ext2fs_generic_bitmap bitmap;
147.86 + errcode_t retval;
147.87 + size_t size;
147.88 +
147.89 + retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
147.90 + &bitmap);
147.91 + if (retval)
147.92 + return retval;
147.93 +
147.94 + bitmap->magic = magic;
147.95 + bitmap->fs = fs;
147.96 + bitmap->start = start;
147.97 + bitmap->end = end;
147.98 + bitmap->real_end = real_end;
147.99 + switch (magic) {
147.100 + case EXT2_ET_MAGIC_INODE_BITMAP:
147.101 + bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
147.102 + break;
147.103 + case EXT2_ET_MAGIC_BLOCK_BITMAP:
147.104 + bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
147.105 + break;
147.106 + default:
147.107 + bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
147.108 + }
147.109 + if (descr) {
147.110 + retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
147.111 + if (retval) {
147.112 + ext2fs_free_mem(&bitmap);
147.113 + return retval;
147.114 + }
147.115 + strcpy(bitmap->description, descr);
147.116 + } else
147.117 + bitmap->description = 0;
147.118 +
147.119 + size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
147.120 + /* Round up to allow for the BT x86 instruction */
147.121 + size = (size + 7) & ~3;
147.122 + retval = ext2fs_get_mem(size, &bitmap->bitmap);
147.123 + if (retval) {
147.124 + ext2fs_free_mem(&bitmap->description);
147.125 + ext2fs_free_mem(&bitmap);
147.126 + return retval;
147.127 + }
147.128 +
147.129 + if (init_map)
147.130 + memcpy(bitmap->bitmap, init_map, size);
147.131 + else
147.132 + memset(bitmap->bitmap, 0, size);
147.133 + *ret = bitmap;
147.134 + return 0;
147.135 +}
147.136 +
147.137 +errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
147.138 + __u32 end,
147.139 + __u32 real_end,
147.140 + const char *descr,
147.141 + ext2fs_generic_bitmap *ret)
147.142 +{
147.143 + return ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_GENERIC_BITMAP, 0,
147.144 + start, end, real_end, descr, 0, ret);
147.145 +}
147.146 +
147.147 +errcode_t ext2fs_copy_generic_bitmap(ext2fs_generic_bitmap src,
147.148 + ext2fs_generic_bitmap *dest)
147.149 +{
147.150 + return (ext2fs_make_generic_bitmap(src->magic, src->fs,
147.151 + src->start, src->end,
147.152 + src->real_end,
147.153 + src->description, src->bitmap,
147.154 + dest));
147.155 +}
147.156 +
147.157 +void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap)
147.158 +{
147.159 + if (check_magic(bitmap))
147.160 + return;
147.161 +
147.162 + bitmap->magic = 0;
147.163 + if (bitmap->description) {
147.164 + ext2fs_free_mem(&bitmap->description);
147.165 + bitmap->description = 0;
147.166 + }
147.167 + if (bitmap->bitmap) {
147.168 + ext2fs_free_mem(&bitmap->bitmap);
147.169 + bitmap->bitmap = 0;
147.170 + }
147.171 + ext2fs_free_mem(&bitmap);
147.172 +}
147.173 +
147.174 +int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
147.175 + blk_t bitno)
147.176 +{
147.177 + if (!EXT2FS_IS_32_BITMAP(bitmap)) {
147.178 + if (EXT2FS_IS_64_BITMAP(bitmap)) {
147.179 + ext2fs_warn_bitmap32(bitmap, __func__);
147.180 + return ext2fs_test_generic_bmap(bitmap, bitno);
147.181 + }
147.182 +#ifndef OMIT_COM_ERR
147.183 + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
147.184 + "test_bitmap(%lu)", (unsigned long) bitno);
147.185 +#endif
147.186 + return 0;
147.187 + }
147.188 +
147.189 + if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
147.190 + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
147.191 + return 0;
147.192 + }
147.193 + return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
147.194 +}
147.195 +
147.196 +int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
147.197 + __u32 bitno)
147.198 +{
147.199 + if (!EXT2FS_IS_32_BITMAP(bitmap)) {
147.200 + if (EXT2FS_IS_64_BITMAP(bitmap)) {
147.201 + ext2fs_warn_bitmap32(bitmap, __func__);
147.202 + return ext2fs_mark_generic_bmap(bitmap, bitno);
147.203 + }
147.204 +#ifndef OMIT_COM_ERR
147.205 + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
147.206 + "mark_bitmap(%lu)", (unsigned long) bitno);
147.207 +#endif
147.208 + return 0;
147.209 + }
147.210 +
147.211 + if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
147.212 + ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
147.213 + return 0;
147.214 + }
147.215 + return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap);
147.216 +}
147.217 +
147.218 +int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
147.219 + blk_t bitno)
147.220 +{
147.221 + if (!EXT2FS_IS_32_BITMAP(bitmap)) {
147.222 + if (EXT2FS_IS_64_BITMAP(bitmap)) {
147.223 + ext2fs_warn_bitmap32(bitmap, __func__);
147.224 + return ext2fs_unmark_generic_bmap(bitmap, bitno);
147.225 + }
147.226 +#ifndef OMIT_COM_ERR
147.227 + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
147.228 + "mark_bitmap(%lu)", (unsigned long) bitno);
147.229 +#endif
147.230 + return 0;
147.231 + }
147.232 +
147.233 + if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
147.234 + ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
147.235 + return 0;
147.236 + }
147.237 + return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap);
147.238 +}
147.239 +
147.240 +__u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap)
147.241 +{
147.242 + if (!EXT2FS_IS_32_BITMAP(bitmap)) {
147.243 + if (EXT2FS_IS_64_BITMAP(bitmap)) {
147.244 + ext2fs_warn_bitmap32(bitmap, __func__);
147.245 + return ext2fs_get_generic_bmap_start(bitmap);
147.246 + }
147.247 +#ifndef OMIT_COM_ERR
147.248 + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
147.249 + "get_bitmap_start");
147.250 +#endif
147.251 + return 0;
147.252 + }
147.253 +
147.254 + return bitmap->start;
147.255 +}
147.256 +
147.257 +__u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap)
147.258 +{
147.259 + if (!EXT2FS_IS_32_BITMAP(bitmap)) {
147.260 + if (EXT2FS_IS_64_BITMAP(bitmap)) {
147.261 + ext2fs_warn_bitmap32(bitmap, __func__);
147.262 + return ext2fs_get_generic_bmap_end(bitmap);
147.263 + }
147.264 +#ifndef OMIT_COM_ERR
147.265 + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
147.266 + "get_bitmap_end");
147.267 +#endif
147.268 + return 0;
147.269 + }
147.270 + return bitmap->end;
147.271 +}
147.272 +
147.273 +void ext2fs_clear_generic_bitmap(ext2fs_generic_bitmap bitmap)
147.274 +{
147.275 + if (!EXT2FS_IS_32_BITMAP(bitmap)) {
147.276 + if (EXT2FS_IS_64_BITMAP(bitmap)) {
147.277 + ext2fs_warn_bitmap32(bitmap, __func__);
147.278 + ext2fs_clear_generic_bmap(bitmap);
147.279 + return;
147.280 + }
147.281 +#ifndef OMIT_COM_ERR
147.282 + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
147.283 + "clear_generic_bitmap");
147.284 +#endif
147.285 + return;
147.286 + }
147.287 +
147.288 + memset(bitmap->bitmap, 0,
147.289 + (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
147.290 +}
147.291 +
147.292 +errcode_t ext2fs_fudge_generic_bitmap_end(ext2fs_inode_bitmap bitmap,
147.293 + errcode_t magic, errcode_t neq,
147.294 + ext2_ino_t end, ext2_ino_t *oend)
147.295 +{
147.296 + EXT2_CHECK_MAGIC(bitmap, magic);
147.297 +
147.298 + if (end > bitmap->real_end)
147.299 + return neq;
147.300 + if (oend)
147.301 + *oend = bitmap->end;
147.302 + bitmap->end = end;
147.303 + return 0;
147.304 +}
147.305 +
147.306 +errcode_t ext2fs_resize_generic_bitmap(errcode_t magic,
147.307 + __u32 new_end, __u32 new_real_end,
147.308 + ext2fs_generic_bitmap bmap)
147.309 +{
147.310 + errcode_t retval;
147.311 + size_t size, new_size;
147.312 + __u32 bitno;
147.313 +
147.314 + if (!bmap || (bmap->magic != magic))
147.315 + return magic;
147.316 +
147.317 + /*
147.318 + * If we're expanding the bitmap, make sure all of the new
147.319 + * parts of the bitmap are zero.
147.320 + */
147.321 + if (new_end > bmap->end) {
147.322 + bitno = bmap->real_end;
147.323 + if (bitno > new_end)
147.324 + bitno = new_end;
147.325 + for (; bitno > bmap->end; bitno--)
147.326 + ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap);
147.327 + }
147.328 + if (new_real_end == bmap->real_end) {
147.329 + bmap->end = new_end;
147.330 + return 0;
147.331 + }
147.332 +
147.333 + size = ((bmap->real_end - bmap->start) / 8) + 1;
147.334 + new_size = ((new_real_end - bmap->start) / 8) + 1;
147.335 +
147.336 + if (size != new_size) {
147.337 + retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap);
147.338 + if (retval)
147.339 + return retval;
147.340 + }
147.341 + if (new_size > size)
147.342 + memset(bmap->bitmap + size, 0, new_size - size);
147.343 +
147.344 + bmap->end = new_end;
147.345 + bmap->real_end = new_real_end;
147.346 + return 0;
147.347 +}
147.348 +
147.349 +errcode_t ext2fs_compare_generic_bitmap(errcode_t magic, errcode_t neq,
147.350 + ext2fs_generic_bitmap bm1,
147.351 + ext2fs_generic_bitmap bm2)
147.352 +{
147.353 + blk_t i;
147.354 +
147.355 + if (!bm1 || bm1->magic != magic)
147.356 + return magic;
147.357 + if (!bm2 || bm2->magic != magic)
147.358 + return magic;
147.359 +
147.360 + if ((bm1->start != bm2->start) ||
147.361 + (bm1->end != bm2->end) ||
147.362 + (memcmp(bm1->bitmap, bm2->bitmap,
147.363 + (size_t) (bm1->end - bm1->start)/8)))
147.364 + return neq;
147.365 +
147.366 + for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
147.367 + if (ext2fs_fast_test_block_bitmap(bm1, i) !=
147.368 + ext2fs_fast_test_block_bitmap(bm2, i))
147.369 + return neq;
147.370 +
147.371 + return 0;
147.372 +}
147.373 +
147.374 +void ext2fs_set_generic_bitmap_padding(ext2fs_generic_bitmap map)
147.375 +{
147.376 + __u32 i, j;
147.377 +
147.378 + /* Protect loop from wrap-around if map->real_end is maxed */
147.379 + for (i=map->end+1, j = i - map->start;
147.380 + i <= map->real_end && i > map->end;
147.381 + i++, j++)
147.382 + ext2fs_set_bit(j, map->bitmap);
147.383 +}
147.384 +
147.385 +errcode_t ext2fs_get_generic_bitmap_range(ext2fs_generic_bitmap bmap,
147.386 + errcode_t magic,
147.387 + __u32 start, __u32 num,
147.388 + void *out)
147.389 +{
147.390 + if (!bmap || (bmap->magic != magic))
147.391 + return magic;
147.392 +
147.393 + if ((start < bmap->start) || (start+num-1 > bmap->real_end))
147.394 + return EXT2_ET_INVALID_ARGUMENT;
147.395 +
147.396 + memcpy(out, bmap->bitmap + (start >> 3), (num+7) >> 3);
147.397 + return 0;
147.398 +}
147.399 +
147.400 +errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap,
147.401 + errcode_t magic,
147.402 + __u32 start, __u32 num,
147.403 + void *in)
147.404 +{
147.405 + if (!bmap || (bmap->magic != magic))
147.406 + return magic;
147.407 +
147.408 + if ((start < bmap->start) || (start+num-1 > bmap->real_end))
147.409 + return EXT2_ET_INVALID_ARGUMENT;
147.410 +
147.411 + memcpy(bmap->bitmap + (start >> 3), in, (num+7) >> 3);
147.412 + return 0;
147.413 +}
147.414 +
147.415 +/*
147.416 + * Compare @mem to zero buffer by 256 bytes.
147.417 + * Return 1 if @mem is zeroed memory, otherwise return 0.
147.418 + */
147.419 +int ext2fs_mem_is_zero(const char *mem, size_t len)
147.420 +{
147.421 + static const char zero_buf[256];
147.422 +
147.423 + while (len >= sizeof(zero_buf)) {
147.424 + if (memcmp(mem, zero_buf, sizeof(zero_buf)))
147.425 + return 0;
147.426 + len -= sizeof(zero_buf);
147.427 + mem += sizeof(zero_buf);
147.428 + }
147.429 + /* Deal with leftover bytes. */
147.430 + if (len)
147.431 + return !memcmp(mem, zero_buf, len);
147.432 + return 1;
147.433 +}
147.434 +
147.435 +/*
147.436 + * Return true if all of the bits in a specified range are clear
147.437 + */
147.438 +static int ext2fs_test_clear_generic_bitmap_range(ext2fs_generic_bitmap bitmap,
147.439 + unsigned int start,
147.440 + unsigned int len)
147.441 +{
147.442 + size_t start_byte, len_byte = len >> 3;
147.443 + unsigned int start_bit, len_bit = len % 8;
147.444 + int first_bit = 0;
147.445 + int last_bit = 0;
147.446 + int mark_count = 0;
147.447 + int mark_bit = 0;
147.448 + int i;
147.449 + const char *ADDR = bitmap->bitmap;
147.450 +
147.451 + start -= bitmap->start;
147.452 + start_byte = start >> 3;
147.453 + start_bit = start % 8;
147.454 +
147.455 + if (start_bit != 0) {
147.456 + /*
147.457 + * The compared start block number or start inode number
147.458 + * is not the first bit in a byte.
147.459 + */
147.460 + mark_count = 8 - start_bit;
147.461 + if (len < 8 - start_bit) {
147.462 + mark_count = (int)len;
147.463 + mark_bit = len + start_bit - 1;
147.464 + } else
147.465 + mark_bit = 7;
147.466 +
147.467 + for (i = mark_count; i > 0; i--, mark_bit--)
147.468 + first_bit |= 1 << mark_bit;
147.469 +
147.470 + /*
147.471 + * Compare blocks or inodes in the first byte.
147.472 + * If there is any marked bit, this function returns 0.
147.473 + */
147.474 + if (first_bit & ADDR[start_byte])
147.475 + return 0;
147.476 + else if (len <= 8 - start_bit)
147.477 + return 1;
147.478 +
147.479 + start_byte++;
147.480 + len_bit = (len - mark_count) % 8;
147.481 + len_byte = (len - mark_count) >> 3;
147.482 + }
147.483 +
147.484 + /*
147.485 + * The compared start block number or start inode number is
147.486 + * the first bit in a byte.
147.487 + */
147.488 + if (len_bit != 0) {
147.489 + /*
147.490 + * The compared end block number or end inode number is
147.491 + * not the last bit in a byte.
147.492 + */
147.493 + for (mark_bit = len_bit - 1; mark_bit >= 0; mark_bit--)
147.494 + last_bit |= 1 << mark_bit;
147.495 +
147.496 + /*
147.497 + * Compare blocks or inodes in the last byte.
147.498 + * If there is any marked bit, this function returns 0.
147.499 + */
147.500 + if (last_bit & ADDR[start_byte + len_byte])
147.501 + return 0;
147.502 + else if (len_byte == 0)
147.503 + return 1;
147.504 + }
147.505 +
147.506 + /* Check whether all bytes are 0 */
147.507 + return ext2fs_mem_is_zero(ADDR + start_byte, len_byte);
147.508 +}
147.509 +
147.510 +errcode_t ext2fs_find_first_zero_generic_bitmap(ext2fs_generic_bitmap bitmap,
147.511 + __u32 start, __u32 end,
147.512 + __u32 *out)
147.513 +{
147.514 + blk_t b;
147.515 +
147.516 + if (start < bitmap->start || end > bitmap->end || start > end) {
147.517 + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
147.518 + return EINVAL;
147.519 + }
147.520 +
147.521 + while (start <= end) {
147.522 + b = ext2fs_test_bit(start - bitmap->start, bitmap->bitmap);
147.523 + if (!b) {
147.524 + *out = start;
147.525 + return 0;
147.526 + }
147.527 + start++;
147.528 + }
147.529 +
147.530 + return ENOENT;
147.531 +}
147.532 +
147.533 +errcode_t ext2fs_find_first_set_generic_bitmap(ext2fs_generic_bitmap bitmap,
147.534 + __u32 start, __u32 end,
147.535 + __u32 *out)
147.536 +{
147.537 + blk_t b;
147.538 +
147.539 + if (start < bitmap->start || end > bitmap->end || start > end) {
147.540 + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
147.541 + return EINVAL;
147.542 + }
147.543 +
147.544 + while (start <= end) {
147.545 + b = ext2fs_test_bit(start - bitmap->start, bitmap->bitmap);
147.546 + if (b) {
147.547 + *out = start;
147.548 + return 0;
147.549 + }
147.550 + start++;
147.551 + }
147.552 +
147.553 + return ENOENT;
147.554 +}
147.555 +
147.556 +int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
147.557 + blk_t block, int num)
147.558 +{
147.559 + EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
147.560 + if ((block < bitmap->start) || (block+num-1 > bitmap->real_end)) {
147.561 + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
147.562 + block, bitmap->description);
147.563 + return 0;
147.564 + }
147.565 + return ext2fs_test_clear_generic_bitmap_range((ext2fs_generic_bitmap)
147.566 + bitmap, block, num);
147.567 +}
147.568 +
147.569 +int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap,
147.570 + ext2_ino_t inode, int num)
147.571 +{
147.572 + EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP);
147.573 + if ((inode < bitmap->start) || (inode+num-1 > bitmap->real_end)) {
147.574 + ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST,
147.575 + inode, bitmap->description);
147.576 + return 0;
147.577 + }
147.578 + return ext2fs_test_clear_generic_bitmap_range((ext2fs_generic_bitmap)
147.579 + bitmap, inode, num);
147.580 +}
147.581 +
147.582 +void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
147.583 + blk_t block, int num)
147.584 +{
147.585 + int i;
147.586 +
147.587 + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
147.588 + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
147.589 + bitmap->description);
147.590 + return;
147.591 + }
147.592 + for (i=0; i < num; i++)
147.593 + ext2fs_fast_set_bit(block + i - bitmap->start, bitmap->bitmap);
147.594 +}
147.595 +
147.596 +void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
147.597 + blk_t block, int num)
147.598 +{
147.599 + int i;
147.600 +
147.601 + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
147.602 + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
147.603 + bitmap->description);
147.604 + return;
147.605 + }
147.606 + for (i=0; i < num; i++)
147.607 + ext2fs_fast_clear_bit(block + i - bitmap->start,
147.608 + bitmap->bitmap);
147.609 +}
147.610 +
148.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
148.2 +++ b/libext2fs/lib/libext2fs/gen_bitmap64.c Wed Aug 25 01:28:08 2021 +0200
148.3 @@ -0,0 +1,907 @@
148.4 +/*
148.5 + * gen_bitmap64.c --- routines to read, write, and manipulate the new qinode and
148.6 + * block bitmaps.
148.7 + *
148.8 + * Copyright (C) 2007, 2008 Theodore Ts'o.
148.9 + *
148.10 + * %Begin-Header%
148.11 + * This file may be redistributed under the terms of the GNU Public
148.12 + * License.
148.13 + * %End-Header%
148.14 + */
148.15 +
148.16 +#include "config.h"
148.17 +#include <stdio.h>
148.18 +#include <string.h>
148.19 +#if HAVE_UNISTD_H
148.20 +#include <unistd.h>
148.21 +#endif
148.22 +#include <fcntl.h>
148.23 +#include <time.h>
148.24 +#include <errno.h>
148.25 +#if HAVE_SYS_STAT_H
148.26 +#include <sys/stat.h>
148.27 +#endif
148.28 +#if HAVE_SYS_TYPES_H
148.29 +#include <sys/types.h>
148.30 +#endif
148.31 +#ifdef HAVE_SYS_TIME_H
148.32 +#include <sys/time.h>
148.33 +#endif
148.34 +
148.35 +#include "ext2_fs.h"
148.36 +#include "ext2fsP.h"
148.37 +#include "bmap64.h"
148.38 +
148.39 +/*
148.40 + * Design of 64-bit bitmaps
148.41 + *
148.42 + * In order maintain ABI compatibility with programs that don't
148.43 + * understand about 64-bit blocks/inodes,
148.44 + * ext2fs_allocate_inode_bitmap() and ext2fs_allocate_block_bitmap()
148.45 + * will create old-style bitmaps unless the application passes the
148.46 + * flag EXT2_FLAG_64BITS to ext2fs_open(). If this flag is
148.47 + * passed, then we know the application has been recompiled, so we can
148.48 + * use the new-style bitmaps. If it is not passed, we have to return
148.49 + * an error if trying to open a filesystem which needs 64-bit bitmaps.
148.50 + *
148.51 + * The new bitmaps use a new set of structure magic numbers, so that
148.52 + * both the old-style and new-style interfaces can identify which
148.53 + * version of the data structure was used. Both the old-style and
148.54 + * new-style interfaces will support either type of bitmap, although
148.55 + * of course 64-bit operation will only be possible when both the
148.56 + * new-style interface and the new-style bitmap are used.
148.57 + *
148.58 + * For example, the new bitmap interfaces will check the structure
148.59 + * magic numbers and so will be able to detect old-stype bitmap. If
148.60 + * they see an old-style bitmap, they will pass it to the gen_bitmap.c
148.61 + * functions for handling. The same will be true for the old
148.62 + * interfaces as well.
148.63 + *
148.64 + * The new-style interfaces will have several different back-end
148.65 + * implementations, so we can support different encodings that are
148.66 + * appropriate for different applications. In general the default
148.67 + * should be whatever makes sense, and what the application/library
148.68 + * will use. However, e2fsck may need specialized implementations for
148.69 + * its own uses. For example, when doing parent directory pointer
148.70 + * loop detections in pass 3, the bitmap will *always* be sparse, so
148.71 + * e2fsck can request an encoding which is optimized for that.
148.72 + */
148.73 +
148.74 +static void warn_bitmap(ext2fs_generic_bitmap bitmap,
148.75 + int code, __u64 arg)
148.76 +{
148.77 +#ifndef OMIT_COM_ERR
148.78 + if (bitmap->description)
148.79 + com_err(0, bitmap->base_error_code+code,
148.80 + "#%llu for %s", arg, bitmap->description);
148.81 + else
148.82 + com_err(0, bitmap->base_error_code + code, "#%llu", arg);
148.83 +#endif
148.84 +}
148.85 +
148.86 +#ifdef ENABLE_BMAP_STATS_OPS
148.87 +#define INC_STAT(map, name) map->stats.name
148.88 +#else
148.89 +#define INC_STAT(map, name) ;;
148.90 +#endif
148.91 +
148.92 +
148.93 +errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
148.94 + int type, __u64 start, __u64 end,
148.95 + __u64 real_end,
148.96 + const char *descr,
148.97 + ext2fs_generic_bitmap *ret)
148.98 +{
148.99 + ext2fs_generic_bitmap bitmap;
148.100 + struct ext2_bitmap_ops *ops;
148.101 + ext2_ino_t num_dirs;
148.102 + errcode_t retval;
148.103 +
148.104 + if (!type)
148.105 + type = EXT2FS_BMAP64_BITARRAY;
148.106 +
148.107 + switch (type) {
148.108 + case EXT2FS_BMAP64_BITARRAY:
148.109 + ops = &ext2fs_blkmap64_bitarray;
148.110 + break;
148.111 + case EXT2FS_BMAP64_RBTREE:
148.112 + ops = &ext2fs_blkmap64_rbtree;
148.113 + break;
148.114 + case EXT2FS_BMAP64_AUTODIR:
148.115 + retval = ext2fs_get_num_dirs(fs, &num_dirs);
148.116 + if (retval || num_dirs > (fs->super->s_inodes_count / 320))
148.117 + ops = &ext2fs_blkmap64_bitarray;
148.118 + else
148.119 + ops = &ext2fs_blkmap64_rbtree;
148.120 + break;
148.121 + default:
148.122 + return EINVAL;
148.123 + }
148.124 +
148.125 + retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap),
148.126 + &bitmap);
148.127 + if (retval)
148.128 + return retval;
148.129 +
148.130 +#ifdef ENABLE_BMAP_STATS
148.131 + if (gettimeofday(&bitmap->stats.created,
148.132 + (struct timezone *) NULL) == -1) {
148.133 + perror("gettimeofday");
148.134 + ext2fs_free_mem(&bitmap);
148.135 + return 1;
148.136 + }
148.137 + bitmap->stats.type = type;
148.138 +#endif
148.139 +
148.140 + /* XXX factor out, repeated in copy_bmap */
148.141 + bitmap->magic = magic;
148.142 + bitmap->fs = fs;
148.143 + bitmap->start = start;
148.144 + bitmap->end = end;
148.145 + bitmap->real_end = real_end;
148.146 + bitmap->bitmap_ops = ops;
148.147 + bitmap->cluster_bits = 0;
148.148 + switch (magic) {
148.149 + case EXT2_ET_MAGIC_INODE_BITMAP64:
148.150 + bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
148.151 + break;
148.152 + case EXT2_ET_MAGIC_BLOCK_BITMAP64:
148.153 + bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
148.154 + bitmap->cluster_bits = fs->cluster_ratio_bits;
148.155 + break;
148.156 + default:
148.157 + bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
148.158 + }
148.159 + if (descr) {
148.160 + retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
148.161 + if (retval) {
148.162 + ext2fs_free_mem(&bitmap);
148.163 + return retval;
148.164 + }
148.165 + strcpy(bitmap->description, descr);
148.166 + } else
148.167 + bitmap->description = 0;
148.168 +
148.169 + retval = bitmap->bitmap_ops->new_bmap(fs, bitmap);
148.170 + if (retval) {
148.171 + ext2fs_free_mem(&bitmap->description);
148.172 + ext2fs_free_mem(&bitmap);
148.173 + return retval;
148.174 + }
148.175 +
148.176 + *ret = bitmap;
148.177 + return 0;
148.178 +}
148.179 +
148.180 +#ifdef ENABLE_BMAP_STATS
148.181 +static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap bitmap)
148.182 +{
148.183 + struct ext2_bmap_statistics *stats = &bitmap->stats;
148.184 +#ifdef ENABLE_BMAP_STATS_OPS
148.185 + float mark_seq_perc = 0.0, test_seq_perc = 0.0;
148.186 + float mark_back_perc = 0.0, test_back_perc = 0.0;
148.187 +#endif
148.188 + double inuse;
148.189 + struct timeval now;
148.190 +
148.191 +#ifdef ENABLE_BMAP_STATS_OPS
148.192 + if (stats->test_count) {
148.193 + test_seq_perc = ((float)stats->test_seq /
148.194 + stats->test_count) * 100;
148.195 + test_back_perc = ((float)stats->test_back /
148.196 + stats->test_count) * 100;
148.197 + }
148.198 +
148.199 + if (stats->mark_count) {
148.200 + mark_seq_perc = ((float)stats->mark_seq /
148.201 + stats->mark_count) * 100;
148.202 + mark_back_perc = ((float)stats->mark_back /
148.203 + stats->mark_count) * 100;
148.204 + }
148.205 +#endif
148.206 +
148.207 + if (gettimeofday(&now, (struct timezone *) NULL) == -1) {
148.208 + perror("gettimeofday");
148.209 + return;
148.210 + }
148.211 +
148.212 + inuse = (double) now.tv_sec + \
148.213 + (((double) now.tv_usec) * 0.000001);
148.214 + inuse -= (double) stats->created.tv_sec + \
148.215 + (((double) stats->created.tv_usec) * 0.000001);
148.216 +
148.217 + fprintf(stderr, "\n[+] %s bitmap (type %d)\n", bitmap->description,
148.218 + stats->type);
148.219 + fprintf(stderr, "=================================================\n");
148.220 +#ifdef ENABLE_BMAP_STATS_OPS
148.221 + fprintf(stderr, "%16llu bits long\n",
148.222 + bitmap->real_end - bitmap->start);
148.223 + fprintf(stderr, "%16lu copy_bmap\n%16lu resize_bmap\n",
148.224 + stats->copy_count, stats->resize_count);
148.225 + fprintf(stderr, "%16lu mark bmap\n%16lu unmark_bmap\n",
148.226 + stats->mark_count, stats->unmark_count);
148.227 + fprintf(stderr, "%16lu test_bmap\n%16lu mark_bmap_extent\n",
148.228 + stats->test_count, stats->mark_ext_count);
148.229 + fprintf(stderr, "%16lu unmark_bmap_extent\n"
148.230 + "%16lu test_clear_bmap_extent\n",
148.231 + stats->unmark_ext_count, stats->test_ext_count);
148.232 + fprintf(stderr, "%16lu set_bmap_range\n%16lu set_bmap_range\n",
148.233 + stats->set_range_count, stats->get_range_count);
148.234 + fprintf(stderr, "%16lu clear_bmap\n%16lu contiguous bit test (%.2f%%)\n",
148.235 + stats->clear_count, stats->test_seq, test_seq_perc);
148.236 + fprintf(stderr, "%16lu contiguous bit mark (%.2f%%)\n"
148.237 + "%16llu bits tested backwards (%.2f%%)\n",
148.238 + stats->mark_seq, mark_seq_perc,
148.239 + stats->test_back, test_back_perc);
148.240 + fprintf(stderr, "%16llu bits marked backwards (%.2f%%)\n"
148.241 + "%16.2f seconds in use\n",
148.242 + stats->mark_back, mark_back_perc, inuse);
148.243 +#endif /* ENABLE_BMAP_STATS_OPS */
148.244 +}
148.245 +#endif
148.246 +
148.247 +void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap)
148.248 +{
148.249 + if (!bmap)
148.250 + return;
148.251 +
148.252 + if (EXT2FS_IS_32_BITMAP(bmap)) {
148.253 + ext2fs_free_generic_bitmap(bmap);
148.254 + return;
148.255 + }
148.256 +
148.257 + if (!EXT2FS_IS_64_BITMAP(bmap))
148.258 + return;
148.259 +
148.260 +#ifdef ENABLE_BMAP_STATS
148.261 + if (getenv("E2FSPROGS_BITMAP_STATS")) {
148.262 + ext2fs_print_bmap_statistics(bmap);
148.263 + bmap->bitmap_ops->print_stats(bmap);
148.264 + }
148.265 +#endif
148.266 +
148.267 + bmap->bitmap_ops->free_bmap(bmap);
148.268 +
148.269 + if (bmap->description) {
148.270 + ext2fs_free_mem(&bmap->description);
148.271 + bmap->description = 0;
148.272 + }
148.273 + bmap->magic = 0;
148.274 + ext2fs_free_mem(&bmap);
148.275 +}
148.276 +
148.277 +errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src,
148.278 + ext2fs_generic_bitmap *dest)
148.279 +{
148.280 + char *descr, *new_descr;
148.281 + ext2fs_generic_bitmap new_bmap;
148.282 + errcode_t retval;
148.283 +
148.284 + if (!src)
148.285 + return EINVAL;
148.286 +
148.287 + if (EXT2FS_IS_32_BITMAP(src))
148.288 + return ext2fs_copy_generic_bitmap(src, dest);
148.289 +
148.290 + if (!EXT2FS_IS_64_BITMAP(src))
148.291 + return EINVAL;
148.292 +
148.293 + /* Allocate a new bitmap struct */
148.294 + retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap),
148.295 + &new_bmap);
148.296 + if (retval)
148.297 + return retval;
148.298 +
148.299 +
148.300 +#ifdef ENABLE_BMAP_STATS_OPS
148.301 + src->stats.copy_count++;
148.302 +#endif
148.303 +#ifdef ENABLE_BMAP_STATS
148.304 + if (gettimeofday(&new_bmap->stats.created,
148.305 + (struct timezone *) NULL) == -1) {
148.306 + perror("gettimeofday");
148.307 + ext2fs_free_mem(&new_bmap);
148.308 + return 1;
148.309 + }
148.310 + new_bmap->stats.type = src->stats.type;
148.311 +#endif
148.312 +
148.313 + /* Copy all the high-level parts over */
148.314 + new_bmap->magic = src->magic;
148.315 + new_bmap->fs = src->fs;
148.316 + new_bmap->start = src->start;
148.317 + new_bmap->end = src->end;
148.318 + new_bmap->real_end = src->real_end;
148.319 + new_bmap->bitmap_ops = src->bitmap_ops;
148.320 + new_bmap->base_error_code = src->base_error_code;
148.321 + new_bmap->cluster_bits = src->cluster_bits;
148.322 +
148.323 + descr = src->description;
148.324 + if (descr) {
148.325 + retval = ext2fs_get_mem(strlen(descr)+10, &new_descr);
148.326 + if (retval) {
148.327 + ext2fs_free_mem(&new_bmap);
148.328 + return retval;
148.329 + }
148.330 + strcpy(new_descr, "copy of ");
148.331 + strcat(new_descr, descr);
148.332 + new_bmap->description = new_descr;
148.333 + }
148.334 +
148.335 + retval = src->bitmap_ops->copy_bmap(src, new_bmap);
148.336 + if (retval) {
148.337 + ext2fs_free_mem(&new_bmap->description);
148.338 + ext2fs_free_mem(&new_bmap);
148.339 + return retval;
148.340 + }
148.341 +
148.342 + *dest = new_bmap;
148.343 +
148.344 + return 0;
148.345 +}
148.346 +
148.347 +errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap,
148.348 + __u64 new_end,
148.349 + __u64 new_real_end)
148.350 +{
148.351 + if (!bmap)
148.352 + return EINVAL;
148.353 +
148.354 + if (EXT2FS_IS_32_BITMAP(bmap))
148.355 + return ext2fs_resize_generic_bitmap(bmap->magic, new_end,
148.356 + new_real_end, bmap);
148.357 +
148.358 + if (!EXT2FS_IS_64_BITMAP(bmap))
148.359 + return EINVAL;
148.360 +
148.361 + INC_STAT(bmap, resize_count);
148.362 +
148.363 + return bmap->bitmap_ops->resize_bmap(bmap, new_end, new_real_end);
148.364 +}
148.365 +
148.366 +errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap,
148.367 + errcode_t neq,
148.368 + __u64 end, __u64 *oend)
148.369 +{
148.370 + if (!bitmap)
148.371 + return EINVAL;
148.372 +
148.373 + if (EXT2FS_IS_32_BITMAP(bitmap)) {
148.374 + ext2_ino_t tmp_oend;
148.375 + int retval;
148.376 +
148.377 + retval = ext2fs_fudge_generic_bitmap_end(bitmap, bitmap->magic,
148.378 + neq, end, &tmp_oend);
148.379 + if (oend)
148.380 + *oend = tmp_oend;
148.381 + return retval;
148.382 + }
148.383 +
148.384 + if (!EXT2FS_IS_64_BITMAP(bitmap))
148.385 + return EINVAL;
148.386 +
148.387 + if (end > bitmap->real_end)
148.388 + return neq;
148.389 + if (oend)
148.390 + *oend = bitmap->end;
148.391 + bitmap->end = end;
148.392 + return 0;
148.393 +}
148.394 +
148.395 +__u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap)
148.396 +{
148.397 + if (!bitmap)
148.398 + return EINVAL;
148.399 +
148.400 + if (EXT2FS_IS_32_BITMAP(bitmap))
148.401 + return ext2fs_get_generic_bitmap_start(bitmap);
148.402 +
148.403 + if (!EXT2FS_IS_64_BITMAP(bitmap))
148.404 + return EINVAL;
148.405 +
148.406 + return bitmap->start;
148.407 +}
148.408 +
148.409 +__u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap)
148.410 +{
148.411 + if (!bitmap)
148.412 + return EINVAL;
148.413 +
148.414 + if (EXT2FS_IS_32_BITMAP(bitmap))
148.415 + return ext2fs_get_generic_bitmap_end(bitmap);
148.416 +
148.417 + if (!EXT2FS_IS_64_BITMAP(bitmap))
148.418 + return EINVAL;
148.419 +
148.420 + return bitmap->end;
148.421 +}
148.422 +
148.423 +void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap)
148.424 +{
148.425 + if (EXT2FS_IS_32_BITMAP(bitmap))
148.426 + ext2fs_clear_generic_bitmap(bitmap);
148.427 + else
148.428 + bitmap->bitmap_ops->clear_bmap (bitmap);
148.429 +}
148.430 +
148.431 +int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap,
148.432 + __u64 arg)
148.433 +{
148.434 + if (!bitmap)
148.435 + return 0;
148.436 +
148.437 + if (EXT2FS_IS_32_BITMAP(bitmap)) {
148.438 + if (arg & ~0xffffffffULL) {
148.439 + ext2fs_warn_bitmap2(bitmap,
148.440 + EXT2FS_MARK_ERROR, 0xffffffff);
148.441 + return 0;
148.442 + }
148.443 + return ext2fs_mark_generic_bitmap(bitmap, arg);
148.444 + }
148.445 +
148.446 + if (!EXT2FS_IS_64_BITMAP(bitmap))
148.447 + return 0;
148.448 +
148.449 + arg >>= bitmap->cluster_bits;
148.450 +
148.451 +#ifdef ENABLE_BMAP_STATS_OPS
148.452 + if (arg == bitmap->stats.last_marked + 1)
148.453 + bitmap->stats.mark_seq++;
148.454 + if (arg < bitmap->stats.last_marked)
148.455 + bitmap->stats.mark_back++;
148.456 + bitmap->stats.last_marked = arg;
148.457 + bitmap->stats.mark_count++;
148.458 +#endif
148.459 +
148.460 + if ((arg < bitmap->start) || (arg > bitmap->end)) {
148.461 + warn_bitmap(bitmap, EXT2FS_MARK_ERROR, arg);
148.462 + return 0;
148.463 + }
148.464 +
148.465 + return bitmap->bitmap_ops->mark_bmap(bitmap, arg);
148.466 +}
148.467 +
148.468 +int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap,
148.469 + __u64 arg)
148.470 +{
148.471 + if (!bitmap)
148.472 + return 0;
148.473 +
148.474 + if (EXT2FS_IS_32_BITMAP(bitmap)) {
148.475 + if (arg & ~0xffffffffULL) {
148.476 + ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR,
148.477 + 0xffffffff);
148.478 + return 0;
148.479 + }
148.480 + return ext2fs_unmark_generic_bitmap(bitmap, arg);
148.481 + }
148.482 +
148.483 + if (!EXT2FS_IS_64_BITMAP(bitmap))
148.484 + return 0;
148.485 +
148.486 + arg >>= bitmap->cluster_bits;
148.487 +
148.488 + INC_STAT(bitmap, unmark_count);
148.489 +
148.490 + if ((arg < bitmap->start) || (arg > bitmap->end)) {
148.491 + warn_bitmap(bitmap, EXT2FS_UNMARK_ERROR, arg);
148.492 + return 0;
148.493 + }
148.494 +
148.495 + return bitmap->bitmap_ops->unmark_bmap(bitmap, arg);
148.496 +}
148.497 +
148.498 +int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap,
148.499 + __u64 arg)
148.500 +{
148.501 + if (!bitmap)
148.502 + return 0;
148.503 +
148.504 + if (EXT2FS_IS_32_BITMAP(bitmap)) {
148.505 + if (arg & ~0xffffffffULL) {
148.506 + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR,
148.507 + 0xffffffff);
148.508 + return 0;
148.509 + }
148.510 + return ext2fs_test_generic_bitmap(bitmap, arg);
148.511 + }
148.512 +
148.513 + if (!EXT2FS_IS_64_BITMAP(bitmap))
148.514 + return 0;
148.515 +
148.516 + arg >>= bitmap->cluster_bits;
148.517 +
148.518 +#ifdef ENABLE_BMAP_STATS_OPS
148.519 + bitmap->stats.test_count++;
148.520 + if (arg == bitmap->stats.last_tested + 1)
148.521 + bitmap->stats.test_seq++;
148.522 + if (arg < bitmap->stats.last_tested)
148.523 + bitmap->stats.test_back++;
148.524 + bitmap->stats.last_tested = arg;
148.525 +#endif
148.526 +
148.527 + if ((arg < bitmap->start) || (arg > bitmap->end)) {
148.528 + warn_bitmap(bitmap, EXT2FS_TEST_ERROR, arg);
148.529 + return 0;
148.530 + }
148.531 +
148.532 + return bitmap->bitmap_ops->test_bmap(bitmap, arg);
148.533 +}
148.534 +
148.535 +errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap,
148.536 + __u64 start, unsigned int num,
148.537 + void *in)
148.538 +{
148.539 + if (!bmap)
148.540 + return EINVAL;
148.541 +
148.542 + if (EXT2FS_IS_32_BITMAP(bmap)) {
148.543 + if ((start+num-1) & ~0xffffffffULL) {
148.544 + ext2fs_warn_bitmap2(bmap, EXT2FS_UNMARK_ERROR,
148.545 + 0xffffffff);
148.546 + return EINVAL;
148.547 + }
148.548 + return ext2fs_set_generic_bitmap_range(bmap, bmap->magic,
148.549 + start, num, in);
148.550 + }
148.551 +
148.552 + if (!EXT2FS_IS_64_BITMAP(bmap))
148.553 + return EINVAL;
148.554 +
148.555 + INC_STAT(bmap, set_range_count);
148.556 +
148.557 + return bmap->bitmap_ops->set_bmap_range(bmap, start, num, in);
148.558 +}
148.559 +
148.560 +errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bmap,
148.561 + __u64 start, unsigned int num,
148.562 + void *out)
148.563 +{
148.564 + if (!bmap)
148.565 + return EINVAL;
148.566 +
148.567 + if (EXT2FS_IS_32_BITMAP(bmap)) {
148.568 + if ((start+num-1) & ~0xffffffffULL) {
148.569 + ext2fs_warn_bitmap2(bmap,
148.570 + EXT2FS_UNMARK_ERROR, 0xffffffff);
148.571 + return EINVAL;
148.572 + }
148.573 + return ext2fs_get_generic_bitmap_range(bmap, bmap->magic,
148.574 + start, num, out);
148.575 + }
148.576 +
148.577 + if (!EXT2FS_IS_64_BITMAP(bmap))
148.578 + return EINVAL;
148.579 +
148.580 + INC_STAT(bmap, get_range_count);
148.581 +
148.582 + return bmap->bitmap_ops->get_bmap_range(bmap, start, num, out);
148.583 +}
148.584 +
148.585 +errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
148.586 + ext2fs_generic_bitmap bm1,
148.587 + ext2fs_generic_bitmap bm2)
148.588 +{
148.589 + blk64_t i;
148.590 +
148.591 + if (!bm1 || !bm2)
148.592 + return EINVAL;
148.593 + if (bm1->magic != bm2->magic)
148.594 + return EINVAL;
148.595 +
148.596 + /* Now we know both bitmaps have the same magic */
148.597 + if (EXT2FS_IS_32_BITMAP(bm1))
148.598 + return ext2fs_compare_generic_bitmap(bm1->magic, neq, bm1, bm2);
148.599 +
148.600 + if (!EXT2FS_IS_64_BITMAP(bm1))
148.601 + return EINVAL;
148.602 +
148.603 + if ((bm1->start != bm2->start) ||
148.604 + (bm1->end != bm2->end))
148.605 + return neq;
148.606 +
148.607 + for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
148.608 + if (ext2fs_test_generic_bmap(bm1, i) !=
148.609 + ext2fs_test_generic_bmap(bm2, i))
148.610 + return neq;
148.611 +
148.612 + return 0;
148.613 +}
148.614 +
148.615 +void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap)
148.616 +{
148.617 + __u64 start, num;
148.618 +
148.619 + if (EXT2FS_IS_32_BITMAP(bmap)) {
148.620 + ext2fs_set_generic_bitmap_padding(bmap);
148.621 + return;
148.622 + }
148.623 +
148.624 + start = bmap->end + 1;
148.625 + num = bmap->real_end - bmap->end;
148.626 + bmap->bitmap_ops->mark_bmap_extent(bmap, start, num);
148.627 + /* XXX ought to warn on error */
148.628 +}
148.629 +
148.630 +int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap,
148.631 + blk64_t block, unsigned int num)
148.632 +{
148.633 + __u64 end = block + num;
148.634 +
148.635 + if (!bmap)
148.636 + return EINVAL;
148.637 +
148.638 + if (num == 1)
148.639 + return !ext2fs_test_generic_bmap((ext2fs_generic_bitmap)
148.640 + bmap, block);
148.641 +
148.642 + if (EXT2FS_IS_32_BITMAP(bmap)) {
148.643 + if ((block+num-1) & ~0xffffffffULL) {
148.644 + ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
148.645 + EXT2FS_UNMARK_ERROR, 0xffffffff);
148.646 + return EINVAL;
148.647 + }
148.648 + return ext2fs_test_block_bitmap_range(
148.649 + (ext2fs_generic_bitmap) bmap, block, num);
148.650 + }
148.651 +
148.652 + if (!EXT2FS_IS_64_BITMAP(bmap))
148.653 + return EINVAL;
148.654 +
148.655 + INC_STAT(bmap, test_ext_count);
148.656 +
148.657 + /* convert to clusters if necessary */
148.658 + block >>= bmap->cluster_bits;
148.659 + end += (1 << bmap->cluster_bits) - 1;
148.660 + end >>= bmap->cluster_bits;
148.661 + num = end - block;
148.662 +
148.663 + if ((block < bmap->start) || (block+num-1 > bmap->end)) {
148.664 + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, block,
148.665 + bmap->description);
148.666 + return EINVAL;
148.667 + }
148.668 +
148.669 + return bmap->bitmap_ops->test_clear_bmap_extent(bmap, block, num);
148.670 +}
148.671 +
148.672 +void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap,
148.673 + blk64_t block, unsigned int num)
148.674 +{
148.675 + __u64 end = block + num;
148.676 +
148.677 + if (!bmap)
148.678 + return;
148.679 +
148.680 + if (EXT2FS_IS_32_BITMAP(bmap)) {
148.681 + if ((block+num-1) & ~0xffffffffULL) {
148.682 + ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
148.683 + EXT2FS_UNMARK_ERROR, 0xffffffff);
148.684 + return;
148.685 + }
148.686 + ext2fs_mark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
148.687 + block, num);
148.688 + }
148.689 +
148.690 + if (!EXT2FS_IS_64_BITMAP(bmap))
148.691 + return;
148.692 +
148.693 + INC_STAT(bmap, mark_ext_count);
148.694 +
148.695 + /* convert to clusters if necessary */
148.696 + block >>= bmap->cluster_bits;
148.697 + end += (1 << bmap->cluster_bits) - 1;
148.698 + end >>= bmap->cluster_bits;
148.699 + num = end - block;
148.700 +
148.701 + if ((block < bmap->start) || (block+num-1 > bmap->end)) {
148.702 + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
148.703 + bmap->description);
148.704 + return;
148.705 + }
148.706 +
148.707 + bmap->bitmap_ops->mark_bmap_extent(bmap, block, num);
148.708 +}
148.709 +
148.710 +void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bmap,
148.711 + blk64_t block, unsigned int num)
148.712 +{
148.713 + __u64 end = block + num;
148.714 +
148.715 + if (!bmap)
148.716 + return;
148.717 +
148.718 + if (EXT2FS_IS_32_BITMAP(bmap)) {
148.719 + if ((block+num-1) & ~0xffffffffULL) {
148.720 + ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
148.721 + EXT2FS_UNMARK_ERROR, 0xffffffff);
148.722 + return;
148.723 + }
148.724 + ext2fs_unmark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
148.725 + block, num);
148.726 + }
148.727 +
148.728 + if (!EXT2FS_IS_64_BITMAP(bmap))
148.729 + return;
148.730 +
148.731 + INC_STAT(bmap, unmark_ext_count);
148.732 +
148.733 + /* convert to clusters if necessary */
148.734 + block >>= bmap->cluster_bits;
148.735 + end += (1 << bmap->cluster_bits) - 1;
148.736 + end >>= bmap->cluster_bits;
148.737 + num = end - block;
148.738 +
148.739 + if ((block < bmap->start) || (block+num-1 > bmap->end)) {
148.740 + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
148.741 + bmap->description);
148.742 + return;
148.743 + }
148.744 +
148.745 + bmap->bitmap_ops->unmark_bmap_extent(bmap, block, num);
148.746 +}
148.747 +
148.748 +void ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func)
148.749 +{
148.750 +#ifndef OMIT_COM_ERR
148.751 + if (bitmap && bitmap->description)
148.752 + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
148.753 + "called %s with 64-bit bitmap for %s", func,
148.754 + bitmap->description);
148.755 + else
148.756 + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
148.757 + "called %s with 64-bit bitmap", func);
148.758 +#endif
148.759 +}
148.760 +
148.761 +errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs,
148.762 + ext2fs_block_bitmap *bitmap)
148.763 +{
148.764 + ext2fs_block_bitmap cmap, bmap;
148.765 + errcode_t retval;
148.766 + blk64_t i, b_end, c_end;
148.767 + int n, ratio;
148.768 +
148.769 + bmap = *bitmap;
148.770 +
148.771 + if (fs->cluster_ratio_bits == ext2fs_get_bitmap_granularity(bmap))
148.772 + return 0; /* Nothing to do */
148.773 +
148.774 + retval = ext2fs_allocate_block_bitmap(fs, "converted cluster bitmap",
148.775 + &cmap);
148.776 + if (retval)
148.777 + return retval;
148.778 +
148.779 + i = bmap->start;
148.780 + b_end = bmap->end;
148.781 + bmap->end = bmap->real_end;
148.782 + c_end = cmap->end;
148.783 + cmap->end = cmap->real_end;
148.784 + n = 0;
148.785 + ratio = 1 << fs->cluster_ratio_bits;
148.786 + while (i < bmap->real_end) {
148.787 + if (ext2fs_test_block_bitmap2(bmap, i)) {
148.788 + ext2fs_mark_block_bitmap2(cmap, i);
148.789 + i += ratio - n;
148.790 + n = 0;
148.791 + continue;
148.792 + }
148.793 + i++; n++;
148.794 + if (n >= ratio)
148.795 + n = 0;
148.796 + }
148.797 + bmap->end = b_end;
148.798 + cmap->end = c_end;
148.799 + ext2fs_free_block_bitmap(bmap);
148.800 + *bitmap = cmap;
148.801 + return 0;
148.802 +}
148.803 +
148.804 +errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap,
148.805 + __u64 start, __u64 end, __u64 *out)
148.806 +{
148.807 + __u64 cstart, cend, cout;
148.808 + errcode_t retval;
148.809 +
148.810 + if (!bitmap)
148.811 + return EINVAL;
148.812 +
148.813 + if (EXT2FS_IS_32_BITMAP(bitmap)) {
148.814 + blk_t blk = 0;
148.815 +
148.816 + if (((start) & ~0xffffffffULL) ||
148.817 + ((end) & ~0xffffffffULL)) {
148.818 + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
148.819 + return EINVAL;
148.820 + }
148.821 +
148.822 + retval = ext2fs_find_first_zero_generic_bitmap(bitmap, start,
148.823 + end, &blk);
148.824 + if (retval == 0)
148.825 + *out = blk;
148.826 + return retval;
148.827 + }
148.828 +
148.829 + if (!EXT2FS_IS_64_BITMAP(bitmap))
148.830 + return EINVAL;
148.831 +
148.832 + cstart = start >> bitmap->cluster_bits;
148.833 + cend = end >> bitmap->cluster_bits;
148.834 +
148.835 + if (cstart < bitmap->start || cend > bitmap->end || start > end) {
148.836 + warn_bitmap(bitmap, EXT2FS_TEST_ERROR, start);
148.837 + return EINVAL;
148.838 + }
148.839 +
148.840 + if (bitmap->bitmap_ops->find_first_zero) {
148.841 + retval = bitmap->bitmap_ops->find_first_zero(bitmap, cstart,
148.842 + cend, &cout);
148.843 + if (retval)
148.844 + return retval;
148.845 + found:
148.846 + cout <<= bitmap->cluster_bits;
148.847 + *out = (cout >= start) ? cout : start;
148.848 + return 0;
148.849 + }
148.850 +
148.851 + for (cout = cstart; cout <= cend; cout++)
148.852 + if (!bitmap->bitmap_ops->test_bmap(bitmap, cout))
148.853 + goto found;
148.854 +
148.855 + return ENOENT;
148.856 +}
148.857 +
148.858 +errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap,
148.859 + __u64 start, __u64 end, __u64 *out)
148.860 +{
148.861 + __u64 cstart, cend, cout;
148.862 + errcode_t retval;
148.863 +
148.864 + if (!bitmap)
148.865 + return EINVAL;
148.866 +
148.867 + if (EXT2FS_IS_32_BITMAP(bitmap)) {
148.868 + blk_t blk = 0;
148.869 +
148.870 + if (((start) & ~0xffffffffULL) ||
148.871 + ((end) & ~0xffffffffULL)) {
148.872 + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
148.873 + return EINVAL;
148.874 + }
148.875 +
148.876 + retval = ext2fs_find_first_set_generic_bitmap(bitmap, start,
148.877 + end, &blk);
148.878 + if (retval == 0)
148.879 + *out = blk;
148.880 + return retval;
148.881 + }
148.882 +
148.883 + if (!EXT2FS_IS_64_BITMAP(bitmap))
148.884 + return EINVAL;
148.885 +
148.886 + cstart = start >> bitmap->cluster_bits;
148.887 + cend = end >> bitmap->cluster_bits;
148.888 +
148.889 + if (cstart < bitmap->start || cend > bitmap->end || start > end) {
148.890 + warn_bitmap(bitmap, EXT2FS_TEST_ERROR, start);
148.891 + return EINVAL;
148.892 + }
148.893 +
148.894 + if (bitmap->bitmap_ops->find_first_set) {
148.895 + retval = bitmap->bitmap_ops->find_first_set(bitmap, cstart,
148.896 + cend, &cout);
148.897 + if (retval)
148.898 + return retval;
148.899 + found:
148.900 + cout <<= bitmap->cluster_bits;
148.901 + *out = (cout >= start) ? cout : start;
148.902 + return 0;
148.903 + }
148.904 +
148.905 + for (cout = cstart; cout <= cend; cout++)
148.906 + if (bitmap->bitmap_ops->test_bmap(bitmap, cout))
148.907 + goto found;
148.908 +
148.909 + return ENOENT;
148.910 +}
149.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
149.2 +++ b/libext2fs/lib/libext2fs/gen_crc32ctable.c Wed Aug 25 01:28:08 2021 +0200
149.3 @@ -0,0 +1,117 @@
149.4 +#include <stdio.h>
149.5 +#include "crc32c_defs.h"
149.6 +#include <inttypes.h>
149.7 +
149.8 +#define ENTRIES_PER_LINE 4
149.9 +
149.10 +#if CRC_LE_BITS > 8
149.11 +# define LE_TABLE_ROWS (CRC_LE_BITS/8)
149.12 +# define LE_TABLE_SIZE 256
149.13 +#else
149.14 +# define LE_TABLE_ROWS 1
149.15 +# define LE_TABLE_SIZE (1 << CRC_LE_BITS)
149.16 +#endif
149.17 +
149.18 +#if CRC_BE_BITS > 8
149.19 +# define BE_TABLE_ROWS (CRC_BE_BITS/8)
149.20 +# define BE_TABLE_SIZE 256
149.21 +#else
149.22 +# define BE_TABLE_ROWS 1
149.23 +# define BE_TABLE_SIZE (1 << CRC_BE_BITS)
149.24 +#endif
149.25 +
149.26 +static uint32_t crc32table_be[BE_TABLE_ROWS][256];
149.27 +static uint32_t crc32ctable_le[LE_TABLE_ROWS][256];
149.28 +
149.29 +/**
149.30 + * crc32init_le() - allocate and initialize LE table data
149.31 + *
149.32 + * crc is the crc of the byte i; other entries are filled in based on the
149.33 + * fact that crctable[i^j] = crctable[i] ^ crctable[j].
149.34 + *
149.35 + */
149.36 +static void crc32cinit_le(void)
149.37 +{
149.38 + unsigned i, j;
149.39 + uint32_t crc = 1;
149.40 +
149.41 + crc32ctable_le[0][0] = 0;
149.42 +
149.43 + for (i = LE_TABLE_SIZE >> 1; i; i >>= 1) {
149.44 + crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
149.45 + for (j = 0; j < LE_TABLE_SIZE; j += 2 * i)
149.46 + crc32ctable_le[0][i + j] = crc ^ crc32ctable_le[0][j];
149.47 + }
149.48 + for (i = 0; i < LE_TABLE_SIZE; i++) {
149.49 + crc = crc32ctable_le[0][i];
149.50 + for (j = 1; j < LE_TABLE_ROWS; j++) {
149.51 + crc = crc32ctable_le[0][crc & 0xff] ^ (crc >> 8);
149.52 + crc32ctable_le[j][i] = crc;
149.53 + }
149.54 + }
149.55 +}
149.56 +
149.57 +/**
149.58 + * crc32init_be() - allocate and initialize BE table data
149.59 + */
149.60 +static void crc32init_be(void)
149.61 +{
149.62 + unsigned i, j;
149.63 + uint32_t crc = 0x80000000;
149.64 +
149.65 + crc32table_be[0][0] = 0;
149.66 +
149.67 + for (i = 1; i < BE_TABLE_SIZE; i <<= 1) {
149.68 + crc = (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : 0);
149.69 + for (j = 0; j < i; j++)
149.70 + crc32table_be[0][i + j] = crc ^ crc32table_be[0][j];
149.71 + }
149.72 + for (i = 0; i < BE_TABLE_SIZE; i++) {
149.73 + crc = crc32table_be[0][i];
149.74 + for (j = 1; j < BE_TABLE_ROWS; j++) {
149.75 + crc = crc32table_be[0][(crc >> 24) & 0xff] ^ (crc << 8);
149.76 + crc32table_be[j][i] = crc;
149.77 + }
149.78 + }
149.79 +}
149.80 +
149.81 +static void output_table(uint32_t (*table)[256], int rows, int len, char *trans)
149.82 +{
149.83 + int i, j;
149.84 +
149.85 + for (j = 0 ; j < rows; j++) {
149.86 + printf("{");
149.87 + for (i = 0; i < len - 1; i++) {
149.88 + if (i % ENTRIES_PER_LINE == 0)
149.89 + printf("\n");
149.90 + printf("%s(0x%8.8xL), ", trans, table[j][i]);
149.91 + }
149.92 + printf("%s(0x%8.8xL)},\n", trans, table[j][len - 1]);
149.93 + }
149.94 +}
149.95 +
149.96 +int main(int argc, char **argv)
149.97 +{
149.98 + printf("/* this file is generated - do not edit */\n\n");
149.99 +
149.100 + if (CRC_BE_BITS > 1) {
149.101 + crc32init_be();
149.102 + printf("static const uint32_t "
149.103 + "crc32table_be[%d][%d] = {",
149.104 + BE_TABLE_ROWS, BE_TABLE_SIZE);
149.105 + output_table(crc32table_be, LE_TABLE_ROWS,
149.106 + BE_TABLE_SIZE, "tobe");
149.107 + printf("};\n");
149.108 + }
149.109 + if (CRC_LE_BITS > 1) {
149.110 + crc32cinit_le();
149.111 + printf("static const uint32_t "
149.112 + "crc32ctable_le[%d][%d] = {",
149.113 + LE_TABLE_ROWS, LE_TABLE_SIZE);
149.114 + output_table(crc32ctable_le, LE_TABLE_ROWS,
149.115 + LE_TABLE_SIZE, "tole");
149.116 + printf("};\n");
149.117 + }
149.118 +
149.119 + return 0;
149.120 +}
150.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
150.2 +++ b/libext2fs/lib/libext2fs/get_num_dirs.c Wed Aug 25 01:28:08 2021 +0200
150.3 @@ -0,0 +1,50 @@
150.4 +/*
150.5 + * get_num_dirs.c -- calculate number of directories
150.6 + *
150.7 + * Copyright 1997 by Theodore Ts'o
150.8 + *
150.9 + * %Begin-Header%
150.10 + * This file may be redistributed under the terms of the GNU Library
150.11 + * General Public License, version 2.
150.12 + * %End-Header%
150.13 + */
150.14 +
150.15 +#include "config.h"
150.16 +#include <stdio.h>
150.17 +#if HAVE_UNISTD_H
150.18 +#include <unistd.h>
150.19 +#endif
150.20 +#include <string.h>
150.21 +#include <time.h>
150.22 +
150.23 +#include "ext2_fs.h"
150.24 +#include "ext2fsP.h"
150.25 +
150.26 +/*
150.27 + * Returns the number of directories in the filesystem as reported by
150.28 + * the group descriptors. Of course, the group descriptors could be
150.29 + * wrong!
150.30 + */
150.31 +errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs)
150.32 +{
150.33 + dgrp_t i;
150.34 + ext2_ino_t num_dirs, max_dirs;
150.35 +
150.36 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
150.37 +
150.38 + num_dirs = 0;
150.39 + max_dirs = fs->super->s_inodes_per_group;
150.40 + for (i = 0; i < fs->group_desc_count; i++) {
150.41 + if (ext2fs_bg_used_dirs_count(fs, i) > max_dirs)
150.42 + num_dirs += max_dirs / 8;
150.43 + else
150.44 + num_dirs += ext2fs_bg_used_dirs_count(fs, i);
150.45 + }
150.46 + if (num_dirs > fs->super->s_inodes_count)
150.47 + num_dirs = fs->super->s_inodes_count;
150.48 +
150.49 + *ret_num_dirs = num_dirs;
150.50 +
150.51 + return 0;
150.52 +}
150.53 +
151.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
151.2 +++ b/libext2fs/lib/libext2fs/get_pathname.c Wed Aug 25 01:28:08 2021 +0200
151.3 @@ -0,0 +1,171 @@
151.4 +/*
151.5 + * get_pathname.c --- do directory/inode -> name translation
151.6 + *
151.7 + * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
151.8 + *
151.9 + * %Begin-Header%
151.10 + * This file may be redistributed under the terms of the GNU Library
151.11 + * General Public License, version 2.
151.12 + * %End-Header%
151.13 + */
151.14 +
151.15 +/*
151.16 + *
151.17 + * ext2fs_get_pathname(fs, dir, ino, name)
151.18 + *
151.19 + * This function translates takes two inode numbers into a
151.20 + * string, placing the result in <name>. <dir> is the containing
151.21 + * directory inode, and <ino> is the inode number itself. If
151.22 + * <ino> is zero, then ext2fs_get_pathname will return pathname
151.23 + * of the the directory <dir>.
151.24 + *
151.25 + */
151.26 +
151.27 +#include "config.h"
151.28 +#include <stdio.h>
151.29 +#include <string.h>
151.30 +#if HAVE_UNISTD_H
151.31 +#include <unistd.h>
151.32 +#endif
151.33 +
151.34 +#include "ext2_fs.h"
151.35 +#include "ext2fs.h"
151.36 +
151.37 +struct get_pathname_struct {
151.38 + ext2_ino_t search_ino;
151.39 + ext2_ino_t parent;
151.40 + char *name;
151.41 + errcode_t errcode;
151.42 +};
151.43 +
151.44 +#ifdef __TURBOC__
151.45 + #pragma argsused
151.46 +#endif
151.47 +static int get_pathname_proc(struct ext2_dir_entry *dirent,
151.48 + int offset EXT2FS_ATTR((unused)),
151.49 + int blocksize EXT2FS_ATTR((unused)),
151.50 + char *buf EXT2FS_ATTR((unused)),
151.51 + void *priv_data)
151.52 +{
151.53 + struct get_pathname_struct *gp;
151.54 + errcode_t retval;
151.55 + int name_len = ext2fs_dirent_name_len(dirent);
151.56 +
151.57 + gp = (struct get_pathname_struct *) priv_data;
151.58 +
151.59 + if ((name_len == 2) && !strncmp(dirent->name, "..", 2))
151.60 + gp->parent = dirent->inode;
151.61 + if (dirent->inode == gp->search_ino) {
151.62 + retval = ext2fs_get_mem(name_len + 1, &gp->name);
151.63 + if (retval) {
151.64 + gp->errcode = retval;
151.65 + return DIRENT_ABORT;
151.66 + }
151.67 + strncpy(gp->name, dirent->name, name_len);
151.68 + gp->name[name_len] = '\0';
151.69 + return DIRENT_ABORT;
151.70 + }
151.71 + return 0;
151.72 +}
151.73 +
151.74 +static errcode_t ext2fs_get_pathname_int(ext2_filsys fs, ext2_ino_t dir,
151.75 + ext2_ino_t ino, int maxdepth,
151.76 + char *buf, char **name)
151.77 +{
151.78 + struct get_pathname_struct gp;
151.79 + char *parent_name = 0, *ret;
151.80 + errcode_t retval;
151.81 +
151.82 + if (dir == ino) {
151.83 + retval = ext2fs_get_mem(2, name);
151.84 + if (retval)
151.85 + return retval;
151.86 + strcpy(*name, (dir == EXT2_ROOT_INO) ? "/" : ".");
151.87 + return 0;
151.88 + }
151.89 +
151.90 + if (!dir || (maxdepth < 0)) {
151.91 + retval = ext2fs_get_mem(4, name);
151.92 + if (retval)
151.93 + return retval;
151.94 + strcpy(*name, "...");
151.95 + return 0;
151.96 + }
151.97 +
151.98 + gp.search_ino = ino;
151.99 + gp.parent = 0;
151.100 + gp.name = 0;
151.101 + gp.errcode = 0;
151.102 +
151.103 + retval = ext2fs_dir_iterate(fs, dir, 0, buf, get_pathname_proc, &gp);
151.104 + if (retval == EXT2_ET_NO_DIRECTORY) {
151.105 + char tmp[32];
151.106 +
151.107 + if (ino)
151.108 + snprintf(tmp, sizeof(tmp), "<%u>/<%u>", dir, ino);
151.109 + else
151.110 + snprintf(tmp, sizeof(tmp), "<%u>", dir);
151.111 + retval = ext2fs_get_mem(strlen(tmp)+1, name);
151.112 + if (retval)
151.113 + goto cleanup;
151.114 + strcpy(*name, tmp);
151.115 + return 0;
151.116 + } else if (retval)
151.117 + goto cleanup;
151.118 + if (gp.errcode) {
151.119 + retval = gp.errcode;
151.120 + goto cleanup;
151.121 + }
151.122 +
151.123 + retval = ext2fs_get_pathname_int(fs, gp.parent, dir, maxdepth-1,
151.124 + buf, &parent_name);
151.125 + if (retval)
151.126 + goto cleanup;
151.127 + if (!ino) {
151.128 + *name = parent_name;
151.129 + return 0;
151.130 + }
151.131 +
151.132 + if (gp.name)
151.133 + retval = ext2fs_get_mem(strlen(parent_name)+strlen(gp.name)+2,
151.134 + &ret);
151.135 + else
151.136 + retval = ext2fs_get_mem(strlen(parent_name)+5, &ret);
151.137 + if (retval)
151.138 + goto cleanup;
151.139 +
151.140 + ret[0] = 0;
151.141 + if (parent_name[1])
151.142 + strcat(ret, parent_name);
151.143 + strcat(ret, "/");
151.144 + if (gp.name)
151.145 + strcat(ret, gp.name);
151.146 + else
151.147 + strcat(ret, "???");
151.148 + *name = ret;
151.149 + retval = 0;
151.150 +
151.151 +cleanup:
151.152 + ext2fs_free_mem(&parent_name);
151.153 + ext2fs_free_mem(&gp.name);
151.154 + return retval;
151.155 +}
151.156 +
151.157 +errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
151.158 + char **name)
151.159 +{
151.160 + char *buf;
151.161 + errcode_t retval;
151.162 +
151.163 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
151.164 +
151.165 + retval = ext2fs_get_mem(fs->blocksize, &buf);
151.166 + if (retval)
151.167 + return retval;
151.168 + if (dir == ino)
151.169 + ino = 0;
151.170 + retval = ext2fs_get_pathname_int(fs, dir, ino, 32, buf, name);
151.171 + ext2fs_free_mem(&buf);
151.172 + return retval;
151.173 +
151.174 +}
152.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
152.2 +++ b/libext2fs/lib/libext2fs/getsectsize.c Wed Aug 25 01:28:08 2021 +0200
152.3 @@ -0,0 +1,136 @@
152.4 +/*
152.5 + * getsectsize.c --- get the sector size of a device.
152.6 + *
152.7 + * Copyright (C) 1995, 1995 Theodore Ts'o.
152.8 + * Copyright (C) 2003 VMware, Inc.
152.9 + *
152.10 + * %Begin-Header%
152.11 + * This file may be redistributed under the terms of the GNU Library
152.12 + * General Public License, version 2.
152.13 + * %End-Header%
152.14 + */
152.15 +
152.16 +#ifndef _LARGEFILE_SOURCE
152.17 +#define _LARGEFILE_SOURCE
152.18 +#endif
152.19 +#ifndef _LARGEFILE64_SOURCE
152.20 +#define _LARGEFILE64_SOURCE
152.21 +#endif
152.22 +
152.23 +#include "config.h"
152.24 +#include <stdio.h>
152.25 +#if HAVE_UNISTD_H
152.26 +#include <unistd.h>
152.27 +#endif
152.28 +#if HAVE_ERRNO_H
152.29 +#include <errno.h>
152.30 +#endif
152.31 +#include <fcntl.h>
152.32 +#ifdef HAVE_SYS_DISK_H
152.33 +#include <sys/disk.h>
152.34 +#endif
152.35 +#ifdef HAVE_LINUX_FD_H
152.36 +#include <sys/ioctl.h>
152.37 +#include <linux/fd.h>
152.38 +#endif
152.39 +
152.40 +#if defined(__linux__) && defined(_IO)
152.41 +#if !defined(BLKSSZGET)
152.42 +#define BLKSSZGET _IO(0x12,104)/* get block device sector size */
152.43 +#endif
152.44 +#if !defined(BLKPBSZGET)
152.45 +#define BLKPBSZGET _IO(0x12,123)/* get block physical sector size */
152.46 +#endif
152.47 +#endif
152.48 +
152.49 +#include "ext2_fs.h"
152.50 +#include "ext2fs.h"
152.51 +
152.52 +/*
152.53 + * Returns the logical sector size of a device
152.54 + */
152.55 +errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize)
152.56 +{
152.57 + int fd;
152.58 +
152.59 + fd = ext2fs_open_file(file, O_RDONLY, 0);
152.60 + if (fd < 0)
152.61 + return errno;
152.62 +
152.63 +#ifdef BLKSSZGET
152.64 + if (ioctl(fd, BLKSSZGET, sectsize) >= 0) {
152.65 + close(fd);
152.66 + return 0;
152.67 + }
152.68 +#endif
152.69 +#ifdef DIOCGSECTORSIZE
152.70 + if (ioctl(fd, DIOCGSECTORSIZE, sectsize) >= 0) {
152.71 + close(fd);
152.72 + return 0;
152.73 + }
152.74 +#endif
152.75 + *sectsize = 0;
152.76 + close(fd);
152.77 + return 0;
152.78 +}
152.79 +
152.80 +/*
152.81 + * Return desired alignment for direct I/O
152.82 + */
152.83 +int ext2fs_get_dio_alignment(int fd)
152.84 +{
152.85 + int align = 0;
152.86 +
152.87 +#ifdef BLKSSZGET
152.88 + if (ioctl(fd, BLKSSZGET, &align) < 0)
152.89 + align = 0;
152.90 +#endif
152.91 +#ifdef DIOCGSECTORSIZE
152.92 + if (align <= 0 &&
152.93 + ioctl(fd, DIOCGSECTORSIZE, &align) < 0)
152.94 + align = 0;
152.95 +#endif
152.96 +
152.97 +#ifdef _SC_PAGESIZE
152.98 + if (align <= 0)
152.99 + align = sysconf(_SC_PAGESIZE);
152.100 +#endif
152.101 +#ifdef HAVE_GETPAGESIZE
152.102 + if (align <= 0)
152.103 + align = getpagesize();
152.104 +#endif
152.105 + if (align <= 0)
152.106 + align = 4096;
152.107 +
152.108 + return align;
152.109 +}
152.110 +
152.111 +/*
152.112 + * Returns the physical sector size of a device
152.113 + */
152.114 +errcode_t ext2fs_get_device_phys_sectsize(const char *file, int *sectsize)
152.115 +{
152.116 + int fd;
152.117 +
152.118 + fd = ext2fs_open_file(file, O_RDONLY, 0);
152.119 + if (fd < 0)
152.120 + return errno;
152.121 +
152.122 +#ifdef BLKPBSZGET
152.123 + if (ioctl(fd, BLKPBSZGET, sectsize) >= 0) {
152.124 + close(fd);
152.125 + return 0;
152.126 + }
152.127 +#endif
152.128 +#ifdef DIOCGSECTORSIZE
152.129 + /* This isn't really the physical sector size, but FreeBSD
152.130 + * doesn't seem to have this concept. */
152.131 + if (ioctl(fd, DIOCGSECTORSIZE, sectsize) >= 0) {
152.132 + close(fd);
152.133 + return 0;
152.134 + }
152.135 +#endif
152.136 + *sectsize = 0;
152.137 + close(fd);
152.138 + return 0;
152.139 +}
153.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
153.2 +++ b/libext2fs/lib/libext2fs/getsize.c Wed Aug 25 01:28:08 2021 +0200
153.3 @@ -0,0 +1,315 @@
153.4 +/*
153.5 + * getsize.c --- get the size of a partition.
153.6 + *
153.7 + * Copyright (C) 1995, 1995 Theodore Ts'o.
153.8 + * Copyright (C) 2003 VMware, Inc.
153.9 + *
153.10 + * Windows version of ext2fs_get_device_size by Chris Li, VMware.
153.11 + *
153.12 + * %Begin-Header%
153.13 + * This file may be redistributed under the terms of the GNU Library
153.14 + * General Public License, version 2.
153.15 + * %End-Header%
153.16 + */
153.17 +
153.18 +#ifndef _LARGEFILE_SOURCE
153.19 +#define _LARGEFILE_SOURCE
153.20 +#endif
153.21 +#ifndef _LARGEFILE64_SOURCE
153.22 +#define _LARGEFILE64_SOURCE
153.23 +#endif
153.24 +
153.25 +#include "config.h"
153.26 +#include <stdio.h>
153.27 +#if HAVE_UNISTD_H
153.28 +#include <unistd.h>
153.29 +#endif
153.30 +#if HAVE_ERRNO_H
153.31 +#include <errno.h>
153.32 +#endif
153.33 +#include <fcntl.h>
153.34 +#ifdef HAVE_SYS_IOCTL_H
153.35 +#include <sys/ioctl.h>
153.36 +#endif
153.37 +#ifdef HAVE_LINUX_FD_H
153.38 +#include <linux/fd.h>
153.39 +#endif
153.40 +#ifdef HAVE_SYS_DISKLABEL_H
153.41 +#include <sys/disklabel.h>
153.42 +#endif
153.43 +#ifdef HAVE_SYS_DISK_H
153.44 +#include <sys/disk.h>
153.45 +#endif
153.46 +#ifdef __linux__
153.47 +#include <sys/utsname.h>
153.48 +#endif
153.49 +#if HAVE_SYS_STAT_H
153.50 +#include <sys/stat.h>
153.51 +#endif
153.52 +#include <ctype.h>
153.53 +
153.54 +#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
153.55 +#define BLKGETSIZE _IO(0x12,96) /* return device size */
153.56 +#endif
153.57 +
153.58 +#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
153.59 +#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
153.60 +#endif
153.61 +
153.62 +#ifdef APPLE_DARWIN
153.63 +#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
153.64 +#endif /* APPLE_DARWIN */
153.65 +
153.66 +#include "ext2_fs.h"
153.67 +#include "ext2fs.h"
153.68 +
153.69 +#if defined(__CYGWIN__) || defined (WIN32)
153.70 +#include "windows.h"
153.71 +#include "winioctl.h"
153.72 +
153.73 +#if (_WIN32_WINNT >= 0x0500)
153.74 +#define HAVE_GET_FILE_SIZE_EX 1
153.75 +#endif
153.76 +
153.77 +errcode_t ext2fs_get_device_size2(const char *file, int blocksize,
153.78 + blk64_t *retblocks)
153.79 +{
153.80 + HANDLE dev;
153.81 + PARTITION_INFORMATION pi;
153.82 + DISK_GEOMETRY gi;
153.83 + DWORD retbytes;
153.84 +#ifdef HAVE_GET_FILE_SIZE_EX
153.85 + LARGE_INTEGER filesize;
153.86 +#else
153.87 + DWORD filesize;
153.88 +#endif /* HAVE_GET_FILE_SIZE_EX */
153.89 +
153.90 + dev = CreateFile(file, GENERIC_READ,
153.91 + FILE_SHARE_READ | FILE_SHARE_WRITE ,
153.92 + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
153.93 +
153.94 + if (dev == INVALID_HANDLE_VALUE)
153.95 + return EBADF;
153.96 + if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
153.97 + &pi, sizeof(PARTITION_INFORMATION),
153.98 + &pi, sizeof(PARTITION_INFORMATION),
153.99 + &retbytes, NULL)) {
153.100 +
153.101 + *retblocks = pi.PartitionLength.QuadPart / blocksize;
153.102 +
153.103 + } else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
153.104 + &gi, sizeof(DISK_GEOMETRY),
153.105 + &gi, sizeof(DISK_GEOMETRY),
153.106 + &retbytes, NULL)) {
153.107 +
153.108 + *retblocks = gi.BytesPerSector *
153.109 + gi.SectorsPerTrack *
153.110 + gi.TracksPerCylinder *
153.111 + gi.Cylinders.QuadPart / blocksize;
153.112 +
153.113 +#ifdef HAVE_GET_FILE_SIZE_EX
153.114 + } else if (GetFileSizeEx(dev, &filesize)) {
153.115 + *retblocks = filesize.QuadPart / blocksize;
153.116 + }
153.117 +#else
153.118 + } else {
153.119 + filesize = GetFileSize(dev, NULL);
153.120 + if (INVALID_FILE_SIZE != filesize) {
153.121 + *retblocks = filesize / blocksize;
153.122 + }
153.123 + }
153.124 +#endif /* HAVE_GET_FILE_SIZE_EX */
153.125 +
153.126 + CloseHandle(dev);
153.127 + return 0;
153.128 +}
153.129 +
153.130 +#else
153.131 +
153.132 +static int valid_offset (int fd, ext2_loff_t offset)
153.133 +{
153.134 + char ch;
153.135 +
153.136 + if (ext2fs_llseek (fd, offset, 0) < 0)
153.137 + return 0;
153.138 + if (read (fd, &ch, 1) < 1)
153.139 + return 0;
153.140 + return 1;
153.141 +}
153.142 +
153.143 +/*
153.144 + * Returns the number of blocks in a partition
153.145 + */
153.146 +errcode_t ext2fs_get_device_size2(const char *file, int blocksize,
153.147 + blk64_t *retblocks)
153.148 +{
153.149 + int fd, rc = 0;
153.150 + unsigned long long size64;
153.151 + ext2_loff_t high, low;
153.152 +
153.153 + fd = ext2fs_open_file(file, O_RDONLY, 0);
153.154 + if (fd < 0)
153.155 + return errno;
153.156 +
153.157 +#if defined DKIOCGETBLOCKCOUNT && defined DKIOCGETBLOCKSIZE /* For Apple Darwin */
153.158 + unsigned int size;
153.159 +
153.160 + if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0 &&
153.161 + ioctl(fd, DKIOCGETBLOCKSIZE, &size) >= 0) {
153.162 + *retblocks = size64 * size / blocksize;
153.163 + goto out;
153.164 + }
153.165 +#endif
153.166 +
153.167 +#ifdef BLKGETSIZE64
153.168 + {
153.169 + int valid_blkgetsize64 = 1;
153.170 +#ifdef __linux__
153.171 + struct utsname ut;
153.172 +
153.173 + if ((uname(&ut) == 0) &&
153.174 + ((ut.release[0] == '2') && (ut.release[1] == '.') &&
153.175 + (ut.release[2] < '6') && (ut.release[3] == '.')))
153.176 + valid_blkgetsize64 = 0;
153.177 +#endif
153.178 + if (valid_blkgetsize64 &&
153.179 + ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
153.180 + *retblocks = size64 / blocksize;
153.181 + goto out;
153.182 + }
153.183 + }
153.184 +#endif /* BLKGETSIZE64 */
153.185 +
153.186 +#ifdef BLKGETSIZE
153.187 + {
153.188 + unsigned long size;
153.189 +
153.190 + if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
153.191 + *retblocks = size / (blocksize / 512);
153.192 + goto out;
153.193 + }
153.194 + }
153.195 +#endif
153.196 +
153.197 +#ifdef FDGETPRM
153.198 + {
153.199 + struct floppy_struct this_floppy;
153.200 +
153.201 + if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
153.202 + *retblocks = this_floppy.size / (blocksize / 512);
153.203 + goto out;
153.204 + }
153.205 + }
153.206 +#endif
153.207 +
153.208 +#ifdef HAVE_SYS_DISKLABEL_H
153.209 + {
153.210 + int part;
153.211 + struct disklabel lab;
153.212 + struct partition *pp;
153.213 + char ch;
153.214 +
153.215 +#if defined(DIOCGMEDIASIZE)
153.216 + {
153.217 + off_t ms;
153.218 + u_int bs;
153.219 + if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) {
153.220 + *retblocks = ms / blocksize;
153.221 + goto out;
153.222 + }
153.223 + }
153.224 +#elif defined(DIOCGDINFO)
153.225 + /* old disklabel interface */
153.226 + part = strlen(file) - 1;
153.227 + if (part >= 0) {
153.228 + ch = file[part];
153.229 + if (isdigit(ch))
153.230 + part = 0;
153.231 + else if (ch >= 'a' && ch <= 'h')
153.232 + part = ch - 'a';
153.233 + else
153.234 + part = -1;
153.235 + }
153.236 + if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
153.237 + pp = &lab.d_partitions[part];
153.238 + if (pp->p_size) {
153.239 + *retblocks = pp->p_size / (blocksize / 512);
153.240 + goto out;
153.241 + }
153.242 + }
153.243 +#endif /* defined(DIOCG*) */
153.244 + }
153.245 +#endif /* HAVE_SYS_DISKLABEL_H */
153.246 +
153.247 + {
153.248 + ext2fs_struct_stat st;
153.249 +
153.250 + if (ext2fs_fstat(fd, &st) == 0)
153.251 + if (S_ISREG(st.st_mode)) {
153.252 + *retblocks = st.st_size / blocksize;
153.253 + goto out;
153.254 + }
153.255 + }
153.256 +
153.257 + /*
153.258 + * OK, we couldn't figure it out by using a specialized ioctl,
153.259 + * which is generally the best way. So do binary search to
153.260 + * find the size of the partition.
153.261 + */
153.262 + low = 0;
153.263 + for (high = 1024; valid_offset(fd, high); high *= 2)
153.264 + low = high;
153.265 + while (low < high - 1) {
153.266 + const ext2_loff_t mid = (low + high) / 2;
153.267 +
153.268 + if (valid_offset (fd, mid))
153.269 + low = mid;
153.270 + else
153.271 + high = mid;
153.272 + }
153.273 + valid_offset(fd, 0);
153.274 + size64 = low + 1;
153.275 + *retblocks = size64 / blocksize;
153.276 +out:
153.277 + close(fd);
153.278 + return rc;
153.279 +}
153.280 +
153.281 +#endif /* WIN32 */
153.282 +
153.283 +errcode_t ext2fs_get_device_size(const char *file, int blocksize,
153.284 + blk_t *retblocks)
153.285 +{
153.286 + errcode_t retval;
153.287 + blk64_t blocks;
153.288 +
153.289 + retval = ext2fs_get_device_size2(file, blocksize, &blocks);
153.290 + if (retval)
153.291 + return retval;
153.292 + if (blocks >= (1ULL << 32))
153.293 + return EFBIG;
153.294 + *retblocks = (blk_t) blocks;
153.295 + return 0;
153.296 +}
153.297 +
153.298 +#ifdef DEBUG
153.299 +int main(int argc, char **argv)
153.300 +{
153.301 + blk_t blocks;
153.302 + int retval;
153.303 +
153.304 + if (argc < 2) {
153.305 + fprintf(stderr, "Usage: %s device\n", argv[0]);
153.306 + exit(1);
153.307 + }
153.308 +
153.309 + retval = ext2fs_get_device_size(argv[1], 1024, &blocks);
153.310 + if (retval) {
153.311 + com_err(argv[0], retval,
153.312 + "while calling ext2fs_get_device_size");
153.313 + exit(1);
153.314 + }
153.315 + printf("Device %s has %u 1k blocks.\n", argv[1], blocks);
153.316 + exit(0);
153.317 +}
153.318 +#endif
154.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
154.2 +++ b/libext2fs/lib/libext2fs/hashmap.c Wed Aug 25 01:28:08 2021 +0200
154.3 @@ -0,0 +1,85 @@
154.4 +#include "hashmap.h"
154.5 +#include <string.h>
154.6 +
154.7 +uint32_t ext2fs_djb2_hash(const void *str, size_t size)
154.8 +{
154.9 + int c;
154.10 + const char *s = str;
154.11 + uint32_t hash = 5381;
154.12 +
154.13 + while (size-- > 0) {
154.14 + c = *s++;
154.15 + hash = ((hash << 5) + hash) + c;
154.16 + }
154.17 + return hash;
154.18 +}
154.19 +
154.20 +struct ext2fs_hashmap *ext2fs_hashmap_create(
154.21 + uint32_t(*hash_fct)(const void*, size_t),
154.22 + void(*free_fct)(void*), size_t size)
154.23 +{
154.24 + struct ext2fs_hashmap *h = calloc(sizeof(struct ext2fs_hashmap) +
154.25 + sizeof(struct ext2fs_hashmap_entry) * size, 1);
154.26 + h->size = size;
154.27 + h->free = free_fct;
154.28 + h->hash = hash_fct;
154.29 + h->first = h->last = NULL;
154.30 + return h;
154.31 +}
154.32 +
154.33 +void ext2fs_hashmap_add(struct ext2fs_hashmap *h, void *data, const void *key,
154.34 + size_t key_len)
154.35 +{
154.36 + uint32_t hash = h->hash(key, key_len) % h->size;
154.37 + struct ext2fs_hashmap_entry *e = malloc(sizeof(*e));
154.38 +
154.39 + e->data = data;
154.40 + e->key = key;
154.41 + e->key_len = key_len;
154.42 + e->next = h->entries[hash];
154.43 + h->entries[hash] = e;
154.44 +
154.45 + e->list_prev = NULL;
154.46 + e->list_next = h->first;
154.47 + if (h->first)
154.48 + h->first->list_prev = e;
154.49 + h->first = e;
154.50 + if (!h->last)
154.51 + h->last = e;
154.52 +}
154.53 +
154.54 +void *ext2fs_hashmap_lookup(struct ext2fs_hashmap *h, const void *key,
154.55 + size_t key_len)
154.56 +{
154.57 + struct ext2fs_hashmap_entry *iter;
154.58 + uint32_t hash = h->hash(key, key_len) % h->size;
154.59 +
154.60 + for (iter = h->entries[hash]; iter; iter = iter->next)
154.61 + if (iter->key_len == key_len && !memcmp(iter->key, key, key_len))
154.62 + return iter->data;
154.63 + return NULL;
154.64 +}
154.65 +
154.66 +void *ext2fs_hashmap_iter_in_order(struct ext2fs_hashmap *h,
154.67 + struct ext2fs_hashmap_entry **it)
154.68 +{
154.69 + *it = *it ? (*it)->list_next : h->first;
154.70 + return *it ? (*it)->data : NULL;
154.71 +}
154.72 +
154.73 +void ext2fs_hashmap_free(struct ext2fs_hashmap *h)
154.74 +{
154.75 + size_t i;
154.76 +
154.77 + for (i = 0; i < h->size; ++i) {
154.78 + struct ext2fs_hashmap_entry *it = h->entries[i];
154.79 + while (it) {
154.80 + struct ext2fs_hashmap_entry *tmp = it->next;
154.81 + if (h->free)
154.82 + h->free(it->data);
154.83 + free(it);
154.84 + it = tmp;
154.85 + }
154.86 + }
154.87 + free(h);
154.88 +}
155.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
155.2 +++ b/libext2fs/lib/libext2fs/i_block.c Wed Aug 25 01:28:08 2021 +0200
155.3 @@ -0,0 +1,90 @@
155.4 +/*
155.5 + * i_block.c --- Manage the i_block field for i_blocks
155.6 + *
155.7 + * Copyright (C) 2008 Theodore Ts'o.
155.8 + *
155.9 + * %Begin-Header%
155.10 + * This file may be redistributed under the terms of the GNU Library
155.11 + * General Public License, version 2.
155.12 + * %End-Header%
155.13 + */
155.14 +
155.15 +#include "config.h"
155.16 +#include <stdio.h>
155.17 +#if HAVE_UNISTD_H
155.18 +#include <unistd.h>
155.19 +#endif
155.20 +#include <time.h>
155.21 +#include <string.h>
155.22 +#if HAVE_SYS_STAT_H
155.23 +#include <sys/stat.h>
155.24 +#endif
155.25 +#if HAVE_SYS_TYPES_H
155.26 +#include <sys/types.h>
155.27 +#endif
155.28 +#include <errno.h>
155.29 +
155.30 +#include "ext2_fs.h"
155.31 +#include "ext2fs.h"
155.32 +
155.33 +errcode_t ext2fs_iblk_add_blocks(ext2_filsys fs, struct ext2_inode *inode,
155.34 + blk64_t num_blocks)
155.35 +{
155.36 + unsigned long long b = inode->i_blocks;
155.37 +
155.38 + if (ext2fs_has_feature_huge_file(fs->super))
155.39 + b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
155.40 +
155.41 + if (!ext2fs_has_feature_huge_file(fs->super) ||
155.42 + !(inode->i_flags & EXT4_HUGE_FILE_FL))
155.43 + num_blocks *= fs->blocksize / 512;
155.44 + num_blocks *= EXT2FS_CLUSTER_RATIO(fs);
155.45 +
155.46 + b += num_blocks;
155.47 +
155.48 + if (ext2fs_has_feature_huge_file(fs->super))
155.49 + inode->osd2.linux2.l_i_blocks_hi = b >> 32;
155.50 + else if (b > 0xFFFFFFFF)
155.51 + return EOVERFLOW;
155.52 + inode->i_blocks = b & 0xFFFFFFFF;
155.53 + return 0;
155.54 +}
155.55 +
155.56 +errcode_t ext2fs_iblk_sub_blocks(ext2_filsys fs, struct ext2_inode *inode,
155.57 + blk64_t num_blocks)
155.58 +{
155.59 + unsigned long long b = inode->i_blocks;
155.60 +
155.61 + if (ext2fs_has_feature_huge_file(fs->super))
155.62 + b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
155.63 +
155.64 + if (!ext2fs_has_feature_huge_file(fs->super) ||
155.65 + !(inode->i_flags & EXT4_HUGE_FILE_FL))
155.66 + num_blocks *= fs->blocksize / 512;
155.67 + num_blocks *= EXT2FS_CLUSTER_RATIO(fs);
155.68 +
155.69 + if (num_blocks > b)
155.70 + return EOVERFLOW;
155.71 +
155.72 + b -= num_blocks;
155.73 +
155.74 + if (ext2fs_has_feature_huge_file(fs->super))
155.75 + inode->osd2.linux2.l_i_blocks_hi = b >> 32;
155.76 + inode->i_blocks = b & 0xFFFFFFFF;
155.77 + return 0;
155.78 +}
155.79 +
155.80 +errcode_t ext2fs_iblk_set(ext2_filsys fs, struct ext2_inode *inode, blk64_t b)
155.81 +{
155.82 + if (!ext2fs_has_feature_huge_file(fs->super) ||
155.83 + !(inode->i_flags & EXT4_HUGE_FILE_FL))
155.84 + b *= fs->blocksize / 512;
155.85 + b *= EXT2FS_CLUSTER_RATIO(fs);
155.86 +
155.87 + inode->i_blocks = b & 0xFFFFFFFF;
155.88 + if (ext2fs_has_feature_huge_file(fs->super))
155.89 + inode->osd2.linux2.l_i_blocks_hi = b >> 32;
155.90 + else if (b >> 32)
155.91 + return EOVERFLOW;
155.92 + return 0;
155.93 +}
156.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
156.2 +++ b/libext2fs/lib/libext2fs/ind_block.c Wed Aug 25 01:28:08 2021 +0200
156.3 @@ -0,0 +1,67 @@
156.4 +/*
156.5 + * ind_block.c --- indirect block I/O routines
156.6 + *
156.7 + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
156.8 + * 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o.
156.9 + *
156.10 + * %Begin-Header%
156.11 + * This file may be redistributed under the terms of the GNU Library
156.12 + * General Public License, version 2.
156.13 + * %End-Header%
156.14 + */
156.15 +
156.16 +#include "config.h"
156.17 +#include <stdio.h>
156.18 +#include <string.h>
156.19 +#if HAVE_UNISTD_H
156.20 +#include <unistd.h>
156.21 +#endif
156.22 +
156.23 +#include "ext2_fs.h"
156.24 +#include "ext2fs.h"
156.25 +
156.26 +errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf)
156.27 +{
156.28 + errcode_t retval;
156.29 +#ifdef WORDS_BIGENDIAN
156.30 + blk_t *block_nr;
156.31 + int i;
156.32 + int limit = fs->blocksize >> 2;
156.33 +#endif
156.34 +
156.35 + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) &&
156.36 + (fs->io != fs->image_io))
156.37 + memset(buf, 0, fs->blocksize);
156.38 + else {
156.39 + retval = io_channel_read_blk(fs->io, blk, 1, buf);
156.40 + if (retval)
156.41 + return retval;
156.42 + }
156.43 +#ifdef WORDS_BIGENDIAN
156.44 + block_nr = (blk_t *) buf;
156.45 + for (i = 0; i < limit; i++, block_nr++)
156.46 + *block_nr = ext2fs_swab32(*block_nr);
156.47 +#endif
156.48 + return 0;
156.49 +}
156.50 +
156.51 +errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf)
156.52 +{
156.53 +#ifdef WORDS_BIGENDIAN
156.54 + blk_t *block_nr;
156.55 + int i;
156.56 + int limit = fs->blocksize >> 2;
156.57 +#endif
156.58 +
156.59 + if (fs->flags & EXT2_FLAG_IMAGE_FILE)
156.60 + return 0;
156.61 +
156.62 +#ifdef WORDS_BIGENDIAN
156.63 + block_nr = (blk_t *) buf;
156.64 + for (i = 0; i < limit; i++, block_nr++)
156.65 + *block_nr = ext2fs_swab32(*block_nr);
156.66 +#endif
156.67 + return io_channel_write_blk(fs->io, blk, 1, buf);
156.68 +}
156.69 +
156.70 +
157.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
157.2 +++ b/libext2fs/lib/libext2fs/initialize.c Wed Aug 25 01:28:08 2021 +0200
157.3 @@ -0,0 +1,570 @@
157.4 +/*
157.5 + * initialize.c --- initialize a filesystem handle given superblock
157.6 + * parameters. Used by mke2fs when initializing a filesystem.
157.7 + *
157.8 + * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
157.9 + *
157.10 + * %Begin-Header%
157.11 + * This file may be redistributed under the terms of the GNU Library
157.12 + * General Public License, version 2.
157.13 + * %End-Header%
157.14 + */
157.15 +
157.16 +#include "config.h"
157.17 +#include <stdio.h>
157.18 +#include <string.h>
157.19 +#if HAVE_UNISTD_H
157.20 +#include <unistd.h>
157.21 +#endif
157.22 +#include <fcntl.h>
157.23 +#include <time.h>
157.24 +#if HAVE_SYS_STAT_H
157.25 +#include <sys/stat.h>
157.26 +#endif
157.27 +#if HAVE_SYS_TYPES_H
157.28 +#include <sys/types.h>
157.29 +#endif
157.30 +
157.31 +#include "ext2_fs.h"
157.32 +#include "ext2fs.h"
157.33 +
157.34 +#ifndef O_BINARY
157.35 +#define O_BINARY 0
157.36 +#endif
157.37 +
157.38 +#if defined(__linux__) && defined(EXT2_OS_LINUX)
157.39 +#define CREATOR_OS EXT2_OS_LINUX
157.40 +#else
157.41 +#if defined(__GNU__) && defined(EXT2_OS_HURD)
157.42 +#define CREATOR_OS EXT2_OS_HURD
157.43 +#else
157.44 +#if defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD)
157.45 +#define CREATOR_OS EXT2_OS_FREEBSD
157.46 +#else
157.47 +#if defined(LITES) && defined(EXT2_OS_LITES)
157.48 +#define CREATOR_OS EXT2_OS_LITES
157.49 +#else
157.50 +#define CREATOR_OS EXT2_OS_LINUX /* by default */
157.51 +#endif /* defined(LITES) && defined(EXT2_OS_LITES) */
157.52 +#endif /* defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) */
157.53 +#endif /* defined(__GNU__) && defined(EXT2_OS_HURD) */
157.54 +#endif /* defined(__linux__) && defined(EXT2_OS_LINUX) */
157.55 +
157.56 +/*
157.57 + * Calculate the number of GDT blocks to reserve for online filesystem growth.
157.58 + * The absolute maximum number of GDT blocks we can reserve is determined by
157.59 + * the number of block pointers that can fit into a single block.
157.60 + */
157.61 +static unsigned int calc_reserved_gdt_blocks(ext2_filsys fs)
157.62 +{
157.63 + struct ext2_super_block *sb = fs->super;
157.64 + unsigned long bpg = sb->s_blocks_per_group;
157.65 + unsigned int gdpb = EXT2_DESC_PER_BLOCK(sb);
157.66 + unsigned long max_blocks = 0xffffffff;
157.67 + unsigned long rsv_groups;
157.68 + unsigned int rsv_gdb;
157.69 +
157.70 + /* We set it at 1024x the current filesystem size, or
157.71 + * the upper block count limit (2^32), whichever is lower.
157.72 + */
157.73 + if (ext2fs_blocks_count(sb) < max_blocks / 1024)
157.74 + max_blocks = ext2fs_blocks_count(sb) * 1024;
157.75 + /*
157.76 + * ext2fs_div64_ceil() is unnecessary because max_blocks is
157.77 + * max _GDT_ blocks, which is limited to 32 bits.
157.78 + */
157.79 + rsv_groups = ext2fs_div_ceil(max_blocks - sb->s_first_data_block, bpg);
157.80 + rsv_gdb = ext2fs_div_ceil(rsv_groups, gdpb) - fs->desc_blocks;
157.81 + if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb))
157.82 + rsv_gdb = EXT2_ADDR_PER_BLOCK(sb);
157.83 +#ifdef RES_GDT_DEBUG
157.84 + printf("max_blocks %lu, rsv_groups = %lu, rsv_gdb = %u\n",
157.85 + max_blocks, rsv_groups, rsv_gdb);
157.86 +#endif
157.87 +
157.88 + return rsv_gdb;
157.89 +}
157.90 +
157.91 +errcode_t ext2fs_initialize(const char *name, int flags,
157.92 + struct ext2_super_block *param,
157.93 + io_manager manager, ext2_filsys *ret_fs)
157.94 +{
157.95 + ext2_filsys fs;
157.96 + errcode_t retval;
157.97 + struct ext2_super_block *super;
157.98 + unsigned int rem;
157.99 + unsigned int overhead = 0;
157.100 + unsigned int ipg;
157.101 + dgrp_t i;
157.102 + blk64_t free_blocks;
157.103 + blk_t numblocks;
157.104 + int rsv_gdt;
157.105 + int csum_flag;
157.106 + int bigalloc_flag;
157.107 + int io_flags;
157.108 + int has_bg;
157.109 + unsigned reserved_inos;
157.110 + char *buf = 0;
157.111 + char c;
157.112 + double reserved_ratio;
157.113 + char *time_env;
157.114 +
157.115 + if (!param || !ext2fs_blocks_count(param))
157.116 + return EXT2_ET_INVALID_ARGUMENT;
157.117 +
157.118 + retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
157.119 + if (retval)
157.120 + return retval;
157.121 +
157.122 + memset(fs, 0, sizeof(struct struct_ext2_filsys));
157.123 + fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
157.124 + fs->flags = flags | EXT2_FLAG_RW;
157.125 + fs->umask = 022;
157.126 + fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;
157.127 +#ifdef WORDS_BIGENDIAN
157.128 + fs->flags |= EXT2_FLAG_SWAP_BYTES;
157.129 +#endif
157.130 +
157.131 + time_env = getenv("E2FSPROGS_FAKE_TIME");
157.132 + if (time_env)
157.133 + fs->now = strtoul(time_env, NULL, 0);
157.134 +
157.135 + io_flags = IO_FLAG_RW;
157.136 + if (flags & EXT2_FLAG_EXCLUSIVE)
157.137 + io_flags |= IO_FLAG_EXCLUSIVE;
157.138 + if (flags & EXT2_FLAG_DIRECT_IO)
157.139 + io_flags |= IO_FLAG_DIRECT_IO;
157.140 + io_flags |= O_BINARY;
157.141 + retval = manager->open(name, io_flags, &fs->io);
157.142 + if (retval)
157.143 + goto cleanup;
157.144 + fs->image_io = fs->io;
157.145 + fs->io->app_data = fs;
157.146 + retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
157.147 + if (retval)
157.148 + goto cleanup;
157.149 +
157.150 + strcpy(fs->device_name, name);
157.151 + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super);
157.152 + if (retval)
157.153 + goto cleanup;
157.154 + fs->super = super;
157.155 +
157.156 + memset(super, 0, SUPERBLOCK_SIZE);
157.157 +
157.158 +#define set_field(field, default) (super->field = param->field ? \
157.159 + param->field : (default))
157.160 +#define assign_field(field) (super->field = param->field)
157.161 +
157.162 + super->s_magic = EXT2_SUPER_MAGIC;
157.163 + super->s_state = EXT2_VALID_FS;
157.164 +
157.165 + bigalloc_flag = ext2fs_has_feature_bigalloc(param);
157.166 +
157.167 + assign_field(s_log_block_size);
157.168 +
157.169 + if (bigalloc_flag) {
157.170 + set_field(s_log_cluster_size, super->s_log_block_size+4);
157.171 + if (super->s_log_block_size > super->s_log_cluster_size) {
157.172 + retval = EXT2_ET_INVALID_ARGUMENT;
157.173 + goto cleanup;
157.174 + }
157.175 + } else
157.176 + super->s_log_cluster_size = super->s_log_block_size;
157.177 +
157.178 + set_field(s_first_data_block, super->s_log_cluster_size ? 0 : 1);
157.179 + set_field(s_max_mnt_count, 0);
157.180 + set_field(s_errors, EXT2_ERRORS_DEFAULT);
157.181 + set_field(s_feature_compat, 0);
157.182 + set_field(s_feature_incompat, 0);
157.183 + set_field(s_feature_ro_compat, 0);
157.184 + set_field(s_default_mount_opts, 0);
157.185 + set_field(s_first_meta_bg, 0);
157.186 + set_field(s_raid_stride, 0); /* default stride size: 0 */
157.187 + set_field(s_raid_stripe_width, 0); /* default stripe width: 0 */
157.188 + set_field(s_log_groups_per_flex, 0);
157.189 + set_field(s_flags, 0);
157.190 + assign_field(s_backup_bgs[0]);
157.191 + assign_field(s_backup_bgs[1]);
157.192 + if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
157.193 + retval = EXT2_ET_UNSUPP_FEATURE;
157.194 + goto cleanup;
157.195 + }
157.196 + if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
157.197 + retval = EXT2_ET_RO_UNSUPP_FEATURE;
157.198 + goto cleanup;
157.199 + }
157.200 +
157.201 + set_field(s_rev_level, EXT2_GOOD_OLD_REV);
157.202 + if (super->s_rev_level >= EXT2_DYNAMIC_REV) {
157.203 + set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
157.204 + set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE);
157.205 + if (super->s_inode_size >= sizeof(struct ext2_inode_large)) {
157.206 + int extra_isize = sizeof(struct ext2_inode_large) -
157.207 + EXT2_GOOD_OLD_INODE_SIZE;
157.208 + set_field(s_min_extra_isize, extra_isize);
157.209 + set_field(s_want_extra_isize, extra_isize);
157.210 + }
157.211 + } else {
157.212 + super->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
157.213 + super->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
157.214 + }
157.215 +
157.216 + set_field(s_checkinterval, 0);
157.217 + super->s_mkfs_time = super->s_lastcheck = fs->now ? fs->now : time(NULL);
157.218 +
157.219 + super->s_creator_os = CREATOR_OS;
157.220 +
157.221 + fs->fragsize = fs->blocksize = EXT2_BLOCK_SIZE(super);
157.222 + fs->cluster_ratio_bits = super->s_log_cluster_size -
157.223 + super->s_log_block_size;
157.224 +
157.225 + if (bigalloc_flag) {
157.226 + unsigned long long bpg;
157.227 +
157.228 + if (param->s_blocks_per_group &&
157.229 + param->s_clusters_per_group &&
157.230 + ((param->s_clusters_per_group * EXT2FS_CLUSTER_RATIO(fs)) !=
157.231 + param->s_blocks_per_group)) {
157.232 + retval = EXT2_ET_INVALID_ARGUMENT;
157.233 + goto cleanup;
157.234 + }
157.235 + if (param->s_clusters_per_group)
157.236 + assign_field(s_clusters_per_group);
157.237 + else if (param->s_blocks_per_group)
157.238 + super->s_clusters_per_group =
157.239 + param->s_blocks_per_group /
157.240 + EXT2FS_CLUSTER_RATIO(fs);
157.241 + else if (super->s_log_cluster_size + 15 < 32)
157.242 + super->s_clusters_per_group = fs->blocksize * 8;
157.243 + else
157.244 + super->s_clusters_per_group = (fs->blocksize - 1) * 8;
157.245 + if (super->s_clusters_per_group > EXT2_MAX_CLUSTERS_PER_GROUP(super))
157.246 + super->s_clusters_per_group = EXT2_MAX_CLUSTERS_PER_GROUP(super);
157.247 + bpg = EXT2FS_C2B(fs,
157.248 + (unsigned long long) super->s_clusters_per_group);
157.249 + if (bpg >= (((unsigned long long) 1) << 32)) {
157.250 + retval = EXT2_ET_INVALID_ARGUMENT;
157.251 + goto cleanup;
157.252 + }
157.253 + super->s_blocks_per_group = bpg;
157.254 + } else {
157.255 + set_field(s_blocks_per_group, fs->blocksize * 8);
157.256 + if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super))
157.257 + super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
157.258 + super->s_clusters_per_group = super->s_blocks_per_group;
157.259 + }
157.260 +
157.261 + ext2fs_blocks_count_set(super, ext2fs_blocks_count(param) &
157.262 + ~((blk64_t) EXT2FS_CLUSTER_MASK(fs)));
157.263 + ext2fs_r_blocks_count_set(super, ext2fs_r_blocks_count(param));
157.264 + if (ext2fs_r_blocks_count(super) >= ext2fs_blocks_count(param)) {
157.265 + retval = EXT2_ET_INVALID_ARGUMENT;
157.266 + goto cleanup;
157.267 + }
157.268 +
157.269 + set_field(s_mmp_update_interval, 0);
157.270 +
157.271 + /*
157.272 + * If we're creating an external journal device, we don't need
157.273 + * to bother with the rest.
157.274 + */
157.275 + if (ext2fs_has_feature_journal_dev(super)) {
157.276 + fs->group_desc_count = 0;
157.277 + ext2fs_mark_super_dirty(fs);
157.278 + *ret_fs = fs;
157.279 + return 0;
157.280 + }
157.281 +
157.282 +retry:
157.283 + fs->group_desc_count = (dgrp_t) ext2fs_div64_ceil(
157.284 + ext2fs_blocks_count(super) - super->s_first_data_block,
157.285 + EXT2_BLOCKS_PER_GROUP(super));
157.286 + if (fs->group_desc_count == 0) {
157.287 + retval = EXT2_ET_TOOSMALL;
157.288 + goto cleanup;
157.289 + }
157.290 +
157.291 + set_field(s_desc_size,
157.292 + ext2fs_has_feature_64bit(super) ?
157.293 + EXT2_MIN_DESC_SIZE_64BIT : 0);
157.294 +
157.295 + fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
157.296 + EXT2_DESC_PER_BLOCK(super));
157.297 +
157.298 + i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize;
157.299 +
157.300 + if (ext2fs_has_feature_64bit(super) &&
157.301 + (ext2fs_blocks_count(super) / i) >= (1ULL << 32))
157.302 + set_field(s_inodes_count, ~0U);
157.303 + else
157.304 + set_field(s_inodes_count, ext2fs_blocks_count(super) / i);
157.305 +
157.306 + /*
157.307 + * Make sure we have at least EXT2_FIRST_INO + 1 inodes, so
157.308 + * that we have enough inodes for the filesystem(!)
157.309 + */
157.310 + if (super->s_inodes_count < EXT2_FIRST_INODE(super)+1)
157.311 + super->s_inodes_count = EXT2_FIRST_INODE(super)+1;
157.312 +
157.313 + /*
157.314 + * There should be at least as many inodes as the user
157.315 + * requested. Figure out how many inodes per group that
157.316 + * should be. But make sure that we don't allocate more than
157.317 + * one bitmap's worth of inodes each group.
157.318 + */
157.319 + ipg = ext2fs_div_ceil(super->s_inodes_count, fs->group_desc_count);
157.320 + if (ipg > fs->blocksize * 8) {
157.321 + if (!bigalloc_flag && super->s_blocks_per_group >= 256) {
157.322 + /* Try again with slightly different parameters */
157.323 + super->s_blocks_per_group -= 8;
157.324 + ext2fs_blocks_count_set(super,
157.325 + ext2fs_blocks_count(param));
157.326 + super->s_clusters_per_group = super->s_blocks_per_group;
157.327 + goto retry;
157.328 + } else {
157.329 + retval = EXT2_ET_TOO_MANY_INODES;
157.330 + goto cleanup;
157.331 + }
157.332 + }
157.333 +
157.334 + if (ipg > (unsigned) EXT2_MAX_INODES_PER_GROUP(super))
157.335 + ipg = EXT2_MAX_INODES_PER_GROUP(super);
157.336 +
157.337 +ipg_retry:
157.338 + super->s_inodes_per_group = ipg;
157.339 +
157.340 + /*
157.341 + * Make sure the number of inodes per group completely fills
157.342 + * the inode table blocks in the descriptor. If not, add some
157.343 + * additional inodes/group. Waste not, want not...
157.344 + */
157.345 + fs->inode_blocks_per_group = (((super->s_inodes_per_group *
157.346 + EXT2_INODE_SIZE(super)) +
157.347 + EXT2_BLOCK_SIZE(super) - 1) /
157.348 + EXT2_BLOCK_SIZE(super));
157.349 + super->s_inodes_per_group = ((fs->inode_blocks_per_group *
157.350 + EXT2_BLOCK_SIZE(super)) /
157.351 + EXT2_INODE_SIZE(super));
157.352 + /*
157.353 + * Finally, make sure the number of inodes per group is a
157.354 + * multiple of 8. This is needed to simplify the bitmap
157.355 + * splicing code.
157.356 + */
157.357 + if (super->s_inodes_per_group < 8)
157.358 + super->s_inodes_per_group = 8;
157.359 + super->s_inodes_per_group &= ~7;
157.360 + fs->inode_blocks_per_group = (((super->s_inodes_per_group *
157.361 + EXT2_INODE_SIZE(super)) +
157.362 + EXT2_BLOCK_SIZE(super) - 1) /
157.363 + EXT2_BLOCK_SIZE(super));
157.364 +
157.365 + /*
157.366 + * adjust inode count to reflect the adjusted inodes_per_group
157.367 + */
157.368 + if ((__u64)super->s_inodes_per_group * fs->group_desc_count > ~0U) {
157.369 + ipg--;
157.370 + goto ipg_retry;
157.371 + }
157.372 + super->s_inodes_count = super->s_inodes_per_group *
157.373 + fs->group_desc_count;
157.374 + super->s_free_inodes_count = super->s_inodes_count;
157.375 +
157.376 + /*
157.377 + * check the number of reserved group descriptor table blocks
157.378 + */
157.379 + if (ext2fs_has_feature_resize_inode(super))
157.380 + rsv_gdt = calc_reserved_gdt_blocks(fs);
157.381 + else
157.382 + rsv_gdt = 0;
157.383 + set_field(s_reserved_gdt_blocks, rsv_gdt);
157.384 + if (super->s_reserved_gdt_blocks > EXT2_ADDR_PER_BLOCK(super)) {
157.385 + retval = EXT2_ET_RES_GDT_BLOCKS;
157.386 + goto cleanup;
157.387 + }
157.388 + /* Enable meta_bg if we'd lose more than 3/4 of a BG to GDT blocks. */
157.389 + if (super->s_reserved_gdt_blocks + fs->desc_blocks >
157.390 + super->s_blocks_per_group * 3 / 4) {
157.391 + ext2fs_set_feature_meta_bg(fs->super);
157.392 + ext2fs_clear_feature_resize_inode(fs->super);
157.393 + set_field(s_reserved_gdt_blocks, 0);
157.394 + }
157.395 +
157.396 + /*
157.397 + * Calculate the maximum number of bookkeeping blocks per
157.398 + * group. It includes the superblock, the block group
157.399 + * descriptors, the block bitmap, the inode bitmap, the inode
157.400 + * table, and the reserved gdt blocks.
157.401 + */
157.402 + overhead = (int) (3 + fs->inode_blocks_per_group +
157.403 + super->s_reserved_gdt_blocks);
157.404 +
157.405 + if (ext2fs_has_feature_meta_bg(fs->super))
157.406 + overhead++;
157.407 + else
157.408 + overhead += fs->desc_blocks;
157.409 +
157.410 + /* This can only happen if the user requested too many inodes */
157.411 + if (overhead > super->s_blocks_per_group) {
157.412 + retval = EXT2_ET_TOO_MANY_INODES;
157.413 + goto cleanup;
157.414 + }
157.415 +
157.416 + /*
157.417 + * See if the last group is big enough to support the
157.418 + * necessary data structures. If not, we need to get rid of
157.419 + * it. We need to recalculate the overhead for the last block
157.420 + * group, since it might or might not have a superblock
157.421 + * backup.
157.422 + */
157.423 + overhead = (int) (2 + fs->inode_blocks_per_group);
157.424 + has_bg = 0;
157.425 + if (ext2fs_has_feature_sparse_super2(super)) {
157.426 + /*
157.427 + * We have to do this manually since
157.428 + * super->s_backup_bgs hasn't been set up yet.
157.429 + */
157.430 + if (fs->group_desc_count == 2)
157.431 + has_bg = param->s_backup_bgs[0] != 0;
157.432 + else
157.433 + has_bg = param->s_backup_bgs[1] != 0;
157.434 + } else
157.435 + has_bg = ext2fs_bg_has_super(fs, fs->group_desc_count - 1);
157.436 + if (has_bg)
157.437 + overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks;
157.438 + rem = ((ext2fs_blocks_count(super) - super->s_first_data_block) %
157.439 + super->s_blocks_per_group);
157.440 + if ((fs->group_desc_count == 1) && rem && (rem < overhead)) {
157.441 + retval = EXT2_ET_TOOSMALL;
157.442 + goto cleanup;
157.443 + }
157.444 + if (rem && (rem < overhead+50)) {
157.445 + ext2fs_blocks_count_set(super, ext2fs_blocks_count(super) -
157.446 + rem);
157.447 + /*
157.448 + * If blocks count is changed, we need to recalculate
157.449 + * reserved blocks count not to exceed 50%.
157.450 + */
157.451 + reserved_ratio = 100.0 * ext2fs_r_blocks_count(param) /
157.452 + ext2fs_blocks_count(param);
157.453 + ext2fs_r_blocks_count_set(super, reserved_ratio *
157.454 + ext2fs_blocks_count(super) / 100.0);
157.455 +
157.456 + goto retry;
157.457 + }
157.458 +
157.459 + /*
157.460 + * At this point we know how big the filesystem will be. So
157.461 + * we can do any and all allocations that depend on the block
157.462 + * count.
157.463 + */
157.464 +
157.465 + /* Set up the locations of the backup superblocks */
157.466 + if (ext2fs_has_feature_sparse_super2(super)) {
157.467 + if (super->s_backup_bgs[0] >= fs->group_desc_count)
157.468 + super->s_backup_bgs[0] = fs->group_desc_count - 1;
157.469 + if (super->s_backup_bgs[1] >= fs->group_desc_count)
157.470 + super->s_backup_bgs[1] = fs->group_desc_count - 1;
157.471 + if (super->s_backup_bgs[0] == super->s_backup_bgs[1])
157.472 + super->s_backup_bgs[1] = 0;
157.473 + if (super->s_backup_bgs[0] > super->s_backup_bgs[1]) {
157.474 + __u32 t = super->s_backup_bgs[0];
157.475 + super->s_backup_bgs[0] = super->s_backup_bgs[1];
157.476 + super->s_backup_bgs[1] = t;
157.477 + }
157.478 + }
157.479 +
157.480 + retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
157.481 + if (retval)
157.482 + goto cleanup;
157.483 +
157.484 + strcpy(buf, "block bitmap for ");
157.485 + strcat(buf, fs->device_name);
157.486 + retval = ext2fs_allocate_subcluster_bitmap(fs, buf, &fs->block_map);
157.487 + if (retval)
157.488 + goto cleanup;
157.489 +
157.490 + strcpy(buf, "inode bitmap for ");
157.491 + strcat(buf, fs->device_name);
157.492 + retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
157.493 + if (retval)
157.494 + goto cleanup;
157.495 +
157.496 + ext2fs_free_mem(&buf);
157.497 +
157.498 + retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
157.499 + &fs->group_desc);
157.500 + if (retval)
157.501 + goto cleanup;
157.502 +
157.503 + memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize);
157.504 +
157.505 + /*
157.506 + * Reserve the superblock and group descriptors for each
157.507 + * group, and fill in the correct group statistics for group.
157.508 + * Note that although the block bitmap, inode bitmap, and
157.509 + * inode table have not been allocated (and in fact won't be
157.510 + * by this routine), they are accounted for nevertheless.
157.511 + *
157.512 + * If FLEX_BG meta-data grouping is used, only account for the
157.513 + * superblock and group descriptors (the inode tables and
157.514 + * bitmaps will be accounted for when allocated).
157.515 + */
157.516 + free_blocks = 0;
157.517 + csum_flag = ext2fs_has_group_desc_csum(fs);
157.518 + reserved_inos = super->s_first_ino;
157.519 + for (i = 0; i < fs->group_desc_count; i++) {
157.520 + /*
157.521 + * Don't set the BLOCK_UNINIT group for the last group
157.522 + * because the block bitmap needs to be padded.
157.523 + */
157.524 + if (csum_flag) {
157.525 + if (i != fs->group_desc_count - 1)
157.526 + ext2fs_bg_flags_set(fs, i,
157.527 + EXT2_BG_BLOCK_UNINIT);
157.528 + ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
157.529 + numblocks = super->s_inodes_per_group;
157.530 + if (reserved_inos) {
157.531 + if (numblocks > reserved_inos) {
157.532 + numblocks -= reserved_inos;
157.533 + reserved_inos = 0;
157.534 + } else {
157.535 + reserved_inos -= numblocks;
157.536 + numblocks = 0;
157.537 + }
157.538 + }
157.539 + ext2fs_bg_itable_unused_set(fs, i, numblocks);
157.540 + }
157.541 + numblocks = ext2fs_reserve_super_and_bgd(fs, i, fs->block_map);
157.542 + if (fs->super->s_log_groups_per_flex)
157.543 + numblocks += 2 + fs->inode_blocks_per_group;
157.544 +
157.545 + free_blocks += numblocks;
157.546 + ext2fs_bg_free_blocks_count_set(fs, i, numblocks);
157.547 + ext2fs_bg_free_inodes_count_set(fs, i, fs->super->s_inodes_per_group);
157.548 + ext2fs_bg_used_dirs_count_set(fs, i, 0);
157.549 + ext2fs_group_desc_csum_set(fs, i);
157.550 + }
157.551 + free_blocks &= ~EXT2FS_CLUSTER_MASK(fs);
157.552 + ext2fs_free_blocks_count_set(super, free_blocks);
157.553 +
157.554 + c = (char) 255;
157.555 + if (((int) c) == -1) {
157.556 + super->s_flags |= EXT2_FLAGS_SIGNED_HASH;
157.557 + } else {
157.558 + super->s_flags |= EXT2_FLAGS_UNSIGNED_HASH;
157.559 + }
157.560 +
157.561 + ext2fs_mark_super_dirty(fs);
157.562 + ext2fs_mark_bb_dirty(fs);
157.563 + ext2fs_mark_ib_dirty(fs);
157.564 +
157.565 + io_channel_set_blksize(fs->io, fs->blocksize);
157.566 +
157.567 + *ret_fs = fs;
157.568 + return 0;
157.569 +cleanup:
157.570 + free(buf);
157.571 + ext2fs_free(fs);
157.572 + return retval;
157.573 +}
158.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
158.2 +++ b/libext2fs/lib/libext2fs/inline.c Wed Aug 25 01:28:08 2021 +0200
158.3 @@ -0,0 +1,118 @@
158.4 +/*
158.5 + * inline.c --- Includes the inlined functions defined in the header
158.6 + * files as standalone functions, in case the application program
158.7 + * is compiled with inlining turned off.
158.8 + *
158.9 + * Copyright (C) 1993, 1994 Theodore Ts'o.
158.10 + *
158.11 + * %Begin-Header%
158.12 + * This file may be redistributed under the terms of the GNU Library
158.13 + * General Public License, version 2.
158.14 + * %End-Header%
158.15 + */
158.16 +
158.17 +#ifndef _XOPEN_SOURCE
158.18 +#define _XOPEN_SOURCE 600 /* for posix_memalign() */
158.19 +#endif
158.20 +
158.21 +#include "config.h"
158.22 +#include <stdio.h>
158.23 +#include <string.h>
158.24 +#if HAVE_UNISTD_H
158.25 +#include <unistd.h>
158.26 +#endif
158.27 +#include <fcntl.h>
158.28 +#include <time.h>
158.29 +#if HAVE_SYS_STAT_H
158.30 +#include <sys/stat.h>
158.31 +#endif
158.32 +#if HAVE_SYS_TYPES_H
158.33 +#include <sys/types.h>
158.34 +#endif
158.35 +#if HAVE_MALLOC_H
158.36 +#include <malloc.h>
158.37 +#endif
158.38 +
158.39 +#include "ext2_fs.h"
158.40 +#define INCLUDE_INLINE_FUNCS
158.41 +#include "ext2fs.h"
158.42 +
158.43 +/*
158.44 + * We used to define this as an inline, but since we are now using
158.45 + * autoconf-defined #ifdef's, we need to export this as a
158.46 + * library-provided function exclusively.
158.47 + */
158.48 +errcode_t ext2fs_get_memalign(unsigned long size,
158.49 + unsigned long align, void *ptr)
158.50 +{
158.51 + errcode_t retval = 0;
158.52 + void **p = ptr;
158.53 +
158.54 + if (align < 8)
158.55 + align = 8;
158.56 +#ifdef HAVE_POSIX_MEMALIGN
158.57 + retval = posix_memalign(p, align, size);
158.58 + if (retval == ENOMEM)
158.59 + return EXT2_ET_NO_MEMORY;
158.60 +#else /* !HAVE_POSIX_MEMALIGN */
158.61 +#ifdef HAVE_MEMALIGN
158.62 + *p = memalign(align, size);
158.63 + if (*p == NULL) {
158.64 + if (errno)
158.65 + return errno;
158.66 + else
158.67 + return EXT2_ET_NO_MEMORY;
158.68 + }
158.69 +#else /* !HAVE_MEMALIGN */
158.70 +#ifdef HAVE_VALLOC
158.71 + if (align > sizeof(long long))
158.72 + *p = valloc(size);
158.73 + else
158.74 +#endif
158.75 + *p = malloc(size);
158.76 + if ((uintptr_t) *p & (align - 1)) {
158.77 + free(*p);
158.78 + *p = 0;
158.79 + }
158.80 + if (*p == 0)
158.81 + return EXT2_ET_NO_MEMORY;
158.82 +#endif /* HAVE_MEMALIGN */
158.83 +#endif /* HAVE_POSIX_MEMALIGN */
158.84 + return retval;
158.85 +}
158.86 +
158.87 +#ifdef DEBUG
158.88 +static int isaligned(void *ptr, unsigned long align)
158.89 +{
158.90 + return (((unsigned long) ptr & (align - 1)) == 0);
158.91 +}
158.92 +
158.93 +static errcode_t test_memalign(unsigned long align)
158.94 +{
158.95 + void *ptr = 0;
158.96 + errcode_t retval;
158.97 +
158.98 + retval = ext2fs_get_memalign(32, align, &ptr);
158.99 + if (!retval && !isaligned(ptr, align))
158.100 + retval = EINVAL;
158.101 + free(ptr);
158.102 + printf("tst_memalign(%lu) is %s\n", align,
158.103 + retval ? error_message(retval) : "OK");
158.104 + return retval;
158.105 +}
158.106 +
158.107 +int main(int argc, char **argv)
158.108 +{
158.109 + int err = 0;
158.110 +
158.111 + if (test_memalign(4))
158.112 + err++;
158.113 + if (test_memalign(32))
158.114 + err++;
158.115 + if (test_memalign(1024))
158.116 + err++;
158.117 + if (test_memalign(4096))
158.118 + err++;
158.119 + return err;
158.120 +}
158.121 +#endif
159.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
159.2 +++ b/libext2fs/lib/libext2fs/inline_data.c Wed Aug 25 01:28:08 2021 +0200
159.3 @@ -0,0 +1,842 @@
159.4 +/*
159.5 + * inline_data.c --- data in inode
159.6 + *
159.7 + * Copyright (C) 2012 Zheng Liu <wenqing.lz@taobao.com>
159.8 + *
159.9 + * %Begin-Header%
159.10 + * This file may be redistributed under the terms of the GNU library
159.11 + * General Public License, version 2.
159.12 + * %End-Header%
159.13 + */
159.14 +
159.15 +#include "config.h"
159.16 +#include <stdio.h>
159.17 +#include <time.h>
159.18 +#include <limits.h> /* for PATH_MAX */
159.19 +
159.20 +#include "ext2_fs.h"
159.21 +#include "ext2_ext_attr.h"
159.22 +
159.23 +#include "ext2fs.h"
159.24 +#include "ext2fsP.h"
159.25 +
159.26 +struct ext2_inline_data {
159.27 + ext2_filsys fs;
159.28 + ext2_ino_t ino;
159.29 + size_t ea_size; /* the size of inline data in ea area */
159.30 + void *ea_data;
159.31 +};
159.32 +
159.33 +static errcode_t ext2fs_inline_data_ea_set(struct ext2_inline_data *data)
159.34 +{
159.35 + struct ext2_xattr_handle *handle;
159.36 + errcode_t retval;
159.37 +
159.38 + retval = ext2fs_xattrs_open(data->fs, data->ino, &handle);
159.39 + if (retval)
159.40 + return retval;
159.41 +
159.42 + retval = ext2fs_xattrs_read(handle);
159.43 + if (retval)
159.44 + goto err;
159.45 +
159.46 + retval = ext2fs_xattr_set(handle, "system.data",
159.47 + data->ea_data, data->ea_size);
159.48 +err:
159.49 + (void) ext2fs_xattrs_close(&handle);
159.50 + return retval;
159.51 +}
159.52 +
159.53 +static errcode_t ext2fs_inline_data_ea_get(struct ext2_inline_data *data)
159.54 +{
159.55 + struct ext2_xattr_handle *handle;
159.56 + errcode_t retval;
159.57 +
159.58 + data->ea_size = 0;
159.59 + data->ea_data = 0;
159.60 +
159.61 + retval = ext2fs_xattrs_open(data->fs, data->ino, &handle);
159.62 + if (retval)
159.63 + return retval;
159.64 +
159.65 + retval = ext2fs_xattrs_read(handle);
159.66 + if (retval)
159.67 + goto err;
159.68 +
159.69 + retval = ext2fs_xattr_get(handle, "system.data",
159.70 + (void **)&data->ea_data, &data->ea_size);
159.71 + if (retval == EXT2_ET_EA_KEY_NOT_FOUND) {
159.72 + data->ea_size = 0;
159.73 + data->ea_data = NULL;
159.74 + retval = 0;
159.75 + } else if (retval)
159.76 + goto err;
159.77 +
159.78 +err:
159.79 + (void) ext2fs_xattrs_close(&handle);
159.80 + return retval;
159.81 +}
159.82 +
159.83 +errcode_t ext2fs_inline_data_init(ext2_filsys fs, ext2_ino_t ino)
159.84 +{
159.85 + struct ext2_inline_data data;
159.86 + char empty[1] = { '\0' };
159.87 +
159.88 + data.fs = fs;
159.89 + data.ino = ino;
159.90 + data.ea_size = 0;
159.91 + data.ea_data = empty;
159.92 + return ext2fs_inline_data_ea_set(&data);
159.93 +}
159.94 +
159.95 +errcode_t ext2fs_inline_data_size(ext2_filsys fs, ext2_ino_t ino, size_t *size)
159.96 +{
159.97 + struct ext2_inode inode;
159.98 + struct ext2_inline_data data;
159.99 + errcode_t retval;
159.100 +
159.101 + retval = ext2fs_read_inode(fs, ino, &inode);
159.102 + if (retval)
159.103 + return retval;
159.104 +
159.105 + if (!(inode.i_flags & EXT4_INLINE_DATA_FL))
159.106 + return EXT2_ET_NO_INLINE_DATA;
159.107 +
159.108 + data.fs = fs;
159.109 + data.ino = ino;
159.110 + retval = ext2fs_inline_data_ea_get(&data);
159.111 + if (retval)
159.112 + return retval;
159.113 +
159.114 + *size = EXT4_MIN_INLINE_DATA_SIZE + data.ea_size;
159.115 + return ext2fs_free_mem(&data.ea_data);
159.116 +}
159.117 +
159.118 +int ext2fs_inline_data_dir_iterate(ext2_filsys fs, ext2_ino_t ino,
159.119 + void *priv_data)
159.120 +{
159.121 + struct dir_context *ctx;
159.122 + struct ext2_inode inode;
159.123 + struct ext2_dir_entry dirent;
159.124 + struct ext2_inline_data data;
159.125 + int ret = BLOCK_ABORT;
159.126 + e2_blkcnt_t blockcnt = 0;
159.127 + char *old_buf;
159.128 + unsigned int old_buflen;
159.129 + int old_flags;
159.130 +
159.131 + ctx = (struct dir_context *)priv_data;
159.132 + old_buf = ctx->buf;
159.133 + old_buflen = ctx->buflen;
159.134 + old_flags = ctx->flags;
159.135 + ctx->flags |= DIRENT_FLAG_INCLUDE_INLINE_DATA;
159.136 +
159.137 + ctx->errcode = ext2fs_read_inode(fs, ino, &inode);
159.138 + if (ctx->errcode)
159.139 + goto out;
159.140 +
159.141 + if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) {
159.142 + ctx->errcode = EXT2_ET_NO_INLINE_DATA;
159.143 + goto out;
159.144 + }
159.145 +
159.146 + if (!LINUX_S_ISDIR(inode.i_mode)) {
159.147 + ctx->errcode = EXT2_ET_NO_DIRECTORY;
159.148 + goto out;
159.149 + }
159.150 + ret = 0;
159.151 +
159.152 + /* we first check '.' and '..' dir */
159.153 + dirent.inode = ino;
159.154 + dirent.name_len = 1;
159.155 + ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(2), &dirent);
159.156 + dirent.name[0] = '.';
159.157 + dirent.name[1] = '\0';
159.158 + ctx->buf = (char *)&dirent;
159.159 + ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
159.160 + ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
159.161 + if (ret & BLOCK_ABORT)
159.162 + goto out;
159.163 +
159.164 + dirent.inode = ext2fs_le32_to_cpu(inode.i_block[0]);
159.165 + dirent.name_len = 2;
159.166 + ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(3), &dirent);
159.167 + dirent.name[0] = '.';
159.168 + dirent.name[1] = '.';
159.169 + dirent.name[2] = '\0';
159.170 + ctx->buf = (char *)&dirent;
159.171 + ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
159.172 + ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
159.173 + if (ret & BLOCK_INLINE_DATA_CHANGED) {
159.174 + errcode_t err;
159.175 +
159.176 + inode.i_block[0] = ext2fs_cpu_to_le32(dirent.inode);
159.177 + err = ext2fs_write_inode(fs, ino, &inode);
159.178 + if (err)
159.179 + goto out;
159.180 + ret &= ~BLOCK_INLINE_DATA_CHANGED;
159.181 + }
159.182 + if (ret & BLOCK_ABORT)
159.183 + goto out;
159.184 +
159.185 + ctx->buf = (char *)inode.i_block + EXT4_INLINE_DATA_DOTDOT_SIZE;
159.186 + ctx->buflen = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE;
159.187 +#ifdef WORDS_BIGENDIAN
159.188 + ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
159.189 + if (ctx->errcode) {
159.190 + ret |= BLOCK_ABORT;
159.191 + goto out;
159.192 + }
159.193 +#endif
159.194 + ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
159.195 + if (ret & BLOCK_INLINE_DATA_CHANGED) {
159.196 +#ifdef WORDS_BIGENDIAN
159.197 + ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
159.198 + ctx->buflen, 0);
159.199 + if (ctx->errcode) {
159.200 + ret |= BLOCK_ABORT;
159.201 + goto out;
159.202 + }
159.203 +#endif
159.204 + ctx->errcode = ext2fs_write_inode(fs, ino, &inode);
159.205 + if (ctx->errcode)
159.206 + ret |= BLOCK_ABORT;
159.207 + ret &= ~BLOCK_INLINE_DATA_CHANGED;
159.208 + }
159.209 + if (ret & BLOCK_ABORT)
159.210 + goto out;
159.211 +
159.212 + data.fs = fs;
159.213 + data.ino = ino;
159.214 + ctx->errcode = ext2fs_inline_data_ea_get(&data);
159.215 + if (ctx->errcode) {
159.216 + ret |= BLOCK_ABORT;
159.217 + goto out;
159.218 + }
159.219 + if (data.ea_size <= 0)
159.220 + goto out1;
159.221 +
159.222 + ctx->buf = data.ea_data;
159.223 + ctx->buflen = data.ea_size;
159.224 +#ifdef WORDS_BIGENDIAN
159.225 + ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
159.226 + if (ctx->errcode) {
159.227 + ret |= BLOCK_ABORT;
159.228 + goto out1;
159.229 + }
159.230 +#endif
159.231 +
159.232 + ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
159.233 + if (ret & BLOCK_INLINE_DATA_CHANGED) {
159.234 +#ifdef WORDS_BIGENDIAN
159.235 + ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
159.236 + ctx->buflen, 0);
159.237 + if (ctx->errcode) {
159.238 + ret |= BLOCK_ABORT;
159.239 + goto out1;
159.240 + }
159.241 +#endif
159.242 + ctx->errcode = ext2fs_inline_data_ea_set(&data);
159.243 + if (ctx->errcode)
159.244 + ret |= BLOCK_ABORT;
159.245 + }
159.246 +
159.247 +out1:
159.248 + ext2fs_free_mem(&data.ea_data);
159.249 +out:
159.250 + ctx->buf = old_buf;
159.251 + ctx->buflen = old_buflen;
159.252 + ctx->flags = old_flags;
159.253 + ret &= ~(BLOCK_ABORT | BLOCK_INLINE_DATA_CHANGED);
159.254 + return ret;
159.255 +}
159.256 +
159.257 +errcode_t ext2fs_inline_data_ea_remove(ext2_filsys fs, ext2_ino_t ino)
159.258 +{
159.259 + struct ext2_xattr_handle *handle;
159.260 + errcode_t retval;
159.261 +
159.262 + retval = ext2fs_xattrs_open(fs, ino, &handle);
159.263 + if (retval)
159.264 + return retval;
159.265 +
159.266 + retval = ext2fs_xattrs_read(handle);
159.267 + if (retval)
159.268 + goto err;
159.269 +
159.270 + retval = ext2fs_xattr_remove(handle, "system.data");
159.271 +err:
159.272 + (void) ext2fs_xattrs_close(&handle);
159.273 + return retval;
159.274 +}
159.275 +
159.276 +static errcode_t ext2fs_inline_data_convert_dir(ext2_filsys fs, ext2_ino_t ino,
159.277 + char *bbuf, char *ibuf, int size)
159.278 +{
159.279 + struct ext2_dir_entry *dir, *dir2;
159.280 + struct ext2_dir_entry_tail *t;
159.281 + errcode_t retval;
159.282 + int offset;
159.283 + unsigned int rec_len;
159.284 + int csum_size = 0;
159.285 + int filetype = 0;
159.286 +
159.287 + if (ext2fs_has_feature_metadata_csum(fs->super))
159.288 + csum_size = sizeof(struct ext2_dir_entry_tail);
159.289 +
159.290 + /* Create '.' and '..' */
159.291 + if (ext2fs_has_feature_filetype(fs->super))
159.292 + filetype = EXT2_FT_DIR;
159.293 +
159.294 + /*
159.295 + * Set up entry for '.'
159.296 + */
159.297 + dir = (struct ext2_dir_entry *) bbuf;
159.298 + dir->inode = ino;
159.299 + ext2fs_dirent_set_name_len(dir, 1);
159.300 + ext2fs_dirent_set_file_type(dir, filetype);
159.301 + dir->name[0] = '.';
159.302 + rec_len = (fs->blocksize - csum_size) - EXT2_DIR_REC_LEN(1);
159.303 + dir->rec_len = EXT2_DIR_REC_LEN(1);
159.304 +
159.305 + /*
159.306 + * Set up entry for '..'
159.307 + */
159.308 + dir = (struct ext2_dir_entry *) (bbuf + dir->rec_len);
159.309 + dir->rec_len = EXT2_DIR_REC_LEN(2);
159.310 + dir->inode = ext2fs_le32_to_cpu(((__u32 *)ibuf)[0]);
159.311 + ext2fs_dirent_set_name_len(dir, 2);
159.312 + ext2fs_dirent_set_file_type(dir, filetype);
159.313 + dir->name[0] = '.';
159.314 + dir->name[1] = '.';
159.315 +
159.316 + /*
159.317 + * Adjust the last rec_len
159.318 + */
159.319 + offset = EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2);
159.320 + dir = (struct ext2_dir_entry *) (bbuf + offset);
159.321 + memcpy(bbuf + offset, ibuf + EXT4_INLINE_DATA_DOTDOT_SIZE,
159.322 + size - EXT4_INLINE_DATA_DOTDOT_SIZE);
159.323 + size += EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) -
159.324 + EXT4_INLINE_DATA_DOTDOT_SIZE;
159.325 +
159.326 + do {
159.327 + dir2 = dir;
159.328 + retval = ext2fs_get_rec_len(fs, dir, &rec_len);
159.329 + if (retval)
159.330 + goto err;
159.331 + offset += rec_len;
159.332 + dir = (struct ext2_dir_entry *) (bbuf + offset);
159.333 + } while (offset < size);
159.334 + rec_len += fs->blocksize - csum_size - offset;
159.335 + retval = ext2fs_set_rec_len(fs, rec_len, dir2);
159.336 + if (retval)
159.337 + goto err;
159.338 +
159.339 + if (csum_size) {
159.340 + t = EXT2_DIRENT_TAIL(bbuf, fs->blocksize);
159.341 + ext2fs_initialize_dirent_tail(fs, t);
159.342 + }
159.343 +
159.344 +err:
159.345 + return retval;
159.346 +}
159.347 +
159.348 +static errcode_t
159.349 +ext2fs_inline_data_dir_expand(ext2_filsys fs, ext2_ino_t ino,
159.350 + struct ext2_inode *inode, char *buf, size_t size)
159.351 +{
159.352 + errcode_t retval;
159.353 + blk64_t blk;
159.354 + char *blk_buf;
159.355 +
159.356 + retval = ext2fs_get_memzero(fs->blocksize, &blk_buf);
159.357 + if (retval)
159.358 + return retval;
159.359 +
159.360 +#ifdef WORDS_BIGENDIAN
159.361 + retval = ext2fs_dirent_swab_in2(fs, buf + EXT4_INLINE_DATA_DOTDOT_SIZE,
159.362 + size, 0);
159.363 + if (retval)
159.364 + goto errout;
159.365 +#endif
159.366 +
159.367 + /* Adjust the rec_len */
159.368 + retval = ext2fs_inline_data_convert_dir(fs, ino, blk_buf, buf, size);
159.369 + if (retval)
159.370 + goto errout;
159.371 + /* Allocate a new block */
159.372 + retval = ext2fs_new_block2(fs, 0, 0, &blk);
159.373 + if (retval)
159.374 + goto errout;
159.375 + retval = ext2fs_write_dir_block4(fs, blk, blk_buf, 0, ino);
159.376 + if (retval)
159.377 + goto errout;
159.378 +
159.379 + /* Update inode */
159.380 + if (ext2fs_has_feature_extents(fs->super))
159.381 + inode->i_flags |= EXT4_EXTENTS_FL;
159.382 + inode->i_flags &= ~EXT4_INLINE_DATA_FL;
159.383 + retval = ext2fs_iblk_add_blocks(fs, inode, 1);
159.384 + if (retval)
159.385 + goto errout;
159.386 + inode->i_size = fs->blocksize;
159.387 + retval = ext2fs_bmap2(fs, ino, inode, 0, BMAP_SET, 0, 0, &blk);
159.388 + if (retval)
159.389 + goto errout;
159.390 + retval = ext2fs_write_inode(fs, ino, inode);
159.391 + if (retval)
159.392 + goto errout;
159.393 + ext2fs_block_alloc_stats(fs, blk, +1);
159.394 +
159.395 +errout:
159.396 + ext2fs_free_mem(&blk_buf);
159.397 + return retval;
159.398 +}
159.399 +
159.400 +static errcode_t
159.401 +ext2fs_inline_data_file_expand(ext2_filsys fs, ext2_ino_t ino,
159.402 + struct ext2_inode *inode, char *buf, size_t size)
159.403 +{
159.404 + ext2_file_t e2_file;
159.405 + errcode_t retval;
159.406 +
159.407 + /* Update inode */
159.408 + memset(inode->i_block, 0, sizeof(inode->i_block));
159.409 + if (ext2fs_has_feature_extents(fs->super)) {
159.410 + ext2_extent_handle_t handle;
159.411 +
159.412 + inode->i_flags &= ~EXT4_EXTENTS_FL;
159.413 + retval = ext2fs_extent_open2(fs, ino, inode, &handle);
159.414 + if (retval)
159.415 + return retval;
159.416 + ext2fs_extent_free(handle);
159.417 + }
159.418 + inode->i_flags &= ~EXT4_INLINE_DATA_FL;
159.419 + inode->i_size = 0;
159.420 + retval = ext2fs_write_inode(fs, ino, inode);
159.421 + if (retval)
159.422 + return retval;
159.423 +
159.424 + /* Write out the block buffer */
159.425 + retval = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &e2_file);
159.426 + if (retval)
159.427 + return retval;
159.428 + retval = ext2fs_file_write(e2_file, buf, size, 0);
159.429 + ext2fs_file_close(e2_file);
159.430 + return retval;
159.431 +}
159.432 +
159.433 +errcode_t ext2fs_inline_data_expand(ext2_filsys fs, ext2_ino_t ino)
159.434 +{
159.435 + struct ext2_inode inode;
159.436 + struct ext2_inline_data data;
159.437 + errcode_t retval;
159.438 + size_t inline_size;
159.439 + char *inline_buf = 0;
159.440 +
159.441 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
159.442 +
159.443 + retval = ext2fs_read_inode(fs, ino, &inode);
159.444 + if (retval)
159.445 + return retval;
159.446 +
159.447 + if (!(inode.i_flags & EXT4_INLINE_DATA_FL))
159.448 + return EXT2_ET_NO_INLINE_DATA;
159.449 +
159.450 + data.fs = fs;
159.451 + data.ino = ino;
159.452 + retval = ext2fs_inline_data_ea_get(&data);
159.453 + if (retval)
159.454 + return retval;
159.455 + inline_size = data.ea_size + EXT4_MIN_INLINE_DATA_SIZE;
159.456 + retval = ext2fs_get_mem(inline_size, &inline_buf);
159.457 + if (retval)
159.458 + goto errout;
159.459 +
159.460 + memcpy(inline_buf, (void *)inode.i_block, EXT4_MIN_INLINE_DATA_SIZE);
159.461 + if (data.ea_size > 0) {
159.462 + memcpy(inline_buf + EXT4_MIN_INLINE_DATA_SIZE,
159.463 + data.ea_data, data.ea_size);
159.464 + }
159.465 +
159.466 + memset((void *)inode.i_block, 0, EXT4_MIN_INLINE_DATA_SIZE);
159.467 + /*
159.468 + * NOTE: We must do this write -> ea_remove -> read cycle here because
159.469 + * removing the inline data EA can free the EA block, which is a change
159.470 + * that our stack copy of the inode will never see. If that happens,
159.471 + * we can end up with the EA block and lblk 0 pointing to the same
159.472 + * pblk, which is bad news.
159.473 + */
159.474 + retval = ext2fs_write_inode(fs, ino, &inode);
159.475 + if (retval)
159.476 + goto errout;
159.477 + retval = ext2fs_inline_data_ea_remove(fs, ino);
159.478 + if (retval)
159.479 + goto errout;
159.480 + retval = ext2fs_read_inode(fs, ino, &inode);
159.481 + if (retval)
159.482 + goto errout;
159.483 +
159.484 + if (LINUX_S_ISDIR(inode.i_mode)) {
159.485 + retval = ext2fs_inline_data_dir_expand(fs, ino, &inode,
159.486 + inline_buf, inline_size);
159.487 + } else {
159.488 + retval = ext2fs_inline_data_file_expand(fs, ino, &inode,
159.489 + inline_buf, inline_size);
159.490 + }
159.491 +
159.492 +errout:
159.493 + if (inline_buf)
159.494 + ext2fs_free_mem(&inline_buf);
159.495 + ext2fs_free_mem(&data.ea_data);
159.496 + return retval;
159.497 +}
159.498 +
159.499 +/*
159.500 + * When caller uses this function to retrieve the inline data, it must
159.501 + * allocate a buffer which has the size of inline data. The size of
159.502 + * inline data can be know by ext2fs_inline_data_get_size().
159.503 + */
159.504 +errcode_t ext2fs_inline_data_get(ext2_filsys fs, ext2_ino_t ino,
159.505 + struct ext2_inode *inode,
159.506 + void *buf, size_t *size)
159.507 +{
159.508 + struct ext2_inode inode_buf;
159.509 + struct ext2_inline_data data;
159.510 + errcode_t retval;
159.511 +
159.512 + if (!inode) {
159.513 + retval = ext2fs_read_inode(fs, ino, &inode_buf);
159.514 + if (retval)
159.515 + return retval;
159.516 + inode = &inode_buf;
159.517 + }
159.518 +
159.519 + data.fs = fs;
159.520 + data.ino = ino;
159.521 + retval = ext2fs_inline_data_ea_get(&data);
159.522 + if (retval)
159.523 + return retval;
159.524 +
159.525 + memcpy(buf, (void *)inode->i_block, EXT4_MIN_INLINE_DATA_SIZE);
159.526 + if (data.ea_size > 0)
159.527 + memcpy((char *) buf + EXT4_MIN_INLINE_DATA_SIZE,
159.528 + data.ea_data, data.ea_size);
159.529 +
159.530 + if (size)
159.531 + *size = EXT4_MIN_INLINE_DATA_SIZE + data.ea_size;
159.532 + ext2fs_free_mem(&data.ea_data);
159.533 + return 0;
159.534 +}
159.535 +
159.536 +errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino,
159.537 + struct ext2_inode *inode,
159.538 + void *buf, size_t size)
159.539 +{
159.540 + struct ext2_inode inode_buf;
159.541 + struct ext2_inline_data data = {
159.542 + .fs = fs,
159.543 + .ino = ino,
159.544 + };
159.545 + errcode_t retval;
159.546 + size_t free_ea_size, existing_size, free_inode_size;
159.547 +
159.548 + if (!inode) {
159.549 + retval = ext2fs_read_inode(fs, ino, &inode_buf);
159.550 + if (retval)
159.551 + return retval;
159.552 + inode = &inode_buf;
159.553 + }
159.554 +
159.555 + if (size <= EXT4_MIN_INLINE_DATA_SIZE) {
159.556 + memcpy((void *)inode->i_block, buf, size);
159.557 + } else {
159.558 + retval = ext2fs_xattr_inode_max_size(fs, ino, &free_ea_size);
159.559 + if (retval)
159.560 + return retval;
159.561 +
159.562 + retval = ext2fs_inline_data_size(fs, ino, &existing_size);
159.563 + if (retval)
159.564 + return retval;
159.565 +
159.566 + if (existing_size < EXT4_MIN_INLINE_DATA_SIZE) {
159.567 + free_inode_size = EXT4_MIN_INLINE_DATA_SIZE -
159.568 + existing_size;
159.569 + } else {
159.570 + free_inode_size = 0;
159.571 + }
159.572 +
159.573 + if (size != existing_size &&
159.574 + size > existing_size + free_ea_size + free_inode_size)
159.575 + return EXT2_ET_INLINE_DATA_NO_SPACE;
159.576 +
159.577 + memcpy((void *)inode->i_block, buf, EXT4_MIN_INLINE_DATA_SIZE);
159.578 + if (size > EXT4_MIN_INLINE_DATA_SIZE)
159.579 + data.ea_size = size - EXT4_MIN_INLINE_DATA_SIZE;
159.580 + data.ea_data = (char *) buf + EXT4_MIN_INLINE_DATA_SIZE;
159.581 + }
159.582 + retval = ext2fs_write_inode(fs, ino, inode);
159.583 + if (retval)
159.584 + return retval;
159.585 + return ext2fs_inline_data_ea_set(&data);
159.586 +}
159.587 +
159.588 +#ifdef DEBUG
159.589 +#include "e2p/e2p.h"
159.590 +
159.591 +/*
159.592 + * The length of buffer is set to 64 because in inode's i_block member it only
159.593 + * can save 60 bytes. Thus this value can let the data being saved in extra
159.594 + * space.
159.595 + */
159.596 +#define BUFF_SIZE (64)
159.597 +
159.598 +static errcode_t file_test(ext2_filsys fs)
159.599 +{
159.600 + struct ext2_inode inode;
159.601 + ext2_ino_t newfile;
159.602 + errcode_t retval;
159.603 + size_t size;
159.604 + char *buf = 0, *cmpbuf = 0;
159.605 +
159.606 + /* create a new file */
159.607 + retval = ext2fs_new_inode(fs, 2, 010755, 0, &newfile);
159.608 + if (retval) {
159.609 + com_err("file_test", retval, "while allocating a new inode");
159.610 + return 1;
159.611 + }
159.612 +
159.613 + memset(&inode, 0, sizeof(inode));
159.614 + inode.i_flags |= EXT4_INLINE_DATA_FL;
159.615 + inode.i_size = EXT4_MIN_INLINE_DATA_SIZE;
159.616 + inode.i_mode = LINUX_S_IFREG;
159.617 + retval = ext2fs_write_new_inode(fs, newfile, &inode);
159.618 + if (retval) {
159.619 + com_err("file_test", retval, "while writing a new inode");
159.620 + return 1;
159.621 + }
159.622 +
159.623 + retval = ext2fs_inline_data_init(fs, newfile);
159.624 + if (retval) {
159.625 + com_err("file_test", retval, "while init 'system.data'");
159.626 + return 1;
159.627 + }
159.628 +
159.629 + retval = ext2fs_inline_data_size(fs, newfile, &size);
159.630 + if (retval) {
159.631 + com_err("file_test", retval, "while getting size");
159.632 + return 1;
159.633 + }
159.634 +
159.635 + if (size != EXT4_MIN_INLINE_DATA_SIZE) {
159.636 + fprintf(stderr,
159.637 + "tst_inline_data: size of inline data is wrong\n");
159.638 + return 1;
159.639 + }
159.640 +
159.641 + ext2fs_get_mem(BUFF_SIZE, &buf);
159.642 + memset(buf, 'a', BUFF_SIZE);
159.643 + retval = ext2fs_inline_data_set(fs, newfile, 0, buf, BUFF_SIZE);
159.644 + if (retval) {
159.645 + com_err("file_test", retval,
159.646 + "while setting inline data %s", buf);
159.647 + goto err;
159.648 + }
159.649 +
159.650 + ext2fs_get_mem(BUFF_SIZE, &cmpbuf);
159.651 + retval = ext2fs_inline_data_get(fs, newfile, 0, cmpbuf, &size);
159.652 + if (retval) {
159.653 + com_err("file_test", retval, "while getting inline data");
159.654 + goto err;
159.655 + }
159.656 +
159.657 + if (size != BUFF_SIZE) {
159.658 + fprintf(stderr,
159.659 + "tst_inline_data: size %lu != buflen %u\n",
159.660 + size, BUFF_SIZE);
159.661 + retval = 1;
159.662 + goto err;
159.663 + }
159.664 +
159.665 + if (memcmp(buf, cmpbuf, BUFF_SIZE)) {
159.666 + fprintf(stderr, "tst_inline_data: buf != cmpbuf\n");
159.667 + retval = 1;
159.668 + goto err;
159.669 + }
159.670 +
159.671 + retval = ext2fs_punch(fs, newfile, 0, 0, 0, ~0ULL);
159.672 + if (retval) {
159.673 + com_err("file_test", retval, "while truncating inode");
159.674 + goto err;
159.675 + }
159.676 +
159.677 + /* reload inode and check isize */
159.678 + ext2fs_read_inode(fs, newfile, &inode);
159.679 + if (inode.i_size != 0) {
159.680 + fprintf(stderr, "tst_inline_data: i_size should be 0\n");
159.681 + retval = 1;
159.682 + }
159.683 +
159.684 +err:
159.685 + if (cmpbuf)
159.686 + ext2fs_free_mem(&cmpbuf);
159.687 + if (buf)
159.688 + ext2fs_free_mem(&buf);
159.689 + return retval;
159.690 +}
159.691 +
159.692 +static errcode_t dir_test(ext2_filsys fs)
159.693 +{
159.694 + const char *dot_name = ".";
159.695 + const char *stub_name = "stub";
159.696 + const char *parent_name = "test";
159.697 + ext2_ino_t parent, dir, tmp;
159.698 + errcode_t retval;
159.699 + char dirname[32];
159.700 + int i;
159.701 +
159.702 + retval = ext2fs_mkdir(fs, 11, 11, stub_name);
159.703 + if (retval) {
159.704 + com_err("dir_test", retval, "while creating %s dir", stub_name);
159.705 + return retval;
159.706 + }
159.707 +
159.708 + retval = ext2fs_mkdir(fs, 11, 0, parent_name);
159.709 + if (retval) {
159.710 + com_err("dir_test", retval,
159.711 + "while creating %s dir", parent_name);
159.712 + return retval;
159.713 + }
159.714 +
159.715 + retval = ext2fs_lookup(fs, 11, parent_name, strlen(parent_name),
159.716 + 0, &parent);
159.717 + if (retval) {
159.718 + com_err("dir_test", retval,
159.719 + "while looking up %s dir", parent_name);
159.720 + return retval;
159.721 + }
159.722 +
159.723 + retval = ext2fs_lookup(fs, parent, dot_name, strlen(dot_name),
159.724 + 0, &tmp);
159.725 + if (retval) {
159.726 + com_err("dir_test", retval,
159.727 + "while looking up %s dir", parent_name);
159.728 + return retval;
159.729 + }
159.730 +
159.731 + if (parent != tmp) {
159.732 + fprintf(stderr, "tst_inline_data: parent (%u) != tmp (%u)\n",
159.733 + parent, tmp);
159.734 + return 1;
159.735 + }
159.736 +
159.737 + for (i = 0, dir = 13; i < 4; i++, dir++) {
159.738 + tmp = 0;
159.739 + snprintf(dirname, sizeof(dirname), "%d", i);
159.740 + retval = ext2fs_mkdir(fs, parent, 0, dirname);
159.741 + if (retval) {
159.742 + com_err("dir_test", retval,
159.743 + "while creating %s dir", dirname);
159.744 + return retval;
159.745 + }
159.746 +
159.747 + retval = ext2fs_lookup(fs, parent, dirname, strlen(dirname),
159.748 + 0, &tmp);
159.749 + if (retval) {
159.750 + com_err("dir_test", retval,
159.751 + "while looking up %s dir", parent_name);
159.752 + return retval;
159.753 + }
159.754 +
159.755 + if (dir != tmp) {
159.756 + fprintf(stderr,
159.757 + "tst_inline_data: dir (%u) != tmp (%u)\n",
159.758 + dir, tmp);
159.759 + return 1;
159.760 + }
159.761 + }
159.762 +
159.763 + snprintf(dirname, sizeof(dirname), "%d", i);
159.764 + retval = ext2fs_mkdir(fs, parent, 0, dirname);
159.765 + if (retval && retval != EXT2_ET_DIR_NO_SPACE) {
159.766 + com_err("dir_test", retval, "while creating %s dir", dirname);
159.767 + return retval;
159.768 + }
159.769 +
159.770 + retval = ext2fs_expand_dir(fs, parent);
159.771 + if (retval) {
159.772 + com_err("dir_test", retval, "while expanding %s dir", parent_name);
159.773 + return retval;
159.774 + }
159.775 +
159.776 + return 0;
159.777 +}
159.778 +
159.779 +int main(int argc, char *argv[])
159.780 +{
159.781 + ext2_filsys fs;
159.782 + struct ext2_super_block param;
159.783 + errcode_t retval;
159.784 +
159.785 + /* setup */
159.786 + initialize_ext2_error_table();
159.787 +
159.788 + memset(¶m, 0, sizeof(param));
159.789 + ext2fs_blocks_count_set(¶m, 32768);
159.790 + param.s_inodes_count = 100;
159.791 +
159.792 + param.s_feature_incompat |= EXT4_FEATURE_INCOMPAT_INLINE_DATA;
159.793 + param.s_rev_level = EXT2_DYNAMIC_REV;
159.794 + param.s_inode_size = 256;
159.795 +
159.796 + retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m,
159.797 + test_io_manager, &fs);
159.798 + if (retval) {
159.799 + com_err("setup", retval,
159.800 + "while initializing filesystem");
159.801 + exit(1);
159.802 + }
159.803 +
159.804 + retval = ext2fs_allocate_tables(fs);
159.805 + if (retval) {
159.806 + com_err("setup", retval,
159.807 + "while allocating tables for test filesystem");
159.808 + exit(1);
159.809 + }
159.810 +
159.811 + /* initialize inode cache */
159.812 + if (!fs->icache) {
159.813 + ext2_ino_t first_ino = EXT2_FIRST_INO(fs->super);
159.814 + int i;
159.815 +
159.816 + /* we just want to init inode cache. So ignore error */
159.817 + ext2fs_create_inode_cache(fs, 16);
159.818 + if (!fs->icache) {
159.819 + fprintf(stderr,
159.820 + "tst_inline_data: init inode cache failed\n");
159.821 + exit(1);
159.822 + }
159.823 +
159.824 + /* setup inode cache */
159.825 + for (i = 0; i < fs->icache->cache_size; i++)
159.826 + fs->icache->cache[i].ino = first_ino++;
159.827 + }
159.828 +
159.829 + /* test */
159.830 + if (file_test(fs)) {
159.831 + fprintf(stderr, "tst_inline_data(FILE): FAILED\n");
159.832 + return 1;
159.833 + }
159.834 + printf("tst_inline_data(FILE): OK\n");
159.835 +
159.836 + if (dir_test(fs)) {
159.837 + fprintf(stderr, "tst_inline_data(DIR): FAILED\n");
159.838 + return 1;
159.839 + }
159.840 + printf("tst_inline_data(DIR): OK\n");
159.841 + ext2fs_free(fs);
159.842 +
159.843 + return 0;
159.844 +}
159.845 +#endif
160.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
160.2 +++ b/libext2fs/lib/libext2fs/inode.c Wed Aug 25 01:28:08 2021 +0200
160.3 @@ -0,0 +1,1062 @@
160.4 +/*
160.5 + * inode.c --- utility routines to read and write inodes
160.6 + *
160.7 + * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
160.8 + *
160.9 + * %Begin-Header%
160.10 + * This file may be redistributed under the terms of the GNU Library
160.11 + * General Public License, version 2.
160.12 + * %End-Header%
160.13 + */
160.14 +
160.15 +#include "config.h"
160.16 +#include <stdio.h>
160.17 +#include <string.h>
160.18 +#if HAVE_UNISTD_H
160.19 +#include <unistd.h>
160.20 +#endif
160.21 +#if HAVE_ERRNO_H
160.22 +#include <errno.h>
160.23 +#endif
160.24 +#include <time.h>
160.25 +#if HAVE_SYS_STAT_H
160.26 +#include <sys/stat.h>
160.27 +#endif
160.28 +#if HAVE_SYS_TYPES_H
160.29 +#include <sys/types.h>
160.30 +#endif
160.31 +
160.32 +#include "ext2_fs.h"
160.33 +#include "ext2fsP.h"
160.34 +#include "e2image.h"
160.35 +
160.36 +#define IBLOCK_STATUS_CSUMS_OK 1
160.37 +#define IBLOCK_STATUS_INSANE 2
160.38 +#define SCAN_BLOCK_STATUS(scan) ((scan)->temp_buffer + (scan)->inode_size)
160.39 +
160.40 +struct ext2_struct_inode_scan {
160.41 + errcode_t magic;
160.42 + ext2_filsys fs;
160.43 + ext2_ino_t current_inode;
160.44 + blk64_t current_block;
160.45 + dgrp_t current_group;
160.46 + ext2_ino_t inodes_left;
160.47 + blk_t blocks_left;
160.48 + dgrp_t groups_left;
160.49 + blk_t inode_buffer_blocks;
160.50 + char * inode_buffer;
160.51 + int inode_size;
160.52 + char * ptr;
160.53 + int bytes_left;
160.54 + char *temp_buffer;
160.55 + errcode_t (*done_group)(ext2_filsys fs,
160.56 + ext2_inode_scan scan,
160.57 + dgrp_t group,
160.58 + void * priv_data);
160.59 + void * done_group_data;
160.60 + int bad_block_ptr;
160.61 + int scan_flags;
160.62 + int reserved[6];
160.63 +};
160.64 +
160.65 +/*
160.66 + * This routine flushes the icache, if it exists.
160.67 + */
160.68 +errcode_t ext2fs_flush_icache(ext2_filsys fs)
160.69 +{
160.70 + unsigned i;
160.71 +
160.72 + if (!fs->icache)
160.73 + return 0;
160.74 +
160.75 + for (i=0; i < fs->icache->cache_size; i++)
160.76 + fs->icache->cache[i].ino = 0;
160.77 +
160.78 + fs->icache->buffer_blk = 0;
160.79 + return 0;
160.80 +}
160.81 +
160.82 +/*
160.83 + * Free the inode cache structure
160.84 + */
160.85 +void ext2fs_free_inode_cache(struct ext2_inode_cache *icache)
160.86 +{
160.87 + unsigned i;
160.88 +
160.89 + if (--icache->refcount)
160.90 + return;
160.91 + if (icache->buffer)
160.92 + ext2fs_free_mem(&icache->buffer);
160.93 + for (i = 0; i < icache->cache_size; i++)
160.94 + ext2fs_free_mem(&icache->cache[i].inode);
160.95 + if (icache->cache)
160.96 + ext2fs_free_mem(&icache->cache);
160.97 + icache->buffer_blk = 0;
160.98 + ext2fs_free_mem(&icache);
160.99 +}
160.100 +
160.101 +errcode_t ext2fs_create_inode_cache(ext2_filsys fs, unsigned int cache_size)
160.102 +{
160.103 + unsigned i;
160.104 + errcode_t retval;
160.105 +
160.106 + if (fs->icache)
160.107 + return 0;
160.108 + retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache);
160.109 + if (retval)
160.110 + return retval;
160.111 +
160.112 + memset(fs->icache, 0, sizeof(struct ext2_inode_cache));
160.113 + retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer);
160.114 + if (retval)
160.115 + goto errout;
160.116 +
160.117 + fs->icache->buffer_blk = 0;
160.118 + fs->icache->cache_last = -1;
160.119 + fs->icache->cache_size = cache_size;
160.120 + fs->icache->refcount = 1;
160.121 + retval = ext2fs_get_array(fs->icache->cache_size,
160.122 + sizeof(struct ext2_inode_cache_ent),
160.123 + &fs->icache->cache);
160.124 + if (retval)
160.125 + goto errout;
160.126 +
160.127 + for (i = 0; i < fs->icache->cache_size; i++) {
160.128 + retval = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super),
160.129 + &fs->icache->cache[i].inode);
160.130 + if (retval)
160.131 + goto errout;
160.132 + }
160.133 +
160.134 + ext2fs_flush_icache(fs);
160.135 + return 0;
160.136 +errout:
160.137 + ext2fs_free_inode_cache(fs->icache);
160.138 + fs->icache = 0;
160.139 + return retval;
160.140 +}
160.141 +
160.142 +errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
160.143 + ext2_inode_scan *ret_scan)
160.144 +{
160.145 + ext2_inode_scan scan;
160.146 + errcode_t retval;
160.147 + errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks);
160.148 +
160.149 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
160.150 +
160.151 + /*
160.152 + * If fs->badblocks isn't set, then set it --- since the inode
160.153 + * scanning functions require it.
160.154 + */
160.155 + if (fs->badblocks == 0) {
160.156 + /*
160.157 + * Temporarily save fs->get_blocks and set it to zero,
160.158 + * for compatibility with old e2fsck's.
160.159 + */
160.160 + save_get_blocks = fs->get_blocks;
160.161 + fs->get_blocks = 0;
160.162 + retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
160.163 + if (retval && fs->badblocks) {
160.164 + ext2fs_badblocks_list_free(fs->badblocks);
160.165 + fs->badblocks = 0;
160.166 + }
160.167 + fs->get_blocks = save_get_blocks;
160.168 + }
160.169 +
160.170 + retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan);
160.171 + if (retval)
160.172 + return retval;
160.173 + memset(scan, 0, sizeof(struct ext2_struct_inode_scan));
160.174 +
160.175 + scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
160.176 + scan->fs = fs;
160.177 + scan->inode_size = EXT2_INODE_SIZE(fs->super);
160.178 + scan->bytes_left = 0;
160.179 + scan->current_group = 0;
160.180 + scan->groups_left = fs->group_desc_count - 1;
160.181 + scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks :
160.182 + EXT2_INODE_SCAN_DEFAULT_BUFFER_BLOCKS;
160.183 + scan->current_block = ext2fs_inode_table_loc(scan->fs,
160.184 + scan->current_group);
160.185 + scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
160.186 + scan->blocks_left = scan->fs->inode_blocks_per_group;
160.187 + if (ext2fs_has_group_desc_csum(fs)) {
160.188 + __u32 unused = ext2fs_bg_itable_unused(fs, scan->current_group);
160.189 + if (scan->inodes_left > unused)
160.190 + scan->inodes_left -= unused;
160.191 + else
160.192 + scan->inodes_left = 0;
160.193 + scan->blocks_left =
160.194 + (scan->inodes_left +
160.195 + (fs->blocksize / scan->inode_size - 1)) *
160.196 + scan->inode_size / fs->blocksize;
160.197 + }
160.198 + retval = io_channel_alloc_buf(fs->io, scan->inode_buffer_blocks,
160.199 + &scan->inode_buffer);
160.200 + scan->done_group = 0;
160.201 + scan->done_group_data = 0;
160.202 + scan->bad_block_ptr = 0;
160.203 + if (retval) {
160.204 + ext2fs_free_mem(&scan);
160.205 + return retval;
160.206 + }
160.207 + retval = ext2fs_get_mem(scan->inode_size + scan->inode_buffer_blocks,
160.208 + &scan->temp_buffer);
160.209 + if (retval) {
160.210 + ext2fs_free_mem(&scan->inode_buffer);
160.211 + ext2fs_free_mem(&scan);
160.212 + return retval;
160.213 + }
160.214 + memset(SCAN_BLOCK_STATUS(scan), 0, scan->inode_buffer_blocks);
160.215 + if (scan->fs->badblocks && scan->fs->badblocks->num)
160.216 + scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
160.217 + if (ext2fs_has_group_desc_csum(fs))
160.218 + scan->scan_flags |= EXT2_SF_DO_LAZY;
160.219 + *ret_scan = scan;
160.220 + return 0;
160.221 +}
160.222 +
160.223 +void ext2fs_close_inode_scan(ext2_inode_scan scan)
160.224 +{
160.225 + if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
160.226 + return;
160.227 +
160.228 + ext2fs_free_mem(&scan->inode_buffer);
160.229 + scan->inode_buffer = NULL;
160.230 + ext2fs_free_mem(&scan->temp_buffer);
160.231 + scan->temp_buffer = NULL;
160.232 + ext2fs_free_mem(&scan);
160.233 + return;
160.234 +}
160.235 +
160.236 +void ext2fs_set_inode_callback(ext2_inode_scan scan,
160.237 + errcode_t (*done_group)(ext2_filsys fs,
160.238 + ext2_inode_scan scan,
160.239 + dgrp_t group,
160.240 + void * priv_data),
160.241 + void *done_group_data)
160.242 +{
160.243 + if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
160.244 + return;
160.245 +
160.246 + scan->done_group = done_group;
160.247 + scan->done_group_data = done_group_data;
160.248 +}
160.249 +
160.250 +int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
160.251 + int clear_flags)
160.252 +{
160.253 + int old_flags;
160.254 +
160.255 + if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
160.256 + return 0;
160.257 +
160.258 + old_flags = scan->scan_flags;
160.259 + scan->scan_flags &= ~clear_flags;
160.260 + scan->scan_flags |= set_flags;
160.261 + return old_flags;
160.262 +}
160.263 +
160.264 +/*
160.265 + * This function is called by ext2fs_get_next_inode when it needs to
160.266 + * get ready to read in a new blockgroup.
160.267 + */
160.268 +static errcode_t get_next_blockgroup(ext2_inode_scan scan)
160.269 +{
160.270 + ext2_filsys fs = scan->fs;
160.271 +
160.272 + scan->current_group++;
160.273 + scan->groups_left--;
160.274 +
160.275 + scan->current_block = ext2fs_inode_table_loc(scan->fs,
160.276 + scan->current_group);
160.277 + scan->current_inode = scan->current_group *
160.278 + EXT2_INODES_PER_GROUP(fs->super);
160.279 +
160.280 + scan->bytes_left = 0;
160.281 + scan->inodes_left = EXT2_INODES_PER_GROUP(fs->super);
160.282 + scan->blocks_left = fs->inode_blocks_per_group;
160.283 + if (ext2fs_has_group_desc_csum(fs)) {
160.284 + __u32 unused = ext2fs_bg_itable_unused(fs, scan->current_group);
160.285 + if (scan->inodes_left > unused)
160.286 + scan->inodes_left -= unused;
160.287 + else
160.288 + scan->inodes_left = 0;
160.289 + scan->blocks_left =
160.290 + (scan->inodes_left +
160.291 + (fs->blocksize / scan->inode_size - 1)) *
160.292 + scan->inode_size / fs->blocksize;
160.293 + }
160.294 +
160.295 + return 0;
160.296 +}
160.297 +
160.298 +errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
160.299 + int group)
160.300 +{
160.301 + scan->current_group = group - 1;
160.302 + scan->groups_left = scan->fs->group_desc_count - group;
160.303 + return get_next_blockgroup(scan);
160.304 +}
160.305 +
160.306 +/*
160.307 + * This function is called by get_next_blocks() to check for bad
160.308 + * blocks in the inode table.
160.309 + *
160.310 + * This function assumes that badblocks_list->list is sorted in
160.311 + * increasing order.
160.312 + */
160.313 +static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan,
160.314 + blk64_t *num_blocks)
160.315 +{
160.316 + blk64_t blk = scan->current_block;
160.317 + badblocks_list bb = scan->fs->badblocks;
160.318 +
160.319 + /*
160.320 + * If the inode table is missing, then obviously there are no
160.321 + * bad blocks. :-)
160.322 + */
160.323 + if (blk == 0)
160.324 + return 0;
160.325 +
160.326 + /*
160.327 + * If the current block is greater than the bad block listed
160.328 + * in the bad block list, then advance the pointer until this
160.329 + * is no longer the case. If we run out of bad blocks, then
160.330 + * we don't need to do any more checking!
160.331 + */
160.332 + while (blk > bb->list[scan->bad_block_ptr]) {
160.333 + if (++scan->bad_block_ptr >= bb->num) {
160.334 + scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
160.335 + return 0;
160.336 + }
160.337 + }
160.338 +
160.339 + /*
160.340 + * If the current block is equal to the bad block listed in
160.341 + * the bad block list, then handle that one block specially.
160.342 + * (We could try to handle runs of bad blocks, but that
160.343 + * only increases CPU efficiency by a small amount, at the
160.344 + * expense of a huge expense of code complexity, and for an
160.345 + * uncommon case at that.)
160.346 + */
160.347 + if (blk == bb->list[scan->bad_block_ptr]) {
160.348 + scan->scan_flags |= EXT2_SF_BAD_INODE_BLK;
160.349 + *num_blocks = 1;
160.350 + if (++scan->bad_block_ptr >= bb->num)
160.351 + scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
160.352 + return 0;
160.353 + }
160.354 +
160.355 + /*
160.356 + * If there is a bad block in the range that we're about to
160.357 + * read in, adjust the number of blocks to read so that we we
160.358 + * don't read in the bad block. (Then the next block to read
160.359 + * will be the bad block, which is handled in the above case.)
160.360 + */
160.361 + if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr])
160.362 + *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk);
160.363 +
160.364 + return 0;
160.365 +}
160.366 +
160.367 +static int block_map_looks_insane(ext2_filsys fs,
160.368 + struct ext2_inode_large *inode)
160.369 +{
160.370 + unsigned int i, bad;
160.371 +
160.372 + /* We're only interested in block mapped files, dirs, and symlinks */
160.373 + if ((inode->i_flags & EXT4_INLINE_DATA_FL) ||
160.374 + (inode->i_flags & EXT4_EXTENTS_FL))
160.375 + return 0;
160.376 + if (!LINUX_S_ISREG(inode->i_mode) &&
160.377 + !LINUX_S_ISLNK(inode->i_mode) &&
160.378 + !LINUX_S_ISDIR(inode->i_mode))
160.379 + return 0;
160.380 + if (LINUX_S_ISLNK(inode->i_mode) &&
160.381 + EXT2_I_SIZE(inode) <= sizeof(inode->i_block))
160.382 + return 0;
160.383 +
160.384 + /* Unused inodes probably aren't insane */
160.385 + if (inode->i_links_count == 0)
160.386 + return 0;
160.387 +
160.388 + /* See if more than half the block maps are insane */
160.389 + for (i = 0, bad = 0; i < EXT2_N_BLOCKS; i++)
160.390 + if (inode->i_block[i] != 0 &&
160.391 + (inode->i_block[i] < fs->super->s_first_data_block ||
160.392 + inode->i_block[i] >= ext2fs_blocks_count(fs->super)))
160.393 + bad++;
160.394 + return bad > EXT2_N_BLOCKS / 2;
160.395 +}
160.396 +
160.397 +static int extent_head_looks_insane(struct ext2_inode_large *inode)
160.398 +{
160.399 + if (!(inode->i_flags & EXT4_EXTENTS_FL) ||
160.400 + ext2fs_extent_header_verify(inode->i_block,
160.401 + sizeof(inode->i_block)) == 0)
160.402 + return 0;
160.403 + return 1;
160.404 +}
160.405 +
160.406 +/*
160.407 + * Check all the inodes that we just read into the buffer. Record what we
160.408 + * find here -- currently, we can observe that all checksums are ok; more
160.409 + * than half the inodes are insane; or no conclusions at all.
160.410 + */
160.411 +static void check_inode_block_sanity(ext2_inode_scan scan, blk64_t num_blocks)
160.412 +{
160.413 + ext2_ino_t ino, inodes_to_scan;
160.414 + unsigned int badness, checksum_failures;
160.415 + unsigned int inodes_in_buf, inodes_per_block;
160.416 + char *p;
160.417 + struct ext2_inode_large *inode;
160.418 + char *block_status;
160.419 + unsigned int blk, bad_csum;
160.420 +
160.421 + if (!(scan->scan_flags & EXT2_SF_WARN_GARBAGE_INODES))
160.422 + return;
160.423 +
160.424 + inodes_to_scan = scan->inodes_left;
160.425 + inodes_in_buf = num_blocks * scan->fs->blocksize / scan->inode_size;
160.426 + if (inodes_to_scan > inodes_in_buf)
160.427 + inodes_to_scan = inodes_in_buf;
160.428 +
160.429 + p = (char *) scan->inode_buffer;
160.430 + ino = scan->current_inode + 1;
160.431 + checksum_failures = badness = 0;
160.432 + block_status = SCAN_BLOCK_STATUS(scan);
160.433 + memset(block_status, 0, scan->inode_buffer_blocks);
160.434 + inodes_per_block = EXT2_INODES_PER_BLOCK(scan->fs->super);
160.435 +
160.436 + if (inodes_per_block < 2)
160.437 + return;
160.438 +
160.439 +#ifdef WORDS_BIGENDIAN
160.440 + if (ext2fs_get_mem(EXT2_INODE_SIZE(scan->fs->super), &inode))
160.441 + return;
160.442 +#endif
160.443 +
160.444 + while (inodes_to_scan > 0) {
160.445 + blk = (p - (char *)scan->inode_buffer) / scan->fs->blocksize;
160.446 + bad_csum = ext2fs_inode_csum_verify(scan->fs, ino,
160.447 + (struct ext2_inode_large *) p) == 0;
160.448 +
160.449 +#ifdef WORDS_BIGENDIAN
160.450 + ext2fs_swap_inode_full(scan->fs,
160.451 + (struct ext2_inode_large *) inode,
160.452 + (struct ext2_inode_large *) p,
160.453 + 0, EXT2_INODE_SIZE(scan->fs->super));
160.454 +#else
160.455 + inode = (struct ext2_inode_large *) p;
160.456 +#endif
160.457 +
160.458 + /* Is this inode insane? */
160.459 + if (bad_csum) {
160.460 + checksum_failures++;
160.461 + badness++;
160.462 + } else if (extent_head_looks_insane(inode) ||
160.463 + block_map_looks_insane(scan->fs, inode))
160.464 + badness++;
160.465 +
160.466 + /* If more than half are insane, declare the whole block bad */
160.467 + if (badness > inodes_per_block / 2) {
160.468 + unsigned int ino_adj;
160.469 +
160.470 + block_status[blk] |= IBLOCK_STATUS_INSANE;
160.471 + ino_adj = inodes_per_block -
160.472 + ((ino - 1) % inodes_per_block);
160.473 + if (ino_adj > inodes_to_scan)
160.474 + ino_adj = inodes_to_scan;
160.475 + inodes_to_scan -= ino_adj;
160.476 + p += scan->inode_size * ino_adj;
160.477 + ino += ino_adj;
160.478 + checksum_failures = badness = 0;
160.479 + continue;
160.480 + }
160.481 +
160.482 + if ((ino % inodes_per_block) == 0) {
160.483 + if (checksum_failures == 0)
160.484 + block_status[blk] |= IBLOCK_STATUS_CSUMS_OK;
160.485 + checksum_failures = badness = 0;
160.486 + }
160.487 + inodes_to_scan--;
160.488 + p += scan->inode_size;
160.489 + ino++;
160.490 + };
160.491 +
160.492 +#ifdef WORDS_BIGENDIAN
160.493 + ext2fs_free_mem(&inode);
160.494 +#endif
160.495 +}
160.496 +
160.497 +/*
160.498 + * This function is called by ext2fs_get_next_inode when it needs to
160.499 + * read in more blocks from the current blockgroup's inode table.
160.500 + */
160.501 +static errcode_t get_next_blocks(ext2_inode_scan scan)
160.502 +{
160.503 + blk64_t num_blocks;
160.504 + errcode_t retval;
160.505 +
160.506 + /*
160.507 + * Figure out how many blocks to read; we read at most
160.508 + * inode_buffer_blocks, and perhaps less if there aren't that
160.509 + * many blocks left to read.
160.510 + */
160.511 + num_blocks = scan->inode_buffer_blocks;
160.512 + if (num_blocks > scan->blocks_left)
160.513 + num_blocks = scan->blocks_left;
160.514 +
160.515 + /*
160.516 + * If the past block "read" was a bad block, then mark the
160.517 + * left-over extra bytes as also being bad.
160.518 + */
160.519 + if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) {
160.520 + if (scan->bytes_left)
160.521 + scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES;
160.522 + scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK;
160.523 + }
160.524 +
160.525 + /*
160.526 + * Do inode bad block processing, if necessary.
160.527 + */
160.528 + if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) {
160.529 + retval = check_for_inode_bad_blocks(scan, &num_blocks);
160.530 + if (retval)
160.531 + return retval;
160.532 + }
160.533 +
160.534 + if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) ||
160.535 + (scan->current_block == 0)) {
160.536 + memset(scan->inode_buffer, 0,
160.537 + (size_t) num_blocks * scan->fs->blocksize);
160.538 + } else {
160.539 + retval = io_channel_read_blk64(scan->fs->io,
160.540 + scan->current_block,
160.541 + (int) num_blocks,
160.542 + scan->inode_buffer);
160.543 + if (retval)
160.544 + return EXT2_ET_NEXT_INODE_READ;
160.545 + }
160.546 + check_inode_block_sanity(scan, num_blocks);
160.547 +
160.548 + scan->ptr = scan->inode_buffer;
160.549 + scan->bytes_left = num_blocks * scan->fs->blocksize;
160.550 +
160.551 + scan->blocks_left -= num_blocks;
160.552 + if (scan->current_block)
160.553 + scan->current_block += num_blocks;
160.554 +
160.555 + return 0;
160.556 +}
160.557 +
160.558 +#if 0
160.559 +/*
160.560 + * Returns 1 if the entire inode_buffer has a non-zero size and
160.561 + * contains all zeros. (Not just deleted inodes, since that means
160.562 + * that part of the inode table was used at one point; we want all
160.563 + * zeros, which means that the inode table is pristine.)
160.564 + */
160.565 +static inline int is_empty_scan(ext2_inode_scan scan)
160.566 +{
160.567 + int i;
160.568 +
160.569 + if (scan->bytes_left == 0)
160.570 + return 0;
160.571 +
160.572 + for (i=0; i < scan->bytes_left; i++)
160.573 + if (scan->ptr[i])
160.574 + return 0;
160.575 + return 1;
160.576 +}
160.577 +#endif
160.578 +
160.579 +errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino,
160.580 + struct ext2_inode *inode, int bufsize)
160.581 +{
160.582 + errcode_t retval;
160.583 + int extra_bytes = 0;
160.584 + int length;
160.585 + struct ext2_inode_large *iptr = (struct ext2_inode_large *)inode;
160.586 + char *iblock_status;
160.587 + unsigned int iblk;
160.588 +
160.589 + EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
160.590 + length = EXT2_INODE_SIZE(scan->fs->super);
160.591 + iblock_status = SCAN_BLOCK_STATUS(scan);
160.592 +
160.593 + /*
160.594 + * Do we need to start reading a new block group?
160.595 + */
160.596 + if (scan->inodes_left <= 0) {
160.597 + force_new_group:
160.598 + if (scan->done_group) {
160.599 + retval = (scan->done_group)
160.600 + (scan->fs, scan, scan->current_group,
160.601 + scan->done_group_data);
160.602 + if (retval)
160.603 + return retval;
160.604 + }
160.605 + if (scan->groups_left <= 0) {
160.606 + *ino = 0;
160.607 + return 0;
160.608 + }
160.609 + retval = get_next_blockgroup(scan);
160.610 + if (retval)
160.611 + return retval;
160.612 + }
160.613 + /*
160.614 + * These checks are done outside the above if statement so
160.615 + * they can be done for block group #0.
160.616 + */
160.617 + if ((scan->scan_flags & EXT2_SF_DO_LAZY) &&
160.618 + (ext2fs_bg_flags_test(scan->fs, scan->current_group, EXT2_BG_INODE_UNINIT)
160.619 + ))
160.620 + goto force_new_group;
160.621 + if (scan->inodes_left == 0)
160.622 + goto force_new_group;
160.623 + if (scan->current_block == 0) {
160.624 + if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
160.625 + goto force_new_group;
160.626 + } else
160.627 + return EXT2_ET_MISSING_INODE_TABLE;
160.628 + }
160.629 +
160.630 +
160.631 + /*
160.632 + * Have we run out of space in the inode buffer? If so, we
160.633 + * need to read in more blocks.
160.634 + */
160.635 + if (scan->bytes_left < scan->inode_size) {
160.636 + if (scan->bytes_left)
160.637 + memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
160.638 + extra_bytes = scan->bytes_left;
160.639 +
160.640 + retval = get_next_blocks(scan);
160.641 + if (retval)
160.642 + return retval;
160.643 +#if 0
160.644 + /*
160.645 + * XXX test Need check for used inode somehow.
160.646 + * (Note: this is hard.)
160.647 + */
160.648 + if (is_empty_scan(scan))
160.649 + goto force_new_group;
160.650 +#endif
160.651 + }
160.652 +
160.653 + if (bufsize < length) {
160.654 + retval = ext2fs_get_mem(length, &iptr);
160.655 + if (retval)
160.656 + return retval;
160.657 + }
160.658 +
160.659 + retval = 0;
160.660 + iblk = scan->current_inode % EXT2_INODES_PER_GROUP(scan->fs->super) /
160.661 + EXT2_INODES_PER_BLOCK(scan->fs->super) %
160.662 + scan->inode_buffer_blocks;
160.663 + if (extra_bytes) {
160.664 + memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
160.665 + scan->inode_size - extra_bytes);
160.666 + scan->ptr += scan->inode_size - extra_bytes;
160.667 + scan->bytes_left -= scan->inode_size - extra_bytes;
160.668 +
160.669 + /* Verify the inode checksum. */
160.670 + if (!(iblock_status[iblk] & IBLOCK_STATUS_CSUMS_OK) &&
160.671 + !(scan->fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
160.672 + !ext2fs_inode_csum_verify(scan->fs, scan->current_inode + 1,
160.673 + (struct ext2_inode_large *)scan->temp_buffer))
160.674 + retval = EXT2_ET_INODE_CSUM_INVALID;
160.675 +
160.676 +#ifdef WORDS_BIGENDIAN
160.677 + memset(iptr, 0, length);
160.678 + ext2fs_swap_inode_full(scan->fs,
160.679 + (struct ext2_inode_large *) iptr,
160.680 + (struct ext2_inode_large *) scan->temp_buffer,
160.681 + 0, length);
160.682 +#else
160.683 + memcpy(iptr, scan->temp_buffer, length);
160.684 +#endif
160.685 + if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES)
160.686 + retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
160.687 + scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES;
160.688 + } else {
160.689 + /* Verify the inode checksum. */
160.690 + if (!(iblock_status[iblk] & IBLOCK_STATUS_CSUMS_OK) &&
160.691 + !(scan->fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
160.692 + !ext2fs_inode_csum_verify(scan->fs, scan->current_inode + 1,
160.693 + (struct ext2_inode_large *)scan->ptr))
160.694 + retval = EXT2_ET_INODE_CSUM_INVALID;
160.695 +
160.696 +#ifdef WORDS_BIGENDIAN
160.697 + memset(iptr, 0, length);
160.698 + ext2fs_swap_inode_full(scan->fs,
160.699 + (struct ext2_inode_large *) iptr,
160.700 + (struct ext2_inode_large *) scan->ptr,
160.701 + 0, length);
160.702 +#else
160.703 + memcpy(iptr, scan->ptr, length);
160.704 +#endif
160.705 + scan->ptr += scan->inode_size;
160.706 + scan->bytes_left -= scan->inode_size;
160.707 + if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
160.708 + retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
160.709 + }
160.710 + if ((iblock_status[iblk] & IBLOCK_STATUS_INSANE) &&
160.711 + (retval == 0 || retval == EXT2_ET_INODE_CSUM_INVALID))
160.712 + retval = EXT2_ET_INODE_IS_GARBAGE;
160.713 +
160.714 + scan->inodes_left--;
160.715 + scan->current_inode++;
160.716 + *ino = scan->current_inode;
160.717 + if (iptr != (struct ext2_inode_large *)inode) {
160.718 + memcpy(inode, iptr, bufsize);
160.719 + ext2fs_free_mem(&iptr);
160.720 + }
160.721 + return retval;
160.722 +}
160.723 +
160.724 +errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
160.725 + struct ext2_inode *inode)
160.726 +{
160.727 + return ext2fs_get_next_inode_full(scan, ino, inode,
160.728 + sizeof(struct ext2_inode));
160.729 +}
160.730 +
160.731 +/*
160.732 + * Functions to read and write a single inode.
160.733 + */
160.734 +errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
160.735 + struct ext2_inode * inode, int bufsize)
160.736 +{
160.737 + blk64_t block_nr;
160.738 + unsigned long group, block, offset;
160.739 + char *ptr;
160.740 + errcode_t retval;
160.741 + unsigned i;
160.742 + int clen, inodes_per_block;
160.743 + io_channel io;
160.744 + int length = EXT2_INODE_SIZE(fs->super);
160.745 + struct ext2_inode_large *iptr;
160.746 + int cache_slot, fail_csum;
160.747 +
160.748 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
160.749 +
160.750 + /* Check to see if user has an override function */
160.751 + if (fs->read_inode &&
160.752 + ((bufsize == sizeof(struct ext2_inode)) ||
160.753 + (EXT2_INODE_SIZE(fs->super) == sizeof(struct ext2_inode)))) {
160.754 + retval = (fs->read_inode)(fs, ino, inode);
160.755 + if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
160.756 + return retval;
160.757 + }
160.758 + if ((ino == 0) || (ino > fs->super->s_inodes_count))
160.759 + return EXT2_ET_BAD_INODE_NUM;
160.760 + /* Create inode cache if not present */
160.761 + if (!fs->icache) {
160.762 + retval = ext2fs_create_inode_cache(fs, 4);
160.763 + if (retval)
160.764 + return retval;
160.765 + }
160.766 + /* Check to see if it's in the inode cache */
160.767 + for (i = 0; i < fs->icache->cache_size; i++) {
160.768 + if (fs->icache->cache[i].ino == ino) {
160.769 + memcpy(inode, fs->icache->cache[i].inode,
160.770 + (bufsize > length) ? length : bufsize);
160.771 + return 0;
160.772 + }
160.773 + }
160.774 + if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
160.775 + inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super);
160.776 + block_nr = ext2fs_le32_to_cpu(fs->image_header->offset_inode) / fs->blocksize;
160.777 + block_nr += (ino - 1) / inodes_per_block;
160.778 + offset = ((ino - 1) % inodes_per_block) *
160.779 + EXT2_INODE_SIZE(fs->super);
160.780 + io = fs->image_io;
160.781 + } else {
160.782 + group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
160.783 + if (group > fs->group_desc_count)
160.784 + return EXT2_ET_BAD_INODE_NUM;
160.785 + offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
160.786 + EXT2_INODE_SIZE(fs->super);
160.787 + block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
160.788 + if (!ext2fs_inode_table_loc(fs, (unsigned) group))
160.789 + return EXT2_ET_MISSING_INODE_TABLE;
160.790 + block_nr = ext2fs_inode_table_loc(fs, group) +
160.791 + block;
160.792 + io = fs->io;
160.793 + }
160.794 + offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
160.795 +
160.796 + cache_slot = (fs->icache->cache_last + 1) % fs->icache->cache_size;
160.797 + iptr = (struct ext2_inode_large *)fs->icache->cache[cache_slot].inode;
160.798 +
160.799 + ptr = (char *) iptr;
160.800 + while (length) {
160.801 + clen = length;
160.802 + if ((offset + length) > fs->blocksize)
160.803 + clen = fs->blocksize - offset;
160.804 +
160.805 + if (block_nr != fs->icache->buffer_blk) {
160.806 + retval = io_channel_read_blk64(io, block_nr, 1,
160.807 + fs->icache->buffer);
160.808 + if (retval)
160.809 + return retval;
160.810 + fs->icache->buffer_blk = block_nr;
160.811 + }
160.812 +
160.813 + memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset,
160.814 + clen);
160.815 +
160.816 + offset = 0;
160.817 + length -= clen;
160.818 + ptr += clen;
160.819 + block_nr++;
160.820 + }
160.821 + length = EXT2_INODE_SIZE(fs->super);
160.822 +
160.823 + /* Verify the inode checksum. */
160.824 + fail_csum = !ext2fs_inode_csum_verify(fs, ino, iptr);
160.825 +
160.826 +#ifdef WORDS_BIGENDIAN
160.827 + ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) iptr,
160.828 + (struct ext2_inode_large *) iptr,
160.829 + 0, length);
160.830 +#endif
160.831 +
160.832 + /* Update the inode cache bookkeeping */
160.833 + if (!fail_csum) {
160.834 + fs->icache->cache_last = cache_slot;
160.835 + fs->icache->cache[cache_slot].ino = ino;
160.836 + }
160.837 + memcpy(inode, iptr, (bufsize > length) ? length : bufsize);
160.838 +
160.839 + if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) && fail_csum)
160.840 + return EXT2_ET_INODE_CSUM_INVALID;
160.841 +
160.842 + return 0;
160.843 +}
160.844 +
160.845 +errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino,
160.846 + struct ext2_inode * inode)
160.847 +{
160.848 + return ext2fs_read_inode_full(fs, ino, inode,
160.849 + sizeof(struct ext2_inode));
160.850 +}
160.851 +
160.852 +errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
160.853 + struct ext2_inode * inode, int bufsize)
160.854 +{
160.855 + blk64_t block_nr;
160.856 + unsigned long group, block, offset;
160.857 + errcode_t retval = 0;
160.858 + struct ext2_inode_large *w_inode;
160.859 + char *ptr;
160.860 + unsigned i;
160.861 + int clen;
160.862 + int length = EXT2_INODE_SIZE(fs->super);
160.863 +
160.864 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
160.865 +
160.866 + /* Check to see if user provided an override function */
160.867 + if (fs->write_inode) {
160.868 + retval = (fs->write_inode)(fs, ino, inode);
160.869 + if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
160.870 + return retval;
160.871 + }
160.872 +
160.873 + if ((ino == 0) || (ino > fs->super->s_inodes_count))
160.874 + return EXT2_ET_BAD_INODE_NUM;
160.875 +
160.876 + /* Prepare our shadow buffer for read/modify/byteswap/write */
160.877 + retval = ext2fs_get_mem(length, &w_inode);
160.878 + if (retval)
160.879 + return retval;
160.880 +
160.881 + if (bufsize < length) {
160.882 + int old_flags = fs->flags;
160.883 + fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
160.884 + retval = ext2fs_read_inode_full(fs, ino,
160.885 + (struct ext2_inode *)w_inode,
160.886 + length);
160.887 + fs->flags = (old_flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) |
160.888 + (fs->flags & ~EXT2_FLAG_IGNORE_CSUM_ERRORS);
160.889 + if (retval)
160.890 + goto errout;
160.891 + }
160.892 +
160.893 + /* Check to see if the inode cache needs to be updated */
160.894 + if (fs->icache) {
160.895 + for (i=0; i < fs->icache->cache_size; i++) {
160.896 + if (fs->icache->cache[i].ino == ino) {
160.897 + memcpy(fs->icache->cache[i].inode, inode,
160.898 + (bufsize > length) ? length : bufsize);
160.899 + break;
160.900 + }
160.901 + }
160.902 + } else {
160.903 + retval = ext2fs_create_inode_cache(fs, 4);
160.904 + if (retval)
160.905 + goto errout;
160.906 + }
160.907 + memcpy(w_inode, inode, (bufsize > length) ? length : bufsize);
160.908 +
160.909 + if (!(fs->flags & EXT2_FLAG_RW)) {
160.910 + retval = EXT2_ET_RO_FILSYS;
160.911 + goto errout;
160.912 + }
160.913 +
160.914 +#ifdef WORDS_BIGENDIAN
160.915 + ext2fs_swap_inode_full(fs, w_inode, w_inode, 1, length);
160.916 +#endif
160.917 +
160.918 + retval = ext2fs_inode_csum_set(fs, ino, w_inode);
160.919 + if (retval)
160.920 + goto errout;
160.921 +
160.922 + group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
160.923 + offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
160.924 + EXT2_INODE_SIZE(fs->super);
160.925 + block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
160.926 + if (!ext2fs_inode_table_loc(fs, (unsigned) group)) {
160.927 + retval = EXT2_ET_MISSING_INODE_TABLE;
160.928 + goto errout;
160.929 + }
160.930 + block_nr = ext2fs_inode_table_loc(fs, (unsigned) group) + block;
160.931 +
160.932 + offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
160.933 +
160.934 + ptr = (char *) w_inode;
160.935 +
160.936 + while (length) {
160.937 + clen = length;
160.938 + if ((offset + length) > fs->blocksize)
160.939 + clen = fs->blocksize - offset;
160.940 +
160.941 + if (fs->icache->buffer_blk != block_nr) {
160.942 + retval = io_channel_read_blk64(fs->io, block_nr, 1,
160.943 + fs->icache->buffer);
160.944 + if (retval)
160.945 + goto errout;
160.946 + fs->icache->buffer_blk = block_nr;
160.947 + }
160.948 +
160.949 +
160.950 + memcpy((char *) fs->icache->buffer + (unsigned) offset,
160.951 + ptr, clen);
160.952 +
160.953 + retval = io_channel_write_blk64(fs->io, block_nr, 1,
160.954 + fs->icache->buffer);
160.955 + if (retval)
160.956 + goto errout;
160.957 +
160.958 + offset = 0;
160.959 + ptr += clen;
160.960 + length -= clen;
160.961 + block_nr++;
160.962 + }
160.963 +
160.964 + fs->flags |= EXT2_FLAG_CHANGED;
160.965 +errout:
160.966 + ext2fs_free_mem(&w_inode);
160.967 + return retval;
160.968 +}
160.969 +
160.970 +errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
160.971 + struct ext2_inode *inode)
160.972 +{
160.973 + return ext2fs_write_inode_full(fs, ino, inode,
160.974 + sizeof(struct ext2_inode));
160.975 +}
160.976 +
160.977 +/*
160.978 + * This function should be called when writing a new inode. It makes
160.979 + * sure that extra part of large inodes is initialized properly.
160.980 + */
160.981 +errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
160.982 + struct ext2_inode *inode)
160.983 +{
160.984 + struct ext2_inode *buf;
160.985 + int size = EXT2_INODE_SIZE(fs->super);
160.986 + struct ext2_inode_large *large_inode;
160.987 + errcode_t retval;
160.988 + __u32 t = fs->now ? fs->now : time(NULL);
160.989 +
160.990 + if (!inode->i_ctime)
160.991 + inode->i_ctime = t;
160.992 + if (!inode->i_mtime)
160.993 + inode->i_mtime = t;
160.994 + if (!inode->i_atime)
160.995 + inode->i_atime = t;
160.996 +
160.997 + if (size == sizeof(struct ext2_inode))
160.998 + return ext2fs_write_inode_full(fs, ino, inode,
160.999 + sizeof(struct ext2_inode));
160.1000 +
160.1001 + buf = malloc(size);
160.1002 + if (!buf)
160.1003 + return ENOMEM;
160.1004 +
160.1005 + memset(buf, 0, size);
160.1006 + *buf = *inode;
160.1007 +
160.1008 + large_inode = (struct ext2_inode_large *) buf;
160.1009 + large_inode->i_extra_isize = sizeof(struct ext2_inode_large) -
160.1010 + EXT2_GOOD_OLD_INODE_SIZE;
160.1011 + if (!large_inode->i_crtime)
160.1012 + large_inode->i_crtime = t;
160.1013 +
160.1014 + retval = ext2fs_write_inode_full(fs, ino, buf, size);
160.1015 + free(buf);
160.1016 + return retval;
160.1017 +}
160.1018 +
160.1019 +
160.1020 +errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks)
160.1021 +{
160.1022 + struct ext2_inode inode;
160.1023 + int i;
160.1024 + errcode_t retval;
160.1025 +
160.1026 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
160.1027 +
160.1028 + if (ino > fs->super->s_inodes_count)
160.1029 + return EXT2_ET_BAD_INODE_NUM;
160.1030 +
160.1031 + if (fs->get_blocks) {
160.1032 + if (!(*fs->get_blocks)(fs, ino, blocks))
160.1033 + return 0;
160.1034 + }
160.1035 + retval = ext2fs_read_inode(fs, ino, &inode);
160.1036 + if (retval)
160.1037 + return retval;
160.1038 + for (i=0; i < EXT2_N_BLOCKS; i++)
160.1039 + blocks[i] = inode.i_block[i];
160.1040 + return 0;
160.1041 +}
160.1042 +
160.1043 +errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino)
160.1044 +{
160.1045 + struct ext2_inode inode;
160.1046 + errcode_t retval;
160.1047 +
160.1048 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
160.1049 +
160.1050 + if (ino > fs->super->s_inodes_count)
160.1051 + return EXT2_ET_BAD_INODE_NUM;
160.1052 +
160.1053 + if (fs->check_directory) {
160.1054 + retval = (fs->check_directory)(fs, ino);
160.1055 + if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
160.1056 + return retval;
160.1057 + }
160.1058 + retval = ext2fs_read_inode(fs, ino, &inode);
160.1059 + if (retval)
160.1060 + return retval;
160.1061 + if (!LINUX_S_ISDIR(inode.i_mode))
160.1062 + return EXT2_ET_NO_DIRECTORY;
160.1063 + return 0;
160.1064 +}
160.1065 +
161.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
161.2 +++ b/libext2fs/lib/libext2fs/inode_io.c Wed Aug 25 01:28:08 2021 +0200
161.3 @@ -0,0 +1,290 @@
161.4 +/*
161.5 + * inode_io.c --- This is allows an inode in an ext2 filesystem image
161.6 + * to be accessed via the I/O manager interface.
161.7 + *
161.8 + * Copyright (C) 2002 Theodore Ts'o.
161.9 + *
161.10 + * %Begin-Header%
161.11 + * This file may be redistributed under the terms of the GNU Library
161.12 + * General Public License, version 2.
161.13 + * %End-Header%
161.14 + */
161.15 +
161.16 +#include "config.h"
161.17 +#include <stdio.h>
161.18 +#include <string.h>
161.19 +#if HAVE_UNISTD_H
161.20 +#include <unistd.h>
161.21 +#endif
161.22 +#if HAVE_ERRNO_H
161.23 +#include <errno.h>
161.24 +#endif
161.25 +#include <time.h>
161.26 +
161.27 +#include "ext2_fs.h"
161.28 +#include "ext2fs.h"
161.29 +
161.30 +/*
161.31 + * For checking structure magic numbers...
161.32 + */
161.33 +
161.34 +#define EXT2_CHECK_MAGIC(struct, code) \
161.35 + if ((struct)->magic != (code)) return (code)
161.36 +
161.37 +struct inode_private_data {
161.38 + int magic;
161.39 + char name[32];
161.40 + ext2_file_t file;
161.41 + ext2_filsys fs;
161.42 + ext2_ino_t ino;
161.43 + struct ext2_inode inode;
161.44 + int flags;
161.45 + struct inode_private_data *next;
161.46 +};
161.47 +
161.48 +#define CHANNEL_HAS_INODE 0x8000
161.49 +
161.50 +static struct inode_private_data *top_intern;
161.51 +static int ino_unique = 0;
161.52 +
161.53 +static errcode_t inode_open(const char *name, int flags, io_channel *channel);
161.54 +static errcode_t inode_close(io_channel channel);
161.55 +static errcode_t inode_set_blksize(io_channel channel, int blksize);
161.56 +static errcode_t inode_read_blk(io_channel channel, unsigned long block,
161.57 + int count, void *data);
161.58 +static errcode_t inode_write_blk(io_channel channel, unsigned long block,
161.59 + int count, const void *data);
161.60 +static errcode_t inode_flush(io_channel channel);
161.61 +static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
161.62 + int size, const void *data);
161.63 +static errcode_t inode_read_blk64(io_channel channel,
161.64 + unsigned long long block, int count, void *data);
161.65 +static errcode_t inode_write_blk64(io_channel channel,
161.66 + unsigned long long block, int count, const void *data);
161.67 +
161.68 +static struct struct_io_manager struct_inode_manager = {
161.69 + .magic = EXT2_ET_MAGIC_IO_MANAGER,
161.70 + .name = "Inode I/O Manager",
161.71 + .open = inode_open,
161.72 + .close = inode_close,
161.73 + .set_blksize = inode_set_blksize,
161.74 + .read_blk = inode_read_blk,
161.75 + .write_blk = inode_write_blk,
161.76 + .flush = inode_flush,
161.77 + .write_byte = inode_write_byte,
161.78 + .read_blk64 = inode_read_blk64,
161.79 + .write_blk64 = inode_write_blk64
161.80 +};
161.81 +
161.82 +io_manager inode_io_manager = &struct_inode_manager;
161.83 +
161.84 +errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
161.85 + struct ext2_inode *inode,
161.86 + char **name)
161.87 +{
161.88 + struct inode_private_data *data;
161.89 + errcode_t retval;
161.90 +
161.91 + if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data),
161.92 + &data)))
161.93 + return retval;
161.94 + data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL;
161.95 + sprintf(data->name, "%u:%d", ino, ino_unique++);
161.96 + data->file = 0;
161.97 + data->fs = fs;
161.98 + data->ino = ino;
161.99 + data->flags = 0;
161.100 + if (inode) {
161.101 + memcpy(&data->inode, inode, sizeof(struct ext2_inode));
161.102 + data->flags |= CHANNEL_HAS_INODE;
161.103 + }
161.104 + data->next = top_intern;
161.105 + top_intern = data;
161.106 + *name = data->name;
161.107 + return 0;
161.108 +}
161.109 +
161.110 +errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
161.111 + char **name)
161.112 +{
161.113 + return ext2fs_inode_io_intern2(fs, ino, NULL, name);
161.114 +}
161.115 +
161.116 +
161.117 +static errcode_t inode_open(const char *name, int flags, io_channel *channel)
161.118 +{
161.119 + io_channel io = NULL;
161.120 + struct inode_private_data *prev, *data = NULL;
161.121 + errcode_t retval;
161.122 + int open_flags;
161.123 +
161.124 + if (name == 0)
161.125 + return EXT2_ET_BAD_DEVICE_NAME;
161.126 +
161.127 + for (data = top_intern, prev = NULL; data;
161.128 + prev = data, data = data->next)
161.129 + if (strcmp(name, data->name) == 0)
161.130 + break;
161.131 + if (!data)
161.132 + return ENOENT;
161.133 + if (prev)
161.134 + prev->next = data->next;
161.135 + else
161.136 + top_intern = data->next;
161.137 +
161.138 + retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
161.139 + if (retval)
161.140 + goto cleanup;
161.141 + memset(io, 0, sizeof(struct struct_io_channel));
161.142 +
161.143 + io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
161.144 + io->manager = inode_io_manager;
161.145 + retval = ext2fs_get_mem(strlen(name)+1, &io->name);
161.146 + if (retval)
161.147 + goto cleanup;
161.148 +
161.149 + strcpy(io->name, name);
161.150 + io->private_data = data;
161.151 + io->block_size = 1024;
161.152 + io->read_error = 0;
161.153 + io->write_error = 0;
161.154 + io->refcount = 1;
161.155 +
161.156 + open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
161.157 + retval = ext2fs_file_open2(data->fs, data->ino,
161.158 + (data->flags & CHANNEL_HAS_INODE) ?
161.159 + &data->inode : 0, open_flags,
161.160 + &data->file);
161.161 + if (retval)
161.162 + goto cleanup;
161.163 +
161.164 + *channel = io;
161.165 + return 0;
161.166 +
161.167 +cleanup:
161.168 + if (io && io->name)
161.169 + ext2fs_free_mem(&io->name);
161.170 + if (data)
161.171 + ext2fs_free_mem(&data);
161.172 + if (io)
161.173 + ext2fs_free_mem(&io);
161.174 + return retval;
161.175 +}
161.176 +
161.177 +static errcode_t inode_close(io_channel channel)
161.178 +{
161.179 + struct inode_private_data *data;
161.180 + errcode_t retval = 0;
161.181 +
161.182 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
161.183 + data = (struct inode_private_data *) channel->private_data;
161.184 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
161.185 +
161.186 + if (--channel->refcount > 0)
161.187 + return 0;
161.188 +
161.189 + retval = ext2fs_file_close(data->file);
161.190 +
161.191 + ext2fs_free_mem(&channel->private_data);
161.192 + if (channel->name)
161.193 + ext2fs_free_mem(&channel->name);
161.194 + ext2fs_free_mem(&channel);
161.195 + return retval;
161.196 +}
161.197 +
161.198 +static errcode_t inode_set_blksize(io_channel channel, int blksize)
161.199 +{
161.200 + struct inode_private_data *data;
161.201 +
161.202 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
161.203 + data = (struct inode_private_data *) channel->private_data;
161.204 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
161.205 +
161.206 + channel->block_size = blksize;
161.207 + return 0;
161.208 +}
161.209 +
161.210 +
161.211 +static errcode_t inode_read_blk64(io_channel channel,
161.212 + unsigned long long block, int count, void *buf)
161.213 +{
161.214 + struct inode_private_data *data;
161.215 + errcode_t retval;
161.216 +
161.217 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
161.218 + data = (struct inode_private_data *) channel->private_data;
161.219 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
161.220 +
161.221 + if ((retval = ext2fs_file_lseek(data->file,
161.222 + block * channel->block_size,
161.223 + EXT2_SEEK_SET, 0)))
161.224 + return retval;
161.225 +
161.226 + count = (count < 0) ? -count : (count * channel->block_size);
161.227 +
161.228 + return ext2fs_file_read(data->file, buf, count, 0);
161.229 +}
161.230 +
161.231 +static errcode_t inode_read_blk(io_channel channel, unsigned long block,
161.232 + int count, void *buf)
161.233 +{
161.234 + return inode_read_blk64(channel, block, count, buf);
161.235 +}
161.236 +
161.237 +static errcode_t inode_write_blk64(io_channel channel,
161.238 + unsigned long long block, int count, const void *buf)
161.239 +{
161.240 + struct inode_private_data *data;
161.241 + errcode_t retval;
161.242 +
161.243 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
161.244 + data = (struct inode_private_data *) channel->private_data;
161.245 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
161.246 +
161.247 + if ((retval = ext2fs_file_lseek(data->file,
161.248 + block * channel->block_size,
161.249 + EXT2_SEEK_SET, 0)))
161.250 + return retval;
161.251 +
161.252 + count = (count < 0) ? -count : (count * channel->block_size);
161.253 +
161.254 + return ext2fs_file_write(data->file, buf, count, 0);
161.255 +}
161.256 +
161.257 +static errcode_t inode_write_blk(io_channel channel, unsigned long block,
161.258 + int count, const void *buf)
161.259 +{
161.260 + return inode_write_blk64(channel, block, count, buf);
161.261 +}
161.262 +
161.263 +static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
161.264 + int size, const void *buf)
161.265 +{
161.266 + struct inode_private_data *data;
161.267 + errcode_t retval = 0;
161.268 +
161.269 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
161.270 + data = (struct inode_private_data *) channel->private_data;
161.271 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
161.272 +
161.273 + if ((retval = ext2fs_file_lseek(data->file, offset,
161.274 + EXT2_SEEK_SET, 0)))
161.275 + return retval;
161.276 +
161.277 + return ext2fs_file_write(data->file, buf, size, 0);
161.278 +}
161.279 +
161.280 +/*
161.281 + * Flush data buffers to disk.
161.282 + */
161.283 +static errcode_t inode_flush(io_channel channel)
161.284 +{
161.285 + struct inode_private_data *data;
161.286 +
161.287 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
161.288 + data = (struct inode_private_data *) channel->private_data;
161.289 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
161.290 +
161.291 + return ext2fs_file_flush(data->file);
161.292 +}
161.293 +
162.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
162.2 +++ b/libext2fs/lib/libext2fs/io_manager.c Wed Aug 25 01:28:08 2021 +0200
162.3 @@ -0,0 +1,150 @@
162.4 +/*
162.5 + * io_manager.c --- the I/O manager abstraction
162.6 + */
162.7 +
162.8 +#include "config.h"
162.9 +#include <stdio.h>
162.10 +#include <string.h>
162.11 +#if HAVE_UNISTD_H
162.12 +#include <unistd.h>
162.13 +#endif
162.14 +#include <fcntl.h>
162.15 +#include <time.h>
162.16 +#if HAVE_SYS_STAT_H
162.17 +#include <sys/stat.h>
162.18 +#endif
162.19 +#if HAVE_SYS_TYPES_H
162.20 +#include <sys/types.h>
162.21 +#endif
162.22 +
162.23 +#include "ext2_fs.h"
162.24 +#include "ext2fs.h"
162.25 +
162.26 +errcode_t io_channel_set_options(io_channel channel, const char *opts)
162.27 +{
162.28 + errcode_t retval = 0;
162.29 + char *next, *ptr, *options, *arg;
162.30 +
162.31 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
162.32 +
162.33 + if (!opts)
162.34 + return 0;
162.35 +
162.36 + if (!channel->manager->set_option)
162.37 + return EXT2_ET_INVALID_ARGUMENT;
162.38 +
162.39 + options = malloc(strlen(opts)+1);
162.40 + if (!options)
162.41 + return EXT2_ET_NO_MEMORY;
162.42 + strcpy(options, opts);
162.43 + ptr = options;
162.44 +
162.45 + while (ptr && *ptr) {
162.46 + next = strchr(ptr, '&');
162.47 + if (next)
162.48 + *next++ = 0;
162.49 +
162.50 + arg = strchr(ptr, '=');
162.51 + if (arg)
162.52 + *arg++ = 0;
162.53 +
162.54 + retval = (channel->manager->set_option)(channel, ptr, arg);
162.55 + if (retval)
162.56 + break;
162.57 + ptr = next;
162.58 + }
162.59 + free(options);
162.60 + return retval;
162.61 +}
162.62 +
162.63 +errcode_t io_channel_write_byte(io_channel channel, unsigned long offset,
162.64 + int count, const void *data)
162.65 +{
162.66 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
162.67 +
162.68 + if (channel->manager->write_byte)
162.69 + return channel->manager->write_byte(channel, offset,
162.70 + count, data);
162.71 +
162.72 + return EXT2_ET_UNIMPLEMENTED;
162.73 +}
162.74 +
162.75 +errcode_t io_channel_read_blk64(io_channel channel, unsigned long long block,
162.76 + int count, void *data)
162.77 +{
162.78 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
162.79 +
162.80 + if (channel->manager->read_blk64)
162.81 + return (channel->manager->read_blk64)(channel, block,
162.82 + count, data);
162.83 +
162.84 + if ((block >> 32) != 0)
162.85 + return EXT2_ET_IO_CHANNEL_NO_SUPPORT_64;
162.86 +
162.87 + return (channel->manager->read_blk)(channel, (unsigned long) block,
162.88 + count, data);
162.89 +}
162.90 +
162.91 +errcode_t io_channel_write_blk64(io_channel channel, unsigned long long block,
162.92 + int count, const void *data)
162.93 +{
162.94 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
162.95 +
162.96 + if (channel->manager->write_blk64)
162.97 + return (channel->manager->write_blk64)(channel, block,
162.98 + count, data);
162.99 +
162.100 + if ((block >> 32) != 0)
162.101 + return EXT2_ET_IO_CHANNEL_NO_SUPPORT_64;
162.102 +
162.103 + return (channel->manager->write_blk)(channel, (unsigned long) block,
162.104 + count, data);
162.105 +}
162.106 +
162.107 +errcode_t io_channel_discard(io_channel channel, unsigned long long block,
162.108 + unsigned long long count)
162.109 +{
162.110 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
162.111 +
162.112 + if (channel->manager->discard)
162.113 + return (channel->manager->discard)(channel, block, count);
162.114 +
162.115 + return EXT2_ET_UNIMPLEMENTED;
162.116 +}
162.117 +
162.118 +errcode_t io_channel_zeroout(io_channel channel, unsigned long long block,
162.119 + unsigned long long count)
162.120 +{
162.121 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
162.122 +
162.123 + if (channel->manager->zeroout)
162.124 + return (channel->manager->zeroout)(channel, block, count);
162.125 +
162.126 + return EXT2_ET_UNIMPLEMENTED;
162.127 +}
162.128 +
162.129 +errcode_t io_channel_alloc_buf(io_channel io, int count, void *ptr)
162.130 +{
162.131 + size_t size;
162.132 +
162.133 + if (count == 0)
162.134 + size = io->block_size;
162.135 + else if (count > 0)
162.136 + size = io->block_size * count;
162.137 + else
162.138 + size = -count;
162.139 +
162.140 + if (io->align)
162.141 + return ext2fs_get_memalign(size, io->align, ptr);
162.142 + else
162.143 + return ext2fs_get_mem(size, ptr);
162.144 +}
162.145 +
162.146 +errcode_t io_channel_cache_readahead(io_channel io, unsigned long long block,
162.147 + unsigned long long count)
162.148 +{
162.149 + if (!io->manager->cache_readahead)
162.150 + return EXT2_ET_OP_NOT_SUPPORTED;
162.151 +
162.152 + return io->manager->cache_readahead(io, block, count);
162.153 +}
163.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
163.2 +++ b/libext2fs/lib/libext2fs/irel.h Wed Aug 25 01:28:08 2021 +0200
163.3 @@ -0,0 +1,114 @@
163.4 +/*
163.5 + * irel.h
163.6 + *
163.7 + * Copyright (C) 1996, 1997 Theodore Ts'o.
163.8 + *
163.9 + * %Begin-Header%
163.10 + * This file may be redistributed under the terms of the GNU Library
163.11 + * General Public License, version 2.
163.12 + * %End-Header%
163.13 + */
163.14 +
163.15 +struct ext2_inode_reference {
163.16 + blk64_t block;
163.17 + __u16 offset;
163.18 +};
163.19 +
163.20 +struct ext2_inode_relocate_entry {
163.21 + ext2_ino_t new;
163.22 + ext2_ino_t orig;
163.23 + __u16 flags;
163.24 + __u16 max_refs;
163.25 +};
163.26 +
163.27 +typedef struct ext2_inode_relocation_table *ext2_irel;
163.28 +
163.29 +struct ext2_inode_relocation_table {
163.30 + __u32 magic;
163.31 + char *name;
163.32 + ext2_ino_t current;
163.33 + void *priv_data;
163.34 +
163.35 + /*
163.36 + * Add an inode relocation entry.
163.37 + */
163.38 + errcode_t (*put)(ext2_irel irel, ext2_ino_t old,
163.39 + struct ext2_inode_relocate_entry *ent);
163.40 + /*
163.41 + * Get an inode relocation entry.
163.42 + */
163.43 + errcode_t (*get)(ext2_irel irel, ext2_ino_t old,
163.44 + struct ext2_inode_relocate_entry *ent);
163.45 +
163.46 + /*
163.47 + * Get an inode relocation entry by its original inode number
163.48 + */
163.49 + errcode_t (*get_by_orig)(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
163.50 + struct ext2_inode_relocate_entry *ent);
163.51 +
163.52 + /*
163.53 + * Initialize for iterating over the inode relocation entries.
163.54 + */
163.55 + errcode_t (*start_iter)(ext2_irel irel);
163.56 +
163.57 + /*
163.58 + * The iterator function for the inode relocation entries.
163.59 + * Returns an inode number of 0 when out of entries.
163.60 + */
163.61 + errcode_t (*next)(ext2_irel irel, ext2_ino_t *old,
163.62 + struct ext2_inode_relocate_entry *ent);
163.63 +
163.64 + /*
163.65 + * Add an inode reference (i.e., note the fact that a
163.66 + * particular block/offset contains a reference to an inode)
163.67 + */
163.68 + errcode_t (*add_ref)(ext2_irel irel, ext2_ino_t ino,
163.69 + struct ext2_inode_reference *ref);
163.70 +
163.71 + /*
163.72 + * Initialize for iterating over the inode references for a
163.73 + * particular inode.
163.74 + */
163.75 + errcode_t (*start_iter_ref)(ext2_irel irel, ext2_ino_t ino);
163.76 +
163.77 + /*
163.78 + * The iterator function for the inode references for an
163.79 + * inode. The references for only one inode can be interator
163.80 + * over at a time, as the iterator state is stored in ext2_irel.
163.81 + */
163.82 + errcode_t (*next_ref)(ext2_irel irel,
163.83 + struct ext2_inode_reference *ref);
163.84 +
163.85 + /*
163.86 + * Move the inode relocation table from one inode number to
163.87 + * another. Note that the inode references also must move.
163.88 + */
163.89 + errcode_t (*move)(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
163.90 +
163.91 + /*
163.92 + * Remove an inode relocation entry, along with all of the
163.93 + * inode references.
163.94 + */
163.95 + errcode_t (*delete)(ext2_irel irel, ext2_ino_t old);
163.96 +
163.97 + /*
163.98 + * Free the inode relocation table.
163.99 + */
163.100 + errcode_t (*free)(ext2_irel irel);
163.101 +};
163.102 +
163.103 +errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
163.104 + ext2_irel *irel);
163.105 +
163.106 +#define ext2fs_irel_put(irel, old, ent) ((irel)->put((irel), old, ent))
163.107 +#define ext2fs_irel_get(irel, old, ent) ((irel)->get((irel), old, ent))
163.108 +#define ext2fs_irel_get_by_orig(irel, orig, old, ent) \
163.109 + ((irel)->get_by_orig((irel), orig, old, ent))
163.110 +#define ext2fs_irel_start_iter(irel) ((irel)->start_iter((irel)))
163.111 +#define ext2fs_irel_next(irel, old, ent) ((irel)->next((irel), old, ent))
163.112 +#define ext2fs_irel_add_ref(irel, ino, ref) ((irel)->add_ref((irel), ino, ref))
163.113 +#define ext2fs_irel_start_iter_ref(irel, ino) ((irel)->start_iter_ref((irel), ino))
163.114 +#define ext2fs_irel_next_ref(irel, ref) ((irel)->next_ref((irel), ref))
163.115 +#define ext2fs_irel_move(irel, old, new) ((irel)->move((irel), old, new))
163.116 +#define ext2fs_irel_delete(irel, old) ((irel)->delete((irel), old))
163.117 +#define ext2fs_irel_free(irel) ((irel)->free((irel)))
164.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
164.2 +++ b/libext2fs/lib/libext2fs/ismounted.c Wed Aug 25 01:28:08 2021 +0200
164.3 @@ -0,0 +1,468 @@
164.4 +/*
164.5 + * ismounted.c --- Check to see if the filesystem was mounted
164.6 + *
164.7 + * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o.
164.8 + *
164.9 + * %Begin-Header%
164.10 + * This file may be redistributed under the terms of the GNU Library
164.11 + * General Public License, version 2.
164.12 + * %End-Header%
164.13 + */
164.14 +
164.15 +/* define BSD_SOURCE to make sure we get the major() macro */
164.16 +#ifndef _BSD_SOURCE
164.17 +#define _BSD_SOURCE
164.18 +#endif
164.19 +#ifndef _DEFAULT_SOURCE
164.20 +#define _DEFAULT_SOURCE /* since glibc 2.20 _SVID_SOURCE is deprecated */
164.21 +#endif
164.22 +
164.23 +#include "config.h"
164.24 +#include <stdio.h>
164.25 +#if HAVE_UNISTD_H
164.26 +#include <unistd.h>
164.27 +#endif
164.28 +#if HAVE_ERRNO_H
164.29 +#include <errno.h>
164.30 +#endif
164.31 +#include <fcntl.h>
164.32 +#ifdef HAVE_LINUX_FD_H
164.33 +#include <linux/fd.h>
164.34 +#endif
164.35 +#ifdef HAVE_LINUX_LOOP_H
164.36 +#include <linux/loop.h>
164.37 +#include <sys/ioctl.h>
164.38 +#ifdef HAVE_LINUX_MAJOR_H
164.39 +#include <linux/major.h>
164.40 +#endif /* HAVE_LINUX_MAJOR_H */
164.41 +#endif /* HAVE_LINUX_LOOP_H */
164.42 +#ifdef HAVE_MNTENT_H
164.43 +#include <mntent.h>
164.44 +#endif
164.45 +#ifdef HAVE_GETMNTINFO
164.46 +#include <paths.h>
164.47 +#include <sys/param.h>
164.48 +#include <sys/mount.h>
164.49 +#endif /* HAVE_GETMNTINFO */
164.50 +#include <string.h>
164.51 +#include <sys/stat.h>
164.52 +#if HAVE_SYS_TYPES_H
164.53 +#include <sys/types.h>
164.54 +#endif
164.55 +#ifdef HAVE_SYS_SYSMACROS_H
164.56 +#include <sys/sysmacros.h>
164.57 +#endif
164.58 +
164.59 +#include "ext2_fs.h"
164.60 +#include "ext2fs.h"
164.61 +#include "ext2fsP.h"
164.62 +
164.63 +#ifdef HAVE_SETMNTENT
164.64 +/*
164.65 + * Check to see if a regular file is mounted.
164.66 + * If /etc/mtab/ is a symlink of /proc/mounts, you will need the following check
164.67 + * because the name in /proc/mounts is a loopback device not a regular file.
164.68 + */
164.69 +static int check_loop_mounted(const char *mnt_fsname, dev_t mnt_rdev,
164.70 + dev_t file_dev, ino_t file_ino)
164.71 +{
164.72 +#if defined(HAVE_LINUX_LOOP_H) && defined(HAVE_LINUX_MAJOR_H)
164.73 + struct loop_info64 loopinfo = {0, };
164.74 + int loop_fd, ret;
164.75 +
164.76 + if (major(mnt_rdev) == LOOP_MAJOR) {
164.77 + loop_fd = open(mnt_fsname, O_RDONLY);
164.78 + if (loop_fd < 0)
164.79 + return -1;
164.80 +
164.81 + ret = ioctl(loop_fd, LOOP_GET_STATUS64, &loopinfo);
164.82 + close(loop_fd);
164.83 + if (ret < 0)
164.84 + return -1;
164.85 +
164.86 + if (file_dev == loopinfo.lo_device &&
164.87 + file_ino == loopinfo.lo_inode)
164.88 + return 1;
164.89 + }
164.90 +#endif /* defined(HAVE_LINUX_LOOP_H) && defined(HAVE_LINUX_MAJOR_H) */
164.91 + return 0;
164.92 +}
164.93 +
164.94 +/*
164.95 + * Helper function which checks a file in /etc/mtab format to see if a
164.96 + * filesystem is mounted. Returns an error if the file doesn't exist
164.97 + * or can't be opened.
164.98 + */
164.99 +static errcode_t check_mntent_file(const char *mtab_file, const char *file,
164.100 + int *mount_flags, char *mtpt, int mtlen)
164.101 +{
164.102 + struct mntent *mnt;
164.103 + struct stat st_buf;
164.104 + errcode_t retval = 0;
164.105 + dev_t file_dev=0, file_rdev=0;
164.106 + ino_t file_ino=0;
164.107 + FILE *f;
164.108 + int fd;
164.109 +
164.110 + *mount_flags = 0;
164.111 +
164.112 + if ((f = setmntent (mtab_file, "r")) == NULL) {
164.113 + if (errno == ENOENT) {
164.114 + if (getenv("EXT2FS_NO_MTAB_OK"))
164.115 + return 0;
164.116 + else
164.117 + return EXT2_ET_NO_MTAB_FILE;
164.118 + }
164.119 + return errno;
164.120 + }
164.121 + if (stat(file, &st_buf) == 0) {
164.122 + if (ext2fsP_is_disk_device(st_buf.st_mode)) {
164.123 +#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
164.124 + file_rdev = st_buf.st_rdev;
164.125 +#endif /* __GNU__ */
164.126 + } else {
164.127 + file_dev = st_buf.st_dev;
164.128 + file_ino = st_buf.st_ino;
164.129 + }
164.130 + }
164.131 + while ((mnt = getmntent (f)) != NULL) {
164.132 + if (mnt->mnt_fsname[0] != '/')
164.133 + continue;
164.134 + if (strcmp(file, mnt->mnt_fsname) == 0)
164.135 + break;
164.136 + if (stat(mnt->mnt_fsname, &st_buf) == 0) {
164.137 + if (ext2fsP_is_disk_device(st_buf.st_mode)) {
164.138 +#ifndef __GNU__
164.139 + if (file_rdev && (file_rdev == st_buf.st_rdev))
164.140 + break;
164.141 + if (check_loop_mounted(mnt->mnt_fsname,
164.142 + st_buf.st_rdev, file_dev,
164.143 + file_ino) == 1)
164.144 + break;
164.145 +#endif /* __GNU__ */
164.146 + } else {
164.147 + if (file_dev && ((file_dev == st_buf.st_dev) &&
164.148 + (file_ino == st_buf.st_ino)))
164.149 + break;
164.150 + }
164.151 + }
164.152 + }
164.153 +
164.154 + if (mnt == 0) {
164.155 +#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
164.156 + /*
164.157 + * Do an extra check to see if this is the root device. We
164.158 + * can't trust /etc/mtab, and /proc/mounts will only list
164.159 + * /dev/root for the root filesystem. Argh. Instead we
164.160 + * check if the given device has the same major/minor number
164.161 + * as the device that the root directory is on.
164.162 + */
164.163 + if (file_rdev && stat("/", &st_buf) == 0) {
164.164 + if (st_buf.st_dev == file_rdev) {
164.165 + *mount_flags = EXT2_MF_MOUNTED;
164.166 + if (mtpt)
164.167 + strncpy(mtpt, "/", mtlen);
164.168 + goto is_root;
164.169 + }
164.170 + }
164.171 +#endif /* __GNU__ */
164.172 + goto errout;
164.173 + }
164.174 +#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
164.175 + /* Validate the entry in case /etc/mtab is out of date */
164.176 + /*
164.177 + * We need to be paranoid, because some broken distributions
164.178 + * (read: Slackware) don't initialize /etc/mtab before checking
164.179 + * all of the non-root filesystems on the disk.
164.180 + */
164.181 + if (stat(mnt->mnt_dir, &st_buf) < 0) {
164.182 + retval = errno;
164.183 + if (retval == ENOENT) {
164.184 +#ifdef DEBUG
164.185 + printf("Bogus entry in %s! (%s does not exist)\n",
164.186 + mtab_file, mnt->mnt_dir);
164.187 +#endif /* DEBUG */
164.188 + retval = 0;
164.189 + }
164.190 + goto errout;
164.191 + }
164.192 + if (file_rdev && (st_buf.st_dev != file_rdev)) {
164.193 +#ifdef DEBUG
164.194 + printf("Bogus entry in %s! (%s not mounted on %s)\n",
164.195 + mtab_file, file, mnt->mnt_dir);
164.196 +#endif /* DEBUG */
164.197 + goto errout;
164.198 + }
164.199 +#endif /* __GNU__ */
164.200 + *mount_flags = EXT2_MF_MOUNTED;
164.201 +
164.202 +#ifdef MNTOPT_RO
164.203 + /* Check to see if the ro option is set */
164.204 + if (hasmntopt(mnt, MNTOPT_RO))
164.205 + *mount_flags |= EXT2_MF_READONLY;
164.206 +#endif
164.207 +
164.208 + if (mtpt)
164.209 + strncpy(mtpt, mnt->mnt_dir, mtlen);
164.210 + /*
164.211 + * Check to see if we're referring to the root filesystem.
164.212 + * If so, do a manual check to see if we can open /etc/mtab
164.213 + * read/write, since if the root is mounted read/only, the
164.214 + * contents of /etc/mtab may not be accurate.
164.215 + */
164.216 + if (!strcmp(mnt->mnt_dir, "/")) {
164.217 +is_root:
164.218 +#define TEST_FILE "/.ismount-test-file"
164.219 + *mount_flags |= EXT2_MF_ISROOT;
164.220 + fd = open(TEST_FILE, O_RDWR|O_CREAT, 0600);
164.221 + if (fd < 0) {
164.222 + if (errno == EROFS)
164.223 + *mount_flags |= EXT2_MF_READONLY;
164.224 + } else
164.225 + close(fd);
164.226 + (void) unlink(TEST_FILE);
164.227 + }
164.228 + retval = 0;
164.229 +errout:
164.230 + endmntent (f);
164.231 + return retval;
164.232 +}
164.233 +
164.234 +static errcode_t check_mntent(const char *file, int *mount_flags,
164.235 + char *mtpt, int mtlen)
164.236 +{
164.237 + errcode_t retval;
164.238 +
164.239 +#ifdef DEBUG
164.240 + retval = check_mntent_file("/tmp/mtab", file, mount_flags,
164.241 + mtpt, mtlen);
164.242 + if (retval == 0)
164.243 + return 0;
164.244 +#endif /* DEBUG */
164.245 +#ifdef __linux__
164.246 + retval = check_mntent_file("/proc/mounts", file, mount_flags,
164.247 + mtpt, mtlen);
164.248 + if (retval == 0 && (*mount_flags != 0))
164.249 + return 0;
164.250 +#endif /* __linux__ */
164.251 +#if defined(MOUNTED) || defined(_PATH_MOUNTED)
164.252 +#ifndef MOUNTED
164.253 +#define MOUNTED _PATH_MOUNTED
164.254 +#endif /* MOUNTED */
164.255 + retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen);
164.256 + return retval;
164.257 +#else
164.258 + *mount_flags = 0;
164.259 + return 0;
164.260 +#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
164.261 +}
164.262 +
164.263 +#else
164.264 +#if defined(HAVE_GETMNTINFO)
164.265 +
164.266 +static errcode_t check_getmntinfo(const char *file, int *mount_flags,
164.267 + char *mtpt, int mtlen)
164.268 +{
164.269 + struct statfs *mp;
164.270 + int len, n;
164.271 + const char *s1;
164.272 + char *s2;
164.273 +
164.274 + n = getmntinfo(&mp, MNT_NOWAIT);
164.275 + if (n == 0)
164.276 + return errno;
164.277 +
164.278 + len = sizeof(_PATH_DEV) - 1;
164.279 + s1 = file;
164.280 + if (strncmp(_PATH_DEV, s1, len) == 0)
164.281 + s1 += len;
164.282 +
164.283 + *mount_flags = 0;
164.284 + while (--n >= 0) {
164.285 + s2 = mp->f_mntfromname;
164.286 + if (strncmp(_PATH_DEV, s2, len) == 0) {
164.287 + s2 += len - 1;
164.288 + *s2 = 'r';
164.289 + }
164.290 + if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
164.291 + *mount_flags = EXT2_MF_MOUNTED;
164.292 + break;
164.293 + }
164.294 + ++mp;
164.295 + }
164.296 + if (mtpt)
164.297 + strncpy(mtpt, mp->f_mntonname, mtlen);
164.298 + return 0;
164.299 +}
164.300 +#endif /* HAVE_GETMNTINFO */
164.301 +#endif /* HAVE_SETMNTENT */
164.302 +
164.303 +/*
164.304 + * Check to see if we're dealing with the swap device.
164.305 + */
164.306 +static int is_swap_device(const char *file)
164.307 +{
164.308 + FILE *f;
164.309 + char buf[1024], *cp;
164.310 + dev_t file_dev;
164.311 + struct stat st_buf;
164.312 + int ret = 0;
164.313 +
164.314 + file_dev = 0;
164.315 +#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
164.316 + if ((stat(file, &st_buf) == 0) &&
164.317 + ext2fsP_is_disk_device(st_buf.st_mode))
164.318 + file_dev = st_buf.st_rdev;
164.319 +#endif /* __GNU__ */
164.320 +
164.321 + if (!(f = fopen("/proc/swaps", "r")))
164.322 + return 0;
164.323 + /* Skip the first line */
164.324 + if (!fgets(buf, sizeof(buf), f))
164.325 + goto leave;
164.326 + if (*buf && strncmp(buf, "Filename\t", 9))
164.327 + /* Linux <=2.6.19 contained a bug in the /proc/swaps
164.328 + * code where the header would not be displayed
164.329 + */
164.330 + goto valid_first_line;
164.331 +
164.332 + while (fgets(buf, sizeof(buf), f)) {
164.333 +valid_first_line:
164.334 + if ((cp = strchr(buf, ' ')) != NULL)
164.335 + *cp = 0;
164.336 + if ((cp = strchr(buf, '\t')) != NULL)
164.337 + *cp = 0;
164.338 + if (strcmp(buf, file) == 0) {
164.339 + ret++;
164.340 + break;
164.341 + }
164.342 +#ifndef __GNU__
164.343 + if (file_dev && (stat(buf, &st_buf) == 0) &&
164.344 + ext2fsP_is_disk_device(st_buf.st_mode) &&
164.345 + file_dev == st_buf.st_rdev) {
164.346 + ret++;
164.347 + break;
164.348 + }
164.349 +#endif /* __GNU__ */
164.350 + }
164.351 +
164.352 +leave:
164.353 + fclose(f);
164.354 + return ret;
164.355 +}
164.356 +
164.357 +
164.358 +/*
164.359 + * ext2fs_check_mount_point() fills determines if the device is
164.360 + * mounted or otherwise busy, and fills in mount_flags with one or
164.361 + * more of the following flags: EXT2_MF_MOUNTED, EXT2_MF_ISROOT,
164.362 + * EXT2_MF_READONLY, EXT2_MF_SWAP, and EXT2_MF_BUSY. If mtpt is
164.363 + * non-NULL, the directory where the device is mounted is copied to
164.364 + * where mtpt is pointing, up to mtlen characters.
164.365 + */
164.366 +#ifdef __TURBOC__
164.367 + #pragma argsused
164.368 +#endif
164.369 +errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
164.370 + char *mtpt, int mtlen)
164.371 +{
164.372 + errcode_t retval = 0;
164.373 +
164.374 + if (getenv("EXT2FS_PRETEND_RO_MOUNT")) {
164.375 + *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_READONLY;
164.376 + if (getenv("EXT2FS_PRETEND_ROOTFS"))
164.377 + *mount_flags = EXT2_MF_ISROOT;
164.378 + return 0;
164.379 + }
164.380 + if (getenv("EXT2FS_PRETEND_RW_MOUNT")) {
164.381 + *mount_flags = EXT2_MF_MOUNTED;
164.382 + if (getenv("EXT2FS_PRETEND_ROOTFS"))
164.383 + *mount_flags = EXT2_MF_ISROOT;
164.384 + return 0;
164.385 + }
164.386 +
164.387 + if (is_swap_device(device)) {
164.388 + *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP;
164.389 + strncpy(mtpt, "<swap>", mtlen);
164.390 + } else {
164.391 +#ifdef HAVE_SETMNTENT
164.392 + retval = check_mntent(device, mount_flags, mtpt, mtlen);
164.393 +#else
164.394 +#ifdef HAVE_GETMNTINFO
164.395 + retval = check_getmntinfo(device, mount_flags, mtpt, mtlen);
164.396 +#else
164.397 +#ifdef __GNUC__
164.398 + #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
164.399 +#endif
164.400 + *mount_flags = 0;
164.401 +#endif /* HAVE_GETMNTINFO */
164.402 +#endif /* HAVE_SETMNTENT */
164.403 + }
164.404 + if (retval)
164.405 + return retval;
164.406 +
164.407 +#ifdef __linux__ /* This only works on Linux 2.6+ systems */
164.408 + {
164.409 + struct stat st_buf;
164.410 +
164.411 + if (stat(device, &st_buf) == 0 &&
164.412 + ext2fsP_is_disk_device(st_buf.st_mode)) {
164.413 + int fd = open(device, O_RDONLY | O_EXCL);
164.414 +
164.415 + if (fd >= 0)
164.416 + close(fd);
164.417 + else if (errno == EBUSY)
164.418 + *mount_flags |= EXT2_MF_BUSY;
164.419 + }
164.420 + }
164.421 +#endif
164.422 +
164.423 + return 0;
164.424 +}
164.425 +
164.426 +/*
164.427 + * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED,
164.428 + * EXT2_MF_READONLY, and EXT2_MF_ROOT
164.429 + *
164.430 + */
164.431 +errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
164.432 +{
164.433 + return ext2fs_check_mount_point(file, mount_flags, NULL, 0);
164.434 +}
164.435 +
164.436 +#ifdef DEBUG
164.437 +int main(int argc, char **argv)
164.438 +{
164.439 + int retval, mount_flags;
164.440 + char mntpt[80];
164.441 +
164.442 + if (argc < 2) {
164.443 + fprintf(stderr, "Usage: %s device\n", argv[0]);
164.444 + exit(1);
164.445 + }
164.446 +
164.447 + add_error_table(&et_ext2_error_table);
164.448 + mntpt[0] = 0;
164.449 + retval = ext2fs_check_mount_point(argv[1], &mount_flags,
164.450 + mntpt, sizeof(mntpt));
164.451 + if (retval) {
164.452 + com_err(argv[0], retval,
164.453 + "while calling ext2fs_check_if_mounted");
164.454 + exit(1);
164.455 + }
164.456 + printf("Device %s reports flags %02x\n", argv[1], mount_flags);
164.457 + if (mount_flags & EXT2_MF_BUSY)
164.458 + printf("\t%s is apparently in use.\n", argv[1]);
164.459 + if (mount_flags & EXT2_MF_MOUNTED)
164.460 + printf("\t%s is mounted.\n", argv[1]);
164.461 + if (mount_flags & EXT2_MF_SWAP)
164.462 + printf("\t%s is a swap device.\n", argv[1]);
164.463 + if (mount_flags & EXT2_MF_READONLY)
164.464 + printf("\t%s is read-only.\n", argv[1]);
164.465 + if (mount_flags & EXT2_MF_ISROOT)
164.466 + printf("\t%s is the root filesystem.\n", argv[1]);
164.467 + if (mntpt[0])
164.468 + printf("\t%s is mounted on %s.\n", argv[1], mntpt);
164.469 + exit(0);
164.470 +}
164.471 +#endif /* DEBUG */
165.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
165.2 +++ b/libext2fs/lib/libext2fs/jfs_compat.h Wed Aug 25 01:28:08 2021 +0200
165.3 @@ -0,0 +1,99 @@
165.4 +
165.5 +#ifndef _JFS_COMPAT_H
165.6 +#define _JFS_COMPAT_H
165.7 +
165.8 +#include "kernel-list.h"
165.9 +#include <errno.h>
165.10 +#ifdef HAVE_NETINET_IN_H
165.11 +#include <netinet/in.h>
165.12 +#endif
165.13 +#ifdef HAVE_WINSOCK_H
165.14 +#include <winsock.h>
165.15 +#else
165.16 +#include <arpa/inet.h>
165.17 +#endif
165.18 +
165.19 +#define printk printf
165.20 +#define KERN_ERR ""
165.21 +#define KERN_DEBUG ""
165.22 +
165.23 +#define READ 0
165.24 +#define WRITE 1
165.25 +
165.26 +#define cpu_to_be32(n) htonl(n)
165.27 +#define be32_to_cpu(n) ntohl(n)
165.28 +#define cpu_to_be16(n) htons(n)
165.29 +#define be16_to_cpu(n) ntohs(n)
165.30 +
165.31 +typedef unsigned int tid_t;
165.32 +typedef struct journal_s journal_t;
165.33 +typedef struct kdev_s *kdev_t;
165.34 +
165.35 +struct buffer_head;
165.36 +struct inode;
165.37 +
165.38 +#define GFP_KERNEL 0
165.39 +#define JFS_TAG_SIZE32 JBD_TAG_SIZE32
165.40 +#define JFS_BARRIER 0
165.41 +typedef __u64 u64;
165.42 +#define JFS_CRC32_CHKSUM JBD2_CRC32_CHKSUM
165.43 +#define JFS_CRC32_CHKSUM_SIZE JBD2_CRC32_CHKSUM_SIZE
165.44 +#define put_bh(x) brelse(x)
165.45 +#define be64_to_cpu(x) ext2fs_be64_to_cpu(x)
165.46 +
165.47 +static inline __u32 jbd2_chksum(journal_t *j EXT2FS_ATTR((unused)),
165.48 + __u32 crc, const void *address,
165.49 + unsigned int length)
165.50 +{
165.51 + return ext2fs_crc32c_le(crc, address, length);
165.52 +}
165.53 +#define crc32_be(x, y, z) ext2fs_crc32_be((x), (y), (z))
165.54 +#define spin_lock_init(x)
165.55 +#define spin_lock(x)
165.56 +#define spin_unlock(x)
165.57 +#define yield()
165.58 +#define SLAB_HWCACHE_ALIGN 0
165.59 +#define SLAB_TEMPORARY 0
165.60 +#define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\
165.61 + sizeof(struct __struct), __alignof__(struct __struct),\
165.62 + (__flags), NULL)
165.63 +
165.64 +#define blkdev_issue_flush(kdev, a, b) sync_blockdev(kdev)
165.65 +#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
165.66 +
165.67 +struct journal_s
165.68 +{
165.69 + unsigned long j_flags;
165.70 + int j_errno;
165.71 + struct buffer_head * j_sb_buffer;
165.72 + struct journal_superblock_s *j_superblock;
165.73 + int j_format_version;
165.74 + unsigned long j_head;
165.75 + unsigned long j_tail;
165.76 + unsigned long j_free;
165.77 + unsigned long j_first, j_last;
165.78 + kdev_t j_dev;
165.79 + kdev_t j_fs_dev;
165.80 + int j_blocksize;
165.81 + unsigned int j_blk_offset;
165.82 + unsigned int j_maxlen;
165.83 + struct inode * j_inode;
165.84 + tid_t j_tail_sequence;
165.85 + tid_t j_transaction_sequence;
165.86 + __u8 j_uuid[16];
165.87 + struct jbd2_revoke_table_s *j_revoke;
165.88 + struct jbd2_revoke_table_s *j_revoke_table[2];
165.89 + tid_t j_failed_commit;
165.90 + __u32 j_csum_seed;
165.91 +};
165.92 +
165.93 +#define is_journal_abort(x) 0
165.94 +
165.95 +#define BUFFER_TRACE(bh, info) do {} while (0)
165.96 +
165.97 +/* Need this so we can compile with configure --enable-gcc-wall */
165.98 +#ifdef NO_INLINE_FUNCS
165.99 +#define inline
165.100 +#endif
165.101 +
165.102 +#endif /* _JFS_COMPAT_H */
166.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
166.2 +++ b/libext2fs/lib/libext2fs/kernel-list.h Wed Aug 25 01:28:08 2021 +0200
166.3 @@ -0,0 +1,109 @@
166.4 +#ifndef _LINUX_LIST_H
166.5 +#define _LINUX_LIST_H
166.6 +
166.7 +/*
166.8 + * Simple doubly linked list implementation.
166.9 + *
166.10 + * Some of the internal functions ("__xxx") are useful when
166.11 + * manipulating whole lists rather than single entries, as
166.12 + * sometimes we already know the next/prev entries and we can
166.13 + * generate better code by using them directly rather than
166.14 + * using the generic single-entry routines.
166.15 + */
166.16 +
166.17 +struct list_head {
166.18 + struct list_head *next, *prev;
166.19 +};
166.20 +
166.21 +#define LIST_HEAD_INIT(name) { &(name), &(name) }
166.22 +
166.23 +#define INIT_LIST_HEAD(ptr) do { \
166.24 + (ptr)->next = (ptr); (ptr)->prev = (ptr); \
166.25 +} while (0)
166.26 +
166.27 +#if (!defined(__GNUC__) && !defined(__WATCOMC__))
166.28 +#define __inline__
166.29 +#endif
166.30 +
166.31 +/*
166.32 + * Insert a new entry between two known consecutive entries.
166.33 + *
166.34 + * This is only for internal list manipulation where we know
166.35 + * the prev/next entries already!
166.36 + */
166.37 +static __inline__ void __list_add(struct list_head * new,
166.38 + struct list_head * prev,
166.39 + struct list_head * next)
166.40 +{
166.41 + next->prev = new;
166.42 + new->next = next;
166.43 + new->prev = prev;
166.44 + prev->next = new;
166.45 +}
166.46 +
166.47 +/*
166.48 + * Insert a new entry after the specified head..
166.49 + */
166.50 +static __inline__ void list_add(struct list_head *new, struct list_head *head)
166.51 +{
166.52 + __list_add(new, head, head->next);
166.53 +}
166.54 +
166.55 +/*
166.56 + * Insert a new entry at the tail
166.57 + */
166.58 +static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
166.59 +{
166.60 + __list_add(new, head->prev, head);
166.61 +}
166.62 +
166.63 +/*
166.64 + * Delete a list entry by making the prev/next entries
166.65 + * point to each other.
166.66 + *
166.67 + * This is only for internal list manipulation where we know
166.68 + * the prev/next entries already!
166.69 + */
166.70 +static __inline__ void __list_del(struct list_head * prev,
166.71 + struct list_head * next)
166.72 +{
166.73 + next->prev = prev;
166.74 + prev->next = next;
166.75 +}
166.76 +
166.77 +static __inline__ void list_del(struct list_head *entry)
166.78 +{
166.79 + __list_del(entry->prev, entry->next);
166.80 +}
166.81 +
166.82 +static __inline__ int list_empty(struct list_head *head)
166.83 +{
166.84 + return head->next == head;
166.85 +}
166.86 +
166.87 +/*
166.88 + * Splice in "list" into "head"
166.89 + */
166.90 +static __inline__ void list_splice(struct list_head *list, struct list_head *head)
166.91 +{
166.92 + struct list_head *first = list->next;
166.93 +
166.94 + if (first != list) {
166.95 + struct list_head *last = list->prev;
166.96 + struct list_head *at = head->next;
166.97 +
166.98 + first->prev = head;
166.99 + head->next = first;
166.100 +
166.101 + last->next = at;
166.102 + at->prev = last;
166.103 + }
166.104 +}
166.105 +
166.106 +#define list_entry(ptr, type, member) \
166.107 + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
166.108 +
166.109 +#define list_for_each(pos, head) \
166.110 + for (pos = (head)->next; pos != (head); pos = pos->next)
166.111 +
166.112 +#endif
167.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
167.2 +++ b/libext2fs/lib/libext2fs/link.c Wed Aug 25 01:28:08 2021 +0200
167.3 @@ -0,0 +1,201 @@
167.4 +/*
167.5 + * link.c --- create links in a ext2fs directory
167.6 + *
167.7 + * Copyright (C) 1993, 1994 Theodore Ts'o.
167.8 + *
167.9 + * %Begin-Header%
167.10 + * This file may be redistributed under the terms of the GNU Library
167.11 + * General Public License, version 2.
167.12 + * %End-Header%
167.13 + */
167.14 +
167.15 +#include "config.h"
167.16 +#include <stdio.h>
167.17 +#include <string.h>
167.18 +#if HAVE_UNISTD_H
167.19 +#include <unistd.h>
167.20 +#endif
167.21 +
167.22 +#include "ext2_fs.h"
167.23 +#include "ext2fs.h"
167.24 +
167.25 +struct link_struct {
167.26 + ext2_filsys fs;
167.27 + const char *name;
167.28 + int namelen;
167.29 + ext2_ino_t inode;
167.30 + int flags;
167.31 + int done;
167.32 + unsigned int blocksize;
167.33 + errcode_t err;
167.34 + struct ext2_super_block *sb;
167.35 +};
167.36 +
167.37 +static int link_proc(struct ext2_dir_entry *dirent,
167.38 + int offset,
167.39 + int blocksize,
167.40 + char *buf,
167.41 + void *priv_data)
167.42 +{
167.43 + struct link_struct *ls = (struct link_struct *) priv_data;
167.44 + struct ext2_dir_entry *next;
167.45 + unsigned int rec_len, min_rec_len, curr_rec_len;
167.46 + int ret = 0;
167.47 + int csum_size = 0;
167.48 + struct ext2_dir_entry_tail *t;
167.49 +
167.50 + if (ls->done)
167.51 + return DIRENT_ABORT;
167.52 +
167.53 + rec_len = EXT2_DIR_REC_LEN(ls->namelen);
167.54 +
167.55 + ls->err = ext2fs_get_rec_len(ls->fs, dirent, &curr_rec_len);
167.56 + if (ls->err)
167.57 + return DIRENT_ABORT;
167.58 +
167.59 + if (ext2fs_has_feature_metadata_csum(ls->fs->super))
167.60 + csum_size = sizeof(struct ext2_dir_entry_tail);
167.61 + /*
167.62 + * See if the following directory entry (if any) is unused;
167.63 + * if so, absorb it into this one.
167.64 + */
167.65 + next = (struct ext2_dir_entry *) (buf + offset + curr_rec_len);
167.66 + if ((offset + (int) curr_rec_len < blocksize - (8 + csum_size)) &&
167.67 + (next->inode == 0) &&
167.68 + (offset + (int) curr_rec_len + (int) next->rec_len <= blocksize)) {
167.69 + curr_rec_len += next->rec_len;
167.70 + ls->err = ext2fs_set_rec_len(ls->fs, curr_rec_len, dirent);
167.71 + if (ls->err)
167.72 + return DIRENT_ABORT;
167.73 + ret = DIRENT_CHANGED;
167.74 + }
167.75 +
167.76 + /*
167.77 + * Since ext2fs_link blows away htree data, we need to be
167.78 + * careful -- if metadata_csum is enabled and we're passed in
167.79 + * a dirent that contains htree data, we need to create the
167.80 + * fake entry at the end of the block that hides the checksum.
167.81 + */
167.82 +
167.83 + /* De-convert a dx_node block */
167.84 + if (csum_size &&
167.85 + curr_rec_len == ls->fs->blocksize &&
167.86 + !dirent->inode) {
167.87 + curr_rec_len -= csum_size;
167.88 + ls->err = ext2fs_set_rec_len(ls->fs, curr_rec_len, dirent);
167.89 + if (ls->err)
167.90 + return DIRENT_ABORT;
167.91 + t = EXT2_DIRENT_TAIL(buf, ls->fs->blocksize);
167.92 + ext2fs_initialize_dirent_tail(ls->fs, t);
167.93 + ret = DIRENT_CHANGED;
167.94 + }
167.95 +
167.96 + /* De-convert a dx_root block */
167.97 + if (csum_size &&
167.98 + curr_rec_len == ls->fs->blocksize - EXT2_DIR_REC_LEN(1) &&
167.99 + offset == EXT2_DIR_REC_LEN(1) &&
167.100 + dirent->name[0] == '.' && dirent->name[1] == '.') {
167.101 + curr_rec_len -= csum_size;
167.102 + ls->err = ext2fs_set_rec_len(ls->fs, curr_rec_len, dirent);
167.103 + if (ls->err)
167.104 + return DIRENT_ABORT;
167.105 + t = EXT2_DIRENT_TAIL(buf, ls->fs->blocksize);
167.106 + ext2fs_initialize_dirent_tail(ls->fs, t);
167.107 + ret = DIRENT_CHANGED;
167.108 + }
167.109 +
167.110 + /*
167.111 + * If the directory entry is used, see if we can split the
167.112 + * directory entry to make room for the new name. If so,
167.113 + * truncate it and return.
167.114 + */
167.115 + if (dirent->inode) {
167.116 + min_rec_len = EXT2_DIR_REC_LEN(ext2fs_dirent_name_len(dirent));
167.117 + if (curr_rec_len < (min_rec_len + rec_len))
167.118 + return ret;
167.119 + rec_len = curr_rec_len - min_rec_len;
167.120 + ls->err = ext2fs_set_rec_len(ls->fs, min_rec_len, dirent);
167.121 + if (ls->err)
167.122 + return DIRENT_ABORT;
167.123 + next = (struct ext2_dir_entry *) (buf + offset +
167.124 + dirent->rec_len);
167.125 + next->inode = 0;
167.126 + ext2fs_dirent_set_name_len(next, 0);
167.127 + ext2fs_dirent_set_file_type(next, 0);
167.128 + ls->err = ext2fs_set_rec_len(ls->fs, rec_len, next);
167.129 + if (ls->err)
167.130 + return DIRENT_ABORT;
167.131 + return DIRENT_CHANGED;
167.132 + }
167.133 +
167.134 + /*
167.135 + * If we get this far, then the directory entry is not used.
167.136 + * See if we can fit the request entry in. If so, do it.
167.137 + */
167.138 + if (curr_rec_len < rec_len)
167.139 + return ret;
167.140 + dirent->inode = ls->inode;
167.141 + ext2fs_dirent_set_name_len(dirent, ls->namelen);
167.142 + strncpy(dirent->name, ls->name, ls->namelen);
167.143 + if (ext2fs_has_feature_filetype(ls->sb))
167.144 + ext2fs_dirent_set_file_type(dirent, ls->flags & 0x7);
167.145 +
167.146 + ls->done++;
167.147 + return DIRENT_ABORT|DIRENT_CHANGED;
167.148 +}
167.149 +
167.150 +/*
167.151 + * Note: the low 3 bits of the flags field are used as the directory
167.152 + * entry filetype.
167.153 + */
167.154 +#ifdef __TURBOC__
167.155 + #pragma argsused
167.156 +#endif
167.157 +errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
167.158 + ext2_ino_t ino, int flags)
167.159 +{
167.160 + errcode_t retval;
167.161 + struct link_struct ls;
167.162 + struct ext2_inode inode;
167.163 +
167.164 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
167.165 +
167.166 + if (!(fs->flags & EXT2_FLAG_RW))
167.167 + return EXT2_ET_RO_FILSYS;
167.168 +
167.169 + ls.fs = fs;
167.170 + ls.name = name;
167.171 + ls.namelen = name ? strlen(name) : 0;
167.172 + ls.inode = ino;
167.173 + ls.flags = flags;
167.174 + ls.done = 0;
167.175 + ls.sb = fs->super;
167.176 + ls.blocksize = fs->blocksize;
167.177 + ls.err = 0;
167.178 +
167.179 + retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
167.180 + 0, link_proc, &ls);
167.181 + if (retval)
167.182 + return retval;
167.183 + if (ls.err)
167.184 + return ls.err;
167.185 +
167.186 + if (!ls.done)
167.187 + return EXT2_ET_DIR_NO_SPACE;
167.188 +
167.189 + if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0)
167.190 + return retval;
167.191 +
167.192 + /*
167.193 + * If this function changes to preserve the htree, remove the
167.194 + * two hunks in link_proc that shove checksum tails into the
167.195 + * former dx_root/dx_node blocks.
167.196 + */
167.197 + if (inode.i_flags & EXT2_INDEX_FL) {
167.198 + inode.i_flags &= ~EXT2_INDEX_FL;
167.199 + if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0)
167.200 + return retval;
167.201 + }
167.202 +
167.203 + return 0;
167.204 +}
168.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
168.2 +++ b/libext2fs/lib/libext2fs/llseek.c Wed Aug 25 01:28:08 2021 +0200
168.3 @@ -0,0 +1,145 @@
168.4 +/*
168.5 + * llseek.c -- stub calling the llseek system call
168.6 + *
168.7 + * Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o.
168.8 + *
168.9 + * %Begin-Header%
168.10 + * This file may be redistributed under the terms of the GNU Library
168.11 + * General Public License, version 2.
168.12 + * %End-Header%
168.13 + */
168.14 +
168.15 +#ifndef _LARGEFILE_SOURCE
168.16 +#define _LARGEFILE_SOURCE
168.17 +#endif
168.18 +#ifndef _LARGEFILE64_SOURCE
168.19 +#define _LARGEFILE64_SOURCE
168.20 +#endif
168.21 +
168.22 +#include "config.h"
168.23 +#if HAVE_SYS_TYPES_H
168.24 +#include <sys/types.h>
168.25 +#endif
168.26 +
168.27 +#if HAVE_ERRNO_H
168.28 +#include <errno.h>
168.29 +#endif
168.30 +#if HAVE_UNISTD_H
168.31 +#include <unistd.h>
168.32 +#endif
168.33 +#ifdef __MSDOS__
168.34 +#include <io.h>
168.35 +#endif
168.36 +#include "et/com_err.h"
168.37 +#include "ext2fs/ext2_io.h"
168.38 +
168.39 +#ifdef __linux__
168.40 +
168.41 +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
168.42 +
168.43 +#define my_llseek lseek64
168.44 +
168.45 +#else
168.46 +#if defined(HAVE_LLSEEK)
168.47 +#include <sys/syscall.h>
168.48 +
168.49 +#ifndef HAVE_LLSEEK_PROTOTYPE
168.50 +extern long long llseek (int fd, long long offset, int origin);
168.51 +#endif
168.52 +
168.53 +#define my_llseek llseek
168.54 +
168.55 +#else /* ! HAVE_LLSEEK */
168.56 +
168.57 +#if SIZEOF_LONG == SIZEOF_LONG_LONG
168.58 +
168.59 +#define my_llseek lseek
168.60 +
168.61 +#else /* SIZEOF_LONG != SIZEOF_LONG_LONG */
168.62 +
168.63 +#include <linux/unistd.h>
168.64 +
168.65 +#ifndef __NR__llseek
168.66 +#define __NR__llseek 140
168.67 +#endif
168.68 +
168.69 +#ifndef __i386__
168.70 +static int _llseek (unsigned int, unsigned long,
168.71 + unsigned long, ext2_loff_t *, unsigned int);
168.72 +
168.73 +static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high,
168.74 + unsigned long, offset_low,ext2_loff_t *,result,
168.75 + unsigned int, origin)
168.76 +#endif
168.77 +
168.78 +static ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin)
168.79 +{
168.80 + ext2_loff_t result;
168.81 + int retval;
168.82 +
168.83 +#ifndef __i386__
168.84 + retval = _llseek(fd, ((unsigned long long) offset) >> 32,
168.85 +#else
168.86 + retval = syscall(__NR__llseek, fd, (unsigned long long) (offset >> 32),
168.87 +#endif
168.88 + ((unsigned long long) offset) & 0xffffffff,
168.89 + &result, origin);
168.90 + return (retval == -1 ? (ext2_loff_t) retval : result);
168.91 +}
168.92 +
168.93 +#endif /* SIZE_LONG == SIZEOF_LONG_LONG */
168.94 +
168.95 +#endif /* HAVE_LLSEEK */
168.96 +#endif /* defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) */
168.97 +
168.98 +ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
168.99 +{
168.100 +#if SIZEOF_OFF_T >= SIZEOF_LONG_LONG
168.101 + return my_llseek (fd, offset, origin);
168.102 +#else
168.103 + ext2_loff_t result;
168.104 + static int do_compat = 0;
168.105 +
168.106 + if (do_compat)
168.107 + goto fallback;
168.108 +
168.109 + result = my_llseek (fd, offset, origin);
168.110 + if (result == -1 && errno == ENOSYS) {
168.111 + /*
168.112 + * Just in case this code runs on top of an old kernel
168.113 + * which does not support the llseek system call
168.114 + */
168.115 + do_compat++;
168.116 + fallback:
168.117 + if (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))
168.118 + return lseek(fd, (off_t) offset, origin);
168.119 + errno = EINVAL;
168.120 + return -1;
168.121 + }
168.122 + return result;
168.123 +#endif
168.124 +}
168.125 +
168.126 +#else /* !linux */
168.127 +
168.128 +#ifndef EINVAL
168.129 +#define EINVAL EXT2_ET_INVALID_ARGUMENT
168.130 +#endif
168.131 +
168.132 +ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
168.133 +{
168.134 +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
168.135 + return lseek64 (fd, offset, origin);
168.136 +#else
168.137 + if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
168.138 + (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
168.139 + errno = EINVAL;
168.140 + return -1;
168.141 + }
168.142 + return lseek (fd, (off_t) offset, origin);
168.143 +#endif
168.144 +}
168.145 +
168.146 +#endif /* linux */
168.147 +
168.148 +
169.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
169.2 +++ b/libext2fs/lib/libext2fs/lookup.c Wed Aug 25 01:28:08 2021 +0200
169.3 @@ -0,0 +1,70 @@
169.4 +/*
169.5 + * lookup.c --- ext2fs directory lookup operations
169.6 + *
169.7 + * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
169.8 + *
169.9 + * %Begin-Header%
169.10 + * This file may be redistributed under the terms of the GNU Library
169.11 + * General Public License, version 2.
169.12 + * %End-Header%
169.13 + */
169.14 +
169.15 +#include "config.h"
169.16 +#include <stdio.h>
169.17 +#include <string.h>
169.18 +#if HAVE_UNISTD_H
169.19 +#include <unistd.h>
169.20 +#endif
169.21 +
169.22 +#include "ext2_fs.h"
169.23 +#include "ext2fs.h"
169.24 +
169.25 +struct lookup_struct {
169.26 + const char *name;
169.27 + int len;
169.28 + ext2_ino_t *inode;
169.29 + int found;
169.30 +};
169.31 +
169.32 +#ifdef __TURBOC__
169.33 + #pragma argsused
169.34 +#endif
169.35 +static int lookup_proc(struct ext2_dir_entry *dirent,
169.36 + int offset EXT2FS_ATTR((unused)),
169.37 + int blocksize EXT2FS_ATTR((unused)),
169.38 + char *buf EXT2FS_ATTR((unused)),
169.39 + void *priv_data)
169.40 +{
169.41 + struct lookup_struct *ls = (struct lookup_struct *) priv_data;
169.42 +
169.43 + if (ls->len != ext2fs_dirent_name_len(dirent))
169.44 + return 0;
169.45 + if (strncmp(ls->name, dirent->name, ext2fs_dirent_name_len(dirent)))
169.46 + return 0;
169.47 + *ls->inode = dirent->inode;
169.48 + ls->found++;
169.49 + return DIRENT_ABORT;
169.50 +}
169.51 +
169.52 +
169.53 +errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
169.54 + int namelen, char *buf, ext2_ino_t *inode)
169.55 +{
169.56 + errcode_t retval;
169.57 + struct lookup_struct ls;
169.58 +
169.59 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
169.60 +
169.61 + ls.name = name;
169.62 + ls.len = namelen;
169.63 + ls.inode = inode;
169.64 + ls.found = 0;
169.65 +
169.66 + retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls);
169.67 + if (retval)
169.68 + return retval;
169.69 +
169.70 + return (ls.found) ? 0 : EXT2_ET_FILE_NOT_FOUND;
169.71 +}
169.72 +
169.73 +
170.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
170.2 +++ b/libext2fs/lib/libext2fs/mkdir.c Wed Aug 25 01:28:08 2021 +0200
170.3 @@ -0,0 +1,192 @@
170.4 +/*
170.5 + * mkdir.c --- make a directory in the filesystem
170.6 + *
170.7 + * Copyright (C) 1994, 1995 Theodore Ts'o.
170.8 + *
170.9 + * %Begin-Header%
170.10 + * This file may be redistributed under the terms of the GNU Library
170.11 + * General Public License, version 2.
170.12 + * %End-Header%
170.13 + */
170.14 +
170.15 +#include "config.h"
170.16 +#include <stdio.h>
170.17 +#include <string.h>
170.18 +#if HAVE_UNISTD_H
170.19 +#include <unistd.h>
170.20 +#endif
170.21 +#include <fcntl.h>
170.22 +#include <time.h>
170.23 +#if HAVE_SYS_STAT_H
170.24 +#include <sys/stat.h>
170.25 +#endif
170.26 +#if HAVE_SYS_TYPES_H
170.27 +#include <sys/types.h>
170.28 +#endif
170.29 +
170.30 +#include "ext2_fs.h"
170.31 +#include "ext2fs.h"
170.32 +#include "ext2fsP.h"
170.33 +
170.34 +#ifndef EXT2_FT_DIR
170.35 +#define EXT2_FT_DIR 2
170.36 +#endif
170.37 +
170.38 +errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
170.39 + const char *name)
170.40 +{
170.41 + ext2_extent_handle_t handle;
170.42 + errcode_t retval;
170.43 + struct ext2_inode parent_inode, inode;
170.44 + ext2_ino_t ino = inum;
170.45 + ext2_ino_t scratch_ino;
170.46 + blk64_t blk;
170.47 + char *block = 0;
170.48 + int inline_data = 0;
170.49 +
170.50 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
170.51 +
170.52 + /*
170.53 + * Create a new dir with inline data iff this feature is enabled
170.54 + * and ino >= EXT2_FIRST_INO.
170.55 + */
170.56 + if ((!ino || ino >= EXT2_FIRST_INO(fs->super)) &&
170.57 + ext2fs_has_feature_inline_data(fs->super))
170.58 + inline_data = 1;
170.59 +
170.60 + /*
170.61 + * Allocate an inode, if necessary
170.62 + */
170.63 + if (!ino) {
170.64 + retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755,
170.65 + 0, &ino);
170.66 + if (retval)
170.67 + goto cleanup;
170.68 + }
170.69 +
170.70 + /*
170.71 + * Allocate a data block for the directory
170.72 + */
170.73 + memset(&inode, 0, sizeof(struct ext2_inode));
170.74 + if (!inline_data) {
170.75 + retval = ext2fs_new_block2(fs, ext2fs_find_inode_goal(fs, ino,
170.76 + &inode,
170.77 + 0),
170.78 + NULL, &blk);
170.79 + if (retval)
170.80 + goto cleanup;
170.81 + }
170.82 +
170.83 + /*
170.84 + * Create a scratch template for the directory
170.85 + */
170.86 + if (inline_data)
170.87 + retval = ext2fs_new_dir_inline_data(fs, ino, parent,
170.88 + inode.i_block);
170.89 + else
170.90 + retval = ext2fs_new_dir_block(fs, ino, parent, &block);
170.91 + if (retval)
170.92 + goto cleanup;
170.93 +
170.94 + /*
170.95 + * Get the parent's inode, if necessary
170.96 + */
170.97 + if (parent != ino) {
170.98 + retval = ext2fs_read_inode(fs, parent, &parent_inode);
170.99 + if (retval)
170.100 + goto cleanup;
170.101 + } else
170.102 + memset(&parent_inode, 0, sizeof(parent_inode));
170.103 +
170.104 + /*
170.105 + * Create the inode structure....
170.106 + */
170.107 + inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask);
170.108 + inode.i_uid = inode.i_gid = 0;
170.109 + if (inline_data) {
170.110 + inode.i_flags |= EXT4_INLINE_DATA_FL;
170.111 + inode.i_size = EXT4_MIN_INLINE_DATA_SIZE;
170.112 + } else {
170.113 + if (ext2fs_has_feature_extents(fs->super))
170.114 + inode.i_flags |= EXT4_EXTENTS_FL;
170.115 + else
170.116 + inode.i_block[0] = blk;
170.117 + inode.i_size = fs->blocksize;
170.118 + ext2fs_iblk_set(fs, &inode, 1);
170.119 + }
170.120 + inode.i_links_count = 2;
170.121 +
170.122 + /*
170.123 + * Write out the inode and inode data block. The inode generation
170.124 + * number is assigned by write_new_inode, which means that the call
170.125 + * to write_dir_block must come after that.
170.126 + */
170.127 + retval = ext2fs_write_new_inode(fs, ino, &inode);
170.128 + if (retval)
170.129 + goto cleanup;
170.130 + if (inline_data) {
170.131 + /* init "system.data" for new dir */
170.132 + retval = ext2fs_inline_data_init(fs, ino);
170.133 + } else {
170.134 + retval = ext2fs_write_dir_block4(fs, blk, block, 0, ino);
170.135 + if (retval)
170.136 + goto cleanup;
170.137 +
170.138 + if (ext2fs_has_feature_extents(fs->super)) {
170.139 + retval = ext2fs_extent_open2(fs, ino, &inode, &handle);
170.140 + if (retval)
170.141 + goto cleanup;
170.142 + retval = ext2fs_extent_set_bmap(handle, 0, blk, 0);
170.143 + ext2fs_extent_free(handle);
170.144 + if (retval)
170.145 + goto cleanup;
170.146 + }
170.147 + }
170.148 +
170.149 + /*
170.150 + * Link the directory into the filesystem hierarchy
170.151 + */
170.152 + if (name) {
170.153 + retval = ext2fs_lookup(fs, parent, name, strlen(name), 0,
170.154 + &scratch_ino);
170.155 + if (!retval) {
170.156 + retval = EXT2_ET_DIR_EXISTS;
170.157 + name = 0;
170.158 + goto cleanup;
170.159 + }
170.160 + if (retval != EXT2_ET_FILE_NOT_FOUND)
170.161 + goto cleanup;
170.162 + retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR);
170.163 + if (retval)
170.164 + goto cleanup;
170.165 + }
170.166 +
170.167 + /*
170.168 + * Update parent inode's counts
170.169 + */
170.170 + if (parent != ino) {
170.171 + /* reload parent inode due to inline data */
170.172 + retval = ext2fs_read_inode(fs, parent, &parent_inode);
170.173 + if (retval)
170.174 + goto cleanup;
170.175 + parent_inode.i_links_count++;
170.176 + retval = ext2fs_write_inode(fs, parent, &parent_inode);
170.177 + if (retval)
170.178 + goto cleanup;
170.179 + }
170.180 +
170.181 + /*
170.182 + * Update accounting....
170.183 + */
170.184 + if (!inline_data)
170.185 + ext2fs_block_alloc_stats2(fs, blk, +1);
170.186 + ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
170.187 +
170.188 +cleanup:
170.189 + if (block)
170.190 + ext2fs_free_mem(&block);
170.191 + return retval;
170.192 +
170.193 +}
170.194 +
170.195 +
171.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
171.2 +++ b/libext2fs/lib/libext2fs/mkjournal.c Wed Aug 25 01:28:08 2021 +0200
171.3 @@ -0,0 +1,589 @@
171.4 +/*
171.5 + * mkjournal.c --- make a journal for a filesystem
171.6 + *
171.7 + * Copyright (C) 2000 Theodore Ts'o.
171.8 + *
171.9 + * %Begin-Header%
171.10 + * This file may be redistributed under the terms of the GNU Library
171.11 + * General Public License, version 2.
171.12 + * %End-Header%
171.13 + */
171.14 +
171.15 +#include "config.h"
171.16 +#include <stdio.h>
171.17 +#include <string.h>
171.18 +#if HAVE_UNISTD_H
171.19 +#include <unistd.h>
171.20 +#endif
171.21 +#if HAVE_ERRNO_H
171.22 +#include <errno.h>
171.23 +#endif
171.24 +#include <fcntl.h>
171.25 +#include <time.h>
171.26 +#if HAVE_SYS_STAT_H
171.27 +#include <sys/stat.h>
171.28 +#endif
171.29 +#if HAVE_SYS_TYPES_H
171.30 +#include <sys/types.h>
171.31 +#endif
171.32 +#if HAVE_SYS_IOCTL_H
171.33 +#include <sys/ioctl.h>
171.34 +#endif
171.35 +#if HAVE_NETINET_IN_H
171.36 +#include <netinet/in.h>
171.37 +#endif
171.38 +
171.39 +#include "ext2_fs.h"
171.40 +#include "e2p/e2p.h"
171.41 +#include "ext2fs.h"
171.42 +
171.43 +#include "kernel-jbd.h"
171.44 +
171.45 +/*
171.46 + * This function automatically sets up the journal superblock and
171.47 + * returns it as an allocated block.
171.48 + */
171.49 +errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
171.50 + __u32 num_blocks, int flags,
171.51 + char **ret_jsb)
171.52 +{
171.53 + errcode_t retval;
171.54 + journal_superblock_t *jsb;
171.55 +
171.56 + if (num_blocks < JFS_MIN_JOURNAL_BLOCKS)
171.57 + return EXT2_ET_JOURNAL_TOO_SMALL;
171.58 +
171.59 + if ((retval = ext2fs_get_mem(fs->blocksize, &jsb)))
171.60 + return retval;
171.61 +
171.62 + memset (jsb, 0, fs->blocksize);
171.63 +
171.64 + jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
171.65 + if (flags & EXT2_MKJOURNAL_V1_SUPER)
171.66 + jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1);
171.67 + else
171.68 + jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
171.69 + jsb->s_blocksize = htonl(fs->blocksize);
171.70 + jsb->s_maxlen = htonl(num_blocks);
171.71 + jsb->s_nr_users = htonl(1);
171.72 + jsb->s_first = htonl(1);
171.73 + jsb->s_sequence = htonl(1);
171.74 + memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid));
171.75 + /*
171.76 + * If we're creating an external journal device, we need to
171.77 + * adjust these fields.
171.78 + */
171.79 + if (ext2fs_has_feature_journal_dev(fs->super)) {
171.80 + jsb->s_nr_users = 0;
171.81 + jsb->s_first = htonl(ext2fs_journal_sb_start(fs->blocksize) + 1);
171.82 + }
171.83 +
171.84 + *ret_jsb = (char *) jsb;
171.85 + return 0;
171.86 +}
171.87 +
171.88 +/*
171.89 + * This function writes a journal using POSIX routines. It is used
171.90 + * for creating external journals and creating journals on live
171.91 + * filesystems.
171.92 + */
171.93 +static errcode_t write_journal_file(ext2_filsys fs, char *filename,
171.94 + blk_t num_blocks, int flags)
171.95 +{
171.96 + errcode_t retval;
171.97 + char *buf = 0;
171.98 + int fd, ret_size;
171.99 + blk_t i;
171.100 +
171.101 + if ((retval = ext2fs_create_journal_superblock(fs, num_blocks, flags,
171.102 + &buf)))
171.103 + return retval;
171.104 +
171.105 + /* Open the device or journal file */
171.106 + if ((fd = open(filename, O_WRONLY)) < 0) {
171.107 + retval = errno;
171.108 + goto errfree;
171.109 + }
171.110 +
171.111 + /* Write the superblock out */
171.112 + retval = EXT2_ET_SHORT_WRITE;
171.113 + ret_size = write(fd, buf, fs->blocksize);
171.114 + if (ret_size < 0) {
171.115 + retval = errno;
171.116 + goto errout;
171.117 + }
171.118 + if (ret_size != (int) fs->blocksize)
171.119 + goto errout;
171.120 + memset(buf, 0, fs->blocksize);
171.121 +
171.122 + if (flags & EXT2_MKJOURNAL_LAZYINIT)
171.123 + goto success;
171.124 +
171.125 + for (i = 1; i < num_blocks; i++) {
171.126 + ret_size = write(fd, buf, fs->blocksize);
171.127 + if (ret_size < 0) {
171.128 + retval = errno;
171.129 + goto errout;
171.130 + }
171.131 + if (ret_size != (int) fs->blocksize)
171.132 + goto errout;
171.133 + }
171.134 +
171.135 +success:
171.136 + retval = 0;
171.137 +errout:
171.138 + close(fd);
171.139 +errfree:
171.140 + ext2fs_free_mem(&buf);
171.141 + return retval;
171.142 +}
171.143 +
171.144 +/*
171.145 + * Convenience function which zeros out _num_ blocks starting at
171.146 + * _blk_. In case of an error, the details of the error is returned
171.147 + * via _ret_blk_ and _ret_count_ if they are non-NULL pointers.
171.148 + * Returns 0 on success, and an error code on an error.
171.149 + *
171.150 + * As a special case, if the first argument is NULL, then it will
171.151 + * attempt to free the static zeroizing buffer. (This is to keep
171.152 + * programs that check for memory leaks happy.)
171.153 + */
171.154 +#define MAX_STRIDE_LENGTH (4194304 / (int) fs->blocksize)
171.155 +errcode_t ext2fs_zero_blocks2(ext2_filsys fs, blk64_t blk, int num,
171.156 + blk64_t *ret_blk, int *ret_count)
171.157 +{
171.158 + int j, count;
171.159 + static void *buf;
171.160 + static int stride_length;
171.161 + errcode_t retval;
171.162 +
171.163 + /* If fs is null, clean up the static buffer and return */
171.164 + if (!fs) {
171.165 + if (buf) {
171.166 + free(buf);
171.167 + buf = 0;
171.168 + stride_length = 0;
171.169 + }
171.170 + return 0;
171.171 + }
171.172 +
171.173 + /* Deal with zeroing less than 1 block */
171.174 + if (num <= 0)
171.175 + return 0;
171.176 +
171.177 + /* Try a zero out command, if supported */
171.178 + retval = io_channel_zeroout(fs->io, blk, num);
171.179 + if (retval == 0)
171.180 + return 0;
171.181 +
171.182 + /* Allocate the zeroizing buffer if necessary */
171.183 + if (num > stride_length && stride_length < MAX_STRIDE_LENGTH) {
171.184 + void *p;
171.185 + int new_stride = num;
171.186 +
171.187 + if (new_stride > MAX_STRIDE_LENGTH)
171.188 + new_stride = MAX_STRIDE_LENGTH;
171.189 + p = realloc(buf, fs->blocksize * new_stride);
171.190 + if (!p)
171.191 + return EXT2_ET_NO_MEMORY;
171.192 + buf = p;
171.193 + stride_length = new_stride;
171.194 + memset(buf, 0, fs->blocksize * stride_length);
171.195 + }
171.196 + /* OK, do the write loop */
171.197 + j=0;
171.198 + while (j < num) {
171.199 + if (blk % stride_length) {
171.200 + count = stride_length - (blk % stride_length);
171.201 + if (count > (num - j))
171.202 + count = num - j;
171.203 + } else {
171.204 + count = num - j;
171.205 + if (count > stride_length)
171.206 + count = stride_length;
171.207 + }
171.208 + retval = io_channel_write_blk64(fs->io, blk, count, buf);
171.209 + if (retval) {
171.210 + if (ret_count)
171.211 + *ret_count = count;
171.212 + if (ret_blk)
171.213 + *ret_blk = blk;
171.214 + return retval;
171.215 + }
171.216 + j += count; blk += count;
171.217 + }
171.218 + return 0;
171.219 +}
171.220 +
171.221 +errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num,
171.222 + blk_t *ret_blk, int *ret_count)
171.223 +{
171.224 + blk64_t ret_blk2;
171.225 + errcode_t retval;
171.226 +
171.227 + retval = ext2fs_zero_blocks2(fs, blk, num, &ret_blk2, ret_count);
171.228 + if (retval)
171.229 + *ret_blk = (blk_t) ret_blk2;
171.230 + return retval;
171.231 +}
171.232 +
171.233 +/*
171.234 + * Calculate the initial goal block to be roughly at the middle of the
171.235 + * filesystem. Pick a group that has the largest number of free
171.236 + * blocks.
171.237 + */
171.238 +static blk64_t get_midpoint_journal_block(ext2_filsys fs)
171.239 +{
171.240 + dgrp_t group, start, end, i, log_flex;
171.241 +
171.242 + group = ext2fs_group_of_blk2(fs, (ext2fs_blocks_count(fs->super) -
171.243 + fs->super->s_first_data_block) / 2);
171.244 + log_flex = 1 << fs->super->s_log_groups_per_flex;
171.245 + if (fs->super->s_log_groups_per_flex && (group > log_flex)) {
171.246 + group = group & ~(log_flex - 1);
171.247 + while ((group < fs->group_desc_count) &&
171.248 + ext2fs_bg_free_blocks_count(fs, group) == 0)
171.249 + group++;
171.250 + if (group == fs->group_desc_count)
171.251 + group = 0;
171.252 + start = group;
171.253 + } else
171.254 + start = (group > 0) ? group-1 : group;
171.255 + end = ((group+1) < fs->group_desc_count) ? group+1 : group;
171.256 + group = start;
171.257 + for (i = start + 1; i <= end; i++)
171.258 + if (ext2fs_bg_free_blocks_count(fs, i) >
171.259 + ext2fs_bg_free_blocks_count(fs, group))
171.260 + group = i;
171.261 + return ext2fs_group_first_block2(fs, group);
171.262 +}
171.263 +
171.264 +/*
171.265 + * This function creates a journal using direct I/O routines.
171.266 + */
171.267 +static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
171.268 + blk_t num_blocks, blk64_t goal, int flags)
171.269 +{
171.270 + char *buf;
171.271 + errcode_t retval;
171.272 + struct ext2_inode inode;
171.273 + unsigned long long inode_size;
171.274 + int falloc_flags = EXT2_FALLOCATE_FORCE_INIT;
171.275 + blk64_t zblk;
171.276 +
171.277 + if ((retval = ext2fs_create_journal_superblock(fs, num_blocks, flags,
171.278 + &buf)))
171.279 + return retval;
171.280 +
171.281 + if ((retval = ext2fs_read_bitmaps(fs)))
171.282 + goto out2;
171.283 +
171.284 + if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
171.285 + goto out2;
171.286 +
171.287 + if (inode.i_blocks > 0) {
171.288 + retval = EEXIST;
171.289 + goto out2;
171.290 + }
171.291 +
171.292 + if (goal == ~0ULL)
171.293 + goal = get_midpoint_journal_block(fs);
171.294 +
171.295 + if (ext2fs_has_feature_extents(fs->super))
171.296 + inode.i_flags |= EXT4_EXTENTS_FL;
171.297 +
171.298 + if (!(flags & EXT2_MKJOURNAL_LAZYINIT))
171.299 + falloc_flags |= EXT2_FALLOCATE_ZERO_BLOCKS;
171.300 +
171.301 + inode_size = (unsigned long long)fs->blocksize * num_blocks;
171.302 + inode.i_mtime = inode.i_ctime = fs->now ? fs->now : time(0);
171.303 + inode.i_links_count = 1;
171.304 + inode.i_mode = LINUX_S_IFREG | 0600;
171.305 + retval = ext2fs_inode_size_set(fs, &inode, inode_size);
171.306 + if (retval)
171.307 + goto out2;
171.308 +
171.309 + retval = ext2fs_fallocate(fs, falloc_flags, journal_ino,
171.310 + &inode, goal, 0, num_blocks);
171.311 + if (retval)
171.312 + goto out2;
171.313 +
171.314 + if ((retval = ext2fs_write_new_inode(fs, journal_ino, &inode)))
171.315 + goto out2;
171.316 +
171.317 + retval = ext2fs_bmap2(fs, journal_ino, &inode, NULL, 0, 0, NULL, &zblk);
171.318 + if (retval)
171.319 + goto out2;
171.320 +
171.321 + retval = io_channel_write_blk64(fs->io, zblk, 1, buf);
171.322 + if (retval)
171.323 + goto out2;
171.324 +
171.325 + memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
171.326 + fs->super->s_jnl_blocks[15] = inode.i_size_high;
171.327 + fs->super->s_jnl_blocks[16] = inode.i_size;
171.328 + fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
171.329 + ext2fs_mark_super_dirty(fs);
171.330 +
171.331 +out2:
171.332 + ext2fs_free_mem(&buf);
171.333 + return retval;
171.334 +}
171.335 +
171.336 +/*
171.337 + * Find a reasonable journal file size (in blocks) given the number of blocks
171.338 + * in the filesystem. For very small filesystems, it is not reasonable to
171.339 + * have a journal that fills more than half of the filesystem.
171.340 + *
171.341 + * n.b. comments assume 4k blocks
171.342 + */
171.343 +int ext2fs_default_journal_size(__u64 num_blocks)
171.344 +{
171.345 + if (num_blocks < 2048)
171.346 + return -1;
171.347 + if (num_blocks < 32768) /* 128 MB */
171.348 + return (1024); /* 4 MB */
171.349 + if (num_blocks < 256*1024) /* 1 GB */
171.350 + return (4096); /* 16 MB */
171.351 + if (num_blocks < 512*1024) /* 2 GB */
171.352 + return (8192); /* 32 MB */
171.353 + if (num_blocks < 4096*1024) /* 16 GB */
171.354 + return (16384); /* 64 MB */
171.355 + if (num_blocks < 8192*1024) /* 32 GB */
171.356 + return (32768); /* 128 MB */
171.357 + if (num_blocks < 16384*1024) /* 64 GB */
171.358 + return (65536); /* 256 MB */
171.359 + if (num_blocks < 32768*1024) /* 128 GB */
171.360 + return (131072); /* 512 MB */
171.361 + return 262144; /* 1 GB */
171.362 +}
171.363 +
171.364 +int ext2fs_journal_sb_start(int blocksize)
171.365 +{
171.366 + if (blocksize == EXT2_MIN_BLOCK_SIZE)
171.367 + return 2;
171.368 + return 1;
171.369 +}
171.370 +
171.371 +/*
171.372 + * This function adds a journal device to a filesystem
171.373 + */
171.374 +errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
171.375 +{
171.376 + struct stat st;
171.377 + errcode_t retval;
171.378 + char buf[SUPERBLOCK_SIZE];
171.379 + journal_superblock_t *jsb;
171.380 + int start;
171.381 + __u32 i, nr_users;
171.382 +
171.383 + /* Make sure the device exists and is a block device */
171.384 + if (stat(journal_dev->device_name, &st) < 0)
171.385 + return errno;
171.386 +
171.387 + if (!S_ISBLK(st.st_mode))
171.388 + return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */
171.389 +
171.390 + /* Get the journal superblock */
171.391 + start = ext2fs_journal_sb_start(journal_dev->blocksize);
171.392 + if ((retval = io_channel_read_blk64(journal_dev->io, start,
171.393 + -SUPERBLOCK_SIZE,
171.394 + buf)))
171.395 + return retval;
171.396 +
171.397 + jsb = (journal_superblock_t *) buf;
171.398 + if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
171.399 + (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2)))
171.400 + return EXT2_ET_NO_JOURNAL_SB;
171.401 +
171.402 + if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize)
171.403 + return EXT2_ET_UNEXPECTED_BLOCK_SIZE;
171.404 +
171.405 + /* Check and see if this filesystem has already been added */
171.406 + nr_users = ntohl(jsb->s_nr_users);
171.407 + if (nr_users > JFS_USERS_MAX)
171.408 + return EXT2_ET_CORRUPT_JOURNAL_SB;
171.409 + for (i=0; i < nr_users; i++) {
171.410 + if (memcmp(fs->super->s_uuid,
171.411 + &jsb->s_users[i*16], 16) == 0)
171.412 + break;
171.413 + }
171.414 + if (i >= nr_users) {
171.415 + memcpy(&jsb->s_users[nr_users*16],
171.416 + fs->super->s_uuid, 16);
171.417 + jsb->s_nr_users = htonl(nr_users+1);
171.418 + }
171.419 +
171.420 + /* Writeback the journal superblock */
171.421 + if ((retval = io_channel_write_blk64(journal_dev->io, start,
171.422 + -SUPERBLOCK_SIZE, buf)))
171.423 + return retval;
171.424 +
171.425 + fs->super->s_journal_inum = 0;
171.426 + fs->super->s_journal_dev = st.st_rdev;
171.427 + memcpy(fs->super->s_journal_uuid, jsb->s_uuid,
171.428 + sizeof(fs->super->s_journal_uuid));
171.429 + memset(fs->super->s_jnl_blocks, 0, sizeof(fs->super->s_jnl_blocks));
171.430 + ext2fs_set_feature_journal(fs->super);
171.431 + ext2fs_mark_super_dirty(fs);
171.432 + return 0;
171.433 +}
171.434 +
171.435 +/*
171.436 + * This function adds a journal inode to a filesystem, using either
171.437 + * POSIX routines if the filesystem is mounted, or using direct I/O
171.438 + * functions if it is not.
171.439 + */
171.440 +errcode_t ext2fs_add_journal_inode2(ext2_filsys fs, blk_t num_blocks,
171.441 + blk64_t goal, int flags)
171.442 +{
171.443 + errcode_t retval;
171.444 + ext2_ino_t journal_ino;
171.445 + struct stat st;
171.446 + char jfile[1024];
171.447 + int mount_flags;
171.448 + int fd = -1;
171.449 +
171.450 + if (flags & EXT2_MKJOURNAL_NO_MNT_CHECK)
171.451 + mount_flags = 0;
171.452 + else if ((retval = ext2fs_check_mount_point(fs->device_name,
171.453 + &mount_flags,
171.454 + jfile, sizeof(jfile)-10)))
171.455 + return retval;
171.456 +
171.457 + if (mount_flags & EXT2_MF_MOUNTED) {
171.458 +#if HAVE_EXT2_IOCTLS
171.459 + int f = 0;
171.460 +#endif
171.461 + strcat(jfile, "/.journal");
171.462 +
171.463 + /*
171.464 + * If .../.journal already exists, make sure any
171.465 + * immutable or append-only flags are cleared.
171.466 + */
171.467 +#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
171.468 + (void) chflags (jfile, 0);
171.469 +#else
171.470 +#if HAVE_EXT2_IOCTLS
171.471 + fd = open(jfile, O_RDONLY);
171.472 + if (fd >= 0) {
171.473 + retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f);
171.474 + close(fd);
171.475 + if (retval)
171.476 + return retval;
171.477 + }
171.478 +#endif
171.479 +#endif
171.480 +
171.481 + /* Create the journal file */
171.482 + if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0)
171.483 + return errno;
171.484 +
171.485 + /* Note that we can't do lazy journal initialization for mounted
171.486 + * filesystems, since the zero writing is also allocating the
171.487 + * journal blocks. We could use fallocate, but not all kernels
171.488 + * support that, and creating a journal on a mounted ext2
171.489 + * filesystems is extremely rare these days... Ignore it. */
171.490 + flags &= ~EXT2_MKJOURNAL_LAZYINIT;
171.491 +
171.492 + if ((retval = write_journal_file(fs, jfile, num_blocks, flags)))
171.493 + goto errout;
171.494 +
171.495 + /* Get inode number of the journal file */
171.496 + if (fstat(fd, &st) < 0) {
171.497 + retval = errno;
171.498 + goto errout;
171.499 + }
171.500 +
171.501 +#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
171.502 + retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE);
171.503 +#else
171.504 +#if HAVE_EXT2_IOCTLS
171.505 + if (ioctl(fd, EXT2_IOC_GETFLAGS, &f) < 0) {
171.506 + retval = errno;
171.507 + goto errout;
171.508 + }
171.509 + f |= EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL;
171.510 + retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f);
171.511 +#endif
171.512 +#endif
171.513 + if (retval) {
171.514 + retval = errno;
171.515 + goto errout;
171.516 + }
171.517 +
171.518 + if (close(fd) < 0) {
171.519 + retval = errno;
171.520 + fd = -1;
171.521 + goto errout;
171.522 + }
171.523 + journal_ino = st.st_ino;
171.524 + memset(fs->super->s_jnl_blocks, 0,
171.525 + sizeof(fs->super->s_jnl_blocks));
171.526 + } else {
171.527 + if ((mount_flags & EXT2_MF_BUSY) &&
171.528 + !(fs->flags & EXT2_FLAG_EXCLUSIVE)) {
171.529 + retval = EBUSY;
171.530 + goto errout;
171.531 + }
171.532 + journal_ino = EXT2_JOURNAL_INO;
171.533 + if ((retval = write_journal_inode(fs, journal_ino,
171.534 + num_blocks, goal, flags)))
171.535 + return retval;
171.536 + }
171.537 +
171.538 + fs->super->s_journal_inum = journal_ino;
171.539 + fs->super->s_journal_dev = 0;
171.540 + memset(fs->super->s_journal_uuid, 0,
171.541 + sizeof(fs->super->s_journal_uuid));
171.542 + ext2fs_set_feature_journal(fs->super);
171.543 +
171.544 + ext2fs_mark_super_dirty(fs);
171.545 + return 0;
171.546 +errout:
171.547 + if (fd >= 0)
171.548 + close(fd);
171.549 + return retval;
171.550 +}
171.551 +
171.552 +errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks, int flags)
171.553 +{
171.554 + return ext2fs_add_journal_inode2(fs, num_blocks, ~0ULL, flags);
171.555 +}
171.556 +
171.557 +
171.558 +#ifdef DEBUG
171.559 +main(int argc, char **argv)
171.560 +{
171.561 + errcode_t retval;
171.562 + char *device_name;
171.563 + ext2_filsys fs;
171.564 +
171.565 + if (argc < 2) {
171.566 + fprintf(stderr, "Usage: %s filesystem\n", argv[0]);
171.567 + exit(1);
171.568 + }
171.569 + device_name = argv[1];
171.570 +
171.571 + retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0,
171.572 + unix_io_manager, &fs);
171.573 + if (retval) {
171.574 + com_err(argv[0], retval, "while opening %s", device_name);
171.575 + exit(1);
171.576 + }
171.577 +
171.578 + retval = ext2fs_add_journal_inode(fs, JFS_MIN_JOURNAL_BLOCKS, 0);
171.579 + if (retval) {
171.580 + com_err(argv[0], retval, "while adding journal to %s",
171.581 + device_name);
171.582 + exit(1);
171.583 + }
171.584 + retval = ext2fs_flush(fs);
171.585 + if (retval) {
171.586 + printf("Warning, had trouble writing out superblocks.\n");
171.587 + }
171.588 + ext2fs_close_free(&fs);
171.589 + exit(0);
171.590 +
171.591 +}
171.592 +#endif
172.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
172.2 +++ b/libext2fs/lib/libext2fs/mmp.c Wed Aug 25 01:28:08 2021 +0200
172.3 @@ -0,0 +1,472 @@
172.4 +/*
172.5 + * Helper functions for multiple mount protection (MMP).
172.6 + *
172.7 + * Copyright (C) 2011 Whamcloud, Inc.
172.8 + *
172.9 + * %Begin-Header%
172.10 + * This file may be redistributed under the terms of the GNU Library
172.11 + * General Public License, version 2.
172.12 + * %End-Header%
172.13 + */
172.14 +
172.15 +#ifndef _GNU_SOURCE
172.16 +#define _GNU_SOURCE
172.17 +#endif
172.18 +#ifndef _DEFAULT_SOURCE
172.19 +#define _DEFAULT_SOURCE /* since glibc 2.20 _SVID_SOURCE is deprecated */
172.20 +#endif
172.21 +
172.22 +#include "config.h"
172.23 +
172.24 +#if HAVE_UNISTD_H
172.25 +#include <unistd.h>
172.26 +#endif
172.27 +#include <sys/time.h>
172.28 +
172.29 +#include <sys/types.h>
172.30 +#include <sys/stat.h>
172.31 +#include <fcntl.h>
172.32 +
172.33 +#include "ext2fs/ext2_fs.h"
172.34 +#include "ext2fs/ext2fs.h"
172.35 +
172.36 +#ifndef O_DIRECT
172.37 +#define O_DIRECT 0
172.38 +#endif
172.39 +
172.40 +#if __GNUC_PREREQ (4, 6)
172.41 +#pragma GCC diagnostic push
172.42 +#ifndef CONFIG_MMP
172.43 +#pragma GCC diagnostic ignored "-Wunused-parameter"
172.44 +#endif
172.45 +#endif
172.46 +
172.47 +errcode_t ext2fs_mmp_read(ext2_filsys fs, blk64_t mmp_blk, void *buf)
172.48 +{
172.49 +#ifdef CONFIG_MMP
172.50 + struct mmp_struct *mmp_cmp;
172.51 + errcode_t retval = 0;
172.52 +
172.53 + if ((mmp_blk <= fs->super->s_first_data_block) ||
172.54 + (mmp_blk >= ext2fs_blocks_count(fs->super)))
172.55 + return EXT2_ET_MMP_BAD_BLOCK;
172.56 +
172.57 + /* ext2fs_open() reserves fd0,1,2 to avoid stdio collision, so checking
172.58 + * mmp_fd <= 0 is OK to validate that the fd is valid. This opens its
172.59 + * own fd to read the MMP block to ensure that it is using O_DIRECT,
172.60 + * regardless of how the io_manager is doing reads, to avoid caching of
172.61 + * the MMP block by the io_manager or the VM. It needs to be fresh. */
172.62 + if (fs->mmp_fd <= 0) {
172.63 + fs->mmp_fd = open(fs->device_name, O_RDWR | O_DIRECT);
172.64 + if (fs->mmp_fd < 0) {
172.65 + retval = EXT2_ET_MMP_OPEN_DIRECT;
172.66 + goto out;
172.67 + }
172.68 + }
172.69 +
172.70 + if (fs->mmp_cmp == NULL) {
172.71 + int align = ext2fs_get_dio_alignment(fs->mmp_fd);
172.72 +
172.73 + retval = ext2fs_get_memalign(fs->blocksize, align,
172.74 + &fs->mmp_cmp);
172.75 + if (retval)
172.76 + return retval;
172.77 + }
172.78 +
172.79 + if ((blk64_t) ext2fs_llseek(fs->mmp_fd, mmp_blk * fs->blocksize,
172.80 + SEEK_SET) !=
172.81 + mmp_blk * fs->blocksize) {
172.82 + retval = EXT2_ET_LLSEEK_FAILED;
172.83 + goto out;
172.84 + }
172.85 +
172.86 + if (read(fs->mmp_fd, fs->mmp_cmp, fs->blocksize) != fs->blocksize) {
172.87 + retval = EXT2_ET_SHORT_READ;
172.88 + goto out;
172.89 + }
172.90 +
172.91 + mmp_cmp = fs->mmp_cmp;
172.92 +
172.93 + if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
172.94 + !ext2fs_mmp_csum_verify(fs, mmp_cmp))
172.95 + retval = EXT2_ET_MMP_CSUM_INVALID;
172.96 +
172.97 +#ifdef WORDS_BIGENDIAN
172.98 + ext2fs_swap_mmp(mmp_cmp);
172.99 +#endif
172.100 +
172.101 + if (buf != NULL && buf != fs->mmp_cmp)
172.102 + memcpy(buf, fs->mmp_cmp, fs->blocksize);
172.103 +
172.104 + if (mmp_cmp->mmp_magic != EXT4_MMP_MAGIC) {
172.105 + retval = EXT2_ET_MMP_MAGIC_INVALID;
172.106 + goto out;
172.107 + }
172.108 +
172.109 +out:
172.110 + return retval;
172.111 +#else
172.112 + return EXT2_ET_OP_NOT_SUPPORTED;
172.113 +#endif
172.114 +}
172.115 +
172.116 +errcode_t ext2fs_mmp_write(ext2_filsys fs, blk64_t mmp_blk, void *buf)
172.117 +{
172.118 +#ifdef CONFIG_MMP
172.119 + struct mmp_struct *mmp_s = buf;
172.120 + struct timeval tv;
172.121 + errcode_t retval = 0;
172.122 +
172.123 + gettimeofday(&tv, 0);
172.124 + mmp_s->mmp_time = tv.tv_sec;
172.125 + fs->mmp_last_written = tv.tv_sec;
172.126 +
172.127 + if (fs->super->s_mmp_block < fs->super->s_first_data_block ||
172.128 + fs->super->s_mmp_block > ext2fs_blocks_count(fs->super))
172.129 + return EXT2_ET_MMP_BAD_BLOCK;
172.130 +
172.131 +#ifdef WORDS_BIGENDIAN
172.132 + ext2fs_swap_mmp(mmp_s);
172.133 +#endif
172.134 +
172.135 + retval = ext2fs_mmp_csum_set(fs, mmp_s);
172.136 + if (retval)
172.137 + return retval;
172.138 +
172.139 + /* I was tempted to make this use O_DIRECT and the mmp_fd, but
172.140 + * this caused no end of grief, while leaving it as-is works. */
172.141 + retval = io_channel_write_blk64(fs->io, mmp_blk, -(int)sizeof(struct mmp_struct), buf);
172.142 +
172.143 +#ifdef WORDS_BIGENDIAN
172.144 + ext2fs_swap_mmp(mmp_s);
172.145 +#endif
172.146 +
172.147 + /* Make sure the block gets to disk quickly */
172.148 + io_channel_flush(fs->io);
172.149 + return retval;
172.150 +#else
172.151 + return EXT2_ET_OP_NOT_SUPPORTED;
172.152 +#endif
172.153 +}
172.154 +
172.155 +#ifdef HAVE_SRANDOM
172.156 +#define srand(x) srandom(x)
172.157 +#define rand() random()
172.158 +#endif
172.159 +
172.160 +unsigned ext2fs_mmp_new_seq(void)
172.161 +{
172.162 +#ifdef CONFIG_MMP
172.163 + unsigned new_seq;
172.164 + struct timeval tv;
172.165 +
172.166 + gettimeofday(&tv, 0);
172.167 + srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
172.168 +
172.169 + gettimeofday(&tv, 0);
172.170 + /* Crank the random number generator a few times */
172.171 + for (new_seq = (tv.tv_sec ^ tv.tv_usec) & 0x1F; new_seq > 0; new_seq--)
172.172 + rand();
172.173 +
172.174 + do {
172.175 + new_seq = rand();
172.176 + } while (new_seq > EXT4_MMP_SEQ_MAX);
172.177 +
172.178 + return new_seq;
172.179 +#else
172.180 + return EXT2_ET_OP_NOT_SUPPORTED;
172.181 +#endif
172.182 +}
172.183 +
172.184 +#ifdef CONFIG_MMP
172.185 +static errcode_t ext2fs_mmp_reset(ext2_filsys fs)
172.186 +{
172.187 + struct mmp_struct *mmp_s = NULL;
172.188 + errcode_t retval = 0;
172.189 +
172.190 + if (fs->mmp_buf == NULL) {
172.191 + retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf);
172.192 + if (retval)
172.193 + goto out;
172.194 + }
172.195 +
172.196 + memset(fs->mmp_buf, 0, fs->blocksize);
172.197 + mmp_s = fs->mmp_buf;
172.198 +
172.199 + mmp_s->mmp_magic = EXT4_MMP_MAGIC;
172.200 + mmp_s->mmp_seq = EXT4_MMP_SEQ_CLEAN;
172.201 + mmp_s->mmp_time = 0;
172.202 +#ifdef HAVE_GETHOSTNAME
172.203 + gethostname(mmp_s->mmp_nodename, sizeof(mmp_s->mmp_nodename));
172.204 +#else
172.205 + mmp_s->mmp_nodename[0] = '\0';
172.206 +#endif
172.207 + strncpy(mmp_s->mmp_bdevname, fs->device_name,
172.208 + sizeof(mmp_s->mmp_bdevname));
172.209 +
172.210 + mmp_s->mmp_check_interval = fs->super->s_mmp_update_interval;
172.211 + if (mmp_s->mmp_check_interval < EXT4_MMP_MIN_CHECK_INTERVAL)
172.212 + mmp_s->mmp_check_interval = EXT4_MMP_MIN_CHECK_INTERVAL;
172.213 +
172.214 + retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf);
172.215 +out:
172.216 + return retval;
172.217 +}
172.218 +#endif
172.219 +
172.220 +errcode_t ext2fs_mmp_update(ext2_filsys fs)
172.221 +{
172.222 + return ext2fs_mmp_update2(fs, 0);
172.223 +}
172.224 +
172.225 +errcode_t ext2fs_mmp_clear(ext2_filsys fs)
172.226 +{
172.227 +#ifdef CONFIG_MMP
172.228 + errcode_t retval = 0;
172.229 +
172.230 + if (!(fs->flags & EXT2_FLAG_RW))
172.231 + return EXT2_ET_RO_FILSYS;
172.232 +
172.233 + retval = ext2fs_mmp_reset(fs);
172.234 +
172.235 + return retval;
172.236 +#else
172.237 + return EXT2_ET_OP_NOT_SUPPORTED;
172.238 +#endif
172.239 +}
172.240 +
172.241 +errcode_t ext2fs_mmp_init(ext2_filsys fs)
172.242 +{
172.243 +#ifdef CONFIG_MMP
172.244 + struct ext2_super_block *sb = fs->super;
172.245 + blk64_t mmp_block;
172.246 + errcode_t retval;
172.247 +
172.248 + if (sb->s_mmp_update_interval == 0)
172.249 + sb->s_mmp_update_interval = EXT4_MMP_UPDATE_INTERVAL;
172.250 + /* This is probably excessively large, but who knows? */
172.251 + else if (sb->s_mmp_update_interval > EXT4_MMP_MAX_UPDATE_INTERVAL)
172.252 + return EXT2_ET_INVALID_ARGUMENT;
172.253 +
172.254 + if (fs->mmp_buf == NULL) {
172.255 + retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf);
172.256 + if (retval)
172.257 + goto out;
172.258 + }
172.259 +
172.260 + retval = ext2fs_alloc_block2(fs, 0, fs->mmp_buf, &mmp_block);
172.261 + if (retval)
172.262 + goto out;
172.263 +
172.264 + sb->s_mmp_block = mmp_block;
172.265 +
172.266 + retval = ext2fs_mmp_reset(fs);
172.267 + if (retval)
172.268 + goto out;
172.269 +
172.270 +out:
172.271 + return retval;
172.272 +#else
172.273 + return EXT2_ET_OP_NOT_SUPPORTED;
172.274 +#endif
172.275 +}
172.276 +
172.277 +#ifndef min
172.278 +#define min(x, y) ((x) < (y) ? (x) : (y))
172.279 +#endif
172.280 +
172.281 +/*
172.282 + * Make sure that the fs is not mounted or being fsck'ed while opening the fs.
172.283 + */
172.284 +errcode_t ext2fs_mmp_start(ext2_filsys fs)
172.285 +{
172.286 +#ifdef CONFIG_MMP
172.287 + struct mmp_struct *mmp_s;
172.288 + unsigned seq;
172.289 + unsigned int mmp_check_interval;
172.290 + errcode_t retval = 0;
172.291 +
172.292 + if (fs->mmp_buf == NULL) {
172.293 + retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf);
172.294 + if (retval)
172.295 + goto mmp_error;
172.296 + }
172.297 +
172.298 + retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf);
172.299 + if (retval)
172.300 + goto mmp_error;
172.301 +
172.302 + mmp_s = fs->mmp_buf;
172.303 +
172.304 + mmp_check_interval = fs->super->s_mmp_update_interval;
172.305 + if (mmp_check_interval < EXT4_MMP_MIN_CHECK_INTERVAL)
172.306 + mmp_check_interval = EXT4_MMP_MIN_CHECK_INTERVAL;
172.307 +
172.308 + seq = mmp_s->mmp_seq;
172.309 + if (seq == EXT4_MMP_SEQ_CLEAN)
172.310 + goto clean_seq;
172.311 + if (seq == EXT4_MMP_SEQ_FSCK) {
172.312 + retval = EXT2_ET_MMP_FSCK_ON;
172.313 + goto mmp_error;
172.314 + }
172.315 +
172.316 + if (seq > EXT4_MMP_SEQ_FSCK) {
172.317 + retval = EXT2_ET_MMP_UNKNOWN_SEQ;
172.318 + goto mmp_error;
172.319 + }
172.320 +
172.321 + /*
172.322 + * If check_interval in MMP block is larger, use that instead of
172.323 + * check_interval from the superblock.
172.324 + */
172.325 + if (mmp_s->mmp_check_interval > mmp_check_interval)
172.326 + mmp_check_interval = mmp_s->mmp_check_interval;
172.327 +
172.328 + sleep(min(mmp_check_interval * 2 + 1, mmp_check_interval + 60));
172.329 +
172.330 + retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf);
172.331 + if (retval)
172.332 + goto mmp_error;
172.333 +
172.334 + if (seq != mmp_s->mmp_seq) {
172.335 + retval = EXT2_ET_MMP_FAILED;
172.336 + goto mmp_error;
172.337 + }
172.338 +
172.339 +clean_seq:
172.340 + if (!(fs->flags & EXT2_FLAG_RW))
172.341 + goto mmp_error;
172.342 +
172.343 + mmp_s->mmp_seq = seq = ext2fs_mmp_new_seq();
172.344 +#ifdef HAVE_GETHOSTNAME
172.345 + gethostname(mmp_s->mmp_nodename, sizeof(mmp_s->mmp_nodename));
172.346 +#else
172.347 + strcpy(mmp_s->mmp_nodename, "unknown host");
172.348 +#endif
172.349 + strncpy(mmp_s->mmp_bdevname, fs->device_name,
172.350 + sizeof(mmp_s->mmp_bdevname));
172.351 +
172.352 + retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf);
172.353 + if (retval)
172.354 + goto mmp_error;
172.355 +
172.356 + sleep(min(2 * mmp_check_interval + 1, mmp_check_interval + 60));
172.357 +
172.358 + retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf);
172.359 + if (retval)
172.360 + goto mmp_error;
172.361 +
172.362 + if (seq != mmp_s->mmp_seq) {
172.363 + retval = EXT2_ET_MMP_FAILED;
172.364 + goto mmp_error;
172.365 + }
172.366 +
172.367 + mmp_s->mmp_seq = EXT4_MMP_SEQ_FSCK;
172.368 + retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf);
172.369 + if (retval)
172.370 + goto mmp_error;
172.371 +
172.372 + return 0;
172.373 +
172.374 +mmp_error:
172.375 + return retval;
172.376 +#else
172.377 + return EXT2_ET_OP_NOT_SUPPORTED;
172.378 +#endif
172.379 +}
172.380 +
172.381 +/*
172.382 + * Clear the MMP usage in the filesystem. If this function returns an
172.383 + * error EXT2_ET_MMP_CHANGE_ABORT it means the filesystem was modified
172.384 + * by some other process while in use, and changes should be dropped, or
172.385 + * risk filesystem corruption.
172.386 + */
172.387 +errcode_t ext2fs_mmp_stop(ext2_filsys fs)
172.388 +{
172.389 +#ifdef CONFIG_MMP
172.390 + struct mmp_struct *mmp, *mmp_cmp;
172.391 + errcode_t retval = 0;
172.392 +
172.393 + if (!ext2fs_has_feature_mmp(fs->super) ||
172.394 + !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
172.395 + goto mmp_error;
172.396 +
172.397 + retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf);
172.398 + if (retval)
172.399 + goto mmp_error;
172.400 +
172.401 + /* Check if the MMP block is not changed. */
172.402 + mmp = fs->mmp_buf;
172.403 + mmp_cmp = fs->mmp_cmp;
172.404 + if (memcmp(mmp, mmp_cmp, sizeof(*mmp_cmp))) {
172.405 + retval = EXT2_ET_MMP_CHANGE_ABORT;
172.406 + goto mmp_error;
172.407 + }
172.408 +
172.409 + mmp_cmp->mmp_seq = EXT4_MMP_SEQ_CLEAN;
172.410 + retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_cmp);
172.411 +
172.412 +mmp_error:
172.413 + if (fs->mmp_fd > 0) {
172.414 + close(fs->mmp_fd);
172.415 + fs->mmp_fd = -1;
172.416 + }
172.417 +
172.418 + return retval;
172.419 +#else
172.420 + if (!ext2fs_has_feature_mmp(fs->super) ||
172.421 + !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
172.422 + return 0;
172.423 +
172.424 + return EXT2_ET_OP_NOT_SUPPORTED;
172.425 +#endif
172.426 +}
172.427 +
172.428 +#define EXT2_MIN_MMP_UPDATE_INTERVAL 60
172.429 +
172.430 +/*
172.431 + * Update the on-disk mmp buffer, after checking that it hasn't been changed.
172.432 + */
172.433 +errcode_t ext2fs_mmp_update2(ext2_filsys fs, int immediately)
172.434 +{
172.435 +#ifdef CONFIG_MMP
172.436 + struct mmp_struct *mmp, *mmp_cmp;
172.437 + struct timeval tv;
172.438 + errcode_t retval = 0;
172.439 +
172.440 + if (!ext2fs_has_feature_mmp(fs->super) ||
172.441 + !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
172.442 + return 0;
172.443 +
172.444 + gettimeofday(&tv, 0);
172.445 + if (!immediately &&
172.446 + tv.tv_sec - fs->mmp_last_written < EXT2_MIN_MMP_UPDATE_INTERVAL)
172.447 + return 0;
172.448 +
172.449 + retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, NULL);
172.450 + if (retval)
172.451 + goto mmp_error;
172.452 +
172.453 + mmp = fs->mmp_buf;
172.454 + mmp_cmp = fs->mmp_cmp;
172.455 +
172.456 + if (memcmp(mmp, mmp_cmp, sizeof(*mmp_cmp)))
172.457 + return EXT2_ET_MMP_CHANGE_ABORT;
172.458 +
172.459 + mmp->mmp_time = tv.tv_sec;
172.460 + mmp->mmp_seq = EXT4_MMP_SEQ_FSCK;
172.461 + retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf);
172.462 +
172.463 +mmp_error:
172.464 + return retval;
172.465 +#else
172.466 + if (!ext2fs_has_feature_mmp(fs->super) ||
172.467 + !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
172.468 + return 0;
172.469 +
172.470 + return EXT2_ET_OP_NOT_SUPPORTED;
172.471 +#endif
172.472 +}
172.473 +#if __GNUC_PREREQ (4, 6)
172.474 +#pragma GCC diagnostic pop
172.475 +#endif
173.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
173.2 +++ b/libext2fs/lib/libext2fs/namei.c Wed Aug 25 01:28:08 2021 +0200
173.3 @@ -0,0 +1,227 @@
173.4 +/*
173.5 + * namei.c --- ext2fs directory lookup operations
173.6 + *
173.7 + * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
173.8 + *
173.9 + * %Begin-Header%
173.10 + * This file may be redistributed under the terms of the GNU Library
173.11 + * General Public License, version 2.
173.12 + * %End-Header%
173.13 + */
173.14 +
173.15 +#include "config.h"
173.16 +#include <stdio.h>
173.17 +#include <string.h>
173.18 +#if HAVE_UNISTD_H
173.19 +#include <unistd.h>
173.20 +#endif
173.21 +
173.22 +/* #define NAMEI_DEBUG */
173.23 +
173.24 +#include "ext2_fs.h"
173.25 +#include "ext2fs.h"
173.26 +#include "ext2fsP.h"
173.27 +
173.28 +static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
173.29 + const char *pathname, size_t pathlen, int follow,
173.30 + int link_count, char *buf, ext2_ino_t *res_inode);
173.31 +
173.32 +static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
173.33 + ext2_ino_t inode, int link_count,
173.34 + char *buf, ext2_ino_t *res_inode)
173.35 +{
173.36 + char *pathname;
173.37 + char *buffer = 0;
173.38 + errcode_t retval;
173.39 + struct ext2_inode ei;
173.40 + blk64_t blk;
173.41 +
173.42 +#ifdef NAMEI_DEBUG
173.43 + printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n",
173.44 + root, dir, inode, link_count);
173.45 +
173.46 +#endif
173.47 + retval = ext2fs_read_inode (fs, inode, &ei);
173.48 + if (retval) return retval;
173.49 + if (!LINUX_S_ISLNK (ei.i_mode)) {
173.50 + *res_inode = inode;
173.51 + return 0;
173.52 + }
173.53 + if (link_count++ >= EXT2FS_MAX_NESTED_LINKS)
173.54 + return EXT2_ET_SYMLINK_LOOP;
173.55 +
173.56 + if (ext2fs_is_fast_symlink(&ei))
173.57 + pathname = (char *)&(ei.i_block[0]);
173.58 + else if (ei.i_flags & EXT4_INLINE_DATA_FL) {
173.59 + retval = ext2fs_get_memzero(ei.i_size, &buffer);
173.60 + if (retval)
173.61 + return retval;
173.62 +
173.63 + retval = ext2fs_inline_data_get(fs, inode,
173.64 + &ei, buffer, NULL);
173.65 + if (retval) {
173.66 + ext2fs_free_mem(&buffer);
173.67 + return retval;
173.68 + }
173.69 + pathname = buffer;
173.70 + } else {
173.71 + retval = ext2fs_bmap2(fs, inode, &ei, NULL, 0, 0, NULL, &blk);
173.72 + if (retval)
173.73 + return retval;
173.74 +
173.75 + retval = ext2fs_get_mem(fs->blocksize, &buffer);
173.76 + if (retval)
173.77 + return retval;
173.78 +
173.79 + retval = io_channel_read_blk64(fs->io, blk, 1, buffer);
173.80 + if (retval) {
173.81 + ext2fs_free_mem(&buffer);
173.82 + return retval;
173.83 + }
173.84 + pathname = buffer;
173.85 + }
173.86 +
173.87 + retval = open_namei(fs, root, dir, pathname, ei.i_size, 1,
173.88 + link_count, buf, res_inode);
173.89 + if (buffer)
173.90 + ext2fs_free_mem(&buffer);
173.91 + return retval;
173.92 +}
173.93 +
173.94 +/*
173.95 + * This routine interprets a pathname in the context of the current
173.96 + * directory and the root directory, and returns the inode of the
173.97 + * containing directory, and a pointer to the filename of the file
173.98 + * (pointing into the pathname) and the length of the filename.
173.99 + */
173.100 +static errcode_t dir_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
173.101 + const char *pathname, int pathlen,
173.102 + int link_count, char *buf,
173.103 + const char **name, int *namelen,
173.104 + ext2_ino_t *res_inode)
173.105 +{
173.106 + char c;
173.107 + const char *thisname;
173.108 + int len;
173.109 + ext2_ino_t inode;
173.110 + errcode_t retval;
173.111 +
173.112 + if ((c = *pathname) == '/') {
173.113 + dir = root;
173.114 + pathname++;
173.115 + pathlen--;
173.116 + }
173.117 + while (1) {
173.118 + thisname = pathname;
173.119 + for (len=0; --pathlen >= 0;len++) {
173.120 + c = *(pathname++);
173.121 + if (c == '/')
173.122 + break;
173.123 + }
173.124 + if (pathlen < 0)
173.125 + break;
173.126 + retval = ext2fs_lookup (fs, dir, thisname, len, buf, &inode);
173.127 + if (retval) return retval;
173.128 + retval = follow_link (fs, root, dir, inode,
173.129 + link_count, buf, &dir);
173.130 + if (retval) return retval;
173.131 + }
173.132 + *name = thisname;
173.133 + *namelen = len;
173.134 + *res_inode = dir;
173.135 + return 0;
173.136 +}
173.137 +
173.138 +static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
173.139 + const char *pathname, size_t pathlen, int follow,
173.140 + int link_count, char *buf, ext2_ino_t *res_inode)
173.141 +{
173.142 + const char *base_name;
173.143 + int namelen;
173.144 + ext2_ino_t dir, inode;
173.145 + errcode_t retval;
173.146 +
173.147 +#ifdef NAMEI_DEBUG
173.148 + printf("open_namei: root=%lu, dir=%lu, path=%.*s, lc=%d\n",
173.149 + root, base, pathlen, pathname, link_count);
173.150 +#endif
173.151 + retval = dir_namei(fs, root, base, pathname, pathlen,
173.152 + link_count, buf, &base_name, &namelen, &dir);
173.153 + if (retval) return retval;
173.154 + if (!namelen) { /* special case: '/usr/' etc */
173.155 + *res_inode=dir;
173.156 + return 0;
173.157 + }
173.158 + retval = ext2fs_lookup (fs, dir, base_name, namelen, buf, &inode);
173.159 + if (retval)
173.160 + return retval;
173.161 + if (follow) {
173.162 + retval = follow_link(fs, root, dir, inode, link_count,
173.163 + buf, &inode);
173.164 + if (retval)
173.165 + return retval;
173.166 + }
173.167 +#ifdef NAMEI_DEBUG
173.168 + printf("open_namei: (link_count=%d) returns %lu\n",
173.169 + link_count, inode);
173.170 +#endif
173.171 + *res_inode = inode;
173.172 + return 0;
173.173 +}
173.174 +
173.175 +errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
173.176 + const char *name, ext2_ino_t *inode)
173.177 +{
173.178 + char *buf;
173.179 + errcode_t retval;
173.180 +
173.181 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
173.182 +
173.183 + retval = ext2fs_get_mem(fs->blocksize, &buf);
173.184 + if (retval)
173.185 + return retval;
173.186 +
173.187 + retval = open_namei(fs, root, cwd, name, strlen(name), 0, 0,
173.188 + buf, inode);
173.189 +
173.190 + ext2fs_free_mem(&buf);
173.191 + return retval;
173.192 +}
173.193 +
173.194 +errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
173.195 + const char *name, ext2_ino_t *inode)
173.196 +{
173.197 + char *buf;
173.198 + errcode_t retval;
173.199 +
173.200 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
173.201 +
173.202 + retval = ext2fs_get_mem(fs->blocksize, &buf);
173.203 + if (retval)
173.204 + return retval;
173.205 +
173.206 + retval = open_namei(fs, root, cwd, name, strlen(name), 1, 0,
173.207 + buf, inode);
173.208 +
173.209 + ext2fs_free_mem(&buf);
173.210 + return retval;
173.211 +}
173.212 +
173.213 +errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
173.214 + ext2_ino_t inode, ext2_ino_t *res_inode)
173.215 +{
173.216 + char *buf;
173.217 + errcode_t retval;
173.218 +
173.219 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
173.220 +
173.221 + retval = ext2fs_get_mem(fs->blocksize, &buf);
173.222 + if (retval)
173.223 + return retval;
173.224 +
173.225 + retval = follow_link(fs, root, cwd, inode, 0, buf, res_inode);
173.226 +
173.227 + ext2fs_free_mem(&buf);
173.228 + return retval;
173.229 +}
173.230 +
175.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
175.2 +++ b/libext2fs/lib/libext2fs/newdir.c Wed Aug 25 01:28:08 2021 +0200
175.3 @@ -0,0 +1,126 @@
175.4 +/*
175.5 + * newdir.c --- create a new directory block
175.6 + *
175.7 + * Copyright (C) 1994, 1995 Theodore Ts'o.
175.8 + *
175.9 + * %Begin-Header%
175.10 + * This file may be redistributed under the terms of the GNU Library
175.11 + * General Public License, version 2.
175.12 + * %End-Header%
175.13 + */
175.14 +
175.15 +#include "config.h"
175.16 +#include <stdio.h>
175.17 +#include <string.h>
175.18 +#if HAVE_UNISTD_H
175.19 +#include <unistd.h>
175.20 +#endif
175.21 +
175.22 +#include "ext2_fs.h"
175.23 +#include "ext2fs.h"
175.24 +
175.25 +#ifndef EXT2_FT_DIR
175.26 +#define EXT2_FT_DIR 2
175.27 +#endif
175.28 +
175.29 +/*
175.30 + * Create new directory block
175.31 + */
175.32 +errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
175.33 + ext2_ino_t parent_ino, char **block)
175.34 +{
175.35 + struct ext2_dir_entry *dir = NULL;
175.36 + errcode_t retval;
175.37 + char *buf;
175.38 + int rec_len;
175.39 + int filetype = 0;
175.40 + struct ext2_dir_entry_tail *t;
175.41 + int csum_size = 0;
175.42 +
175.43 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
175.44 +
175.45 + retval = ext2fs_get_mem(fs->blocksize, &buf);
175.46 + if (retval)
175.47 + return retval;
175.48 + memset(buf, 0, fs->blocksize);
175.49 + dir = (struct ext2_dir_entry *) buf;
175.50 +
175.51 + if (ext2fs_has_feature_metadata_csum(fs->super))
175.52 + csum_size = sizeof(struct ext2_dir_entry_tail);
175.53 +
175.54 + retval = ext2fs_set_rec_len(fs, fs->blocksize - csum_size, dir);
175.55 + if (retval) {
175.56 + ext2fs_free_mem(&buf);
175.57 + return retval;
175.58 + }
175.59 +
175.60 + if (dir_ino) {
175.61 + if (ext2fs_has_feature_filetype(fs->super))
175.62 + filetype = EXT2_FT_DIR;
175.63 + /*
175.64 + * Set up entry for '.'
175.65 + */
175.66 + dir->inode = dir_ino;
175.67 + ext2fs_dirent_set_name_len(dir, 1);
175.68 + ext2fs_dirent_set_file_type(dir, filetype);
175.69 + dir->name[0] = '.';
175.70 + rec_len = (fs->blocksize - csum_size) - EXT2_DIR_REC_LEN(1);
175.71 + dir->rec_len = EXT2_DIR_REC_LEN(1);
175.72 +
175.73 + /*
175.74 + * Set up entry for '..'
175.75 + */
175.76 + dir = (struct ext2_dir_entry *) (buf + dir->rec_len);
175.77 + retval = ext2fs_set_rec_len(fs, rec_len, dir);
175.78 + if (retval) {
175.79 + ext2fs_free_mem(&buf);
175.80 + return retval;
175.81 + }
175.82 + dir->inode = parent_ino;
175.83 + ext2fs_dirent_set_name_len(dir, 2);
175.84 + ext2fs_dirent_set_file_type(dir, filetype);
175.85 + dir->name[0] = '.';
175.86 + dir->name[1] = '.';
175.87 +
175.88 + }
175.89 +
175.90 + if (csum_size) {
175.91 + t = EXT2_DIRENT_TAIL(buf, fs->blocksize);
175.92 + ext2fs_initialize_dirent_tail(fs, t);
175.93 + }
175.94 + *block = buf;
175.95 + return 0;
175.96 +}
175.97 +
175.98 +/*
175.99 + * Create new directory on inline data
175.100 + */
175.101 +errcode_t ext2fs_new_dir_inline_data(ext2_filsys fs,
175.102 + ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
175.103 + ext2_ino_t parent_ino, __u32 *iblock)
175.104 +{
175.105 + struct ext2_dir_entry *dir = NULL;
175.106 + errcode_t retval;
175.107 + int rec_len;
175.108 +
175.109 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
175.110 +
175.111 + iblock[0] = ext2fs_cpu_to_le32(parent_ino);
175.112 +
175.113 + dir = (struct ext2_dir_entry *)((char *)iblock +
175.114 + EXT4_INLINE_DATA_DOTDOT_SIZE);
175.115 + dir->inode = 0;
175.116 + rec_len = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE;
175.117 + retval = ext2fs_set_rec_len(fs, rec_len, dir);
175.118 + if (retval)
175.119 + goto errout;
175.120 +
175.121 +#ifdef WORDS_BIGENDIAN
175.122 + retval = ext2fs_dirent_swab_out2(fs, (char *)dir, rec_len, 0);
175.123 + if (retval)
175.124 + goto errout;
175.125 +#endif
175.126 +
175.127 +errout:
175.128 + return retval;
175.129 +}
176.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
176.2 +++ b/libext2fs/lib/libext2fs/openfs.c Wed Aug 25 01:28:08 2021 +0200
176.3 @@ -0,0 +1,562 @@
176.4 +/*
176.5 + * openfs.c --- open an ext2 filesystem
176.6 + *
176.7 + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
176.8 + *
176.9 + * %Begin-Header%
176.10 + * This file may be redistributed under the terms of the GNU Library
176.11 + * General Public License, version 2.
176.12 + * %End-Header%
176.13 + */
176.14 +
176.15 +#include "config.h"
176.16 +#include <stdio.h>
176.17 +#include <string.h>
176.18 +#if HAVE_UNISTD_H
176.19 +#include <unistd.h>
176.20 +#endif
176.21 +#include <fcntl.h>
176.22 +#include <time.h>
176.23 +#if HAVE_SYS_STAT_H
176.24 +#include <sys/stat.h>
176.25 +#endif
176.26 +#if HAVE_SYS_TYPES_H
176.27 +#include <sys/types.h>
176.28 +#endif
176.29 +#ifdef HAVE_ERRNO_H
176.30 +#include <errno.h>
176.31 +#endif
176.32 +
176.33 +#include "ext2_fs.h"
176.34 +
176.35 +
176.36 +#include "ext2fs.h"
176.37 +#include "e2image.h"
176.38 +
176.39 +blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs, blk64_t group_block,
176.40 + dgrp_t i)
176.41 +{
176.42 + int bg;
176.43 + int has_super = 0, group_zero_adjust = 0;
176.44 + blk64_t ret_blk;
176.45 +
176.46 + /*
176.47 + * On a bigalloc FS with 1K blocks, block 0 is reserved for non-ext4
176.48 + * stuff, so adjust for that if we're being asked for group 0.
176.49 + */
176.50 + if (i == 0 && fs->blocksize == 1024 && EXT2FS_CLUSTER_RATIO(fs) > 1)
176.51 + group_zero_adjust = 1;
176.52 +
176.53 + if (!ext2fs_has_feature_meta_bg(fs->super) ||
176.54 + (i < fs->super->s_first_meta_bg))
176.55 + return group_block + i + 1 + group_zero_adjust;
176.56 +
176.57 + bg = EXT2_DESC_PER_BLOCK(fs->super) * i;
176.58 + if (ext2fs_bg_has_super(fs, bg))
176.59 + has_super = 1;
176.60 + ret_blk = ext2fs_group_first_block2(fs, bg);
176.61 + /*
176.62 + * If group_block is not the normal value, we're trying to use
176.63 + * the backup group descriptors and superblock --- so use the
176.64 + * alternate location of the second block group in the
176.65 + * metablock group. Ideally we should be testing each bg
176.66 + * descriptor block individually for correctness, but we don't
176.67 + * have the infrastructure in place to do that.
176.68 + */
176.69 + if (group_block != fs->super->s_first_data_block &&
176.70 + ((ret_blk + has_super + fs->super->s_blocks_per_group) <
176.71 + ext2fs_blocks_count(fs->super))) {
176.72 + ret_blk += fs->super->s_blocks_per_group;
176.73 +
176.74 + /*
176.75 + * If we're going to jump forward a block group, make sure
176.76 + * that we adjust has_super to account for the next group's
176.77 + * backup superblock (or lack thereof).
176.78 + */
176.79 + if (ext2fs_bg_has_super(fs, bg + 1))
176.80 + has_super = 1;
176.81 + else
176.82 + has_super = 0;
176.83 + }
176.84 + return ret_blk + has_super + group_zero_adjust;
176.85 +}
176.86 +
176.87 +blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
176.88 +{
176.89 + return ext2fs_descriptor_block_loc2(fs, group_block, i);
176.90 +}
176.91 +
176.92 +errcode_t ext2fs_open(const char *name, int flags, int superblock,
176.93 + unsigned int block_size, io_manager manager,
176.94 + ext2_filsys *ret_fs)
176.95 +{
176.96 + return ext2fs_open2(name, 0, flags, superblock, block_size,
176.97 + manager, ret_fs);
176.98 +}
176.99 +
176.100 +static void block_sha_map_free_entry(void *data)
176.101 +{
176.102 + free(data);
176.103 + return;
176.104 +}
176.105 +
176.106 +/*
176.107 + * Note: if superblock is non-zero, block-size must also be non-zero.
176.108 + * Superblock and block_size can be zero to use the default size.
176.109 + *
176.110 + * Valid flags for ext2fs_open()
176.111 + *
176.112 + * EXT2_FLAG_RW - Open the filesystem for read/write.
176.113 + * EXT2_FLAG_FORCE - Open the filesystem even if some of the
176.114 + * features aren't supported.
176.115 + * EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device
176.116 + * EXT2_FLAG_SKIP_MMP - Open without multi-mount protection check.
176.117 + * EXT2_FLAG_64BITS - Allow 64-bit bitfields (needed for large
176.118 + * filesystems)
176.119 + */
176.120 +errcode_t ext2fs_open2(const char *name, const char *io_options,
176.121 + int flags, int superblock,
176.122 + unsigned int block_size, io_manager manager,
176.123 + ext2_filsys *ret_fs)
176.124 +{
176.125 + ext2_filsys fs;
176.126 + errcode_t retval;
176.127 + unsigned long i, first_meta_bg;
176.128 + __u32 features;
176.129 + unsigned int blocks_per_group, io_flags;
176.130 + blk64_t group_block, blk;
176.131 + char *dest, *cp;
176.132 + int group_zero_adjust = 0;
176.133 + unsigned int inode_size;
176.134 + __u64 groups_cnt;
176.135 +#ifdef WORDS_BIGENDIAN
176.136 + unsigned int groups_per_block;
176.137 + struct ext2_group_desc *gdp;
176.138 + int j;
176.139 +#endif
176.140 + char *time_env;
176.141 +
176.142 + EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);
176.143 +
176.144 + retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
176.145 + if (retval)
176.146 + return retval;
176.147 +
176.148 + memset(fs, 0, sizeof(struct struct_ext2_filsys));
176.149 + fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
176.150 + fs->flags = flags;
176.151 + /* don't overwrite sb backups unless flag is explicitly cleared */
176.152 + fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
176.153 + fs->umask = 022;
176.154 +
176.155 + time_env = getenv("E2FSPROGS_FAKE_TIME");
176.156 + if (time_env)
176.157 + fs->now = strtoul(time_env, NULL, 0);
176.158 +
176.159 + retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
176.160 + if (retval)
176.161 + goto cleanup;
176.162 + strcpy(fs->device_name, name);
176.163 + cp = strchr(fs->device_name, '?');
176.164 + if (!io_options && cp) {
176.165 + *cp++ = 0;
176.166 + io_options = cp;
176.167 + }
176.168 +
176.169 + io_flags = 0;
176.170 + if (flags & EXT2_FLAG_RW)
176.171 + io_flags |= IO_FLAG_RW;
176.172 + if (flags & EXT2_FLAG_EXCLUSIVE)
176.173 + io_flags |= IO_FLAG_EXCLUSIVE;
176.174 + if (flags & EXT2_FLAG_DIRECT_IO)
176.175 + io_flags |= IO_FLAG_DIRECT_IO;
176.176 + retval = manager->open(fs->device_name, io_flags, &fs->io);
176.177 + if (retval)
176.178 + goto cleanup;
176.179 + if (io_options &&
176.180 + (retval = io_channel_set_options(fs->io, io_options)))
176.181 + goto cleanup;
176.182 + fs->image_io = fs->io;
176.183 + fs->io->app_data = fs;
176.184 + retval = io_channel_alloc_buf(fs->io, -SUPERBLOCK_SIZE, &fs->super);
176.185 + if (retval)
176.186 + goto cleanup;
176.187 + if (flags & EXT2_FLAG_IMAGE_FILE) {
176.188 + retval = ext2fs_get_mem(sizeof(struct ext2_image_hdr),
176.189 + &fs->image_header);
176.190 + if (retval)
176.191 + goto cleanup;
176.192 + retval = io_channel_read_blk(fs->io, 0,
176.193 + -(int)sizeof(struct ext2_image_hdr),
176.194 + fs->image_header);
176.195 + if (retval)
176.196 + goto cleanup;
176.197 + if (ext2fs_le32_to_cpu(fs->image_header->magic_number) != EXT2_ET_MAGIC_E2IMAGE)
176.198 + return EXT2_ET_MAGIC_E2IMAGE;
176.199 + superblock = 1;
176.200 + block_size = ext2fs_le32_to_cpu(fs->image_header->fs_blocksize);
176.201 + }
176.202 +
176.203 + /*
176.204 + * If the user specifies a specific block # for the
176.205 + * superblock, then he/she must also specify the block size!
176.206 + * Otherwise, read the master superblock located at offset
176.207 + * SUPERBLOCK_OFFSET from the start of the partition.
176.208 + *
176.209 + * Note: we only save a backup copy of the superblock if we
176.210 + * are reading the superblock from the primary superblock location.
176.211 + */
176.212 + if (superblock) {
176.213 + if (!block_size) {
176.214 + retval = EXT2_ET_INVALID_ARGUMENT;
176.215 + goto cleanup;
176.216 + }
176.217 + io_channel_set_blksize(fs->io, block_size);
176.218 + group_block = superblock;
176.219 + fs->orig_super = 0;
176.220 + } else {
176.221 + io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
176.222 + superblock = 1;
176.223 + group_block = 0;
176.224 + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
176.225 + if (retval)
176.226 + goto cleanup;
176.227 + }
176.228 + retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE,
176.229 + fs->super);
176.230 + if (retval)
176.231 + goto cleanup;
176.232 + if (fs->orig_super)
176.233 + memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE);
176.234 +
176.235 + if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS)) {
176.236 + retval = 0;
176.237 + if (!ext2fs_verify_csum_type(fs, fs->super))
176.238 + retval = EXT2_ET_UNKNOWN_CSUM;
176.239 + if (!ext2fs_superblock_csum_verify(fs, fs->super))
176.240 + retval = EXT2_ET_SB_CSUM_INVALID;
176.241 + }
176.242 +
176.243 +#ifdef WORDS_BIGENDIAN
176.244 + fs->flags |= EXT2_FLAG_SWAP_BYTES;
176.245 + ext2fs_swap_super(fs->super);
176.246 +#else
176.247 + if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
176.248 + retval = EXT2_ET_UNIMPLEMENTED;
176.249 + goto cleanup;
176.250 + }
176.251 +#endif
176.252 +
176.253 + if (fs->super->s_magic != EXT2_SUPER_MAGIC)
176.254 + retval = EXT2_ET_BAD_MAGIC;
176.255 + if (retval)
176.256 + goto cleanup;
176.257 +
176.258 + if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) {
176.259 + retval = EXT2_ET_REV_TOO_HIGH;
176.260 + goto cleanup;
176.261 + }
176.262 +
176.263 + /*
176.264 + * Check for feature set incompatibility
176.265 + */
176.266 + if (!(flags & EXT2_FLAG_FORCE)) {
176.267 + features = fs->super->s_feature_incompat;
176.268 +#ifdef EXT2_LIB_SOFTSUPP_INCOMPAT
176.269 + if (flags & EXT2_FLAG_SOFTSUPP_FEATURES)
176.270 + features &= ~EXT2_LIB_SOFTSUPP_INCOMPAT;
176.271 +#endif
176.272 + if (features & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
176.273 + retval = EXT2_ET_UNSUPP_FEATURE;
176.274 + goto cleanup;
176.275 + }
176.276 +
176.277 + features = fs->super->s_feature_ro_compat;
176.278 +#ifdef EXT2_LIB_SOFTSUPP_RO_COMPAT
176.279 + if (flags & EXT2_FLAG_SOFTSUPP_FEATURES)
176.280 + features &= ~EXT2_LIB_SOFTSUPP_RO_COMPAT;
176.281 +#endif
176.282 + if ((flags & EXT2_FLAG_RW) &&
176.283 + (features & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) {
176.284 + retval = EXT2_ET_RO_UNSUPP_FEATURE;
176.285 + goto cleanup;
176.286 + }
176.287 +
176.288 + if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) &&
176.289 + ext2fs_has_feature_journal_dev(fs->super)) {
176.290 + retval = EXT2_ET_UNSUPP_FEATURE;
176.291 + goto cleanup;
176.292 + }
176.293 + }
176.294 +
176.295 + if (fs->super->s_log_block_size >
176.296 + (unsigned) (EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE)) {
176.297 + retval = EXT2_ET_CORRUPT_SUPERBLOCK;
176.298 + goto cleanup;
176.299 + }
176.300 +
176.301 + /*
176.302 + * bigalloc requires cluster-aware bitfield operations, which at the
176.303 + * moment means we need EXT2_FLAG_64BITS.
176.304 + */
176.305 + if (ext2fs_has_feature_bigalloc(fs->super) &&
176.306 + !(flags & EXT2_FLAG_64BITS)) {
176.307 + retval = EXT2_ET_CANT_USE_LEGACY_BITMAPS;
176.308 + goto cleanup;
176.309 + }
176.310 +
176.311 + if (!ext2fs_has_feature_bigalloc(fs->super) &&
176.312 + (fs->super->s_log_block_size != fs->super->s_log_cluster_size)) {
176.313 + retval = EXT2_ET_CORRUPT_SUPERBLOCK;
176.314 + goto cleanup;
176.315 + }
176.316 + fs->fragsize = fs->blocksize = EXT2_BLOCK_SIZE(fs->super);
176.317 + inode_size = EXT2_INODE_SIZE(fs->super);
176.318 + if ((inode_size < EXT2_GOOD_OLD_INODE_SIZE) ||
176.319 + (inode_size > fs->blocksize) ||
176.320 + (inode_size & (inode_size - 1))) {
176.321 + retval = EXT2_ET_CORRUPT_SUPERBLOCK;
176.322 + goto cleanup;
176.323 + }
176.324 +
176.325 + /* Enforce the block group descriptor size */
176.326 + if (ext2fs_has_feature_64bit(fs->super)) {
176.327 + if (fs->super->s_desc_size < EXT2_MIN_DESC_SIZE_64BIT) {
176.328 + retval = EXT2_ET_BAD_DESC_SIZE;
176.329 + goto cleanup;
176.330 + }
176.331 + }
176.332 +
176.333 + fs->cluster_ratio_bits = fs->super->s_log_cluster_size -
176.334 + fs->super->s_log_block_size;
176.335 + if (EXT2_BLOCKS_PER_GROUP(fs->super) !=
176.336 + EXT2_CLUSTERS_PER_GROUP(fs->super) << fs->cluster_ratio_bits) {
176.337 + retval = EXT2_ET_CORRUPT_SUPERBLOCK;
176.338 + goto cleanup;
176.339 + }
176.340 + fs->inode_blocks_per_group = ((EXT2_INODES_PER_GROUP(fs->super) *
176.341 + EXT2_INODE_SIZE(fs->super) +
176.342 + EXT2_BLOCK_SIZE(fs->super) - 1) /
176.343 + EXT2_BLOCK_SIZE(fs->super));
176.344 + if (block_size) {
176.345 + if (block_size != fs->blocksize) {
176.346 + retval = EXT2_ET_UNEXPECTED_BLOCK_SIZE;
176.347 + goto cleanup;
176.348 + }
176.349 + }
176.350 + /*
176.351 + * Set the blocksize to the filesystem's blocksize.
176.352 + */
176.353 + io_channel_set_blksize(fs->io, fs->blocksize);
176.354 +
176.355 + /*
176.356 + * If this is an external journal device, don't try to read
176.357 + * the group descriptors, because they're not there.
176.358 + */
176.359 + if (ext2fs_has_feature_journal_dev(fs->super)) {
176.360 + fs->group_desc_count = 0;
176.361 + *ret_fs = fs;
176.362 + return 0;
176.363 + }
176.364 +
176.365 + if (EXT2_INODES_PER_GROUP(fs->super) == 0) {
176.366 + retval = EXT2_ET_CORRUPT_SUPERBLOCK;
176.367 + goto cleanup;
176.368 + }
176.369 + /* Precompute the FS UUID to seed other checksums */
176.370 + ext2fs_init_csum_seed(fs);
176.371 +
176.372 + /*
176.373 + * Read group descriptors
176.374 + */
176.375 + blocks_per_group = EXT2_BLOCKS_PER_GROUP(fs->super);
176.376 + if (blocks_per_group == 0 ||
176.377 + blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(fs->super) ||
176.378 + fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super) ||
176.379 + EXT2_DESC_PER_BLOCK(fs->super) == 0 ||
176.380 + fs->super->s_first_data_block >= ext2fs_blocks_count(fs->super)) {
176.381 + retval = EXT2_ET_CORRUPT_SUPERBLOCK;
176.382 + goto cleanup;
176.383 + }
176.384 + groups_cnt = ext2fs_div64_ceil(ext2fs_blocks_count(fs->super) -
176.385 + fs->super->s_first_data_block,
176.386 + blocks_per_group);
176.387 + if (groups_cnt >> 32) {
176.388 + retval = EXT2_ET_CORRUPT_SUPERBLOCK;
176.389 + goto cleanup;
176.390 + }
176.391 + fs->group_desc_count = groups_cnt;
176.392 + if (!(flags & EXT2_FLAG_IGNORE_SB_ERRORS) &&
176.393 + (__u64)fs->group_desc_count * EXT2_INODES_PER_GROUP(fs->super) !=
176.394 + fs->super->s_inodes_count) {
176.395 + retval = EXT2_ET_CORRUPT_SUPERBLOCK;
176.396 + goto cleanup;
176.397 + }
176.398 + fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
176.399 + EXT2_DESC_PER_BLOCK(fs->super));
176.400 + retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
176.401 + &fs->group_desc);
176.402 + if (retval)
176.403 + goto cleanup;
176.404 + if (!group_block)
176.405 + group_block = fs->super->s_first_data_block;
176.406 + /*
176.407 + * On a FS with a 1K blocksize, block 0 is reserved for bootloaders
176.408 + * so we must increment block numbers to any group 0 items.
176.409 + *
176.410 + * However, we cannot touch group_block directly because in the meta_bg
176.411 + * case, the ext2fs_descriptor_block_loc2() function will interpret
176.412 + * group_block != s_first_data_block to mean that we want to access the
176.413 + * backup group descriptors. This is not what we want if the caller
176.414 + * set superblock == 0 (i.e. auto-detect the superblock), which is
176.415 + * what's going on here.
176.416 + */
176.417 + if (group_block == 0 && fs->blocksize == 1024)
176.418 + group_zero_adjust = 1;
176.419 + dest = (char *) fs->group_desc;
176.420 +#ifdef WORDS_BIGENDIAN
176.421 + groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
176.422 +#endif
176.423 + if (ext2fs_has_feature_meta_bg(fs->super) &&
176.424 + !(flags & EXT2_FLAG_IMAGE_FILE)) {
176.425 + first_meta_bg = fs->super->s_first_meta_bg;
176.426 + if (first_meta_bg > fs->desc_blocks)
176.427 + first_meta_bg = fs->desc_blocks;
176.428 + } else
176.429 + first_meta_bg = fs->desc_blocks;
176.430 + if (first_meta_bg) {
176.431 + retval = io_channel_read_blk(fs->io, group_block +
176.432 + group_zero_adjust + 1,
176.433 + first_meta_bg, dest);
176.434 + if (retval)
176.435 + goto cleanup;
176.436 +#ifdef WORDS_BIGENDIAN
176.437 + gdp = (struct ext2_group_desc *) dest;
176.438 + for (j=0; j < groups_per_block*first_meta_bg; j++) {
176.439 + gdp = ext2fs_group_desc(fs, fs->group_desc, j);
176.440 + ext2fs_swap_group_desc2(fs, gdp);
176.441 + }
176.442 +#endif
176.443 + dest += fs->blocksize*first_meta_bg;
176.444 + }
176.445 +
176.446 + for (i = first_meta_bg ; i < fs->desc_blocks; i++) {
176.447 + blk = ext2fs_descriptor_block_loc2(fs, group_block, i);
176.448 + io_channel_cache_readahead(fs->io, blk, 1);
176.449 + }
176.450 +
176.451 + for (i=first_meta_bg ; i < fs->desc_blocks; i++) {
176.452 + blk = ext2fs_descriptor_block_loc2(fs, group_block, i);
176.453 + retval = io_channel_read_blk64(fs->io, blk, 1, dest);
176.454 + if (retval)
176.455 + goto cleanup;
176.456 +#ifdef WORDS_BIGENDIAN
176.457 + for (j=0; j < groups_per_block; j++) {
176.458 + gdp = ext2fs_group_desc(fs, fs->group_desc,
176.459 + i * groups_per_block + j);
176.460 + ext2fs_swap_group_desc2(fs, gdp);
176.461 + }
176.462 +#endif
176.463 + dest += fs->blocksize;
176.464 + }
176.465 +
176.466 + fs->stride = fs->super->s_raid_stride;
176.467 +
176.468 + /*
176.469 + * If recovery is from backup superblock, Clear _UNININT flags &
176.470 + * reset bg_itable_unused to zero
176.471 + */
176.472 + if (superblock > 1 && ext2fs_has_group_desc_csum(fs)) {
176.473 + dgrp_t group;
176.474 +
176.475 + for (group = 0; group < fs->group_desc_count; group++) {
176.476 + ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
176.477 + ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
176.478 + ext2fs_bg_itable_unused_set(fs, group, 0);
176.479 + /* The checksum will be reset later, but fix it here
176.480 + * anyway to avoid printing a lot of spurious errors. */
176.481 + ext2fs_group_desc_csum_set(fs, group);
176.482 + }
176.483 + if (fs->flags & EXT2_FLAG_RW)
176.484 + ext2fs_mark_super_dirty(fs);
176.485 + }
176.486 +
176.487 + if (ext2fs_has_feature_mmp(fs->super) &&
176.488 + !(flags & EXT2_FLAG_SKIP_MMP) &&
176.489 + (flags & (EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE))) {
176.490 + retval = ext2fs_mmp_start(fs);
176.491 + if (retval) {
176.492 + fs->flags |= EXT2_FLAG_SKIP_MMP; /* just do cleanup */
176.493 + ext2fs_mmp_stop(fs);
176.494 + goto cleanup;
176.495 + }
176.496 + }
176.497 +
176.498 + if (fs->flags & EXT2_FLAG_SHARE_DUP) {
176.499 + fs->block_sha_map = ext2fs_hashmap_create(ext2fs_djb2_hash,
176.500 + block_sha_map_free_entry, 4096);
176.501 + if (!fs->block_sha_map) {
176.502 + retval = EXT2_ET_NO_MEMORY;
176.503 + goto cleanup;
176.504 + }
176.505 + ext2fs_set_feature_shared_blocks(fs->super);
176.506 + }
176.507 +
176.508 + fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR;
176.509 + *ret_fs = fs;
176.510 +
176.511 + return 0;
176.512 +cleanup:
176.513 + if (!(flags & EXT2_FLAG_NOFREE_ON_ERROR)) {
176.514 + ext2fs_free(fs);
176.515 + fs = NULL;
176.516 + }
176.517 + *ret_fs = fs;
176.518 + return retval;
176.519 +}
176.520 +
176.521 +/*
176.522 + * Set/get the filesystem data I/O channel.
176.523 + *
176.524 + * These functions are only valid if EXT2_FLAG_IMAGE_FILE is true.
176.525 + */
176.526 +errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io)
176.527 +{
176.528 + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
176.529 + return EXT2_ET_NOT_IMAGE_FILE;
176.530 + if (old_io) {
176.531 + *old_io = (fs->image_io == fs->io) ? 0 : fs->io;
176.532 + }
176.533 + return 0;
176.534 +}
176.535 +
176.536 +errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io)
176.537 +{
176.538 + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
176.539 + return EXT2_ET_NOT_IMAGE_FILE;
176.540 + fs->io = new_io ? new_io : fs->image_io;
176.541 + return 0;
176.542 +}
176.543 +
176.544 +errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io)
176.545 +{
176.546 + errcode_t err;
176.547 +
176.548 + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
176.549 + return EXT2_ET_NOT_IMAGE_FILE;
176.550 + err = io_channel_set_blksize(new_io, fs->blocksize);
176.551 + if (err)
176.552 + return err;
176.553 + if ((new_io == fs->image_io) || (new_io == fs->io))
176.554 + return 0;
176.555 + if ((fs->image_io != fs->io) &&
176.556 + fs->image_io)
176.557 + io_channel_close(fs->image_io);
176.558 + if (fs->io)
176.559 + io_channel_close(fs->io);
176.560 + fs->io = fs->image_io = new_io;
176.561 + fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_RW |
176.562 + EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
176.563 + fs->flags &= ~EXT2_FLAG_IMAGE_FILE;
176.564 + return 0;
176.565 +}
177.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
177.2 +++ b/libext2fs/lib/libext2fs/progress.c Wed Aug 25 01:28:08 2021 +0200
177.3 @@ -0,0 +1,103 @@
177.4 +/*
177.5 + * progress.c - Numeric progress meter
177.6 + *
177.7 + * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
177.8 + * 2003, 2004, 2005 by Theodore Ts'o.
177.9 + *
177.10 + * %Begin-Header%
177.11 + * This file may be redistributed under the terms of the GNU Public
177.12 + * License.
177.13 + * %End-Header%
177.14 + */
177.15 +
177.16 +#include "config.h"
177.17 +#include "ext2fs.h"
177.18 +#include "ext2fsP.h"
177.19 +
177.20 +#include <time.h>
177.21 +
177.22 +static char spaces[80], backspaces[80];
177.23 +static time_t last_update;
177.24 +
177.25 +struct ext2fs_progress_ops ext2fs_numeric_progress_ops = {
177.26 + .init = ext2fs_numeric_progress_init,
177.27 + .update = ext2fs_numeric_progress_update,
177.28 + .close = ext2fs_numeric_progress_close,
177.29 +};
177.30 +
177.31 +static int int_log10(unsigned int arg)
177.32 +{
177.33 + int l;
177.34 +
177.35 + for (l=0; arg ; l++)
177.36 + arg = arg / 10;
177.37 + return l;
177.38 +}
177.39 +
177.40 +void ext2fs_numeric_progress_init(ext2_filsys fs,
177.41 + struct ext2fs_numeric_progress_struct * progress,
177.42 + const char *label, __u64 max)
177.43 +{
177.44 + /*
177.45 + * The PRINT_PROGRESS flag turns on or off ALL
177.46 + * progress-related messages, whereas the SKIP_PROGRESS
177.47 + * environment variable prints the start and end messages but
177.48 + * not the numeric countdown in the middle.
177.49 + */
177.50 + if (!(fs->flags & EXT2_FLAG_PRINT_PROGRESS))
177.51 + return;
177.52 +
177.53 + memset(spaces, ' ', sizeof(spaces)-1);
177.54 + spaces[sizeof(spaces)-1] = 0;
177.55 + memset(backspaces, '\b', sizeof(backspaces)-1);
177.56 + backspaces[sizeof(backspaces)-1] = 0;
177.57 +
177.58 + memset(progress, 0, sizeof(*progress));
177.59 + if (getenv("E2FSPROGS_SKIP_PROGRESS"))
177.60 + progress->skip_progress++;
177.61 +
177.62 +
177.63 + /*
177.64 + * Figure out how many digits we need
177.65 + */
177.66 + progress->max = max;
177.67 + progress->log_max = int_log10(max);
177.68 +
177.69 + if (label) {
177.70 + fputs(label, stdout);
177.71 + fflush(stdout);
177.72 + }
177.73 + last_update = 0;
177.74 +}
177.75 +
177.76 +void ext2fs_numeric_progress_update(ext2_filsys fs,
177.77 + struct ext2fs_numeric_progress_struct * progress,
177.78 + __u64 val)
177.79 +{
177.80 + time_t now;
177.81 +
177.82 + if (!(fs->flags & EXT2_FLAG_PRINT_PROGRESS))
177.83 + return;
177.84 + if (progress->skip_progress)
177.85 + return;
177.86 + now = time(0);
177.87 + if (now == last_update)
177.88 + return;
177.89 + last_update = now;
177.90 +
177.91 + printf("%*llu/%*llu", progress->log_max, val,
177.92 + progress->log_max, progress->max);
177.93 + fprintf(stdout, "%.*s", (2*progress->log_max)+1, backspaces);
177.94 +}
177.95 +
177.96 +void ext2fs_numeric_progress_close(ext2_filsys fs,
177.97 + struct ext2fs_numeric_progress_struct * progress,
177.98 + const char *message)
177.99 +{
177.100 + if (!(fs->flags & EXT2_FLAG_PRINT_PROGRESS))
177.101 + return;
177.102 + fprintf(stdout, "%.*s", (2*progress->log_max)+1, spaces);
177.103 + fprintf(stdout, "%.*s", (2*progress->log_max)+1, backspaces);
177.104 + if (message)
177.105 + fputs(message, stdout);
177.106 +}
178.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
178.2 +++ b/libext2fs/lib/libext2fs/punch.c Wed Aug 25 01:28:08 2021 +0200
178.3 @@ -0,0 +1,509 @@
178.4 +/*
178.5 + * punch.c --- deallocate blocks allocated to an inode
178.6 + *
178.7 + * Copyright (C) 2010 Theodore Ts'o.
178.8 + *
178.9 + * %Begin-Header%
178.10 + * This file may be redistributed under the terms of the GNU Library
178.11 + * General Public License, version 2.
178.12 + * %End-Header%
178.13 + */
178.14 +
178.15 +#include "config.h"
178.16 +#include <stdio.h>
178.17 +#include <string.h>
178.18 +#if HAVE_UNISTD_H
178.19 +#include <unistd.h>
178.20 +#endif
178.21 +#include <errno.h>
178.22 +
178.23 +#include "ext2_fs.h"
178.24 +#include "ext2fs.h"
178.25 +#include "ext2fsP.h"
178.26 +
178.27 +#undef PUNCH_DEBUG
178.28 +
178.29 +/*
178.30 + * This function returns 1 if the specified block is all zeros
178.31 + */
178.32 +static int check_zero_block(char *buf, int blocksize)
178.33 +{
178.34 + char *cp = buf;
178.35 + int left = blocksize;
178.36 +
178.37 + while (left > 0) {
178.38 + if (*cp++)
178.39 + return 0;
178.40 + left--;
178.41 + }
178.42 + return 1;
178.43 +}
178.44 +
178.45 +/*
178.46 + * This clever recursive function handles i_blocks[] as well as
178.47 + * indirect, double indirect, and triple indirect blocks. It iterates
178.48 + * over the entries in the i_blocks array or indirect blocks, and for
178.49 + * each one, will recursively handle any indirect blocks and then
178.50 + * frees and deallocates the blocks.
178.51 + */
178.52 +static errcode_t ind_punch(ext2_filsys fs, struct ext2_inode *inode,
178.53 + char *block_buf, blk_t *p, int level,
178.54 + blk64_t start, blk64_t count, int max)
178.55 +{
178.56 + errcode_t retval;
178.57 + blk_t b;
178.58 + int i;
178.59 + blk64_t offset, incr;
178.60 + int freed = 0;
178.61 +
178.62 +#ifdef PUNCH_DEBUG
178.63 + printf("Entering ind_punch, level %d, start %llu, count %llu, "
178.64 + "max %d\n", level, start, count, max);
178.65 +#endif
178.66 + incr = 1ULL << ((EXT2_BLOCK_SIZE_BITS(fs->super) - 2) * level);
178.67 + for (i = 0, offset = 0; i < max; i++, p++, offset += incr) {
178.68 + if (offset >= start + count)
178.69 + break;
178.70 + if (*p == 0 || (offset+incr) <= start)
178.71 + continue;
178.72 + b = *p;
178.73 + if (level > 0) {
178.74 + blk_t start2;
178.75 +#ifdef PUNCH_DEBUG
178.76 + printf("Reading indirect block %u\n", b);
178.77 +#endif
178.78 + retval = ext2fs_read_ind_block(fs, b, block_buf);
178.79 + if (retval)
178.80 + return retval;
178.81 + start2 = (start > offset) ? start - offset : 0;
178.82 + retval = ind_punch(fs, inode, block_buf + fs->blocksize,
178.83 + (blk_t *) block_buf, level - 1,
178.84 + start2, count - offset,
178.85 + fs->blocksize >> 2);
178.86 + if (retval)
178.87 + return retval;
178.88 + retval = ext2fs_write_ind_block(fs, b, block_buf);
178.89 + if (retval)
178.90 + return retval;
178.91 + if (!check_zero_block(block_buf, fs->blocksize))
178.92 + continue;
178.93 + }
178.94 +#ifdef PUNCH_DEBUG
178.95 + printf("Freeing block %u (offset %llu)\n", b, offset);
178.96 +#endif
178.97 + ext2fs_block_alloc_stats(fs, b, -1);
178.98 + *p = 0;
178.99 + freed++;
178.100 + }
178.101 +#ifdef PUNCH_DEBUG
178.102 + printf("Freed %d blocks\n", freed);
178.103 +#endif
178.104 + return ext2fs_iblk_sub_blocks(fs, inode, freed);
178.105 +}
178.106 +
178.107 +#define BLK_T_MAX ((blk_t)~0ULL)
178.108 +static errcode_t ext2fs_punch_ind(ext2_filsys fs, struct ext2_inode *inode,
178.109 + char *block_buf, blk64_t start, blk64_t end)
178.110 +{
178.111 + errcode_t retval;
178.112 + char *buf = 0;
178.113 + int level;
178.114 + int num = EXT2_NDIR_BLOCKS;
178.115 + blk_t *bp = inode->i_block;
178.116 + blk_t addr_per_block;
178.117 + blk64_t max = EXT2_NDIR_BLOCKS;
178.118 + blk_t count;
178.119 +
178.120 + /* Check start/end don't overflow the 2^32-1 indirect block limit */
178.121 + if (start > BLK_T_MAX)
178.122 + return 0;
178.123 + if (end >= BLK_T_MAX || end - start + 1 >= BLK_T_MAX)
178.124 + count = BLK_T_MAX - start;
178.125 + else
178.126 + count = end - start + 1;
178.127 +
178.128 + if (!block_buf) {
178.129 + retval = ext2fs_get_array(3, fs->blocksize, &buf);
178.130 + if (retval)
178.131 + return retval;
178.132 + block_buf = buf;
178.133 + }
178.134 +
178.135 + addr_per_block = (blk_t)fs->blocksize >> 2;
178.136 +
178.137 + for (level = 0; level < 4; level++, max *= (blk64_t)addr_per_block) {
178.138 +#ifdef PUNCH_DEBUG
178.139 + printf("Main loop level %d, start %llu count %u "
178.140 + "max %llu num %d\n", level, start, count, max, num);
178.141 +#endif
178.142 + if (start < max) {
178.143 + retval = ind_punch(fs, inode, block_buf, bp, level,
178.144 + start, count, num);
178.145 + if (retval)
178.146 + goto errout;
178.147 + if (count > max)
178.148 + count -= max - start;
178.149 + else
178.150 + break;
178.151 + start = 0;
178.152 + } else
178.153 + start -= max;
178.154 + bp += num;
178.155 + if (level == 0) {
178.156 + num = 1;
178.157 + max = 1;
178.158 + }
178.159 + }
178.160 + retval = 0;
178.161 +errout:
178.162 + if (buf)
178.163 + ext2fs_free_mem(&buf);
178.164 + return retval;
178.165 +}
178.166 +#undef BLK_T_MAX
178.167 +
178.168 +#ifdef PUNCH_DEBUG
178.169 +
178.170 +#define dbg_printf(f, a...) printf(f, ## a)
178.171 +
178.172 +static void dbg_print_extent(char *desc, struct ext2fs_extent *extent)
178.173 +{
178.174 + if (desc)
178.175 + printf("%s: ", desc);
178.176 + printf("extent: lblk %llu--%llu, len %u, pblk %llu, flags: ",
178.177 + extent->e_lblk, extent->e_lblk + extent->e_len - 1,
178.178 + extent->e_len, extent->e_pblk);
178.179 + if (extent->e_flags & EXT2_EXTENT_FLAGS_LEAF)
178.180 + fputs("LEAF ", stdout);
178.181 + if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
178.182 + fputs("UNINIT ", stdout);
178.183 + if (extent->e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)
178.184 + fputs("2ND_VISIT ", stdout);
178.185 + if (!extent->e_flags)
178.186 + fputs("(none)", stdout);
178.187 + fputc('\n', stdout);
178.188 +
178.189 +}
178.190 +#else
178.191 +#define dbg_print_extent(desc, ex) do { } while (0)
178.192 +#define dbg_printf(f, a...) do { } while (0)
178.193 +#endif
178.194 +
178.195 +/* Free a range of blocks, respecting cluster boundaries */
178.196 +static errcode_t punch_extent_blocks(ext2_filsys fs, ext2_ino_t ino,
178.197 + struct ext2_inode *inode,
178.198 + blk64_t lfree_start, blk64_t free_start,
178.199 + __u32 free_count, int *freed)
178.200 +{
178.201 + blk64_t pblk;
178.202 + int freed_now = 0;
178.203 + __u32 cluster_freed;
178.204 + errcode_t retval = 0;
178.205 +
178.206 + /* No bigalloc? Just free each block. */
178.207 + if (EXT2FS_CLUSTER_RATIO(fs) == 1) {
178.208 + *freed += free_count;
178.209 + while (free_count-- > 0)
178.210 + ext2fs_block_alloc_stats2(fs, free_start++, -1);
178.211 + return retval;
178.212 + }
178.213 +
178.214 + /*
178.215 + * Try to free up to the next cluster boundary. We assume that all
178.216 + * blocks in a logical cluster map to blocks from the same physical
178.217 + * cluster, and that the offsets within the [pl]clusters match.
178.218 + */
178.219 + if (free_start & EXT2FS_CLUSTER_MASK(fs)) {
178.220 + retval = ext2fs_map_cluster_block(fs, ino, inode,
178.221 + lfree_start, &pblk);
178.222 + if (retval)
178.223 + goto errout;
178.224 + if (!pblk) {
178.225 + ext2fs_block_alloc_stats2(fs, free_start, -1);
178.226 + freed_now++;
178.227 + }
178.228 + cluster_freed = EXT2FS_CLUSTER_RATIO(fs) -
178.229 + (free_start & EXT2FS_CLUSTER_MASK(fs));
178.230 + if (cluster_freed > free_count)
178.231 + cluster_freed = free_count;
178.232 + free_count -= cluster_freed;
178.233 + free_start += cluster_freed;
178.234 + lfree_start += cluster_freed;
178.235 + }
178.236 +
178.237 + /* Free whole clusters from the middle of the range. */
178.238 + while (free_count > 0 && free_count >= (unsigned) EXT2FS_CLUSTER_RATIO(fs)) {
178.239 + ext2fs_block_alloc_stats2(fs, free_start, -1);
178.240 + freed_now++;
178.241 + cluster_freed = EXT2FS_CLUSTER_RATIO(fs);
178.242 + free_count -= cluster_freed;
178.243 + free_start += cluster_freed;
178.244 + lfree_start += cluster_freed;
178.245 + }
178.246 +
178.247 + /* Try to free the last cluster. */
178.248 + if (free_count > 0) {
178.249 + retval = ext2fs_map_cluster_block(fs, ino, inode,
178.250 + lfree_start, &pblk);
178.251 + if (retval)
178.252 + goto errout;
178.253 + if (!pblk) {
178.254 + ext2fs_block_alloc_stats2(fs, free_start, -1);
178.255 + freed_now++;
178.256 + }
178.257 + }
178.258 +
178.259 +errout:
178.260 + *freed += freed_now;
178.261 + return retval;
178.262 +}
178.263 +
178.264 +static errcode_t ext2fs_punch_extent(ext2_filsys fs, ext2_ino_t ino,
178.265 + struct ext2_inode *inode,
178.266 + blk64_t start, blk64_t end)
178.267 +{
178.268 + ext2_extent_handle_t handle = 0;
178.269 + struct ext2fs_extent extent;
178.270 + errcode_t retval;
178.271 + blk64_t free_start, next, lfree_start;
178.272 + __u32 free_count, newlen;
178.273 + int freed = 0;
178.274 + int op;
178.275 +
178.276 + retval = ext2fs_extent_open2(fs, ino, inode, &handle);
178.277 + if (retval)
178.278 + return retval;
178.279 + /*
178.280 + * Find the extent closest to the start of the punch range. We don't
178.281 + * check the return value because _goto() sets the current node to the
178.282 + * next-lowest extent if 'start' is in a hole, and doesn't set a
178.283 + * current node if there was a real error reading the extent tree.
178.284 + * In that case, _get() will error out.
178.285 + *
178.286 + * Note: If _get() returns 'no current node', that simply means that
178.287 + * there aren't any blocks mapped past this point in the file, so we're
178.288 + * done.
178.289 + */
178.290 + ext2fs_extent_goto(handle, start);
178.291 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
178.292 + if (retval == EXT2_ET_NO_CURRENT_NODE) {
178.293 + retval = 0;
178.294 + goto errout;
178.295 + } else if (retval)
178.296 + goto errout;
178.297 + while (1) {
178.298 + op = EXT2_EXTENT_NEXT_LEAF;
178.299 + dbg_print_extent("main loop", &extent);
178.300 + next = extent.e_lblk + extent.e_len;
178.301 + dbg_printf("start %llu, end %llu, next %llu\n",
178.302 + (unsigned long long) start,
178.303 + (unsigned long long) end,
178.304 + (unsigned long long) next);
178.305 + if (start <= extent.e_lblk) {
178.306 + /*
178.307 + * Have we iterated past the end of the punch region?
178.308 + * If so, we can stop.
178.309 + */
178.310 + if (end < extent.e_lblk)
178.311 + break;
178.312 + dbg_printf("Case #%d\n", 1);
178.313 + /* Start of deleted region before extent;
178.314 + adjust beginning of extent */
178.315 + free_start = extent.e_pblk;
178.316 + lfree_start = extent.e_lblk;
178.317 + if (next > end)
178.318 + free_count = end - extent.e_lblk + 1;
178.319 + else
178.320 + free_count = extent.e_len;
178.321 + extent.e_len -= free_count;
178.322 + extent.e_lblk += free_count;
178.323 + extent.e_pblk += free_count;
178.324 + } else if (end >= next-1) {
178.325 + /*
178.326 + * Is the punch region beyond this extent? This can
178.327 + * happen if start is already inside a hole. Try to
178.328 + * advance to the next extent if this is the case.
178.329 + */
178.330 + if (start >= next)
178.331 + goto next_extent;
178.332 + /* End of deleted region after extent;
178.333 + adjust end of extent */
178.334 + dbg_printf("Case #%d\n", 2);
178.335 + newlen = start - extent.e_lblk;
178.336 + free_start = extent.e_pblk + newlen;
178.337 + lfree_start = extent.e_lblk + newlen;
178.338 + free_count = extent.e_len - newlen;
178.339 + extent.e_len = newlen;
178.340 + } else {
178.341 + struct ext2fs_extent newex;
178.342 +
178.343 + dbg_printf("Case #%d\n", 3);
178.344 + /* The hard case; we need to split the extent */
178.345 + newex.e_pblk = extent.e_pblk +
178.346 + (end + 1 - extent.e_lblk);
178.347 + newex.e_lblk = end + 1;
178.348 + newex.e_len = next - end - 1;
178.349 + newex.e_flags = extent.e_flags;
178.350 +
178.351 + extent.e_len = start - extent.e_lblk;
178.352 + free_start = extent.e_pblk + extent.e_len;
178.353 + lfree_start = extent.e_lblk + extent.e_len;
178.354 + free_count = end - start + 1;
178.355 +
178.356 + dbg_print_extent("inserting", &newex);
178.357 + retval = ext2fs_extent_insert(handle,
178.358 + EXT2_EXTENT_INSERT_AFTER, &newex);
178.359 + if (retval)
178.360 + goto errout;
178.361 + retval = ext2fs_extent_fix_parents(handle);
178.362 + if (retval)
178.363 + goto errout;
178.364 + /*
178.365 + * Now pointing at inserted extent; so go back.
178.366 + *
178.367 + * We cannot use EXT2_EXTENT_PREV to go back; note the
178.368 + * subtlety in the comment for fix_parents().
178.369 + */
178.370 + retval = ext2fs_extent_goto(handle, extent.e_lblk);
178.371 + if (retval)
178.372 + goto errout;
178.373 + }
178.374 + if (extent.e_len) {
178.375 + dbg_print_extent("replacing", &extent);
178.376 + retval = ext2fs_extent_replace(handle, 0, &extent);
178.377 + if (retval)
178.378 + goto errout;
178.379 + retval = ext2fs_extent_fix_parents(handle);
178.380 + } else {
178.381 + struct ext2fs_extent newex;
178.382 + blk64_t old_lblk, next_lblk;
178.383 + dbg_printf("deleting current extent%s\n", "");
178.384 +
178.385 + /*
178.386 + * Save the location of the next leaf, then slip
178.387 + * back to the current extent.
178.388 + */
178.389 + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT,
178.390 + &newex);
178.391 + if (retval)
178.392 + goto errout;
178.393 + old_lblk = newex.e_lblk;
178.394 +
178.395 + retval = ext2fs_extent_get(handle,
178.396 + EXT2_EXTENT_NEXT_LEAF,
178.397 + &newex);
178.398 + if (retval == EXT2_ET_EXTENT_NO_NEXT)
178.399 + next_lblk = old_lblk;
178.400 + else if (retval)
178.401 + goto errout;
178.402 + else
178.403 + next_lblk = newex.e_lblk;
178.404 +
178.405 + retval = ext2fs_extent_goto(handle, old_lblk);
178.406 + if (retval)
178.407 + goto errout;
178.408 +
178.409 + /* Now delete the extent. */
178.410 + retval = ext2fs_extent_delete(handle, 0);
178.411 + if (retval)
178.412 + goto errout;
178.413 +
178.414 + retval = ext2fs_extent_fix_parents(handle);
178.415 + if (retval && retval != EXT2_ET_NO_CURRENT_NODE)
178.416 + goto errout;
178.417 + retval = 0;
178.418 +
178.419 + /*
178.420 + * Jump forward to the next extent. If there are
178.421 + * errors, the ext2fs_extent_get down below will
178.422 + * capture them for us.
178.423 + */
178.424 + (void)ext2fs_extent_goto(handle, next_lblk);
178.425 + op = EXT2_EXTENT_CURRENT;
178.426 + }
178.427 + if (retval)
178.428 + goto errout;
178.429 + dbg_printf("Free start %llu, free count = %u\n",
178.430 + free_start, free_count);
178.431 + retval = punch_extent_blocks(fs, ino, inode, lfree_start,
178.432 + free_start, free_count, &freed);
178.433 + if (retval)
178.434 + goto errout;
178.435 + next_extent:
178.436 + retval = ext2fs_extent_get(handle, op,
178.437 + &extent);
178.438 + if (retval == EXT2_ET_EXTENT_NO_NEXT ||
178.439 + retval == EXT2_ET_NO_CURRENT_NODE)
178.440 + break;
178.441 + if (retval)
178.442 + goto errout;
178.443 + }
178.444 + dbg_printf("Freed %d blocks\n", freed);
178.445 + retval = ext2fs_iblk_sub_blocks(fs, inode, freed);
178.446 +errout:
178.447 + ext2fs_extent_free(handle);
178.448 + return retval;
178.449 +}
178.450 +
178.451 +static errcode_t ext2fs_punch_inline_data(ext2_filsys fs, ext2_ino_t ino,
178.452 + struct ext2_inode *inode,
178.453 + blk64_t start,
178.454 + blk64_t end EXT2FS_ATTR((unused)))
178.455 +{
178.456 + errcode_t retval;
178.457 +
178.458 + /*
178.459 + * In libext2fs ext2fs_punch is based on block unit. So that
178.460 + * means that if start > 0 we don't need to do nothing. Due
178.461 + * to this we will remove all inline data in ext2fs_punch()
178.462 + * now.
178.463 + */
178.464 + if (start > 0)
178.465 + return 0;
178.466 +
178.467 + memset((char *)inode->i_block, 0, EXT4_MIN_INLINE_DATA_SIZE);
178.468 + inode->i_size = 0;
178.469 + retval = ext2fs_write_inode(fs, ino, inode);
178.470 + if (retval)
178.471 + return retval;
178.472 +
178.473 + return ext2fs_inline_data_ea_remove(fs, ino);
178.474 +}
178.475 +
178.476 +/*
178.477 + * Deallocate all logical _blocks_ starting at start to end, inclusive.
178.478 + * If end is ~0ULL, then this is effectively truncate.
178.479 + */
178.480 +errcode_t ext2fs_punch(ext2_filsys fs, ext2_ino_t ino,
178.481 + struct ext2_inode *inode,
178.482 + char *block_buf, blk64_t start,
178.483 + blk64_t end)
178.484 +{
178.485 + errcode_t retval;
178.486 + struct ext2_inode inode_buf;
178.487 +
178.488 + if (start > end)
178.489 + return EINVAL;
178.490 +
178.491 + /* Read inode structure if necessary */
178.492 + if (!inode) {
178.493 + retval = ext2fs_read_inode(fs, ino, &inode_buf);
178.494 + if (retval)
178.495 + return retval;
178.496 + inode = &inode_buf;
178.497 + }
178.498 + if (inode->i_flags & EXT4_INLINE_DATA_FL)
178.499 + return ext2fs_punch_inline_data(fs, ino, inode, start, end);
178.500 + else if (inode->i_flags & EXT4_EXTENTS_FL)
178.501 + retval = ext2fs_punch_extent(fs, ino, inode, start, end);
178.502 + else
178.503 + retval = ext2fs_punch_ind(fs, inode, block_buf, start, end);
178.504 + if (retval)
178.505 + return retval;
178.506 +
178.507 +#ifdef PUNCH_DEBUG
178.508 + printf("%u: write inode size now %u blocks %u\n",
178.509 + ino, inode->i_size, inode->i_blocks);
178.510 +#endif
178.511 + return ext2fs_write_inode(fs, ino, inode);
178.512 +}
179.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
179.2 +++ b/libext2fs/lib/libext2fs/rbtree.c Wed Aug 25 01:28:08 2021 +0200
179.3 @@ -0,0 +1,451 @@
179.4 +/*
179.5 + Red Black Trees
179.6 + (C) 1999 Andrea Arcangeli <andrea@suse.de>
179.7 + (C) 2002 David Woodhouse <dwmw2@infradead.org>
179.8 +
179.9 + This program is free software; you can redistribute it and/or modify
179.10 + it under the terms of the GNU General Public License as published by
179.11 + the Free Software Foundation; either version 2 of the License, or
179.12 + (at your option) any later version.
179.13 +
179.14 + This program is distributed in the hope that it will be useful,
179.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
179.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
179.17 + GNU General Public License for more details.
179.18 +
179.19 + You should have received a copy of the GNU General Public License
179.20 + along with this program; if not, write to the Free Software
179.21 + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
179.22 +
179.23 + linux/lib/rbtree.c
179.24 +*/
179.25 +
179.26 +#include "rbtree.h"
179.27 +
179.28 +static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
179.29 +{
179.30 + struct rb_node *right = node->rb_right;
179.31 + struct rb_node *parent = ext2fs_rb_parent(node);
179.32 +
179.33 + if ((node->rb_right = right->rb_left))
179.34 + ext2fs_rb_set_parent(right->rb_left, node);
179.35 + right->rb_left = node;
179.36 +
179.37 + ext2fs_rb_set_parent(right, parent);
179.38 +
179.39 + if (parent)
179.40 + {
179.41 + if (node == parent->rb_left)
179.42 + parent->rb_left = right;
179.43 + else
179.44 + parent->rb_right = right;
179.45 + }
179.46 + else
179.47 + root->rb_node = right;
179.48 + ext2fs_rb_set_parent(node, right);
179.49 +}
179.50 +
179.51 +static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
179.52 +{
179.53 + struct rb_node *left = node->rb_left;
179.54 + struct rb_node *parent = ext2fs_rb_parent(node);
179.55 +
179.56 + if ((node->rb_left = left->rb_right))
179.57 + ext2fs_rb_set_parent(left->rb_right, node);
179.58 + left->rb_right = node;
179.59 +
179.60 + ext2fs_rb_set_parent(left, parent);
179.61 +
179.62 + if (parent)
179.63 + {
179.64 + if (node == parent->rb_right)
179.65 + parent->rb_right = left;
179.66 + else
179.67 + parent->rb_left = left;
179.68 + }
179.69 + else
179.70 + root->rb_node = left;
179.71 + ext2fs_rb_set_parent(node, left);
179.72 +}
179.73 +
179.74 +void ext2fs_rb_insert_color(struct rb_node *node, struct rb_root *root)
179.75 +{
179.76 + struct rb_node *parent, *gparent;
179.77 +
179.78 + while ((parent = ext2fs_rb_parent(node)) && ext2fs_rb_is_red(parent))
179.79 + {
179.80 + gparent = ext2fs_rb_parent(parent);
179.81 +
179.82 + if (parent == gparent->rb_left)
179.83 + {
179.84 + {
179.85 + register struct rb_node *uncle = gparent->rb_right;
179.86 + if (uncle && ext2fs_rb_is_red(uncle))
179.87 + {
179.88 + ext2fs_rb_set_black(uncle);
179.89 + ext2fs_rb_set_black(parent);
179.90 + ext2fs_rb_set_red(gparent);
179.91 + node = gparent;
179.92 + continue;
179.93 + }
179.94 + }
179.95 +
179.96 + if (parent->rb_right == node)
179.97 + {
179.98 + register struct rb_node *tmp;
179.99 + __rb_rotate_left(parent, root);
179.100 + tmp = parent;
179.101 + parent = node;
179.102 + node = tmp;
179.103 + }
179.104 +
179.105 + ext2fs_rb_set_black(parent);
179.106 + ext2fs_rb_set_red(gparent);
179.107 + __rb_rotate_right(gparent, root);
179.108 + } else {
179.109 + {
179.110 + register struct rb_node *uncle = gparent->rb_left;
179.111 + if (uncle && ext2fs_rb_is_red(uncle))
179.112 + {
179.113 + ext2fs_rb_set_black(uncle);
179.114 + ext2fs_rb_set_black(parent);
179.115 + ext2fs_rb_set_red(gparent);
179.116 + node = gparent;
179.117 + continue;
179.118 + }
179.119 + }
179.120 +
179.121 + if (parent->rb_left == node)
179.122 + {
179.123 + register struct rb_node *tmp;
179.124 + __rb_rotate_right(parent, root);
179.125 + tmp = parent;
179.126 + parent = node;
179.127 + node = tmp;
179.128 + }
179.129 +
179.130 + ext2fs_rb_set_black(parent);
179.131 + ext2fs_rb_set_red(gparent);
179.132 + __rb_rotate_left(gparent, root);
179.133 + }
179.134 + }
179.135 +
179.136 + ext2fs_rb_set_black(root->rb_node);
179.137 +}
179.138 +
179.139 +static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
179.140 + struct rb_root *root)
179.141 +{
179.142 + struct rb_node *other;
179.143 +
179.144 + while ((!node || ext2fs_rb_is_black(node)) && node != root->rb_node)
179.145 + {
179.146 + if (parent->rb_left == node)
179.147 + {
179.148 + other = parent->rb_right;
179.149 + if (ext2fs_rb_is_red(other))
179.150 + {
179.151 + ext2fs_rb_set_black(other);
179.152 + ext2fs_rb_set_red(parent);
179.153 + __rb_rotate_left(parent, root);
179.154 + other = parent->rb_right;
179.155 + }
179.156 + if ((!other->rb_left || ext2fs_rb_is_black(other->rb_left)) &&
179.157 + (!other->rb_right || ext2fs_rb_is_black(other->rb_right)))
179.158 + {
179.159 + ext2fs_rb_set_red(other);
179.160 + node = parent;
179.161 + parent = ext2fs_rb_parent(node);
179.162 + }
179.163 + else
179.164 + {
179.165 + if (!other->rb_right || ext2fs_rb_is_black(other->rb_right))
179.166 + {
179.167 + ext2fs_rb_set_black(other->rb_left);
179.168 + ext2fs_rb_set_red(other);
179.169 + __rb_rotate_right(other, root);
179.170 + other = parent->rb_right;
179.171 + }
179.172 + ext2fs_rb_set_color(other, ext2fs_rb_color(parent));
179.173 + ext2fs_rb_set_black(parent);
179.174 + ext2fs_rb_set_black(other->rb_right);
179.175 + __rb_rotate_left(parent, root);
179.176 + node = root->rb_node;
179.177 + break;
179.178 + }
179.179 + }
179.180 + else
179.181 + {
179.182 + other = parent->rb_left;
179.183 + if (ext2fs_rb_is_red(other))
179.184 + {
179.185 + ext2fs_rb_set_black(other);
179.186 + ext2fs_rb_set_red(parent);
179.187 + __rb_rotate_right(parent, root);
179.188 + other = parent->rb_left;
179.189 + }
179.190 + if ((!other->rb_left || ext2fs_rb_is_black(other->rb_left)) &&
179.191 + (!other->rb_right || ext2fs_rb_is_black(other->rb_right)))
179.192 + {
179.193 + ext2fs_rb_set_red(other);
179.194 + node = parent;
179.195 + parent = ext2fs_rb_parent(node);
179.196 + }
179.197 + else
179.198 + {
179.199 + if (!other->rb_left || ext2fs_rb_is_black(other->rb_left))
179.200 + {
179.201 + ext2fs_rb_set_black(other->rb_right);
179.202 + ext2fs_rb_set_red(other);
179.203 + __rb_rotate_left(other, root);
179.204 + other = parent->rb_left;
179.205 + }
179.206 + ext2fs_rb_set_color(other, ext2fs_rb_color(parent));
179.207 + ext2fs_rb_set_black(parent);
179.208 + ext2fs_rb_set_black(other->rb_left);
179.209 + __rb_rotate_right(parent, root);
179.210 + node = root->rb_node;
179.211 + break;
179.212 + }
179.213 + }
179.214 + }
179.215 + if (node)
179.216 + ext2fs_rb_set_black(node);
179.217 +}
179.218 +
179.219 +void ext2fs_rb_erase(struct rb_node *node, struct rb_root *root)
179.220 +{
179.221 + struct rb_node *child, *parent;
179.222 + int color;
179.223 +
179.224 + if (!node->rb_left)
179.225 + child = node->rb_right;
179.226 + else if (!node->rb_right)
179.227 + child = node->rb_left;
179.228 + else
179.229 + {
179.230 + struct rb_node *old = node, *left;
179.231 +
179.232 + node = node->rb_right;
179.233 + while ((left = node->rb_left) != NULL)
179.234 + node = left;
179.235 +
179.236 + if (ext2fs_rb_parent(old)) {
179.237 + if (ext2fs_rb_parent(old)->rb_left == old)
179.238 + ext2fs_rb_parent(old)->rb_left = node;
179.239 + else
179.240 + ext2fs_rb_parent(old)->rb_right = node;
179.241 + } else
179.242 + root->rb_node = node;
179.243 +
179.244 + child = node->rb_right;
179.245 + parent = ext2fs_rb_parent(node);
179.246 + color = ext2fs_rb_color(node);
179.247 +
179.248 + if (parent == old) {
179.249 + parent = node;
179.250 + } else {
179.251 + if (child)
179.252 + ext2fs_rb_set_parent(child, parent);
179.253 + parent->rb_left = child;
179.254 +
179.255 + node->rb_right = old->rb_right;
179.256 + ext2fs_rb_set_parent(old->rb_right, node);
179.257 + }
179.258 +
179.259 + node->rb_parent_color = old->rb_parent_color;
179.260 + node->rb_left = old->rb_left;
179.261 + ext2fs_rb_set_parent(old->rb_left, node);
179.262 +
179.263 + goto color;
179.264 + }
179.265 +
179.266 + parent = ext2fs_rb_parent(node);
179.267 + color = ext2fs_rb_color(node);
179.268 +
179.269 + if (child)
179.270 + ext2fs_rb_set_parent(child, parent);
179.271 + if (parent)
179.272 + {
179.273 + if (parent->rb_left == node)
179.274 + parent->rb_left = child;
179.275 + else
179.276 + parent->rb_right = child;
179.277 + }
179.278 + else
179.279 + root->rb_node = child;
179.280 +
179.281 + color:
179.282 + if (color == RB_BLACK)
179.283 + __rb_erase_color(child, parent, root);
179.284 +}
179.285 +
179.286 +static void ext2fs_rb_augment_path(struct rb_node *node, rb_augment_f func, void *data)
179.287 +{
179.288 + struct rb_node *parent;
179.289 +
179.290 +up:
179.291 + func(node, data);
179.292 + parent = ext2fs_rb_parent(node);
179.293 + if (!parent)
179.294 + return;
179.295 +
179.296 + if (node == parent->rb_left && parent->rb_right)
179.297 + func(parent->rb_right, data);
179.298 + else if (parent->rb_left)
179.299 + func(parent->rb_left, data);
179.300 +
179.301 + node = parent;
179.302 + goto up;
179.303 +}
179.304 +
179.305 +/*
179.306 + * after inserting @node into the tree, update the tree to account for
179.307 + * both the new entry and any damage done by rebalance
179.308 + */
179.309 +void ext2fs_rb_augment_insert(struct rb_node *node, rb_augment_f func, void *data)
179.310 +{
179.311 + if (node->rb_left)
179.312 + node = node->rb_left;
179.313 + else if (node->rb_right)
179.314 + node = node->rb_right;
179.315 +
179.316 + ext2fs_rb_augment_path(node, func, data);
179.317 +}
179.318 +
179.319 +/*
179.320 + * before removing the node, find the deepest node on the rebalance path
179.321 + * that will still be there after @node gets removed
179.322 + */
179.323 +struct rb_node *ext2fs_rb_augment_erase_begin(struct rb_node *node)
179.324 +{
179.325 + struct rb_node *deepest;
179.326 +
179.327 + if (!node->rb_right && !node->rb_left)
179.328 + deepest = ext2fs_rb_parent(node);
179.329 + else if (!node->rb_right)
179.330 + deepest = node->rb_left;
179.331 + else if (!node->rb_left)
179.332 + deepest = node->rb_right;
179.333 + else {
179.334 + deepest = ext2fs_rb_next(node);
179.335 + if (deepest->rb_right)
179.336 + deepest = deepest->rb_right;
179.337 + else if (ext2fs_rb_parent(deepest) != node)
179.338 + deepest = ext2fs_rb_parent(deepest);
179.339 + }
179.340 +
179.341 + return deepest;
179.342 +}
179.343 +
179.344 +/*
179.345 + * after removal, update the tree to account for the removed entry
179.346 + * and any rebalance damage.
179.347 + */
179.348 +void ext2fs_rb_augment_erase_end(struct rb_node *node, rb_augment_f func, void *data)
179.349 +{
179.350 + if (node)
179.351 + ext2fs_rb_augment_path(node, func, data);
179.352 +}
179.353 +
179.354 +/*
179.355 + * This function returns the first node (in sort order) of the tree.
179.356 + */
179.357 +struct rb_node *ext2fs_rb_first(const struct rb_root *root)
179.358 +{
179.359 + struct rb_node *n;
179.360 +
179.361 + n = root->rb_node;
179.362 + if (!n)
179.363 + return NULL;
179.364 + while (n->rb_left)
179.365 + n = n->rb_left;
179.366 + return n;
179.367 +}
179.368 +
179.369 +struct rb_node *ext2fs_rb_last(const struct rb_root *root)
179.370 +{
179.371 + struct rb_node *n;
179.372 +
179.373 + n = root->rb_node;
179.374 + if (!n)
179.375 + return NULL;
179.376 + while (n->rb_right)
179.377 + n = n->rb_right;
179.378 + return n;
179.379 +}
179.380 +
179.381 +struct rb_node *ext2fs_rb_next(struct rb_node *node)
179.382 +{
179.383 + struct rb_node *parent;
179.384 +
179.385 + if (ext2fs_rb_parent(node) == node)
179.386 + return NULL;
179.387 +
179.388 + /* If we have a right-hand child, go down and then left as far
179.389 + as we can. */
179.390 + if (node->rb_right) {
179.391 + node = node->rb_right;
179.392 + while (node->rb_left)
179.393 + node=node->rb_left;
179.394 + return (struct rb_node *)node;
179.395 + }
179.396 +
179.397 + /* No right-hand children. Everything down and left is
179.398 + smaller than us, so any 'next' node must be in the general
179.399 + direction of our parent. Go up the tree; any time the
179.400 + ancestor is a right-hand child of its parent, keep going
179.401 + up. First time it's a left-hand child of its parent, said
179.402 + parent is our 'next' node. */
179.403 + while ((parent = ext2fs_rb_parent(node)) && node == parent->rb_right)
179.404 + node = parent;
179.405 +
179.406 + return parent;
179.407 +}
179.408 +
179.409 +struct rb_node *ext2fs_rb_prev(struct rb_node *node)
179.410 +{
179.411 + struct rb_node *parent;
179.412 +
179.413 + if (ext2fs_rb_parent(node) == node)
179.414 + return NULL;
179.415 +
179.416 + /* If we have a left-hand child, go down and then right as far
179.417 + as we can. */
179.418 + if (node->rb_left) {
179.419 + node = node->rb_left;
179.420 + while (node->rb_right)
179.421 + node=node->rb_right;
179.422 + return (struct rb_node *)node;
179.423 + }
179.424 +
179.425 + /* No left-hand children. Go up till we find an ancestor which
179.426 + is a right-hand child of its parent */
179.427 + while ((parent = ext2fs_rb_parent(node)) && node == parent->rb_left)
179.428 + node = parent;
179.429 +
179.430 + return parent;
179.431 +}
179.432 +
179.433 +void ext2fs_rb_replace_node(struct rb_node *victim, struct rb_node *new,
179.434 + struct rb_root *root)
179.435 +{
179.436 + struct rb_node *parent = ext2fs_rb_parent(victim);
179.437 +
179.438 + /* Set the surrounding nodes to point to the replacement */
179.439 + if (parent) {
179.440 + if (victim == parent->rb_left)
179.441 + parent->rb_left = new;
179.442 + else
179.443 + parent->rb_right = new;
179.444 + } else {
179.445 + root->rb_node = new;
179.446 + }
179.447 + if (victim->rb_left)
179.448 + ext2fs_rb_set_parent(victim->rb_left, new);
179.449 + if (victim->rb_right)
179.450 + ext2fs_rb_set_parent(victim->rb_right, new);
179.451 +
179.452 + /* Copy the pointers/colour from the victim to the replacement */
179.453 + *new = *victim;
179.454 +}
180.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
180.2 +++ b/libext2fs/lib/libext2fs/rbtree.h Wed Aug 25 01:28:08 2021 +0200
180.3 @@ -0,0 +1,192 @@
180.4 +/*
180.5 + Red Black Trees
180.6 + (C) 1999 Andrea Arcangeli <andrea@suse.de>
180.7 +
180.8 + This program is free software; you can redistribute it and/or modify
180.9 + it under the terms of the GNU General Public License as published by
180.10 + the Free Software Foundation; either version 2 of the License, or
180.11 + (at your option) any later version.
180.12 +
180.13 + This program is distributed in the hope that it will be useful,
180.14 + but WITHOUT ANY WARRANTY; without even the implied warranty of
180.15 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
180.16 + GNU General Public License for more details.
180.17 +
180.18 + You should have received a copy of the GNU General Public License
180.19 + along with this program; if not, write to the Free Software
180.20 + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
180.21 +
180.22 + linux/include/linux/rbtree.h
180.23 +
180.24 + To use rbtrees you'll have to implement your own insert and search cores.
180.25 + This will avoid us to use callbacks and to drop dramatically performances.
180.26 + I know it's not the cleaner way, but in C (not in C++) to get
180.27 + performances and genericity...
180.28 +
180.29 + Some example of insert and search follows here. The search is a plain
180.30 + normal search over an ordered tree. The insert instead must be implemented
180.31 + in two steps: First, the code must insert the element in order as a red leaf
180.32 + in the tree, and then the support library function rb_insert_color() must
180.33 + be called. Such function will do the not trivial work to rebalance the
180.34 + rbtree, if necessary.
180.35 +
180.36 +-----------------------------------------------------------------------
180.37 +static inline struct page * rb_search_page_cache(struct inode * inode,
180.38 + unsigned long offset)
180.39 +{
180.40 + struct rb_node * n = inode->i_rb_page_cache.rb_node;
180.41 + struct page * page;
180.42 +
180.43 + while (n)
180.44 + {
180.45 + page = rb_entry(n, struct page, rb_page_cache);
180.46 +
180.47 + if (offset < page->offset)
180.48 + n = n->rb_left;
180.49 + else if (offset > page->offset)
180.50 + n = n->rb_right;
180.51 + else
180.52 + return page;
180.53 + }
180.54 + return NULL;
180.55 +}
180.56 +
180.57 +static inline struct page * __rb_insert_page_cache(struct inode * inode,
180.58 + unsigned long offset,
180.59 + struct rb_node * node)
180.60 +{
180.61 + struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
180.62 + struct rb_node * parent = NULL;
180.63 + struct page * page;
180.64 +
180.65 + while (*p)
180.66 + {
180.67 + parent = *p;
180.68 + page = rb_entry(parent, struct page, rb_page_cache);
180.69 +
180.70 + if (offset < page->offset)
180.71 + p = &(*p)->rb_left;
180.72 + else if (offset > page->offset)
180.73 + p = &(*p)->rb_right;
180.74 + else
180.75 + return page;
180.76 + }
180.77 +
180.78 + rb_link_node(node, parent, p);
180.79 +
180.80 + return NULL;
180.81 +}
180.82 +
180.83 +static inline struct page * rb_insert_page_cache(struct inode * inode,
180.84 + unsigned long offset,
180.85 + struct rb_node * node)
180.86 +{
180.87 + struct page * ret;
180.88 + if ((ret = __rb_insert_page_cache(inode, offset, node)))
180.89 + goto out;
180.90 + rb_insert_color(node, &inode->i_rb_page_cache);
180.91 + out:
180.92 + return ret;
180.93 +}
180.94 +-----------------------------------------------------------------------
180.95 +*/
180.96 +
180.97 +#ifndef _LINUX_RBTREE_H
180.98 +#define _LINUX_RBTREE_H
180.99 +
180.100 +#include <stdlib.h>
180.101 +#include <stdint.h>
180.102 +
180.103 +#undef offsetof
180.104 +#ifdef __compiler_offsetof
180.105 +#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
180.106 +#else
180.107 +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
180.108 +#endif
180.109 +
180.110 +#define container_of(ptr, type, member) ({ \
180.111 + const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
180.112 + (type *)( (char *)__mptr - offsetof(type,member) );})
180.113 +
180.114 +struct rb_node
180.115 +{
180.116 + uintptr_t rb_parent_color;
180.117 +#define RB_RED 0
180.118 +#define RB_BLACK 1
180.119 + struct rb_node *rb_right;
180.120 + struct rb_node *rb_left;
180.121 +} __attribute__((aligned(sizeof(long))));
180.122 + /* The alignment might seem pointless, but allegedly CRIS needs it */
180.123 +
180.124 +struct rb_root
180.125 +{
180.126 + struct rb_node *rb_node;
180.127 +};
180.128 +
180.129 +
180.130 +#define ext2fs_rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
180.131 +#define ext2fs_rb_color(r) ((r)->rb_parent_color & 1)
180.132 +#define ext2fs_rb_is_red(r) (!ext2fs_rb_color(r))
180.133 +#define ext2fs_rb_is_black(r) ext2fs_rb_color(r)
180.134 +#define ext2fs_rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
180.135 +#define ext2fs_rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
180.136 +
180.137 +static inline void ext2fs_rb_set_parent(struct rb_node *rb, struct rb_node *p)
180.138 +{
180.139 + rb->rb_parent_color = (rb->rb_parent_color & 3) | (uintptr_t)p;
180.140 +}
180.141 +static inline void ext2fs_rb_set_color(struct rb_node *rb, int color)
180.142 +{
180.143 + rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
180.144 +}
180.145 +
180.146 +#define RB_ROOT (struct rb_root) { NULL, }
180.147 +#define ext2fs_rb_entry(ptr, type, member) container_of(ptr, type, member)
180.148 +
180.149 +static inline int ext2fs_rb_empty_root(struct rb_root *root)
180.150 +{
180.151 + return root->rb_node == NULL;
180.152 +}
180.153 +
180.154 +static inline int ext2fs_rb_empty_node(struct rb_node *node)
180.155 +{
180.156 + return ext2fs_rb_parent(node) == node;
180.157 +}
180.158 +
180.159 +static inline void ext2fs_rb_clear_node(struct rb_node *node)
180.160 +{
180.161 + ext2fs_rb_set_parent(node, node);
180.162 +}
180.163 +
180.164 +extern void ext2fs_rb_insert_color(struct rb_node *, struct rb_root *);
180.165 +extern void ext2fs_rb_erase(struct rb_node *, struct rb_root *);
180.166 +
180.167 +typedef void (*rb_augment_f)(struct rb_node *node, void *data);
180.168 +
180.169 +extern void ext2fs_rb_augment_insert(struct rb_node *node,
180.170 + rb_augment_f func, void *data);
180.171 +extern struct rb_node *ext2fs_rb_augment_erase_begin(struct rb_node *node);
180.172 +extern void ext2fs_rb_augment_erase_end(struct rb_node *node,
180.173 + rb_augment_f func, void *data);
180.174 +
180.175 +/* Find logical next and previous nodes in a tree */
180.176 +extern struct rb_node *ext2fs_rb_next(struct rb_node *);
180.177 +extern struct rb_node *ext2fs_rb_prev(struct rb_node *);
180.178 +extern struct rb_node *ext2fs_rb_first(const struct rb_root *);
180.179 +extern struct rb_node *ext2fs_rb_last(const struct rb_root *);
180.180 +
180.181 +/* Fast replacement of a single node without remove/rebalance/add/rebalance */
180.182 +extern void ext2fs_rb_replace_node(struct rb_node *victim, struct rb_node *new,
180.183 + struct rb_root *root);
180.184 +
180.185 +static inline void ext2fs_rb_link_node(struct rb_node * node,
180.186 + struct rb_node * parent,
180.187 + struct rb_node ** rb_link)
180.188 +{
180.189 + node->rb_parent_color = (uintptr_t)parent;
180.190 + node->rb_left = node->rb_right = NULL;
180.191 +
180.192 + *rb_link = node;
180.193 +}
180.194 +
180.195 +#endif /* _LINUX_RBTREE_H */
181.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
181.2 +++ b/libext2fs/lib/libext2fs/read_bb.c Wed Aug 25 01:28:08 2021 +0200
181.3 @@ -0,0 +1,102 @@
181.4 +/*
181.5 + * read_bb --- read the bad blocks inode
181.6 + *
181.7 + * Copyright (C) 1994 Theodore Ts'o.
181.8 + *
181.9 + * %Begin-Header%
181.10 + * This file may be redistributed under the terms of the GNU Library
181.11 + * General Public License, version 2.
181.12 + * %End-Header%
181.13 + */
181.14 +
181.15 +#include "config.h"
181.16 +#include <stdio.h>
181.17 +#include <string.h>
181.18 +#if HAVE_UNISTD_H
181.19 +#include <unistd.h>
181.20 +#endif
181.21 +#include <fcntl.h>
181.22 +#include <time.h>
181.23 +#if HAVE_SYS_STAT_H
181.24 +#include <sys/stat.h>
181.25 +#endif
181.26 +#if HAVE_SYS_TYPES_H
181.27 +#include <sys/types.h>
181.28 +#endif
181.29 +
181.30 +#include "ext2_fs.h"
181.31 +#include "ext2fs.h"
181.32 +
181.33 +struct read_bb_record {
181.34 + ext2_badblocks_list bb_list;
181.35 + errcode_t err;
181.36 +};
181.37 +
181.38 +/*
181.39 + * Helper function for ext2fs_read_bb_inode()
181.40 + */
181.41 +#ifdef __TURBOC__
181.42 + #pragma argsused
181.43 +#endif
181.44 +static int mark_bad_block(ext2_filsys fs, blk_t *block_nr,
181.45 + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
181.46 + blk_t ref_block EXT2FS_ATTR((unused)),
181.47 + int ref_offset EXT2FS_ATTR((unused)),
181.48 + void *priv_data)
181.49 +{
181.50 + struct read_bb_record *rb = (struct read_bb_record *) priv_data;
181.51 +
181.52 + if (blockcnt < 0)
181.53 + return 0;
181.54 +
181.55 + if ((*block_nr < fs->super->s_first_data_block) ||
181.56 + (*block_nr >= ext2fs_blocks_count(fs->super)))
181.57 + return 0; /* Ignore illegal blocks */
181.58 +
181.59 + rb->err = ext2fs_badblocks_list_add(rb->bb_list, *block_nr);
181.60 + if (rb->err)
181.61 + return BLOCK_ABORT;
181.62 + return 0;
181.63 +}
181.64 +
181.65 +/*
181.66 + * Reads the current bad blocks from the bad blocks inode.
181.67 + */
181.68 +errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list)
181.69 +{
181.70 + errcode_t retval;
181.71 + struct read_bb_record rb;
181.72 + struct ext2_inode inode;
181.73 + blk_t numblocks;
181.74 +
181.75 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
181.76 +
181.77 + if (!*bb_list) {
181.78 + retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
181.79 + if (retval)
181.80 + return retval;
181.81 + numblocks = inode.i_blocks;
181.82 + if (!(ext2fs_has_feature_huge_file(fs->super) &&
181.83 + (inode.i_flags & EXT4_HUGE_FILE_FL)))
181.84 + numblocks = numblocks / (fs->blocksize / 512);
181.85 + numblocks += 20;
181.86 + if (numblocks < 50)
181.87 + numblocks = 50;
181.88 + if (numblocks > 50000)
181.89 + numblocks = 500;
181.90 + retval = ext2fs_badblocks_list_create(bb_list, numblocks);
181.91 + if (retval)
181.92 + return retval;
181.93 + }
181.94 +
181.95 + rb.bb_list = *bb_list;
181.96 + rb.err = 0;
181.97 + retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, BLOCK_FLAG_READ_ONLY,
181.98 + 0, mark_bad_block, &rb);
181.99 + if (retval)
181.100 + return retval;
181.101 +
181.102 + return rb.err;
181.103 +}
181.104 +
181.105 +
182.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
182.2 +++ b/libext2fs/lib/libext2fs/read_bb_file.c Wed Aug 25 01:28:08 2021 +0200
182.3 @@ -0,0 +1,109 @@
182.4 +/*
182.5 + * read_bb_file.c --- read a list of bad blocks from a FILE *
182.6 + *
182.7 + * Copyright (C) 1994, 1995, 2000 Theodore Ts'o.
182.8 + *
182.9 + * %Begin-Header%
182.10 + * This file may be redistributed under the terms of the GNU Library
182.11 + * General Public License, version 2.
182.12 + * %End-Header%
182.13 + */
182.14 +
182.15 +#include "config.h"
182.16 +#include <stdio.h>
182.17 +#include <string.h>
182.18 +#if HAVE_UNISTD_H
182.19 +#include <unistd.h>
182.20 +#endif
182.21 +#include <fcntl.h>
182.22 +#include <time.h>
182.23 +#if HAVE_SYS_STAT_H
182.24 +#include <sys/stat.h>
182.25 +#endif
182.26 +#if HAVE_SYS_TYPES_H
182.27 +#include <sys/types.h>
182.28 +#endif
182.29 +
182.30 +#include "ext2_fs.h"
182.31 +#include "ext2fs.h"
182.32 +
182.33 +/*
182.34 + * Reads a list of bad blocks from a FILE *
182.35 + */
182.36 +errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f,
182.37 + ext2_badblocks_list *bb_list,
182.38 + void *priv_data,
182.39 + void (*invalid)(ext2_filsys fs,
182.40 + blk_t blk,
182.41 + char *badstr,
182.42 + void *priv_data))
182.43 +{
182.44 + errcode_t retval;
182.45 + blk64_t blockno;
182.46 + int count;
182.47 + char buf[128];
182.48 +
182.49 + if (fs)
182.50 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
182.51 +
182.52 + if (!*bb_list) {
182.53 + retval = ext2fs_badblocks_list_create(bb_list, 10);
182.54 + if (retval)
182.55 + return retval;
182.56 + }
182.57 +
182.58 + while (!feof (f)) {
182.59 + if (fgets(buf, sizeof(buf), f) == NULL)
182.60 + break;
182.61 + count = sscanf(buf, "%llu", &blockno);
182.62 + if (count <= 0)
182.63 + continue;
182.64 + /* Badblocks isn't going to be updated for 64bit */
182.65 + if (blockno >> 32)
182.66 + return EOVERFLOW;
182.67 + if (fs &&
182.68 + ((blockno < fs->super->s_first_data_block) ||
182.69 + (blockno >= ext2fs_blocks_count(fs->super)))) {
182.70 + if (invalid)
182.71 + (invalid)(fs, blockno, buf, priv_data);
182.72 + continue;
182.73 + }
182.74 + retval = ext2fs_badblocks_list_add(*bb_list, blockno);
182.75 + if (retval)
182.76 + return retval;
182.77 + }
182.78 + return 0;
182.79 +}
182.80 +
182.81 +struct compat_struct {
182.82 + void (*invalid)(ext2_filsys, blk_t);
182.83 +};
182.84 +
182.85 +static void call_compat_invalid(ext2_filsys fs, blk_t blk,
182.86 + char *badstr EXT2FS_ATTR((unused)),
182.87 + void *priv_data)
182.88 +{
182.89 + struct compat_struct *st;
182.90 +
182.91 + st = (struct compat_struct *) priv_data;
182.92 + if (st->invalid)
182.93 + (st->invalid)(fs, blk);
182.94 +}
182.95 +
182.96 +
182.97 +/*
182.98 + * Reads a list of bad blocks from a FILE *
182.99 + */
182.100 +errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
182.101 + ext2_badblocks_list *bb_list,
182.102 + void (*invalid)(ext2_filsys fs, blk_t blk))
182.103 +{
182.104 + struct compat_struct st;
182.105 +
182.106 + st.invalid = invalid;
182.107 +
182.108 + return ext2fs_read_bb_FILE2(fs, f, bb_list, &st,
182.109 + call_compat_invalid);
182.110 +}
182.111 +
182.112 +
183.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
183.2 +++ b/libext2fs/lib/libext2fs/res_gdt.c Wed Aug 25 01:28:08 2021 +0200
183.3 @@ -0,0 +1,239 @@
183.4 +/*
183.5 + * res_gdt.c --- reserve blocks for growing the group descriptor table
183.6 + * during online resizing.
183.7 + *
183.8 + * Copyright (C) 2002 Andreas Dilger
183.9 + *
183.10 + * %Begin-Header%
183.11 + * This file may be redistributed under the terms of the GNU Library
183.12 + * General Public License, version 2.
183.13 + * %End-Header%
183.14 + */
183.15 +
183.16 +#include "config.h"
183.17 +#include <stdio.h>
183.18 +#include <string.h>
183.19 +#include <time.h>
183.20 +#include "ext2_fs.h"
183.21 +#include "ext2fs.h"
183.22 +
183.23 +/*
183.24 + * Iterate through the groups which hold BACKUP superblock/GDT copies in an
183.25 + * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before
183.26 + * calling this for the first time. In a sparse filesystem it will be the
183.27 + * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
183.28 + * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
183.29 + */
183.30 +static unsigned int list_backups(ext2_filsys fs, unsigned int *three,
183.31 + unsigned int *five, unsigned int *seven)
183.32 +{
183.33 + unsigned int *min = three;
183.34 + int mult = 3;
183.35 + unsigned int ret;
183.36 +
183.37 + if (ext2fs_has_feature_sparse_super2(fs->super)) {
183.38 + if (*min == 1) {
183.39 + *min += 1;
183.40 + if (fs->super->s_backup_bgs[0])
183.41 + return fs->super->s_backup_bgs[0];
183.42 + }
183.43 + if (*min == 2) {
183.44 + *min += 1;
183.45 + if (fs->super->s_backup_bgs[1])
183.46 + return fs->super->s_backup_bgs[1];
183.47 + }
183.48 + return fs->group_desc_count;
183.49 + }
183.50 + if (!ext2fs_has_feature_sparse_super(fs->super)) {
183.51 + ret = *min;
183.52 + *min += 1;
183.53 + return ret;
183.54 + }
183.55 +
183.56 + if (*five < *min) {
183.57 + min = five;
183.58 + mult = 5;
183.59 + }
183.60 + if (*seven < *min) {
183.61 + min = seven;
183.62 + mult = 7;
183.63 + }
183.64 +
183.65 + ret = *min;
183.66 + *min *= mult;
183.67 +
183.68 + return ret;
183.69 +}
183.70 +
183.71 +/*
183.72 + * This code assumes that the reserved blocks have already been marked in-use
183.73 + * during ext2fs_initialize(), so that they are not allocated for other
183.74 + * uses before we can add them to the resize inode (which has to come
183.75 + * after the creation of the inode table).
183.76 + */
183.77 +errcode_t ext2fs_create_resize_inode(ext2_filsys fs)
183.78 +{
183.79 + errcode_t retval, retval2;
183.80 + struct ext2_super_block *sb;
183.81 + struct ext2_inode inode;
183.82 + __u32 *dindir_buf, *gdt_buf;
183.83 + unsigned long long apb, inode_size;
183.84 + /* FIXME-64 - can't deal with extents */
183.85 + blk_t dindir_blk, rsv_off, gdt_off, gdt_blk;
183.86 + int dindir_dirty = 0, inode_dirty = 0, sb_blk = 0;
183.87 +
183.88 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
183.89 +
183.90 + sb = fs->super;
183.91 +
183.92 + retval = ext2fs_get_array(2, fs->blocksize, &dindir_buf);
183.93 + if (retval)
183.94 + return retval;
183.95 + gdt_buf = (__u32 *)((char *)dindir_buf + fs->blocksize);
183.96 +
183.97 + retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
183.98 + if (retval)
183.99 + goto out_free;
183.100 +
183.101 + /*
183.102 + * File systems with a blocksize of 1024 and bigalloc have
183.103 + * sb->s_first_data_block of 0; yet the superblock is still at
183.104 + * block #1. We compensate for it here.
183.105 + */
183.106 + sb_blk = sb->s_first_data_block;
183.107 + if (fs->blocksize == 1024 && sb_blk == 0)
183.108 + sb_blk = 1;
183.109 +
183.110 + /* Maximum possible file size (we only use double indirect blocks) */
183.111 + apb = EXT2_ADDR_PER_BLOCK(sb);
183.112 + if ((dindir_blk = inode.i_block[EXT2_DIND_BLOCK])) {
183.113 +#ifdef RES_GDT_DEBUG
183.114 + printf("reading GDT dindir %u\n", dindir_blk);
183.115 +#endif
183.116 + retval = ext2fs_read_ind_block(fs, dindir_blk, dindir_buf);
183.117 + if (retval)
183.118 + goto out_inode;
183.119 + } else {
183.120 + blk_t goal = sb_blk + fs->desc_blocks +
183.121 + sb->s_reserved_gdt_blocks + 2 +
183.122 + fs->inode_blocks_per_group;
183.123 +
183.124 + retval = ext2fs_alloc_block(fs, goal, 0, &dindir_blk);
183.125 + if (retval)
183.126 + goto out_free;
183.127 + inode.i_mode = LINUX_S_IFREG | 0600;
183.128 + inode.i_links_count = 1;
183.129 + inode.i_block[EXT2_DIND_BLOCK] = dindir_blk;
183.130 + ext2fs_iblk_set(fs, &inode, 1);
183.131 + memset(dindir_buf, 0, fs->blocksize);
183.132 +#ifdef RES_GDT_DEBUG
183.133 + printf("allocated GDT dindir %u\n", dindir_blk);
183.134 +#endif
183.135 + dindir_dirty = inode_dirty = 1;
183.136 + inode_size = apb*apb + apb + EXT2_NDIR_BLOCKS;
183.137 + inode_size *= fs->blocksize;
183.138 + retval = ext2fs_inode_size_set(fs, &inode, inode_size);
183.139 + if (retval)
183.140 + goto out_free;
183.141 + inode.i_ctime = fs->now ? fs->now : time(0);
183.142 + }
183.143 +
183.144 + for (rsv_off = 0, gdt_off = fs->desc_blocks,
183.145 + gdt_blk = sb_blk + 1 + fs->desc_blocks;
183.146 + rsv_off < sb->s_reserved_gdt_blocks;
183.147 + rsv_off++, gdt_off++, gdt_blk++) {
183.148 + unsigned int three = 1, five = 5, seven = 7;
183.149 + unsigned int grp, last = 0;
183.150 + int gdt_dirty = 0;
183.151 +
183.152 + gdt_off %= apb;
183.153 + if (!dindir_buf[gdt_off]) {
183.154 + /* FIXME XXX XXX
183.155 + blk_t new_blk;
183.156 +
183.157 + retval = ext2fs_new_block(fs, gdt_blk, 0, &new_blk);
183.158 + if (retval)
183.159 + goto out_free;
183.160 + if (new_blk != gdt_blk) {
183.161 + // XXX free block
183.162 + retval = -1; // XXX
183.163 + }
183.164 + */
183.165 + gdt_dirty = dindir_dirty = inode_dirty = 1;
183.166 + memset(gdt_buf, 0, fs->blocksize);
183.167 + dindir_buf[gdt_off] = gdt_blk;
183.168 + ext2fs_iblk_add_blocks(fs, &inode, 1);
183.169 +#ifdef RES_GDT_DEBUG
183.170 + printf("added primary GDT block %u at %u[%u]\n",
183.171 + gdt_blk, dindir_blk, gdt_off);
183.172 +#endif
183.173 + } else if (dindir_buf[gdt_off] == gdt_blk) {
183.174 +#ifdef RES_GDT_DEBUG
183.175 + printf("reading primary GDT block %u\n", gdt_blk);
183.176 +#endif
183.177 + retval = ext2fs_read_ind_block(fs, gdt_blk, gdt_buf);
183.178 + if (retval)
183.179 + goto out_dindir;
183.180 + } else {
183.181 +#ifdef RES_GDT_DEBUG
183.182 + printf("bad primary GDT %u != %u at %u[%u]\n",
183.183 + dindir_buf[gdt_off], gdt_blk,dindir_blk,gdt_off);
183.184 +#endif
183.185 + retval = EXT2_ET_RESIZE_INODE_CORRUPT;
183.186 + goto out_dindir;
183.187 + }
183.188 +
183.189 + while ((grp = list_backups(fs, &three, &five, &seven)) <
183.190 + fs->group_desc_count) {
183.191 + blk_t expect = gdt_blk + grp * sb->s_blocks_per_group;
183.192 +
183.193 + if (!gdt_buf[last]) {
183.194 +#ifdef RES_GDT_DEBUG
183.195 + printf("added backup GDT %u grp %u@%u[%u]\n",
183.196 + expect, grp, gdt_blk, last);
183.197 +#endif
183.198 + gdt_buf[last] = expect;
183.199 + ext2fs_iblk_add_blocks(fs, &inode, 1);
183.200 + gdt_dirty = inode_dirty = 1;
183.201 + } else if (gdt_buf[last] != expect) {
183.202 +#ifdef RES_GDT_DEBUG
183.203 + printf("bad backup GDT %u != %u at %u[%u]\n",
183.204 + gdt_buf[last], expect, gdt_blk, last);
183.205 +#endif
183.206 + retval = EXT2_ET_RESIZE_INODE_CORRUPT;
183.207 + goto out_dindir;
183.208 + }
183.209 + last++;
183.210 + }
183.211 + if (gdt_dirty) {
183.212 +#ifdef RES_GDT_DEBUG
183.213 + printf("writing primary GDT block %u\n", gdt_blk);
183.214 +#endif
183.215 + retval = ext2fs_write_ind_block(fs, gdt_blk, gdt_buf);
183.216 + if (retval)
183.217 + goto out_dindir;
183.218 + }
183.219 + }
183.220 +
183.221 +out_dindir:
183.222 + if (dindir_dirty) {
183.223 + retval2 = ext2fs_write_ind_block(fs, dindir_blk, dindir_buf);
183.224 + if (!retval)
183.225 + retval = retval2;
183.226 + }
183.227 +out_inode:
183.228 +#ifdef RES_GDT_DEBUG
183.229 + printf("inode.i_blocks = %u, i_size = %u\n", inode.i_blocks,
183.230 + inode.i_size);
183.231 +#endif
183.232 + if (inode_dirty) {
183.233 + inode.i_atime = inode.i_mtime = fs->now ? fs->now : time(0);
183.234 + retval2 = ext2fs_write_new_inode(fs, EXT2_RESIZE_INO, &inode);
183.235 + if (!retval)
183.236 + retval = retval2;
183.237 + }
183.238 +out_free:
183.239 + ext2fs_free_mem(&dindir_buf);
183.240 + return retval;
183.241 +}
183.242 +
184.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
184.2 +++ b/libext2fs/lib/libext2fs/rw_bitmaps.c Wed Aug 25 01:28:08 2021 +0200
184.3 @@ -0,0 +1,430 @@
184.4 +/*
184.5 + * rw_bitmaps.c --- routines to read and write the inode and block bitmaps.
184.6 + *
184.7 + * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o.
184.8 + *
184.9 + * %Begin-Header%
184.10 + * This file may be redistributed under the terms of the GNU Library
184.11 + * General Public License, version 2.
184.12 + * %End-Header%
184.13 + */
184.14 +
184.15 +#include "config.h"
184.16 +#include <stdio.h>
184.17 +#include <string.h>
184.18 +#if HAVE_UNISTD_H
184.19 +#include <unistd.h>
184.20 +#endif
184.21 +#include <fcntl.h>
184.22 +#include <time.h>
184.23 +#ifdef HAVE_SYS_STAT_H
184.24 +#include <sys/stat.h>
184.25 +#endif
184.26 +#ifdef HAVE_SYS_TYPES_H
184.27 +#include <sys/types.h>
184.28 +#endif
184.29 +
184.30 +#include "ext2_fs.h"
184.31 +#include "ext2fs.h"
184.32 +#include "e2image.h"
184.33 +
184.34 +static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
184.35 +{
184.36 + dgrp_t i;
184.37 + unsigned int j;
184.38 + int block_nbytes, inode_nbytes;
184.39 + unsigned int nbits;
184.40 + errcode_t retval;
184.41 + char *block_buf = NULL, *inode_buf = NULL;
184.42 + int csum_flag;
184.43 + blk64_t blk;
184.44 + blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
184.45 + ext2_ino_t ino_itr = 1;
184.46 +
184.47 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
184.48 +
184.49 + if (!(fs->flags & EXT2_FLAG_RW))
184.50 + return EXT2_ET_RO_FILSYS;
184.51 +
184.52 + csum_flag = ext2fs_has_group_desc_csum(fs);
184.53 +
184.54 + inode_nbytes = block_nbytes = 0;
184.55 + if (do_block) {
184.56 + block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
184.57 + retval = io_channel_alloc_buf(fs->io, 0, &block_buf);
184.58 + if (retval)
184.59 + goto errout;
184.60 + memset(block_buf, 0xff, fs->blocksize);
184.61 + }
184.62 + if (do_inode) {
184.63 + inode_nbytes = (size_t)
184.64 + ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
184.65 + retval = io_channel_alloc_buf(fs->io, 0, &inode_buf);
184.66 + if (retval)
184.67 + goto errout;
184.68 + memset(inode_buf, 0xff, fs->blocksize);
184.69 + }
184.70 +
184.71 + for (i = 0; i < fs->group_desc_count; i++) {
184.72 + if (!do_block)
184.73 + goto skip_block_bitmap;
184.74 +
184.75 + if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT)
184.76 + )
184.77 + goto skip_this_block_bitmap;
184.78 +
184.79 + retval = ext2fs_get_block_bitmap_range2(fs->block_map,
184.80 + blk_itr, block_nbytes << 3, block_buf);
184.81 + if (retval)
184.82 + goto errout;
184.83 +
184.84 + if (i == fs->group_desc_count - 1) {
184.85 + /* Force bitmap padding for the last group */
184.86 + nbits = EXT2FS_NUM_B2C(fs,
184.87 + ((ext2fs_blocks_count(fs->super)
184.88 + - (__u64) fs->super->s_first_data_block)
184.89 + % (__u64) EXT2_BLOCKS_PER_GROUP(fs->super)));
184.90 + if (nbits)
184.91 + for (j = nbits; j < fs->blocksize * 8; j++)
184.92 + ext2fs_set_bit(j, block_buf);
184.93 + }
184.94 +
184.95 + retval = ext2fs_block_bitmap_csum_set(fs, i, block_buf,
184.96 + block_nbytes);
184.97 + if (retval)
184.98 + return retval;
184.99 + ext2fs_group_desc_csum_set(fs, i);
184.100 + fs->flags |= EXT2_FLAG_DIRTY;
184.101 +
184.102 + blk = ext2fs_block_bitmap_loc(fs, i);
184.103 + if (blk) {
184.104 + retval = io_channel_write_blk64(fs->io, blk, 1,
184.105 + block_buf);
184.106 + if (retval) {
184.107 + retval = EXT2_ET_BLOCK_BITMAP_WRITE;
184.108 + goto errout;
184.109 + }
184.110 + }
184.111 + skip_this_block_bitmap:
184.112 + blk_itr += block_nbytes << 3;
184.113 + skip_block_bitmap:
184.114 +
184.115 + if (!do_inode)
184.116 + continue;
184.117 +
184.118 + if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT)
184.119 + )
184.120 + goto skip_this_inode_bitmap;
184.121 +
184.122 + retval = ext2fs_get_inode_bitmap_range2(fs->inode_map,
184.123 + ino_itr, inode_nbytes << 3, inode_buf);
184.124 + if (retval)
184.125 + goto errout;
184.126 +
184.127 + retval = ext2fs_inode_bitmap_csum_set(fs, i, inode_buf,
184.128 + inode_nbytes);
184.129 + if (retval)
184.130 + goto errout;
184.131 + ext2fs_group_desc_csum_set(fs, i);
184.132 + fs->flags |= EXT2_FLAG_DIRTY;
184.133 +
184.134 + blk = ext2fs_inode_bitmap_loc(fs, i);
184.135 + if (blk) {
184.136 + retval = io_channel_write_blk64(fs->io, blk, 1,
184.137 + inode_buf);
184.138 + if (retval) {
184.139 + retval = EXT2_ET_INODE_BITMAP_WRITE;
184.140 + goto errout;
184.141 + }
184.142 + }
184.143 + skip_this_inode_bitmap:
184.144 + ino_itr += inode_nbytes << 3;
184.145 +
184.146 + }
184.147 + if (do_block) {
184.148 + fs->flags &= ~EXT2_FLAG_BB_DIRTY;
184.149 + ext2fs_free_mem(&block_buf);
184.150 + }
184.151 + if (do_inode) {
184.152 + fs->flags &= ~EXT2_FLAG_IB_DIRTY;
184.153 + ext2fs_free_mem(&inode_buf);
184.154 + }
184.155 + return 0;
184.156 +errout:
184.157 + if (inode_buf)
184.158 + ext2fs_free_mem(&inode_buf);
184.159 + if (block_buf)
184.160 + ext2fs_free_mem(&block_buf);
184.161 + return retval;
184.162 +}
184.163 +
184.164 +static errcode_t mark_uninit_bg_group_blocks(ext2_filsys fs)
184.165 +{
184.166 + dgrp_t i;
184.167 + blk64_t blk;
184.168 + ext2fs_block_bitmap bmap = fs->block_map;
184.169 +
184.170 + for (i = 0; i < fs->group_desc_count; i++) {
184.171 + if (!ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT))
184.172 + continue;
184.173 +
184.174 + ext2fs_reserve_super_and_bgd(fs, i, bmap);
184.175 +
184.176 + /*
184.177 + * Mark the blocks used for the inode table
184.178 + */
184.179 + blk = ext2fs_inode_table_loc(fs, i);
184.180 + if (blk)
184.181 + ext2fs_mark_block_bitmap_range2(bmap, blk,
184.182 + fs->inode_blocks_per_group);
184.183 +
184.184 + /*
184.185 + * Mark block used for the block bitmap
184.186 + */
184.187 + blk = ext2fs_block_bitmap_loc(fs, i);
184.188 + if (blk)
184.189 + ext2fs_mark_block_bitmap2(bmap, blk);
184.190 +
184.191 + /*
184.192 + * Mark block used for the inode bitmap
184.193 + */
184.194 + blk = ext2fs_inode_bitmap_loc(fs, i);
184.195 + if (blk)
184.196 + ext2fs_mark_block_bitmap2(bmap, blk);
184.197 + }
184.198 + return 0;
184.199 +}
184.200 +
184.201 +static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
184.202 +{
184.203 + dgrp_t i;
184.204 + char *block_bitmap = 0, *inode_bitmap = 0;
184.205 + char *buf;
184.206 + errcode_t retval;
184.207 + int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
184.208 + int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
184.209 + int csum_flag;
184.210 + unsigned int cnt;
184.211 + blk64_t blk;
184.212 + blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
184.213 + blk64_t blk_cnt;
184.214 + ext2_ino_t ino_itr = 1;
184.215 + ext2_ino_t ino_cnt;
184.216 +
184.217 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
184.218 +
184.219 + if ((block_nbytes > (int) fs->blocksize) ||
184.220 + (inode_nbytes > (int) fs->blocksize))
184.221 + return EXT2_ET_CORRUPT_SUPERBLOCK;
184.222 +
184.223 + fs->write_bitmaps = ext2fs_write_bitmaps;
184.224 +
184.225 + csum_flag = ext2fs_has_group_desc_csum(fs);
184.226 +
184.227 + retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
184.228 + if (retval)
184.229 + return retval;
184.230 + if (do_block) {
184.231 + if (fs->block_map)
184.232 + ext2fs_free_block_bitmap(fs->block_map);
184.233 + strcpy(buf, "block bitmap for ");
184.234 + strcat(buf, fs->device_name);
184.235 + retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
184.236 + if (retval)
184.237 + goto cleanup;
184.238 + retval = io_channel_alloc_buf(fs->io, 0, &block_bitmap);
184.239 + if (retval)
184.240 + goto cleanup;
184.241 + } else
184.242 + block_nbytes = 0;
184.243 + if (do_inode) {
184.244 + if (fs->inode_map)
184.245 + ext2fs_free_inode_bitmap(fs->inode_map);
184.246 + strcpy(buf, "inode bitmap for ");
184.247 + strcat(buf, fs->device_name);
184.248 + retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
184.249 + if (retval)
184.250 + goto cleanup;
184.251 + retval = io_channel_alloc_buf(fs->io, 0, &inode_bitmap);
184.252 + if (retval)
184.253 + goto cleanup;
184.254 + } else
184.255 + inode_nbytes = 0;
184.256 + ext2fs_free_mem(&buf);
184.257 +
184.258 + if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
184.259 + blk = (ext2fs_le32_to_cpu(fs->image_header->offset_inodemap) / fs->blocksize);
184.260 + ino_cnt = fs->super->s_inodes_count;
184.261 + while (inode_bitmap && ino_cnt > 0) {
184.262 + retval = io_channel_read_blk64(fs->image_io, blk++,
184.263 + 1, inode_bitmap);
184.264 + if (retval)
184.265 + goto cleanup;
184.266 + cnt = fs->blocksize << 3;
184.267 + if (cnt > ino_cnt)
184.268 + cnt = ino_cnt;
184.269 + retval = ext2fs_set_inode_bitmap_range2(fs->inode_map,
184.270 + ino_itr, cnt, inode_bitmap);
184.271 + if (retval)
184.272 + goto cleanup;
184.273 + ino_itr += cnt;
184.274 + ino_cnt -= cnt;
184.275 + }
184.276 + blk = (ext2fs_le32_to_cpu(fs->image_header->offset_blockmap) /
184.277 + fs->blocksize);
184.278 + blk_cnt = EXT2_GROUPS_TO_CLUSTERS(fs->super,
184.279 + fs->group_desc_count);
184.280 + while (block_bitmap && blk_cnt > 0) {
184.281 + retval = io_channel_read_blk64(fs->image_io, blk++,
184.282 + 1, block_bitmap);
184.283 + if (retval)
184.284 + goto cleanup;
184.285 + cnt = fs->blocksize << 3;
184.286 + if (cnt > blk_cnt)
184.287 + cnt = blk_cnt;
184.288 + retval = ext2fs_set_block_bitmap_range2(fs->block_map,
184.289 + blk_itr, cnt, block_bitmap);
184.290 + if (retval)
184.291 + goto cleanup;
184.292 + blk_itr += cnt;
184.293 + blk_cnt -= cnt;
184.294 + }
184.295 + goto success_cleanup;
184.296 + }
184.297 +
184.298 + for (i = 0; i < fs->group_desc_count; i++) {
184.299 + if (block_bitmap) {
184.300 + blk = ext2fs_block_bitmap_loc(fs, i);
184.301 + if (csum_flag &&
184.302 + ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) &&
184.303 + ext2fs_group_desc_csum_verify(fs, i))
184.304 + blk = 0;
184.305 + if (blk) {
184.306 + retval = io_channel_read_blk64(fs->io, blk,
184.307 + 1, block_bitmap);
184.308 + if (retval) {
184.309 + retval = EXT2_ET_BLOCK_BITMAP_READ;
184.310 + goto cleanup;
184.311 + }
184.312 + /* verify block bitmap checksum */
184.313 + if (!(fs->flags &
184.314 + EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
184.315 + !ext2fs_block_bitmap_csum_verify(fs, i,
184.316 + block_bitmap, block_nbytes)) {
184.317 + retval =
184.318 + EXT2_ET_BLOCK_BITMAP_CSUM_INVALID;
184.319 + goto cleanup;
184.320 + }
184.321 + } else
184.322 + memset(block_bitmap, 0, block_nbytes);
184.323 + cnt = block_nbytes << 3;
184.324 + retval = ext2fs_set_block_bitmap_range2(fs->block_map,
184.325 + blk_itr, cnt, block_bitmap);
184.326 + if (retval)
184.327 + goto cleanup;
184.328 + blk_itr += block_nbytes << 3;
184.329 + }
184.330 + if (inode_bitmap) {
184.331 + blk = ext2fs_inode_bitmap_loc(fs, i);
184.332 + if (csum_flag &&
184.333 + ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) &&
184.334 + ext2fs_group_desc_csum_verify(fs, i))
184.335 + blk = 0;
184.336 + if (blk) {
184.337 + retval = io_channel_read_blk64(fs->io, blk,
184.338 + 1, inode_bitmap);
184.339 + if (retval) {
184.340 + retval = EXT2_ET_INODE_BITMAP_READ;
184.341 + goto cleanup;
184.342 + }
184.343 +
184.344 + /* verify inode bitmap checksum */
184.345 + if (!(fs->flags &
184.346 + EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
184.347 + !ext2fs_inode_bitmap_csum_verify(fs, i,
184.348 + inode_bitmap, inode_nbytes)) {
184.349 + retval =
184.350 + EXT2_ET_INODE_BITMAP_CSUM_INVALID;
184.351 + goto cleanup;
184.352 + }
184.353 + } else
184.354 + memset(inode_bitmap, 0, inode_nbytes);
184.355 + cnt = inode_nbytes << 3;
184.356 + retval = ext2fs_set_inode_bitmap_range2(fs->inode_map,
184.357 + ino_itr, cnt, inode_bitmap);
184.358 + if (retval)
184.359 + goto cleanup;
184.360 + ino_itr += inode_nbytes << 3;
184.361 + }
184.362 + }
184.363 +
184.364 + /* Mark group blocks for any BLOCK_UNINIT groups */
184.365 + if (do_block) {
184.366 + retval = mark_uninit_bg_group_blocks(fs);
184.367 + if (retval)
184.368 + goto cleanup;
184.369 + }
184.370 +
184.371 +success_cleanup:
184.372 + if (inode_bitmap)
184.373 + ext2fs_free_mem(&inode_bitmap);
184.374 + if (block_bitmap)
184.375 + ext2fs_free_mem(&block_bitmap);
184.376 + return 0;
184.377 +
184.378 +cleanup:
184.379 + if (do_block) {
184.380 + ext2fs_free_mem(&fs->block_map);
184.381 + fs->block_map = 0;
184.382 + }
184.383 + if (do_inode) {
184.384 + ext2fs_free_mem(&fs->inode_map);
184.385 + fs->inode_map = 0;
184.386 + }
184.387 + if (inode_bitmap)
184.388 + ext2fs_free_mem(&inode_bitmap);
184.389 + if (block_bitmap)
184.390 + ext2fs_free_mem(&block_bitmap);
184.391 + if (buf)
184.392 + ext2fs_free_mem(&buf);
184.393 + return retval;
184.394 +}
184.395 +
184.396 +errcode_t ext2fs_read_inode_bitmap(ext2_filsys fs)
184.397 +{
184.398 + return read_bitmaps(fs, 1, 0);
184.399 +}
184.400 +
184.401 +errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
184.402 +{
184.403 + return read_bitmaps(fs, 0, 1);
184.404 +}
184.405 +
184.406 +errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
184.407 +{
184.408 + return write_bitmaps(fs, 1, 0);
184.409 +}
184.410 +
184.411 +errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
184.412 +{
184.413 + return write_bitmaps(fs, 0, 1);
184.414 +}
184.415 +
184.416 +errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
184.417 +{
184.418 + if (fs->inode_map && fs->block_map)
184.419 + return 0;
184.420 +
184.421 + return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
184.422 +}
184.423 +
184.424 +errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
184.425 +{
184.426 + int do_inode = fs->inode_map && ext2fs_test_ib_dirty(fs);
184.427 + int do_block = fs->block_map && ext2fs_test_bb_dirty(fs);
184.428 +
184.429 + if (!do_inode && !do_block)
184.430 + return 0;
184.431 +
184.432 + return write_bitmaps(fs, do_inode, do_block);
184.433 +}
185.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
185.2 +++ b/libext2fs/lib/libext2fs/sha256.c Wed Aug 25 01:28:08 2021 +0200
185.3 @@ -0,0 +1,254 @@
185.4 +/*
185.5 + * sha256.c --- The sh256 algorithm
185.6 + *
185.7 + * Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
185.8 + * (copied from libtomcrypt and then relicensed under GPLv2)
185.9 + *
185.10 + * %Begin-Header%
185.11 + * This file may be redistributed under the terms of the GNU Library
185.12 + * General Public License, version 2.
185.13 + * %End-Header%
185.14 + */
185.15 +
185.16 +
185.17 +#include "config.h"
185.18 +#if HAVE_SYS_TYPES_H
185.19 +#include <sys/types.h>
185.20 +#endif
185.21 +#include "ext2fs.h"
185.22 +
185.23 +static const __u32 K[64] = {
185.24 + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
185.25 + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
185.26 + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
185.27 + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
185.28 + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
185.29 + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
185.30 + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
185.31 + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
185.32 + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
185.33 + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
185.34 + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
185.35 + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
185.36 + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
185.37 +};
185.38 +
185.39 +/* Various logical functions */
185.40 +#define Ch(x,y,z) (z ^ (x & (y ^ z)))
185.41 +#define Maj(x,y,z) (((x | y) & z) | (x & y))
185.42 +#define S(x, n) RORc((x),(n))
185.43 +#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
185.44 +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
185.45 +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
185.46 +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
185.47 +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
185.48 +#define RORc(x, y) ( ((((__u32)(x)&0xFFFFFFFFUL)>>(__u32)((y)&31)) | ((__u32)(x)<<(__u32)(32-((y)&31)))) & 0xFFFFFFFFUL)
185.49 +
185.50 +#define RND(a,b,c,d,e,f,g,h,i) \
185.51 + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
185.52 + t1 = Sigma0(a) + Maj(a, b, c); \
185.53 + d += t0; \
185.54 + h = t0 + t1;
185.55 +
185.56 +#define STORE64H(x, y) \
185.57 + do { \
185.58 + (y)[0] = (unsigned char)(((x)>>56)&255);\
185.59 + (y)[1] = (unsigned char)(((x)>>48)&255);\
185.60 + (y)[2] = (unsigned char)(((x)>>40)&255);\
185.61 + (y)[3] = (unsigned char)(((x)>>32)&255);\
185.62 + (y)[4] = (unsigned char)(((x)>>24)&255);\
185.63 + (y)[5] = (unsigned char)(((x)>>16)&255);\
185.64 + (y)[6] = (unsigned char)(((x)>>8)&255);\
185.65 + (y)[7] = (unsigned char)((x)&255); } while(0)
185.66 +
185.67 +#define STORE32H(x, y) \
185.68 + do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
185.69 + (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0)
185.70 +
185.71 +#define LOAD32H(x, y) \
185.72 + do { x = ((__u32)((y)[0] & 255)<<24) | \
185.73 + ((__u32)((y)[1] & 255)<<16) | \
185.74 + ((__u32)((y)[2] & 255)<<8) | \
185.75 + ((__u32)((y)[3] & 255)); } while(0)
185.76 +
185.77 +struct sha256_state {
185.78 + __u64 length;
185.79 + __u32 state[8], curlen;
185.80 + unsigned char buf[64];
185.81 +};
185.82 +
185.83 +/* This is a highly simplified version from libtomcrypt */
185.84 +struct hash_state {
185.85 + struct sha256_state sha256;
185.86 +};
185.87 +
185.88 +static void sha256_compress(struct hash_state * md, const unsigned char *buf)
185.89 +{
185.90 + __u32 S[8], W[64], t0, t1;
185.91 + __u32 t;
185.92 + int i;
185.93 +
185.94 + /* copy state into S */
185.95 + for (i = 0; i < 8; i++) {
185.96 + S[i] = md->sha256.state[i];
185.97 + }
185.98 +
185.99 + /* copy the state into 512-bits into W[0..15] */
185.100 + for (i = 0; i < 16; i++) {
185.101 + LOAD32H(W[i], buf + (4*i));
185.102 + }
185.103 +
185.104 + /* fill W[16..63] */
185.105 + for (i = 16; i < 64; i++) {
185.106 + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
185.107 + }
185.108 +
185.109 + /* Compress */
185.110 + for (i = 0; i < 64; ++i) {
185.111 + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i);
185.112 + t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
185.113 + S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
185.114 + }
185.115 +
185.116 + /* feedback */
185.117 + for (i = 0; i < 8; i++) {
185.118 + md->sha256.state[i] = md->sha256.state[i] + S[i];
185.119 + }
185.120 +}
185.121 +
185.122 +static void sha256_init(struct hash_state * md)
185.123 +{
185.124 + md->sha256.curlen = 0;
185.125 + md->sha256.length = 0;
185.126 + md->sha256.state[0] = 0x6A09E667UL;
185.127 + md->sha256.state[1] = 0xBB67AE85UL;
185.128 + md->sha256.state[2] = 0x3C6EF372UL;
185.129 + md->sha256.state[3] = 0xA54FF53AUL;
185.130 + md->sha256.state[4] = 0x510E527FUL;
185.131 + md->sha256.state[5] = 0x9B05688CUL;
185.132 + md->sha256.state[6] = 0x1F83D9ABUL;
185.133 + md->sha256.state[7] = 0x5BE0CD19UL;
185.134 +}
185.135 +
185.136 +#define MIN(x, y) ( ((x)<(y))?(x):(y) )
185.137 +#define SHA256_BLOCKSIZE 64
185.138 +static void sha256_process(struct hash_state * md, const unsigned char *in, unsigned long inlen)
185.139 +{
185.140 + unsigned long n;
185.141 +
185.142 + while (inlen > 0) {
185.143 + if (md->sha256.curlen == 0 && inlen >= SHA256_BLOCKSIZE) {
185.144 + sha256_compress(md, in);
185.145 + md->sha256.length += SHA256_BLOCKSIZE * 8;
185.146 + in += SHA256_BLOCKSIZE;
185.147 + inlen -= SHA256_BLOCKSIZE;
185.148 + } else {
185.149 + n = MIN(inlen, (SHA256_BLOCKSIZE - md->sha256.curlen));
185.150 + memcpy(md->sha256.buf + md->sha256.curlen, in, (size_t)n);
185.151 + md->sha256.curlen += n;
185.152 + in += n;
185.153 + inlen -= n;
185.154 + if (md->sha256.curlen == SHA256_BLOCKSIZE) {
185.155 + sha256_compress(md, md->sha256.buf);
185.156 + md->sha256.length += 8*SHA256_BLOCKSIZE;
185.157 + md->sha256.curlen = 0;
185.158 + }
185.159 + }
185.160 + }
185.161 +}
185.162 +
185.163 +
185.164 +static void sha256_done(struct hash_state * md, unsigned char *out)
185.165 +{
185.166 + int i;
185.167 +
185.168 + /* increase the length of the message */
185.169 + md->sha256.length += md->sha256.curlen * 8;
185.170 +
185.171 + /* append the '1' bit */
185.172 + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80;
185.173 +
185.174 + /* if the length is currently above 56 bytes we append zeros
185.175 + * then compress. Then we can fall back to padding zeros and length
185.176 + * encoding like normal.
185.177 + */
185.178 + if (md->sha256.curlen > 56) {
185.179 + while (md->sha256.curlen < 64) {
185.180 + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
185.181 + }
185.182 + sha256_compress(md, md->sha256.buf);
185.183 + md->sha256.curlen = 0;
185.184 + }
185.185 +
185.186 + /* pad upto 56 bytes of zeroes */
185.187 + while (md->sha256.curlen < 56) {
185.188 + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
185.189 + }
185.190 +
185.191 + /* store length */
185.192 + STORE64H(md->sha256.length, md->sha256.buf+56);
185.193 + sha256_compress(md, md->sha256.buf);
185.194 +
185.195 + /* copy output */
185.196 + for (i = 0; i < 8; i++) {
185.197 + STORE32H(md->sha256.state[i], out+(4*i));
185.198 + }
185.199 +}
185.200 +
185.201 +void ext2fs_sha256(const unsigned char *in, unsigned long in_size,
185.202 + unsigned char out[EXT2FS_SHA256_LENGTH])
185.203 +{
185.204 + struct hash_state md;
185.205 +
185.206 + sha256_init(&md);
185.207 + sha256_process(&md, in, in_size);
185.208 + sha256_done(&md, out);
185.209 +}
185.210 +
185.211 +#ifdef UNITTEST
185.212 +static const struct {
185.213 + char *msg;
185.214 + unsigned char hash[32];
185.215 +} tests[] = {
185.216 + { "",
185.217 + { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
185.218 + 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
185.219 + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
185.220 + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 }
185.221 + },
185.222 + { "abc",
185.223 + { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
185.224 + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
185.225 + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
185.226 + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }
185.227 + },
185.228 + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
185.229 + { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
185.230 + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
185.231 + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
185.232 + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }
185.233 + },
185.234 +};
185.235 +
185.236 +int main(int argc, char **argv)
185.237 +{
185.238 + int i;
185.239 + int errors = 0;
185.240 + unsigned char tmp[32];
185.241 +
185.242 + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
185.243 + unsigned char *msg = (unsigned char *) tests[i].msg;
185.244 + int len = strlen(tests[i].msg);
185.245 +
185.246 + ext2fs_sha256(msg, len, tmp);
185.247 + printf("SHA256 test message %d: ", i);
185.248 + if (memcmp(tmp, tests[i].hash, 32) != 0) {
185.249 + printf("FAILED\n");
185.250 + errors++;
185.251 + } else
185.252 + printf("OK\n");
185.253 + }
185.254 + return errors;
185.255 +}
185.256 +
185.257 +#endif /* UNITTEST */
186.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
186.2 +++ b/libext2fs/lib/libext2fs/sha512.c Wed Aug 25 01:28:08 2021 +0200
186.3 @@ -0,0 +1,302 @@
186.4 +/*
186.5 + * sha512.c --- The sha512 algorithm
186.6 + *
186.7 + * Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
186.8 + * (copied from libtomcrypt and then relicensed under GPLv2)
186.9 + *
186.10 + * %Begin-Header%
186.11 + * This file may be redistributed under the terms of the GNU Library
186.12 + * General Public License, version 2.
186.13 + * %End-Header%
186.14 + */
186.15 +
186.16 +
186.17 +#include "config.h"
186.18 +#if HAVE_SYS_TYPES_H
186.19 +#include <sys/types.h>
186.20 +#endif
186.21 +#include "ext2fs.h"
186.22 +
186.23 +/* the K array */
186.24 +#define CONST64(n) n
186.25 +static const __u64 K[80] = {
186.26 + CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
186.27 + CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
186.28 + CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
186.29 + CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
186.30 + CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
186.31 + CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
186.32 + CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
186.33 + CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
186.34 + CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
186.35 + CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
186.36 + CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
186.37 + CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
186.38 + CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
186.39 + CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
186.40 + CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
186.41 + CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
186.42 + CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
186.43 + CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
186.44 + CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
186.45 + CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
186.46 + CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
186.47 + CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
186.48 + CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
186.49 + CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
186.50 + CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
186.51 + CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
186.52 + CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
186.53 + CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
186.54 + CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
186.55 + CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
186.56 + CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
186.57 + CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
186.58 + CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
186.59 + CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
186.60 + CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
186.61 + CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
186.62 + CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
186.63 + CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
186.64 + CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
186.65 + CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
186.66 +};
186.67 +#define Ch(x,y,z) (z ^ (x & (y ^ z)))
186.68 +#define Maj(x,y,z) (((x | y) & z) | (x & y))
186.69 +#define S(x, n) ROR64c(x, n)
186.70 +#define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((__u64)n))
186.71 +#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
186.72 +#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
186.73 +#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
186.74 +#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
186.75 +#define RND(a,b,c,d,e,f,g,h,i)\
186.76 + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];\
186.77 + t1 = Sigma0(a) + Maj(a, b, c);\
186.78 + d += t0;\
186.79 + h = t0 + t1;
186.80 +#define STORE64H(x, y) \
186.81 + do { \
186.82 + (y)[0] = (unsigned char)(((x)>>56)&255);\
186.83 + (y)[1] = (unsigned char)(((x)>>48)&255);\
186.84 + (y)[2] = (unsigned char)(((x)>>40)&255);\
186.85 + (y)[3] = (unsigned char)(((x)>>32)&255);\
186.86 + (y)[4] = (unsigned char)(((x)>>24)&255);\
186.87 + (y)[5] = (unsigned char)(((x)>>16)&255);\
186.88 + (y)[6] = (unsigned char)(((x)>>8)&255);\
186.89 + (y)[7] = (unsigned char)((x)&255); } while(0)
186.90 +
186.91 +#define LOAD64H(x, y)\
186.92 + do {x = \
186.93 + (((__u64)((y)[0] & 255)) << 56) |\
186.94 + (((__u64)((y)[1] & 255)) << 48) |\
186.95 + (((__u64)((y)[2] & 255)) << 40) |\
186.96 + (((__u64)((y)[3] & 255)) << 32) |\
186.97 + (((__u64)((y)[4] & 255)) << 24) |\
186.98 + (((__u64)((y)[5] & 255)) << 16) |\
186.99 + (((__u64)((y)[6] & 255)) << 8) |\
186.100 + (((__u64)((y)[7] & 255)));\
186.101 + } while(0)
186.102 +
186.103 +#define ROR64c(x, y) \
186.104 + ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((__u64)(y)&CONST64(63))) | \
186.105 + ((x)<<((__u64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
186.106 +
186.107 +struct sha512_state {
186.108 + __u64 length, state[8];
186.109 + unsigned long curlen;
186.110 + unsigned char buf[128];
186.111 +};
186.112 +
186.113 +/* This is a highly simplified version from libtomcrypt */
186.114 +struct hash_state {
186.115 + struct sha512_state sha512;
186.116 +};
186.117 +
186.118 +static void sha512_compress(struct hash_state * md, const unsigned char *buf)
186.119 +{
186.120 + __u64 S[8], W[80], t0, t1;
186.121 + int i;
186.122 +
186.123 + /* copy state into S */
186.124 + for (i = 0; i < 8; i++) {
186.125 + S[i] = md->sha512.state[i];
186.126 + }
186.127 +
186.128 + /* copy the state into 1024-bits into W[0..15] */
186.129 + for (i = 0; i < 16; i++) {
186.130 + LOAD64H(W[i], buf + (8*i));
186.131 + }
186.132 +
186.133 + /* fill W[16..79] */
186.134 + for (i = 16; i < 80; i++) {
186.135 + W[i] = Gamma1(W[i - 2]) + W[i - 7] +
186.136 + Gamma0(W[i - 15]) + W[i - 16];
186.137 + }
186.138 +
186.139 + for (i = 0; i < 80; i += 8) {
186.140 + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
186.141 + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
186.142 + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
186.143 + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
186.144 + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
186.145 + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
186.146 + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
186.147 + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
186.148 + }
186.149 +
186.150 + /* feedback */
186.151 + for (i = 0; i < 8; i++) {
186.152 + md->sha512.state[i] = md->sha512.state[i] + S[i];
186.153 + }
186.154 +}
186.155 +
186.156 +static void sha512_init(struct hash_state * md)
186.157 +{
186.158 + md->sha512.curlen = 0;
186.159 + md->sha512.length = 0;
186.160 + md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);
186.161 + md->sha512.state[1] = CONST64(0xbb67ae8584caa73b);
186.162 + md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b);
186.163 + md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1);
186.164 + md->sha512.state[4] = CONST64(0x510e527fade682d1);
186.165 + md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);
186.166 + md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);
186.167 + md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
186.168 +}
186.169 +
186.170 +static void sha512_done(struct hash_state * md, unsigned char *out)
186.171 +{
186.172 + int i;
186.173 +
186.174 + /* increase the length of the message */
186.175 + md->sha512.length += md->sha512.curlen * CONST64(8);
186.176 +
186.177 + /* append the '1' bit */
186.178 + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80;
186.179 +
186.180 + /* if the length is currently above 112 bytes we append zeros then
186.181 + * compress. Then we can fall back to padding zeros and length encoding
186.182 + * like normal. */
186.183 + if (md->sha512.curlen > 112) {
186.184 + while (md->sha512.curlen < 128) {
186.185 + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
186.186 + }
186.187 + sha512_compress(md, md->sha512.buf);
186.188 + md->sha512.curlen = 0;
186.189 + }
186.190 +
186.191 + /* pad upto 120 bytes of zeroes note: that from 112 to 120 is the 64 MSB
186.192 + * of the length. We assume that you won't hash > 2^64 bits of data. */
186.193 + while (md->sha512.curlen < 120) {
186.194 + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
186.195 + }
186.196 +
186.197 + /* store length */
186.198 + STORE64H(md->sha512.length, md->sha512.buf + 120);
186.199 + sha512_compress(md, md->sha512.buf);
186.200 +
186.201 + /* copy output */
186.202 + for (i = 0; i < 8; i++) {
186.203 + STORE64H(md->sha512.state[i], out+(8 * i));
186.204 + }
186.205 +}
186.206 +
186.207 +#define MIN(x, y) ( ((x)<(y))?(x):(y) )
186.208 +#define SHA512_BLOCKSIZE 128
186.209 +static void sha512_process(struct hash_state * md,
186.210 + const unsigned char *in,
186.211 + unsigned long inlen)
186.212 +{
186.213 + unsigned long n;
186.214 +
186.215 + while (inlen > 0) {
186.216 + if (md->sha512.curlen == 0 && inlen >= SHA512_BLOCKSIZE) {
186.217 + sha512_compress(md, in);
186.218 + md->sha512.length += SHA512_BLOCKSIZE * 8;
186.219 + in += SHA512_BLOCKSIZE;
186.220 + inlen -= SHA512_BLOCKSIZE;
186.221 + } else {
186.222 + n = MIN(inlen, (SHA512_BLOCKSIZE - md->sha512.curlen));
186.223 + memcpy(md->sha512.buf + md->sha512.curlen,
186.224 + in, (size_t)n);
186.225 + md->sha512.curlen += n;
186.226 + in += n;
186.227 + inlen -= n;
186.228 + if (md->sha512.curlen == SHA512_BLOCKSIZE) {
186.229 + sha512_compress(md, md->sha512.buf);
186.230 + md->sha512.length += SHA512_BLOCKSIZE * 8;
186.231 + md->sha512.curlen = 0;
186.232 + }
186.233 + }
186.234 + }
186.235 +}
186.236 +
186.237 +void ext2fs_sha512(const unsigned char *in, unsigned long in_size,
186.238 + unsigned char out[EXT2FS_SHA512_LENGTH])
186.239 +{
186.240 + struct hash_state md;
186.241 +
186.242 + sha512_init(&md);
186.243 + sha512_process(&md, in, in_size);
186.244 + sha512_done(&md, out);
186.245 +}
186.246 +
186.247 +#ifdef UNITTEST
186.248 +static const struct {
186.249 + char *msg;
186.250 + unsigned char hash[64];
186.251 +} tests[] = {
186.252 + { "",
186.253 + { 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
186.254 + 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
186.255 + 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
186.256 + 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
186.257 + 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
186.258 + 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
186.259 + 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
186.260 + 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e }
186.261 + },
186.262 + { "abc",
186.263 + { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
186.264 + 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
186.265 + 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
186.266 + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
186.267 + 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
186.268 + 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
186.269 + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
186.270 + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }
186.271 + },
186.272 + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
186.273 + { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
186.274 + 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
186.275 + 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
186.276 + 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
186.277 + 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
186.278 + 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
186.279 + 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
186.280 + 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }
186.281 + },
186.282 +};
186.283 +
186.284 +int main(int argc, char **argv)
186.285 +{
186.286 + int i;
186.287 + int errors = 0;
186.288 + unsigned char tmp[64];
186.289 +
186.290 + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
186.291 + unsigned char *msg = (unsigned char *) tests[i].msg;
186.292 + int len = strlen(tests[i].msg);
186.293 +
186.294 + ext2fs_sha512(msg, len, tmp);
186.295 + printf("SHA512 test message %d: ", i);
186.296 + if (memcmp(tmp, tests[i].hash, 64) != 0) {
186.297 + printf("FAILED\n");
186.298 + errors++;
186.299 + } else
186.300 + printf("OK\n");
186.301 + }
186.302 + return errors;
186.303 +}
186.304 +
186.305 +#endif /* UNITTEST */
187.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
187.2 +++ b/libext2fs/lib/libext2fs/symlink.c Wed Aug 25 01:28:08 2021 +0200
187.3 @@ -0,0 +1,204 @@
187.4 +/*
187.5 + * symlink.c --- make a symlink in the filesystem, based on mkdir.c
187.6 + *
187.7 + * Copyright (c) 2012, Intel Corporation.
187.8 + * All Rights Reserved.
187.9 + *
187.10 + * %Begin-Header%
187.11 + * This file may be redistributed under the terms of the GNU Library
187.12 + * General Public License, version 2.
187.13 + * %End-Header%
187.14 + */
187.15 +
187.16 +#include "config.h"
187.17 +#include <stdio.h>
187.18 +#include <string.h>
187.19 +#if HAVE_UNISTD_H
187.20 +#include <unistd.h>
187.21 +#endif
187.22 +#include <fcntl.h>
187.23 +#include <time.h>
187.24 +#if HAVE_SYS_STAT_H
187.25 +#include <sys/stat.h>
187.26 +#endif
187.27 +#if HAVE_SYS_TYPES_H
187.28 +#include <sys/types.h>
187.29 +#endif
187.30 +
187.31 +#include "ext2_fs.h"
187.32 +#include "ext2fs.h"
187.33 +
187.34 +#ifndef HAVE_STRNLEN
187.35 +/*
187.36 + * Incredibly, libc5 doesn't appear to have strnlen. So we have to
187.37 + * provide our own.
187.38 + */
187.39 +static int my_strnlen(const char * s, int count)
187.40 +{
187.41 + const char *cp = s;
187.42 +
187.43 + while (count-- && *cp)
187.44 + cp++;
187.45 + return cp - s;
187.46 +}
187.47 +#define strnlen(str, x) my_strnlen((str),(x))
187.48 +#endif
187.49 +
187.50 +errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino,
187.51 + const char *name, const char *target)
187.52 +{
187.53 + errcode_t retval;
187.54 + struct ext2_inode inode;
187.55 + ext2_ino_t scratch_ino;
187.56 + blk64_t blk;
187.57 + int fastlink, inlinelink;
187.58 + unsigned int target_len;
187.59 + char *block_buf = 0;
187.60 +
187.61 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
187.62 +
187.63 + /*
187.64 + * The Linux kernel doesn't allow for links longer than a block
187.65 + * (counting the NUL terminator)
187.66 + */
187.67 + target_len = strnlen(target, fs->blocksize + 1);
187.68 + if (target_len >= fs->blocksize) {
187.69 + retval = EXT2_ET_INVALID_ARGUMENT;
187.70 + goto cleanup;
187.71 + }
187.72 +
187.73 + /*
187.74 + * Allocate a data block for slow links
187.75 + */
187.76 + retval = ext2fs_get_mem(fs->blocksize, &block_buf);
187.77 + if (retval)
187.78 + goto cleanup;
187.79 + memset(block_buf, 0, fs->blocksize);
187.80 + strncpy(block_buf, target, fs->blocksize);
187.81 +
187.82 + memset(&inode, 0, sizeof(struct ext2_inode));
187.83 + fastlink = (target_len < sizeof(inode.i_block));
187.84 + if (!fastlink) {
187.85 + retval = ext2fs_new_block2(fs, ext2fs_find_inode_goal(fs, ino,
187.86 + &inode,
187.87 + 0),
187.88 + NULL, &blk);
187.89 + if (retval)
187.90 + goto cleanup;
187.91 + }
187.92 +
187.93 + /*
187.94 + * Allocate an inode, if necessary
187.95 + */
187.96 + if (!ino) {
187.97 + retval = ext2fs_new_inode(fs, parent, LINUX_S_IFLNK | 0755,
187.98 + 0, &ino);
187.99 + if (retval)
187.100 + goto cleanup;
187.101 + }
187.102 +
187.103 + /*
187.104 + * Create the inode structure....
187.105 + */
187.106 + inode.i_mode = LINUX_S_IFLNK | 0777;
187.107 + inode.i_uid = inode.i_gid = 0;
187.108 + inode.i_links_count = 1;
187.109 + ext2fs_inode_size_set(fs, &inode, target_len);
187.110 + /* The time fields are set by ext2fs_write_new_inode() */
187.111 +
187.112 + inlinelink = !fastlink && ext2fs_has_feature_inline_data(fs->super);
187.113 + if (fastlink) {
187.114 + /* Fast symlinks, target stored in inode */
187.115 + strcpy((char *)&inode.i_block, target);
187.116 + } else if (inlinelink) {
187.117 + /* Try inserting an inline data symlink */
187.118 + inode.i_flags |= EXT4_INLINE_DATA_FL;
187.119 + retval = ext2fs_write_new_inode(fs, ino, &inode);
187.120 + if (retval)
187.121 + goto cleanup;
187.122 + retval = ext2fs_inline_data_set(fs, ino, &inode, block_buf,
187.123 + target_len);
187.124 + if (retval) {
187.125 + inode.i_flags &= ~EXT4_INLINE_DATA_FL;
187.126 + inlinelink = 0;
187.127 + goto need_block;
187.128 + }
187.129 + retval = ext2fs_read_inode(fs, ino, &inode);
187.130 + if (retval)
187.131 + goto cleanup;
187.132 + } else {
187.133 +need_block:
187.134 + /* Slow symlinks, target stored in the first block */
187.135 + ext2fs_iblk_set(fs, &inode, 1);
187.136 + if (ext2fs_has_feature_extents(fs->super)) {
187.137 + /*
187.138 + * The extent bmap is setup after the inode and block
187.139 + * have been written out below.
187.140 + */
187.141 + inode.i_flags |= EXT4_EXTENTS_FL;
187.142 + }
187.143 + }
187.144 +
187.145 + /*
187.146 + * Write out the inode and inode data block. The inode generation
187.147 + * number is assigned by write_new_inode, which means that the
187.148 + * operations using ino must come after it.
187.149 + */
187.150 + if (inlinelink)
187.151 + retval = ext2fs_write_inode(fs, ino, &inode);
187.152 + else
187.153 + retval = ext2fs_write_new_inode(fs, ino, &inode);
187.154 + if (retval)
187.155 + goto cleanup;
187.156 +
187.157 + if (!fastlink && !inlinelink) {
187.158 + retval = ext2fs_bmap2(fs, ino, &inode, NULL, BMAP_SET, 0, NULL,
187.159 + &blk);
187.160 + if (retval)
187.161 + goto cleanup;
187.162 +
187.163 + retval = io_channel_write_blk64(fs->io, blk, 1, block_buf);
187.164 + if (retval)
187.165 + goto cleanup;
187.166 + }
187.167 +
187.168 + /*
187.169 + * Link the symlink into the filesystem hierarchy
187.170 + */
187.171 + if (name) {
187.172 + retval = ext2fs_lookup(fs, parent, name, strlen(name), 0,
187.173 + &scratch_ino);
187.174 + if (!retval) {
187.175 + retval = EXT2_ET_FILE_EXISTS;
187.176 + goto cleanup;
187.177 + }
187.178 + if (retval != EXT2_ET_FILE_NOT_FOUND)
187.179 + goto cleanup;
187.180 + retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_SYMLINK);
187.181 + if (retval)
187.182 + goto cleanup;
187.183 + }
187.184 +
187.185 + /*
187.186 + * Update accounting....
187.187 + */
187.188 + if (!fastlink && !inlinelink)
187.189 + ext2fs_block_alloc_stats2(fs, blk, +1);
187.190 + ext2fs_inode_alloc_stats2(fs, ino, +1, 0);
187.191 +
187.192 +cleanup:
187.193 + if (block_buf)
187.194 + ext2fs_free_mem(&block_buf);
187.195 + return retval;
187.196 +}
187.197 +
187.198 +/*
187.199 + * Test whether an inode is a fast symlink.
187.200 + *
187.201 + * A fast symlink has its symlink data stored in inode->i_block.
187.202 + */
187.203 +int ext2fs_is_fast_symlink(struct ext2_inode *inode)
187.204 +{
187.205 + return LINUX_S_ISLNK(inode->i_mode) && EXT2_I_SIZE(inode) &&
187.206 + EXT2_I_SIZE(inode) < sizeof(inode->i_block);
187.207 +}
188.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
188.2 +++ b/libext2fs/lib/libext2fs/unix_io.c Wed Aug 25 01:28:08 2021 +0200
188.3 @@ -0,0 +1,1244 @@
188.4 +/*
188.5 + * unix_io.c --- This is the Unix (well, really POSIX) implementation
188.6 + * of the I/O manager.
188.7 + *
188.8 + * Implements a one-block write-through cache.
188.9 + *
188.10 + * Includes support for Windows NT support under Cygwin.
188.11 + *
188.12 + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
188.13 + * 2002 by Theodore Ts'o.
188.14 + *
188.15 + * %Begin-Header%
188.16 + * This file may be redistributed under the terms of the GNU Library
188.17 + * General Public License, version 2.
188.18 + * %End-Header%
188.19 + */
188.20 +
188.21 +#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
188.22 +#define _XOPEN_SOURCE 600
188.23 +#define _DARWIN_C_SOURCE
188.24 +#define _FILE_OFFSET_BITS 64
188.25 +#ifndef _LARGEFILE_SOURCE
188.26 +#define _LARGEFILE_SOURCE
188.27 +#endif
188.28 +#ifndef _LARGEFILE64_SOURCE
188.29 +#define _LARGEFILE64_SOURCE
188.30 +#endif
188.31 +#ifndef _GNU_SOURCE
188.32 +#define _GNU_SOURCE
188.33 +#endif
188.34 +#endif
188.35 +
188.36 +#include "config.h"
188.37 +#include <stdio.h>
188.38 +#include <string.h>
188.39 +#if HAVE_UNISTD_H
188.40 +#include <unistd.h>
188.41 +#endif
188.42 +#if HAVE_ERRNO_H
188.43 +#include <errno.h>
188.44 +#endif
188.45 +#include <fcntl.h>
188.46 +#include <time.h>
188.47 +#ifdef __linux__
188.48 +#include <sys/utsname.h>
188.49 +#endif
188.50 +#if HAVE_SYS_TYPES_H
188.51 +#include <sys/types.h>
188.52 +#endif
188.53 +#ifdef HAVE_SYS_IOCTL_H
188.54 +#include <sys/ioctl.h>
188.55 +#endif
188.56 +#ifdef HAVE_SYS_MOUNT_H
188.57 +#include <sys/mount.h>
188.58 +#endif
188.59 +#ifdef HAVE_SYS_PRCTL_H
188.60 +#include <sys/prctl.h>
188.61 +#else
188.62 +#define PR_GET_DUMPABLE 3
188.63 +#endif
188.64 +#if HAVE_SYS_STAT_H
188.65 +#include <sys/stat.h>
188.66 +#endif
188.67 +#if HAVE_SYS_RESOURCE_H
188.68 +#include <sys/resource.h>
188.69 +#endif
188.70 +#if HAVE_LINUX_FALLOC_H
188.71 +#include <linux/falloc.h>
188.72 +#endif
188.73 +
188.74 +#if defined(__linux__) && defined(_IO) && !defined(BLKROGET)
188.75 +#define BLKROGET _IO(0x12, 94) /* Get read-only status (0 = read_write). */
188.76 +#endif
188.77 +
188.78 +#undef ALIGN_DEBUG
188.79 +
188.80 +#include "ext2_fs.h"
188.81 +#include "ext2fs.h"
188.82 +#include "ext2fsP.h"
188.83 +
188.84 +/*
188.85 + * For checking structure magic numbers...
188.86 + */
188.87 +
188.88 +#define EXT2_CHECK_MAGIC(struct, code) \
188.89 + if ((struct)->magic != (code)) return (code)
188.90 +
188.91 +struct unix_cache {
188.92 + char *buf;
188.93 + unsigned long long block;
188.94 + int access_time;
188.95 + unsigned dirty:1;
188.96 + unsigned in_use:1;
188.97 +};
188.98 +
188.99 +#define CACHE_SIZE 8
188.100 +#define WRITE_DIRECT_SIZE 4 /* Must be smaller than CACHE_SIZE */
188.101 +#define READ_DIRECT_SIZE 4 /* Should be smaller than CACHE_SIZE */
188.102 +
188.103 +struct unix_private_data {
188.104 + int magic;
188.105 + int dev;
188.106 + int flags;
188.107 + int align;
188.108 + int access_time;
188.109 + ext2_loff_t offset;
188.110 + struct unix_cache cache[CACHE_SIZE];
188.111 + void *bounce;
188.112 + struct struct_io_stats io_stats;
188.113 +};
188.114 +
188.115 +#define IS_ALIGNED(n, align) ((((uintptr_t) n) & \
188.116 + ((uintptr_t) ((align)-1))) == 0)
188.117 +
188.118 +static errcode_t unix_get_stats(io_channel channel, io_stats *stats)
188.119 +{
188.120 + errcode_t retval = 0;
188.121 +
188.122 + struct unix_private_data *data;
188.123 +
188.124 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
188.125 + data = (struct unix_private_data *) channel->private_data;
188.126 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
188.127 +
188.128 + if (stats)
188.129 + *stats = &data->io_stats;
188.130 +
188.131 + return retval;
188.132 +}
188.133 +
188.134 +static char *safe_getenv(const char *arg)
188.135 +{
188.136 + if ((getuid() != geteuid()) || (getgid() != getegid()))
188.137 + return NULL;
188.138 +#ifdef HAVE_PRCTL
188.139 + if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
188.140 + return NULL;
188.141 +#else
188.142 +#if (defined(linux) && defined(SYS_prctl))
188.143 + if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
188.144 + return NULL;
188.145 +#endif
188.146 +#endif
188.147 +
188.148 +#if defined(HAVE_SECURE_GETENV)
188.149 + return secure_getenv(arg);
188.150 +#elif defined(HAVE___SECURE_GETENV)
188.151 + return __secure_getenv(arg);
188.152 +#else
188.153 + return getenv(arg);
188.154 +#endif
188.155 +}
188.156 +
188.157 +/*
188.158 + * Here are the raw I/O functions
188.159 + */
188.160 +static errcode_t raw_read_blk(io_channel channel,
188.161 + struct unix_private_data *data,
188.162 + unsigned long long block,
188.163 + int count, void *bufv)
188.164 +{
188.165 + errcode_t retval;
188.166 + ssize_t size;
188.167 + ext2_loff_t location;
188.168 + int actual = 0;
188.169 + unsigned char *buf = bufv;
188.170 + ssize_t really_read = 0;
188.171 +
188.172 + size = (count < 0) ? -count : count * channel->block_size;
188.173 + data->io_stats.bytes_read += size;
188.174 + location = ((ext2_loff_t) block * channel->block_size) + data->offset;
188.175 +
188.176 + if (data->flags & IO_FLAG_FORCE_BOUNCE) {
188.177 + if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
188.178 + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
188.179 + goto error_out;
188.180 + }
188.181 + goto bounce_read;
188.182 + }
188.183 +
188.184 +#ifdef HAVE_PREAD64
188.185 + /* Try an aligned pread */
188.186 + if ((channel->align == 0) ||
188.187 + (IS_ALIGNED(buf, channel->align) &&
188.188 + IS_ALIGNED(size, channel->align))) {
188.189 + actual = pread64(data->dev, buf, size, location);
188.190 + if (actual == size)
188.191 + return 0;
188.192 + actual = 0;
188.193 + }
188.194 +#elif HAVE_PREAD
188.195 + /* Try an aligned pread */
188.196 + if ((sizeof(off_t) >= sizeof(ext2_loff_t)) &&
188.197 + ((channel->align == 0) ||
188.198 + (IS_ALIGNED(buf, channel->align) &&
188.199 + IS_ALIGNED(size, channel->align)))) {
188.200 + actual = pread(data->dev, buf, size, location);
188.201 + if (actual == size)
188.202 + return 0;
188.203 + actual = 0;
188.204 + }
188.205 +#endif /* HAVE_PREAD */
188.206 +
188.207 + if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
188.208 + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
188.209 + goto error_out;
188.210 + }
188.211 + if ((channel->align == 0) ||
188.212 + (IS_ALIGNED(buf, channel->align) &&
188.213 + IS_ALIGNED(size, channel->align))) {
188.214 + actual = read(data->dev, buf, size);
188.215 + if (actual != size) {
188.216 + short_read:
188.217 + if (actual < 0) {
188.218 + retval = errno;
188.219 + actual = 0;
188.220 + } else
188.221 + retval = EXT2_ET_SHORT_READ;
188.222 + goto error_out;
188.223 + }
188.224 + return 0;
188.225 + }
188.226 +
188.227 +#ifdef ALIGN_DEBUG
188.228 + printf("raw_read_blk: O_DIRECT fallback: %p %lu\n", buf,
188.229 + (unsigned long) size);
188.230 +#endif
188.231 +
188.232 + /*
188.233 + * The buffer or size which we're trying to read isn't aligned
188.234 + * to the O_DIRECT rules, so we need to do this the hard way...
188.235 + */
188.236 +bounce_read:
188.237 + while (size > 0) {
188.238 + actual = read(data->dev, data->bounce, channel->block_size);
188.239 + if (actual != channel->block_size) {
188.240 + actual = really_read;
188.241 + buf -= really_read;
188.242 + size += really_read;
188.243 + goto short_read;
188.244 + }
188.245 + actual = size;
188.246 + if (size > channel->block_size)
188.247 + actual = channel->block_size;
188.248 + memcpy(buf, data->bounce, actual);
188.249 + really_read += actual;
188.250 + size -= actual;
188.251 + buf += actual;
188.252 + }
188.253 + return 0;
188.254 +
188.255 +error_out:
188.256 + if (actual >= 0 && actual < size)
188.257 + memset((char *) buf+actual, 0, size-actual);
188.258 + if (channel->read_error)
188.259 + retval = (channel->read_error)(channel, block, count, buf,
188.260 + size, actual, retval);
188.261 + return retval;
188.262 +}
188.263 +
188.264 +static errcode_t raw_write_blk(io_channel channel,
188.265 + struct unix_private_data *data,
188.266 + unsigned long long block,
188.267 + int count, const void *bufv)
188.268 +{
188.269 + ssize_t size;
188.270 + ext2_loff_t location;
188.271 + int actual = 0;
188.272 + errcode_t retval;
188.273 + const unsigned char *buf = bufv;
188.274 +
188.275 + if (count == 1)
188.276 + size = channel->block_size;
188.277 + else {
188.278 + if (count < 0)
188.279 + size = -count;
188.280 + else
188.281 + size = count * channel->block_size;
188.282 + }
188.283 + data->io_stats.bytes_written += size;
188.284 +
188.285 + location = ((ext2_loff_t) block * channel->block_size) + data->offset;
188.286 +
188.287 + if (data->flags & IO_FLAG_FORCE_BOUNCE) {
188.288 + if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
188.289 + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
188.290 + goto error_out;
188.291 + }
188.292 + goto bounce_write;
188.293 + }
188.294 +
188.295 +#ifdef HAVE_PWRITE64
188.296 + /* Try an aligned pwrite */
188.297 + if ((channel->align == 0) ||
188.298 + (IS_ALIGNED(buf, channel->align) &&
188.299 + IS_ALIGNED(size, channel->align))) {
188.300 + actual = pwrite64(data->dev, buf, size, location);
188.301 + if (actual == size)
188.302 + return 0;
188.303 + }
188.304 +#elif HAVE_PWRITE
188.305 + /* Try an aligned pwrite */
188.306 + if ((sizeof(off_t) >= sizeof(ext2_loff_t)) &&
188.307 + ((channel->align == 0) ||
188.308 + (IS_ALIGNED(buf, channel->align) &&
188.309 + IS_ALIGNED(size, channel->align)))) {
188.310 + actual = pwrite(data->dev, buf, size, location);
188.311 + if (actual == size)
188.312 + return 0;
188.313 + }
188.314 +#endif /* HAVE_PWRITE */
188.315 +
188.316 + if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
188.317 + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
188.318 + goto error_out;
188.319 + }
188.320 +
188.321 + if ((channel->align == 0) ||
188.322 + (IS_ALIGNED(buf, channel->align) &&
188.323 + IS_ALIGNED(size, channel->align))) {
188.324 + actual = write(data->dev, buf, size);
188.325 + if (actual < 0) {
188.326 + retval = errno;
188.327 + goto error_out;
188.328 + }
188.329 + if (actual != size) {
188.330 + short_write:
188.331 + retval = EXT2_ET_SHORT_WRITE;
188.332 + goto error_out;
188.333 + }
188.334 + return 0;
188.335 + }
188.336 +
188.337 +#ifdef ALIGN_DEBUG
188.338 + printf("raw_write_blk: O_DIRECT fallback: %p %lu\n", buf,
188.339 + (unsigned long) size);
188.340 +#endif
188.341 + /*
188.342 + * The buffer or size which we're trying to write isn't aligned
188.343 + * to the O_DIRECT rules, so we need to do this the hard way...
188.344 + */
188.345 +bounce_write:
188.346 + while (size > 0) {
188.347 + if (size < channel->block_size) {
188.348 + actual = read(data->dev, data->bounce,
188.349 + channel->block_size);
188.350 + if (actual != channel->block_size) {
188.351 + if (actual < 0) {
188.352 + retval = errno;
188.353 + goto error_out;
188.354 + }
188.355 + memset((char *) data->bounce + actual, 0,
188.356 + channel->block_size - actual);
188.357 + }
188.358 + }
188.359 + actual = size;
188.360 + if (size > channel->block_size)
188.361 + actual = channel->block_size;
188.362 + memcpy(data->bounce, buf, actual);
188.363 + if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
188.364 + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
188.365 + goto error_out;
188.366 + }
188.367 + actual = write(data->dev, data->bounce, channel->block_size);
188.368 + if (actual < 0) {
188.369 + retval = errno;
188.370 + goto error_out;
188.371 + }
188.372 + if (actual != channel->block_size)
188.373 + goto short_write;
188.374 + size -= actual;
188.375 + buf += actual;
188.376 + location += actual;
188.377 + }
188.378 + return 0;
188.379 +
188.380 +error_out:
188.381 + if (channel->write_error)
188.382 + retval = (channel->write_error)(channel, block, count, buf,
188.383 + size, actual, retval);
188.384 + return retval;
188.385 +}
188.386 +
188.387 +
188.388 +/*
188.389 + * Here we implement the cache functions
188.390 + */
188.391 +
188.392 +/* Allocate the cache buffers */
188.393 +static errcode_t alloc_cache(io_channel channel,
188.394 + struct unix_private_data *data)
188.395 +{
188.396 + errcode_t retval;
188.397 + struct unix_cache *cache;
188.398 + int i;
188.399 +
188.400 + data->access_time = 0;
188.401 + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
188.402 + cache->block = 0;
188.403 + cache->access_time = 0;
188.404 + cache->dirty = 0;
188.405 + cache->in_use = 0;
188.406 + if (cache->buf)
188.407 + ext2fs_free_mem(&cache->buf);
188.408 + retval = io_channel_alloc_buf(channel, 0, &cache->buf);
188.409 + if (retval)
188.410 + return retval;
188.411 + }
188.412 + if (channel->align || data->flags & IO_FLAG_FORCE_BOUNCE) {
188.413 + if (data->bounce)
188.414 + ext2fs_free_mem(&data->bounce);
188.415 + retval = io_channel_alloc_buf(channel, 0, &data->bounce);
188.416 + }
188.417 + return retval;
188.418 +}
188.419 +
188.420 +/* Free the cache buffers */
188.421 +static void free_cache(struct unix_private_data *data)
188.422 +{
188.423 + struct unix_cache *cache;
188.424 + int i;
188.425 +
188.426 + data->access_time = 0;
188.427 + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
188.428 + cache->block = 0;
188.429 + cache->access_time = 0;
188.430 + cache->dirty = 0;
188.431 + cache->in_use = 0;
188.432 + if (cache->buf)
188.433 + ext2fs_free_mem(&cache->buf);
188.434 + }
188.435 + if (data->bounce)
188.436 + ext2fs_free_mem(&data->bounce);
188.437 +}
188.438 +
188.439 +#ifndef NO_IO_CACHE
188.440 +/*
188.441 + * Try to find a block in the cache. If the block is not found, and
188.442 + * eldest is a non-zero pointer, then fill in eldest with the cache
188.443 + * entry to that should be reused.
188.444 + */
188.445 +static struct unix_cache *find_cached_block(struct unix_private_data *data,
188.446 + unsigned long long block,
188.447 + struct unix_cache **eldest)
188.448 +{
188.449 + struct unix_cache *cache, *unused_cache, *oldest_cache;
188.450 + int i;
188.451 +
188.452 + unused_cache = oldest_cache = 0;
188.453 + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
188.454 + if (!cache->in_use) {
188.455 + if (!unused_cache)
188.456 + unused_cache = cache;
188.457 + continue;
188.458 + }
188.459 + if (cache->block == block) {
188.460 + cache->access_time = ++data->access_time;
188.461 + return cache;
188.462 + }
188.463 + if (!oldest_cache ||
188.464 + (cache->access_time < oldest_cache->access_time))
188.465 + oldest_cache = cache;
188.466 + }
188.467 + if (eldest)
188.468 + *eldest = (unused_cache) ? unused_cache : oldest_cache;
188.469 + return 0;
188.470 +}
188.471 +
188.472 +/*
188.473 + * Reuse a particular cache entry for another block.
188.474 + */
188.475 +static void reuse_cache(io_channel channel, struct unix_private_data *data,
188.476 + struct unix_cache *cache, unsigned long long block)
188.477 +{
188.478 + if (cache->dirty && cache->in_use)
188.479 + raw_write_blk(channel, data, cache->block, 1, cache->buf);
188.480 +
188.481 + cache->in_use = 1;
188.482 + cache->dirty = 0;
188.483 + cache->block = block;
188.484 + cache->access_time = ++data->access_time;
188.485 +}
188.486 +
188.487 +/*
188.488 + * Flush all of the blocks in the cache
188.489 + */
188.490 +static errcode_t flush_cached_blocks(io_channel channel,
188.491 + struct unix_private_data *data,
188.492 + int invalidate)
188.493 +
188.494 +{
188.495 + struct unix_cache *cache;
188.496 + errcode_t retval, retval2;
188.497 + int i;
188.498 +
188.499 + retval2 = 0;
188.500 + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
188.501 + if (!cache->in_use)
188.502 + continue;
188.503 +
188.504 + if (invalidate)
188.505 + cache->in_use = 0;
188.506 +
188.507 + if (!cache->dirty)
188.508 + continue;
188.509 +
188.510 + retval = raw_write_blk(channel, data,
188.511 + cache->block, 1, cache->buf);
188.512 + if (retval)
188.513 + retval2 = retval;
188.514 + else
188.515 + cache->dirty = 0;
188.516 + }
188.517 + return retval2;
188.518 +}
188.519 +#endif /* NO_IO_CACHE */
188.520 +
188.521 +#ifdef __linux__
188.522 +#ifndef BLKDISCARDZEROES
188.523 +#define BLKDISCARDZEROES _IO(0x12,124)
188.524 +#endif
188.525 +#endif
188.526 +
188.527 +int ext2fs_open_file(const char *pathname, int flags, mode_t mode)
188.528 +{
188.529 + if (mode)
188.530 +#if defined(HAVE_OPEN64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
188.531 + return open64(pathname, flags, mode);
188.532 + else
188.533 + return open64(pathname, flags);
188.534 +#else
188.535 + return open(pathname, flags, mode);
188.536 + else
188.537 + return open(pathname, flags);
188.538 +#endif
188.539 +}
188.540 +
188.541 +int ext2fs_stat(const char *path, ext2fs_struct_stat *buf)
188.542 +{
188.543 +#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
188.544 + return stat64(path, buf);
188.545 +#else
188.546 + return stat(path, buf);
188.547 +#endif
188.548 +}
188.549 +
188.550 +int ext2fs_fstat(int fd, ext2fs_struct_stat *buf)
188.551 +{
188.552 +#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
188.553 + return fstat64(fd, buf);
188.554 +#else
188.555 + return fstat(fd, buf);
188.556 +#endif
188.557 +}
188.558 +
188.559 +
188.560 +static errcode_t unix_open_channel(const char *name, int fd,
188.561 + int flags, io_channel *channel,
188.562 + io_manager io_mgr)
188.563 +{
188.564 + io_channel io = NULL;
188.565 + struct unix_private_data *data = NULL;
188.566 + errcode_t retval;
188.567 + ext2fs_struct_stat st;
188.568 +#ifdef __linux__
188.569 + struct utsname ut;
188.570 +#endif
188.571 +
188.572 + if (safe_getenv("UNIX_IO_FORCE_BOUNCE"))
188.573 + flags |= IO_FLAG_FORCE_BOUNCE;
188.574 +
188.575 +#ifdef __linux__
188.576 + /*
188.577 + * We need to make sure any previous errors in the block
188.578 + * device are thrown away, sigh.
188.579 + */
188.580 + (void) fsync(fd);
188.581 +#endif
188.582 +
188.583 + retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
188.584 + if (retval)
188.585 + goto cleanup;
188.586 + memset(io, 0, sizeof(struct struct_io_channel));
188.587 + io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
188.588 + retval = ext2fs_get_mem(sizeof(struct unix_private_data), &data);
188.589 + if (retval)
188.590 + goto cleanup;
188.591 +
188.592 + io->manager = io_mgr;
188.593 + retval = ext2fs_get_mem(strlen(name)+1, &io->name);
188.594 + if (retval)
188.595 + goto cleanup;
188.596 +
188.597 + strcpy(io->name, name);
188.598 + io->private_data = data;
188.599 + io->block_size = 1024;
188.600 + io->read_error = 0;
188.601 + io->write_error = 0;
188.602 + io->refcount = 1;
188.603 +
188.604 + memset(data, 0, sizeof(struct unix_private_data));
188.605 + data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
188.606 + data->io_stats.num_fields = 2;
188.607 + data->flags = flags;
188.608 + data->dev = fd;
188.609 +
188.610 +#if defined(O_DIRECT)
188.611 + if (flags & IO_FLAG_DIRECT_IO)
188.612 + io->align = ext2fs_get_dio_alignment(data->dev);
188.613 +#elif defined(F_NOCACHE)
188.614 + if (flags & IO_FLAG_DIRECT_IO)
188.615 + io->align = 4096;
188.616 +#endif
188.617 +
188.618 + /*
188.619 + * If the device is really a block device, then set the
188.620 + * appropriate flag, otherwise we can set DISCARD_ZEROES flag
188.621 + * because we are going to use punch hole instead of discard
188.622 + * and if it succeed, subsequent read from sparse area returns
188.623 + * zero.
188.624 + */
188.625 + if (ext2fs_fstat(data->dev, &st) == 0) {
188.626 + if (ext2fsP_is_disk_device(st.st_mode))
188.627 + io->flags |= CHANNEL_FLAGS_BLOCK_DEVICE;
188.628 + else
188.629 + io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES;
188.630 + }
188.631 +
188.632 +#ifdef BLKDISCARDZEROES
188.633 + {
188.634 + int zeroes = 0;
188.635 + if (ioctl(data->dev, BLKDISCARDZEROES, &zeroes) == 0 &&
188.636 + zeroes)
188.637 + io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES;
188.638 + }
188.639 +#endif
188.640 +
188.641 +#if defined(__CYGWIN__)
188.642 + /*
188.643 + * Some operating systems require that the buffers be aligned,
188.644 + * regardless of O_DIRECT
188.645 + */
188.646 + if (!io->align)
188.647 + io->align = 512;
188.648 +#endif
188.649 +
188.650 +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
188.651 + if (io->flags & CHANNEL_FLAGS_BLOCK_DEVICE) {
188.652 + int dio_align = ext2fs_get_dio_alignment(fd);
188.653 +
188.654 + if (io->align < dio_align)
188.655 + io->align = dio_align;
188.656 + }
188.657 +#endif
188.658 +
188.659 + if ((retval = alloc_cache(io, data)))
188.660 + goto cleanup;
188.661 +
188.662 +#ifdef BLKROGET
188.663 + if (flags & IO_FLAG_RW) {
188.664 + int error;
188.665 + int readonly = 0;
188.666 +
188.667 + /* Is the block device actually writable? */
188.668 + error = ioctl(data->dev, BLKROGET, &readonly);
188.669 + if (!error && readonly) {
188.670 + retval = EPERM;
188.671 + goto cleanup;
188.672 + }
188.673 + }
188.674 +#endif
188.675 +
188.676 +#ifdef __linux__
188.677 +#undef RLIM_INFINITY
188.678 +#if (defined(__alpha__) || ((defined(__sparc__) || defined(__mips__)) && (SIZEOF_LONG == 4)))
188.679 +#define RLIM_INFINITY ((unsigned long)(~0UL>>1))
188.680 +#else
188.681 +#define RLIM_INFINITY (~0UL)
188.682 +#endif
188.683 + /*
188.684 + * Work around a bug in 2.4.10-2.4.18 kernels where writes to
188.685 + * block devices are wrongly getting hit by the filesize
188.686 + * limit. This workaround isn't perfect, since it won't work
188.687 + * if glibc wasn't built against 2.2 header files. (Sigh.)
188.688 + *
188.689 + */
188.690 + if ((flags & IO_FLAG_RW) &&
188.691 + (uname(&ut) == 0) &&
188.692 + ((ut.release[0] == '2') && (ut.release[1] == '.') &&
188.693 + (ut.release[2] == '4') && (ut.release[3] == '.') &&
188.694 + (ut.release[4] == '1') && (ut.release[5] >= '0') &&
188.695 + (ut.release[5] < '8')) &&
188.696 + (ext2fs_fstat(data->dev, &st) == 0) &&
188.697 + (ext2fsP_is_disk_device(st.st_mode))) {
188.698 + struct rlimit rlim;
188.699 +
188.700 + rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY;
188.701 + setrlimit(RLIMIT_FSIZE, &rlim);
188.702 + getrlimit(RLIMIT_FSIZE, &rlim);
188.703 + if (((unsigned long) rlim.rlim_cur) <
188.704 + ((unsigned long) rlim.rlim_max)) {
188.705 + rlim.rlim_cur = rlim.rlim_max;
188.706 + setrlimit(RLIMIT_FSIZE, &rlim);
188.707 + }
188.708 + }
188.709 +#endif
188.710 + *channel = io;
188.711 + return 0;
188.712 +
188.713 +cleanup:
188.714 + if (data) {
188.715 + if (data->dev >= 0)
188.716 + close(data->dev);
188.717 + free_cache(data);
188.718 + ext2fs_free_mem(&data);
188.719 + }
188.720 + if (io) {
188.721 + if (io->name) {
188.722 + ext2fs_free_mem(&io->name);
188.723 + }
188.724 + ext2fs_free_mem(&io);
188.725 + }
188.726 + return retval;
188.727 +}
188.728 +
188.729 +static errcode_t unixfd_open(const char *str_fd, int flags,
188.730 + io_channel *channel)
188.731 +{
188.732 + int fd;
188.733 + int fd_flags;
188.734 +
188.735 + fd = atoi(str_fd);
188.736 +#if defined(HAVE_FCNTL)
188.737 + fd_flags = fcntl(fd, F_GETFD);
188.738 + if (fd_flags == -1)
188.739 + return -EBADF;
188.740 +
188.741 + flags = 0;
188.742 + if (fd_flags & O_RDWR)
188.743 + flags |= IO_FLAG_RW;
188.744 + if (fd_flags & O_EXCL)
188.745 + flags |= IO_FLAG_EXCLUSIVE;
188.746 +#if defined(O_DIRECT)
188.747 + if (fd_flags & O_DIRECT)
188.748 + flags |= IO_FLAG_DIRECT_IO;
188.749 +#endif
188.750 +#endif /* HAVE_FCNTL */
188.751 +
188.752 + return unix_open_channel(str_fd, fd, flags, channel, unixfd_io_manager);
188.753 +}
188.754 +
188.755 +static errcode_t unix_open(const char *name, int flags,
188.756 + io_channel *channel)
188.757 +{
188.758 + int fd = -1;
188.759 + int open_flags;
188.760 +
188.761 + if (name == 0)
188.762 + return EXT2_ET_BAD_DEVICE_NAME;
188.763 +
188.764 + open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY;
188.765 + if (flags & IO_FLAG_EXCLUSIVE)
188.766 + open_flags |= O_EXCL;
188.767 +#if defined(O_DIRECT)
188.768 + if (flags & IO_FLAG_DIRECT_IO)
188.769 + open_flags |= O_DIRECT;
188.770 +#endif
188.771 + fd = ext2fs_open_file(name, open_flags, 0);
188.772 + if (fd < 0)
188.773 + return errno;
188.774 +#if defined(F_NOCACHE) && !defined(IO_DIRECT)
188.775 + if (flags & IO_FLAG_DIRECT_IO) {
188.776 + if (fcntl(fd, F_NOCACHE, 1) < 0)
188.777 + return errno;
188.778 + }
188.779 +#endif
188.780 + return unix_open_channel(name, fd, flags, channel, unix_io_manager);
188.781 +}
188.782 +
188.783 +static errcode_t unix_close(io_channel channel)
188.784 +{
188.785 + struct unix_private_data *data;
188.786 + errcode_t retval = 0;
188.787 +
188.788 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
188.789 + data = (struct unix_private_data *) channel->private_data;
188.790 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
188.791 +
188.792 + if (--channel->refcount > 0)
188.793 + return 0;
188.794 +
188.795 +#ifndef NO_IO_CACHE
188.796 + retval = flush_cached_blocks(channel, data, 0);
188.797 +#endif
188.798 +
188.799 + if (close(data->dev) < 0)
188.800 + retval = errno;
188.801 + free_cache(data);
188.802 +
188.803 + ext2fs_free_mem(&channel->private_data);
188.804 + if (channel->name)
188.805 + ext2fs_free_mem(&channel->name);
188.806 + ext2fs_free_mem(&channel);
188.807 + return retval;
188.808 +}
188.809 +
188.810 +static errcode_t unix_set_blksize(io_channel channel, int blksize)
188.811 +{
188.812 + struct unix_private_data *data;
188.813 + errcode_t retval;
188.814 +
188.815 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
188.816 + data = (struct unix_private_data *) channel->private_data;
188.817 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
188.818 +
188.819 + if (channel->block_size != blksize) {
188.820 +#ifndef NO_IO_CACHE
188.821 + if ((retval = flush_cached_blocks(channel, data, 0)))
188.822 + return retval;
188.823 +#endif
188.824 +
188.825 + channel->block_size = blksize;
188.826 + free_cache(data);
188.827 + if ((retval = alloc_cache(channel, data)))
188.828 + return retval;
188.829 + }
188.830 + return 0;
188.831 +}
188.832 +
188.833 +static errcode_t unix_read_blk64(io_channel channel, unsigned long long block,
188.834 + int count, void *buf)
188.835 +{
188.836 + struct unix_private_data *data;
188.837 + struct unix_cache *cache, *reuse[READ_DIRECT_SIZE];
188.838 + errcode_t retval;
188.839 + char *cp;
188.840 + int i, j;
188.841 +
188.842 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
188.843 + data = (struct unix_private_data *) channel->private_data;
188.844 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
188.845 +
188.846 +#ifdef NO_IO_CACHE
188.847 + return raw_read_blk(channel, data, block, count, buf);
188.848 +#else
188.849 + /*
188.850 + * If we're doing an odd-sized read or a very large read,
188.851 + * flush out the cache and then do a direct read.
188.852 + */
188.853 + if (count < 0 || count > WRITE_DIRECT_SIZE) {
188.854 + if ((retval = flush_cached_blocks(channel, data, 0)))
188.855 + return retval;
188.856 + return raw_read_blk(channel, data, block, count, buf);
188.857 + }
188.858 +
188.859 + cp = buf;
188.860 + while (count > 0) {
188.861 + /* If it's in the cache, use it! */
188.862 + if ((cache = find_cached_block(data, block, &reuse[0]))) {
188.863 +#ifdef DEBUG
188.864 + printf("Using cached block %lu\n", block);
188.865 +#endif
188.866 + memcpy(cp, cache->buf, channel->block_size);
188.867 + count--;
188.868 + block++;
188.869 + cp += channel->block_size;
188.870 + continue;
188.871 + }
188.872 + if (count == 1) {
188.873 + /*
188.874 + * Special case where we read directly into the
188.875 + * cache buffer; important in the O_DIRECT case
188.876 + */
188.877 + cache = reuse[0];
188.878 + reuse_cache(channel, data, cache, block);
188.879 + if ((retval = raw_read_blk(channel, data, block, 1,
188.880 + cache->buf))) {
188.881 + cache->in_use = 0;
188.882 + return retval;
188.883 + }
188.884 + memcpy(cp, cache->buf, channel->block_size);
188.885 + return 0;
188.886 + }
188.887 +
188.888 + /*
188.889 + * Find the number of uncached blocks so we can do a
188.890 + * single read request
188.891 + */
188.892 + for (i=1; i < count; i++)
188.893 + if (find_cached_block(data, block+i, &reuse[i]))
188.894 + break;
188.895 +#ifdef DEBUG
188.896 + printf("Reading %d blocks starting at %lu\n", i, block);
188.897 +#endif
188.898 + if ((retval = raw_read_blk(channel, data, block, i, cp)))
188.899 + return retval;
188.900 +
188.901 + /* Save the results in the cache */
188.902 + for (j=0; j < i; j++) {
188.903 + count--;
188.904 + cache = reuse[j];
188.905 + reuse_cache(channel, data, cache, block++);
188.906 + memcpy(cache->buf, cp, channel->block_size);
188.907 + cp += channel->block_size;
188.908 + }
188.909 + }
188.910 + return 0;
188.911 +#endif /* NO_IO_CACHE */
188.912 +}
188.913 +
188.914 +static errcode_t unix_read_blk(io_channel channel, unsigned long block,
188.915 + int count, void *buf)
188.916 +{
188.917 + return unix_read_blk64(channel, block, count, buf);
188.918 +}
188.919 +
188.920 +static errcode_t unix_write_blk64(io_channel channel, unsigned long long block,
188.921 + int count, const void *buf)
188.922 +{
188.923 + struct unix_private_data *data;
188.924 + struct unix_cache *cache, *reuse;
188.925 + errcode_t retval = 0;
188.926 + const char *cp;
188.927 + int writethrough;
188.928 +
188.929 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
188.930 + data = (struct unix_private_data *) channel->private_data;
188.931 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
188.932 +
188.933 +#ifdef NO_IO_CACHE
188.934 + return raw_write_blk(channel, data, block, count, buf);
188.935 +#else
188.936 + /*
188.937 + * If we're doing an odd-sized write or a very large write,
188.938 + * flush out the cache completely and then do a direct write.
188.939 + */
188.940 + if (count < 0 || count > WRITE_DIRECT_SIZE) {
188.941 + if ((retval = flush_cached_blocks(channel, data, 1)))
188.942 + return retval;
188.943 + return raw_write_blk(channel, data, block, count, buf);
188.944 + }
188.945 +
188.946 + /*
188.947 + * For a moderate-sized multi-block write, first force a write
188.948 + * if we're in write-through cache mode, and then fill the
188.949 + * cache with the blocks.
188.950 + */
188.951 + writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH;
188.952 + if (writethrough)
188.953 + retval = raw_write_blk(channel, data, block, count, buf);
188.954 +
188.955 + cp = buf;
188.956 + while (count > 0) {
188.957 + cache = find_cached_block(data, block, &reuse);
188.958 + if (!cache) {
188.959 + cache = reuse;
188.960 + reuse_cache(channel, data, cache, block);
188.961 + }
188.962 + if (cache->buf != cp)
188.963 + memcpy(cache->buf, cp, channel->block_size);
188.964 + cache->dirty = !writethrough;
188.965 + count--;
188.966 + block++;
188.967 + cp += channel->block_size;
188.968 + }
188.969 + return retval;
188.970 +#endif /* NO_IO_CACHE */
188.971 +}
188.972 +
188.973 +static errcode_t unix_cache_readahead(io_channel channel,
188.974 + unsigned long long block,
188.975 + unsigned long long count)
188.976 +{
188.977 +#ifdef POSIX_FADV_WILLNEED
188.978 + struct unix_private_data *data;
188.979 +
188.980 + data = (struct unix_private_data *)channel->private_data;
188.981 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
188.982 + return posix_fadvise(data->dev,
188.983 + (ext2_loff_t)block * channel->block_size + data->offset,
188.984 + (ext2_loff_t)count * channel->block_size,
188.985 + POSIX_FADV_WILLNEED);
188.986 +#else
188.987 + return EXT2_ET_OP_NOT_SUPPORTED;
188.988 +#endif
188.989 +}
188.990 +
188.991 +static errcode_t unix_write_blk(io_channel channel, unsigned long block,
188.992 + int count, const void *buf)
188.993 +{
188.994 + return unix_write_blk64(channel, block, count, buf);
188.995 +}
188.996 +
188.997 +static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
188.998 + int size, const void *buf)
188.999 +{
188.1000 + struct unix_private_data *data;
188.1001 + errcode_t retval = 0;
188.1002 + ssize_t actual;
188.1003 +
188.1004 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
188.1005 + data = (struct unix_private_data *) channel->private_data;
188.1006 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
188.1007 +
188.1008 + if (channel->align != 0) {
188.1009 +#ifdef ALIGN_DEBUG
188.1010 + printf("unix_write_byte: O_DIRECT fallback\n");
188.1011 +#endif
188.1012 + return EXT2_ET_UNIMPLEMENTED;
188.1013 + }
188.1014 +
188.1015 +#ifndef NO_IO_CACHE
188.1016 + /*
188.1017 + * Flush out the cache completely
188.1018 + */
188.1019 + if ((retval = flush_cached_blocks(channel, data, 1)))
188.1020 + return retval;
188.1021 +#endif
188.1022 +
188.1023 + if (lseek(data->dev, offset + data->offset, SEEK_SET) < 0)
188.1024 + return errno;
188.1025 +
188.1026 + actual = write(data->dev, buf, size);
188.1027 + if (actual < 0)
188.1028 + return errno;
188.1029 + if (actual != size)
188.1030 + return EXT2_ET_SHORT_WRITE;
188.1031 +
188.1032 + return 0;
188.1033 +}
188.1034 +
188.1035 +/*
188.1036 + * Flush data buffers to disk.
188.1037 + */
188.1038 +static errcode_t unix_flush(io_channel channel)
188.1039 +{
188.1040 + struct unix_private_data *data;
188.1041 + errcode_t retval = 0;
188.1042 +
188.1043 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
188.1044 + data = (struct unix_private_data *) channel->private_data;
188.1045 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
188.1046 +
188.1047 +#ifndef NO_IO_CACHE
188.1048 + retval = flush_cached_blocks(channel, data, 0);
188.1049 +#endif
188.1050 +#ifdef HAVE_FSYNC
188.1051 + if (!retval && fsync(data->dev) != 0)
188.1052 + return errno;
188.1053 +#endif
188.1054 + return retval;
188.1055 +}
188.1056 +
188.1057 +static errcode_t unix_set_option(io_channel channel, const char *option,
188.1058 + const char *arg)
188.1059 +{
188.1060 + struct unix_private_data *data;
188.1061 + unsigned long long tmp;
188.1062 + char *end;
188.1063 +
188.1064 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
188.1065 + data = (struct unix_private_data *) channel->private_data;
188.1066 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
188.1067 +
188.1068 + if (!strcmp(option, "offset")) {
188.1069 + if (!arg)
188.1070 + return EXT2_ET_INVALID_ARGUMENT;
188.1071 +
188.1072 + tmp = strtoull(arg, &end, 0);
188.1073 + if (*end)
188.1074 + return EXT2_ET_INVALID_ARGUMENT;
188.1075 + data->offset = tmp;
188.1076 + if (data->offset < 0)
188.1077 + return EXT2_ET_INVALID_ARGUMENT;
188.1078 + return 0;
188.1079 + }
188.1080 + return EXT2_ET_INVALID_ARGUMENT;
188.1081 +}
188.1082 +
188.1083 +#if defined(__linux__) && !defined(BLKDISCARD)
188.1084 +#define BLKDISCARD _IO(0x12,119)
188.1085 +#endif
188.1086 +
188.1087 +static errcode_t unix_discard(io_channel channel, unsigned long long block,
188.1088 + unsigned long long count)
188.1089 +{
188.1090 + struct unix_private_data *data;
188.1091 + int ret;
188.1092 +
188.1093 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
188.1094 + data = (struct unix_private_data *) channel->private_data;
188.1095 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
188.1096 +
188.1097 + if (channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE) {
188.1098 +#ifdef BLKDISCARD
188.1099 + __u64 range[2];
188.1100 +
188.1101 + range[0] = (__u64)(block) * channel->block_size + data->offset;
188.1102 + range[1] = (__u64)(count) * channel->block_size;
188.1103 +
188.1104 + ret = ioctl(data->dev, BLKDISCARD, &range);
188.1105 +#else
188.1106 + goto unimplemented;
188.1107 +#endif
188.1108 + } else {
188.1109 +#if defined(HAVE_FALLOCATE) && defined(FALLOC_FL_PUNCH_HOLE)
188.1110 + /*
188.1111 + * If we are not on block device, try to use punch hole
188.1112 + * to reclaim free space.
188.1113 + */
188.1114 + ret = fallocate(data->dev,
188.1115 + FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
188.1116 + (off_t)(block) * channel->block_size + data->offset,
188.1117 + (off_t)(count) * channel->block_size);
188.1118 +#else
188.1119 + goto unimplemented;
188.1120 +#endif
188.1121 + }
188.1122 + if (ret < 0) {
188.1123 + if (errno == EOPNOTSUPP)
188.1124 + goto unimplemented;
188.1125 + return errno;
188.1126 + }
188.1127 + return 0;
188.1128 +unimplemented:
188.1129 + return EXT2_ET_UNIMPLEMENTED;
188.1130 +}
188.1131 +
188.1132 +/* parameters might not be used if OS doesn't support zeroout */
188.1133 +#if __GNUC_PREREQ (4, 6)
188.1134 +#pragma GCC diagnostic push
188.1135 +#pragma GCC diagnostic ignored "-Wunused-parameter"
188.1136 +#endif
188.1137 +static errcode_t unix_zeroout(io_channel channel, unsigned long long block,
188.1138 + unsigned long long count)
188.1139 +{
188.1140 + struct unix_private_data *data;
188.1141 + int ret;
188.1142 +
188.1143 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
188.1144 + data = (struct unix_private_data *) channel->private_data;
188.1145 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
188.1146 +
188.1147 + if (safe_getenv("UNIX_IO_NOZEROOUT"))
188.1148 + goto unimplemented;
188.1149 +
188.1150 + if (channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE) {
188.1151 + /* Not implemented until the BLKZEROOUT mess is fixed */
188.1152 + goto unimplemented;
188.1153 + } else {
188.1154 + /* Regular file, try to use truncate/punch/zero. */
188.1155 + struct stat statbuf;
188.1156 +
188.1157 + if (count == 0)
188.1158 + return 0;
188.1159 + /*
188.1160 + * If we're trying to zero a range past the end of the file,
188.1161 + * extend the file size, then truncate everything.
188.1162 + */
188.1163 + ret = fstat(data->dev, &statbuf);
188.1164 + if (ret)
188.1165 + goto err;
188.1166 + if ((unsigned long long) statbuf.st_size <
188.1167 + (block + count) * channel->block_size + data->offset) {
188.1168 + ret = ftruncate(data->dev,
188.1169 + (block + count) * channel->block_size + data->offset);
188.1170 + if (ret)
188.1171 + goto err;
188.1172 + }
188.1173 +#if defined(HAVE_FALLOCATE) && (defined(FALLOC_FL_ZERO_RANGE) || \
188.1174 + (defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE)))
188.1175 +#if defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE)
188.1176 + ret = fallocate(data->dev,
188.1177 + FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
188.1178 + (off_t)(block) * channel->block_size + data->offset,
188.1179 + (off_t)(count) * channel->block_size);
188.1180 + if (ret == 0)
188.1181 + goto err;
188.1182 +#endif
188.1183 +#ifdef FALLOC_FL_ZERO_RANGE
188.1184 + ret = fallocate(data->dev,
188.1185 + FALLOC_FL_ZERO_RANGE,
188.1186 + (off_t)(block) * channel->block_size + data->offset,
188.1187 + (off_t)(count) * channel->block_size);
188.1188 +#endif
188.1189 +#else
188.1190 + goto unimplemented;
188.1191 +#endif /* HAVE_FALLOCATE && (ZERO_RANGE || (PUNCH_HOLE && KEEP_SIZE)) */
188.1192 + }
188.1193 +err:
188.1194 + if (ret < 0) {
188.1195 + if (errno == EOPNOTSUPP)
188.1196 + goto unimplemented;
188.1197 + return errno;
188.1198 + }
188.1199 + return 0;
188.1200 +unimplemented:
188.1201 + return EXT2_ET_UNIMPLEMENTED;
188.1202 +}
188.1203 +#if __GNUC_PREREQ (4, 6)
188.1204 +#pragma GCC diagnostic pop
188.1205 +#endif
188.1206 +
188.1207 +static struct struct_io_manager struct_unix_manager = {
188.1208 + .magic = EXT2_ET_MAGIC_IO_MANAGER,
188.1209 + .name = "Unix I/O Manager",
188.1210 + .open = unix_open,
188.1211 + .close = unix_close,
188.1212 + .set_blksize = unix_set_blksize,
188.1213 + .read_blk = unix_read_blk,
188.1214 + .write_blk = unix_write_blk,
188.1215 + .flush = unix_flush,
188.1216 + .write_byte = unix_write_byte,
188.1217 + .set_option = unix_set_option,
188.1218 + .get_stats = unix_get_stats,
188.1219 + .read_blk64 = unix_read_blk64,
188.1220 + .write_blk64 = unix_write_blk64,
188.1221 + .discard = unix_discard,
188.1222 + .cache_readahead = unix_cache_readahead,
188.1223 + .zeroout = unix_zeroout,
188.1224 +};
188.1225 +
188.1226 +io_manager unix_io_manager = &struct_unix_manager;
188.1227 +
188.1228 +static struct struct_io_manager struct_unixfd_manager = {
188.1229 + .magic = EXT2_ET_MAGIC_IO_MANAGER,
188.1230 + .name = "Unix fd I/O Manager",
188.1231 + .open = unixfd_open,
188.1232 + .close = unix_close,
188.1233 + .set_blksize = unix_set_blksize,
188.1234 + .read_blk = unix_read_blk,
188.1235 + .write_blk = unix_write_blk,
188.1236 + .flush = unix_flush,
188.1237 + .write_byte = unix_write_byte,
188.1238 + .set_option = unix_set_option,
188.1239 + .get_stats = unix_get_stats,
188.1240 + .read_blk64 = unix_read_blk64,
188.1241 + .write_blk64 = unix_write_blk64,
188.1242 + .discard = unix_discard,
188.1243 + .cache_readahead = unix_cache_readahead,
188.1244 + .zeroout = unix_zeroout,
188.1245 +};
188.1246 +
188.1247 +io_manager unixfd_io_manager = &struct_unixfd_manager;
189.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
189.2 +++ b/libext2fs/lib/libext2fs/unlink.c Wed Aug 25 01:28:08 2021 +0200
189.3 @@ -0,0 +1,100 @@
189.4 +/*
189.5 + * unlink.c --- delete links in a ext2fs directory
189.6 + *
189.7 + * Copyright (C) 1993, 1994, 1997 Theodore Ts'o.
189.8 + *
189.9 + * %Begin-Header%
189.10 + * This file may be redistributed under the terms of the GNU Library
189.11 + * General Public License, version 2.
189.12 + * %End-Header%
189.13 + */
189.14 +
189.15 +#include "config.h"
189.16 +#include <stdio.h>
189.17 +#include <string.h>
189.18 +#if HAVE_UNISTD_H
189.19 +#include <unistd.h>
189.20 +#endif
189.21 +
189.22 +#include "ext2_fs.h"
189.23 +#include "ext2fs.h"
189.24 +
189.25 +struct link_struct {
189.26 + const char *name;
189.27 + int namelen;
189.28 + ext2_ino_t inode;
189.29 + int flags;
189.30 + struct ext2_dir_entry *prev;
189.31 + int done;
189.32 +};
189.33 +
189.34 +#ifdef __TURBOC__
189.35 + #pragma argsused
189.36 +#endif
189.37 +static int unlink_proc(struct ext2_dir_entry *dirent,
189.38 + int offset,
189.39 + int blocksize EXT2FS_ATTR((unused)),
189.40 + char *buf EXT2FS_ATTR((unused)),
189.41 + void *priv_data)
189.42 +{
189.43 + struct link_struct *ls = (struct link_struct *) priv_data;
189.44 + struct ext2_dir_entry *prev;
189.45 +
189.46 + prev = ls->prev;
189.47 + ls->prev = dirent;
189.48 +
189.49 + if (ls->name) {
189.50 + if (ext2fs_dirent_name_len(dirent) != ls->namelen)
189.51 + return 0;
189.52 + if (strncmp(ls->name, dirent->name, ext2fs_dirent_name_len(dirent)))
189.53 + return 0;
189.54 + }
189.55 + if (ls->inode) {
189.56 + if (dirent->inode != ls->inode)
189.57 + return 0;
189.58 + } else {
189.59 + if (!dirent->inode)
189.60 + return 0;
189.61 + }
189.62 +
189.63 + if (offset)
189.64 + prev->rec_len += dirent->rec_len;
189.65 + else
189.66 + dirent->inode = 0;
189.67 + ls->done++;
189.68 + return DIRENT_ABORT|DIRENT_CHANGED;
189.69 +}
189.70 +
189.71 +#ifdef __TURBOC__
189.72 + #pragma argsused
189.73 +#endif
189.74 +errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir,
189.75 + const char *name, ext2_ino_t ino,
189.76 + int flags EXT2FS_ATTR((unused)))
189.77 +{
189.78 + errcode_t retval;
189.79 + struct link_struct ls;
189.80 +
189.81 + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
189.82 +
189.83 + if (!name && !ino)
189.84 + return EXT2_ET_INVALID_ARGUMENT;
189.85 +
189.86 + if (!(fs->flags & EXT2_FLAG_RW))
189.87 + return EXT2_ET_RO_FILSYS;
189.88 +
189.89 + ls.name = name;
189.90 + ls.namelen = name ? strlen(name) : 0;
189.91 + ls.inode = ino;
189.92 + ls.flags = 0;
189.93 + ls.done = 0;
189.94 + ls.prev = 0;
189.95 +
189.96 + retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
189.97 + 0, unlink_proc, &ls);
189.98 + if (retval)
189.99 + return retval;
189.100 +
189.101 + return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE;
189.102 +}
189.103 +
190.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
190.2 +++ b/libext2fs/lib/libext2fs/valid_blk.c Wed Aug 25 01:28:08 2021 +0200
190.3 @@ -0,0 +1,68 @@
190.4 +/*
190.5 + * valid_blk.c --- does the inode have valid blocks?
190.6 + *
190.7 + * Copyright 1997 by Theodore Ts'o
190.8 + *
190.9 + * %Begin-Header%
190.10 + * This file may be redistributed under the terms of the GNU Library
190.11 + * General Public License, version 2.
190.12 + * %End-Header%
190.13 + */
190.14 +
190.15 +#include "config.h"
190.16 +#include <stdio.h>
190.17 +#if HAVE_UNISTD_H
190.18 +#include <unistd.h>
190.19 +#endif
190.20 +#include <string.h>
190.21 +#include <time.h>
190.22 +
190.23 +#include "ext2_fs.h"
190.24 +#include "ext2fs.h"
190.25 +
190.26 +/*
190.27 + * This function returns 1 if the inode's block entries actually
190.28 + * contain block entries.
190.29 + */
190.30 +int ext2fs_inode_has_valid_blocks2(ext2_filsys fs, struct ext2_inode *inode)
190.31 +{
190.32 + /*
190.33 + * Only directories, regular files, and some symbolic links
190.34 + * have valid block entries.
190.35 + */
190.36 + if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) &&
190.37 + !LINUX_S_ISLNK(inode->i_mode))
190.38 + return 0;
190.39 +
190.40 + /*
190.41 + * If the symbolic link is a "fast symlink", then the symlink
190.42 + * target is stored in the block entries.
190.43 + */
190.44 + if (LINUX_S_ISLNK (inode->i_mode)) {
190.45 + if (ext2fs_file_acl_block(fs, inode) == 0) {
190.46 + /* With no EA block, we can rely on i_blocks */
190.47 + if (inode->i_blocks == 0)
190.48 + return 0;
190.49 + } else {
190.50 + /* With an EA block, life gets more tricky */
190.51 + if (inode->i_size >= EXT2_N_BLOCKS*4)
190.52 + return 1; /* definitely using i_block[] */
190.53 + if (inode->i_size > 4 && inode->i_block[1] == 0)
190.54 + return 1; /* definitely using i_block[] */
190.55 + return 0; /* Probably a fast symlink */
190.56 + }
190.57 + }
190.58 +
190.59 + /*
190.60 + * If this inode has inline data, it shouldn't have valid block
190.61 + * entries.
190.62 + */
190.63 + if (inode->i_flags & EXT4_INLINE_DATA_FL)
190.64 + return 0;
190.65 + return 1;
190.66 +}
190.67 +
190.68 +int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode)
190.69 +{
190.70 + return ext2fs_inode_has_valid_blocks2(NULL, inode);
190.71 +}
192.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
192.2 +++ b/libext2fs/lib/libext2fs/write_bb_file.c Wed Aug 25 01:28:08 2021 +0200
192.3 @@ -0,0 +1,35 @@
192.4 +/*
192.5 + * write_bb_file.c --- write a list of bad blocks to a FILE *
192.6 + *
192.7 + * Copyright (C) 1994, 1995 Theodore Ts'o.
192.8 + *
192.9 + * %Begin-Header%
192.10 + * This file may be redistributed under the terms of the GNU Library
192.11 + * General Public License, version 2.
192.12 + * %End-Header%
192.13 + */
192.14 +
192.15 +#include "config.h"
192.16 +#include <stdio.h>
192.17 +
192.18 +#include "ext2_fs.h"
192.19 +#include "ext2fs.h"
192.20 +
192.21 +errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
192.22 + unsigned int flags EXT2FS_ATTR((unused)),
192.23 + FILE *f)
192.24 +{
192.25 + badblocks_iterate bb_iter;
192.26 + blk_t blk;
192.27 + errcode_t retval;
192.28 +
192.29 + retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
192.30 + if (retval)
192.31 + return retval;
192.32 +
192.33 + while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) {
192.34 + fprintf(f, "%u\n", blk);
192.35 + }
192.36 + ext2fs_badblocks_list_iterate_end(bb_iter);
192.37 + return 0;
192.38 +}
193.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
193.2 +++ b/libext2fs/lib/libsupport/Makefile Wed Aug 25 01:28:08 2021 +0200
193.3 @@ -0,0 +1,24 @@
193.4 +PKGDIR ?= ../..
193.5 +L4DIR ?= $(PKGDIR)/../../..
193.6 +
193.7 +TARGET = libsupport.a libsupport.so
193.8 +PC_FILENAME = libsupport
193.9 +SRC_C = \
193.10 + argv_parse.c cstring.c mkquota.c parse_qtype.c plausible.c profile.c \
193.11 + profile_helpers.c prof_err.c quotaio.c quotaio_tree.c quotaio_v2.c \
193.12 + dict.c
193.13 +
193.14 +REQUIRES_LIBS = libblkid
193.15 +
193.16 +PRIVATE_INCDIR += \
193.17 + $(PKGDIR)/lib $(PKGDIR)/lib/libsupport \
193.18 + $(PKGDIR)/include/libsupport \
193.19 + $(PKGDIR)/include/libsupport/support \
193.20 + $(PKGDIR)/include/libext2fs \
193.21 + $(PKGDIR)/include/libet \
193.22 + $(PKGDIR)/include/libe2p \
193.23 + $(PKGDIR)/include/libblkid
193.24 +
193.25 +CONTRIB_INCDIR = libsupport
193.26 +
193.27 +include $(L4DIR)/mk/lib.mk
194.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
194.2 +++ b/libext2fs/lib/libsupport/argv_parse.c Wed Aug 25 01:28:08 2021 +0200
194.3 @@ -0,0 +1,166 @@
194.4 +/*
194.5 + * argv_parse.c --- utility function for parsing a string into a
194.6 + * argc, argv array.
194.7 + *
194.8 + * This file defines a function argv_parse() which parsing a
194.9 + * passed-in string, handling double quotes and backslashes, and
194.10 + * creates an allocated argv vector which can be freed using the
194.11 + * argv_free() function.
194.12 + *
194.13 + * See argv_parse.h for the formal definition of the functions.
194.14 + *
194.15 + * Copyright 1999 by Theodore Ts'o.
194.16 + *
194.17 + * Permission to use, copy, modify, and distribute this software for
194.18 + * any purpose with or without fee is hereby granted, provided that
194.19 + * the above copyright notice and this permission notice appear in all
194.20 + * copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE
194.21 + * AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
194.22 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
194.23 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
194.24 + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
194.25 + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
194.26 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
194.27 + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (Isn't
194.28 + * it sick that the U.S. culture of lawsuit-happy lawyers requires
194.29 + * this kind of disclaimer?)
194.30 + *
194.31 + * Version 1.1, modified 2/27/1999
194.32 + */
194.33 +
194.34 +#include "config.h"
194.35 +#ifdef HAVE_STDLIB_H
194.36 +#include <stdlib.h>
194.37 +#endif
194.38 +#include <ctype.h>
194.39 +#include <string.h>
194.40 +#include "argv_parse.h"
194.41 +
194.42 +#define STATE_WHITESPACE 1
194.43 +#define STATE_TOKEN 2
194.44 +#define STATE_QUOTED 3
194.45 +
194.46 +/*
194.47 + * Returns 0 on success, -1 on failure.
194.48 + */
194.49 +int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv)
194.50 +{
194.51 + int argc = 0, max_argc = 0;
194.52 + char **argv, **new_argv, *buf, ch;
194.53 + char *cp = 0, *outcp = 0;
194.54 + int state = STATE_WHITESPACE;
194.55 +
194.56 + buf = malloc(strlen(in_buf)+1);
194.57 + if (!buf)
194.58 + return -1;
194.59 +
194.60 + max_argc = 0; argc = 0; argv = 0;
194.61 + outcp = buf;
194.62 + for (cp = in_buf; (ch = *cp); cp++) {
194.63 + if (state == STATE_WHITESPACE) {
194.64 + if (isspace((int) ch))
194.65 + continue;
194.66 + /* Not whitespace, so start a new token */
194.67 + state = STATE_TOKEN;
194.68 + if (argc >= max_argc) {
194.69 + max_argc += 3;
194.70 + new_argv = realloc(argv,
194.71 + (max_argc+1)*sizeof(char *));
194.72 + if (!new_argv) {
194.73 + free(argv);
194.74 + free(buf);
194.75 + return -1;
194.76 + }
194.77 + argv = new_argv;
194.78 + }
194.79 + argv[argc++] = outcp;
194.80 + }
194.81 + if (state == STATE_QUOTED) {
194.82 + if (ch == '"')
194.83 + state = STATE_TOKEN;
194.84 + else
194.85 + *outcp++ = ch;
194.86 + continue;
194.87 + }
194.88 + /* Must be processing characters in a word */
194.89 + if (isspace((int) ch)) {
194.90 + /*
194.91 + * Terminate the current word and start
194.92 + * looking for the beginning of the next word.
194.93 + */
194.94 + *outcp++ = 0;
194.95 + state = STATE_WHITESPACE;
194.96 + continue;
194.97 + }
194.98 + if (ch == '"') {
194.99 + state = STATE_QUOTED;
194.100 + continue;
194.101 + }
194.102 + if (ch == '\\') {
194.103 + ch = *++cp;
194.104 + switch (ch) {
194.105 + case '\0':
194.106 + ch = '\\'; cp--; break;
194.107 + case 'n':
194.108 + ch = '\n'; break;
194.109 + case 't':
194.110 + ch = '\t'; break;
194.111 + case 'b':
194.112 + ch = '\b'; break;
194.113 + }
194.114 + }
194.115 + *outcp++ = ch;
194.116 + }
194.117 + if (state != STATE_WHITESPACE)
194.118 + *outcp++ = '\0';
194.119 + if (argv == 0) {
194.120 + argv = malloc(sizeof(char *));
194.121 + free(buf);
194.122 + }
194.123 + argv[argc] = 0;
194.124 + if (ret_argc)
194.125 + *ret_argc = argc;
194.126 + if (ret_argv)
194.127 + *ret_argv = argv;
194.128 + return 0;
194.129 +}
194.130 +
194.131 +void argv_free(char **argv)
194.132 +{
194.133 + free(*argv);
194.134 + free(argv);
194.135 +}
194.136 +
194.137 +#ifdef DEBUG
194.138 +/*
194.139 + * For debugging
194.140 + */
194.141 +
194.142 +#include <stdio.h>
194.143 +
194.144 +int main(int argc, char **argv)
194.145 +{
194.146 + int ac, ret;
194.147 + char **av, **cpp;
194.148 + char buf[256];
194.149 +
194.150 + while (!feof(stdin)) {
194.151 + if (fgets(buf, sizeof(buf), stdin) == NULL)
194.152 + break;
194.153 + ret = argv_parse(buf, &ac, &av);
194.154 + if (ret != 0) {
194.155 + printf("Argv_parse returned %d!\n", ret);
194.156 + continue;
194.157 + }
194.158 + printf("Argv_parse returned %d arguments...\n", ac);
194.159 + for (cpp = av; *cpp; cpp++) {
194.160 + if (cpp != av)
194.161 + printf(", ");
194.162 + printf("'%s'", *cpp);
194.163 + }
194.164 + printf("\n");
194.165 + argv_free(av);
194.166 + }
194.167 + exit(0);
194.168 +}
194.169 +#endif /* DEBUG */
195.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
195.2 +++ b/libext2fs/lib/libsupport/argv_parse.h Wed Aug 25 01:28:08 2021 +0200
195.3 @@ -0,0 +1,43 @@
195.4 +/*
195.5 + * argv_parse.h --- header file for the argv parser.
195.6 + *
195.7 + * This file defines the interface for the functions argv_parse() and
195.8 + * argv_free().
195.9 + *
195.10 + ***********************************************************************
195.11 + * int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv)
195.12 + *
195.13 + * This function takes as its first argument a string which it will
195.14 + * parse into an argv argument vector, with each white-space separated
195.15 + * word placed into its own slot in the argv. This function handles
195.16 + * double quotes and backslashes so that the parsed words can contain
195.17 + * special characters. The count of the number words found in the
195.18 + * parsed string, as well as the argument vector, are returned into
195.19 + * ret_argc and ret_argv, respectively.
195.20 + ***********************************************************************
195.21 + * extern void argv_free(char **argv);
195.22 + *
195.23 + * This function frees the argument vector created by argv_parse().
195.24 + ***********************************************************************
195.25 + *
195.26 + * Copyright 1999 by Theodore Ts'o.
195.27 + *
195.28 + * Permission to use, copy, modify, and distribute this software for
195.29 + * any purpose with or without fee is hereby granted, provided that
195.30 + * the above copyright notice and this permission notice appear in all
195.31 + * copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE
195.32 + * AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
195.33 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
195.34 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
195.35 + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
195.36 + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
195.37 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
195.38 + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (Isn't
195.39 + * it sick that the U.S. culture of lawsuit-happy lawyers requires
195.40 + * this kind of disclaimer?)
195.41 + *
195.42 + * Version 1.1, modified 2/27/1999
195.43 + */
195.44 +
195.45 +extern int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv);
195.46 +extern void argv_free(char **argv);
196.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
196.2 +++ b/libext2fs/lib/libsupport/common.h Wed Aug 25 01:28:08 2021 +0200
196.3 @@ -0,0 +1,36 @@
196.4 +/*
196.5 + *
196.6 + * Various things common for all utilities
196.7 + *
196.8 + */
196.9 +
196.10 +#ifndef __QUOTA_COMMON_H__
196.11 +#define __QUOTA_COMMON_H__
196.12 +
196.13 +#if EXT2_FLAT_INCLUDES
196.14 +#include "e2_types.h"
196.15 +#else
196.16 +#include <ext2fs/ext2_types.h>
196.17 +#endif /* EXT2_FLAT_INCLUDES */
196.18 +
196.19 +/* #define DEBUG_QUOTA 1 */
196.20 +
196.21 +#ifndef __attribute__
196.22 +# if !defined __GNUC__ || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
196.23 +# define __attribute__(x)
196.24 +# endif
196.25 +#endif
196.26 +
196.27 +#define log_err(format, arg ...) \
196.28 + fprintf(stderr, "[ERROR] %s:%d:%s:: " format "\n", \
196.29 + __FILE__, __LINE__, __func__, ## arg)
196.30 +
196.31 +#ifdef DEBUG_QUOTA
196.32 +# define log_debug(format, arg ...) \
196.33 + fprintf(stderr, "[DEBUG] %s:%d:%s:: " format "\n", \
196.34 + __FILE__, __LINE__, __func__, ## arg)
196.35 +#else
196.36 +# define log_debug(...)
196.37 +#endif
196.38 +
196.39 +#endif /* __QUOTA_COMMON_H__ */
197.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
197.2 +++ b/libext2fs/lib/libsupport/cstring.c Wed Aug 25 01:28:08 2021 +0200
197.3 @@ -0,0 +1,162 @@
197.4 +/*
197.5 + * cstring.c -- parse and print strings using the C escape sequences
197.6 + */
197.7 +
197.8 +#include "config.h"
197.9 +#include <stdio.h>
197.10 +#include <stdlib.h>
197.11 +#include <ctype.h>
197.12 +#ifdef HAVE_GETOPT_H
197.13 +#include <getopt.h>
197.14 +#endif
197.15 +#include <string.h>
197.16 +
197.17 +#include "cstring.h"
197.18 +
197.19 +int parse_c_string(char *str)
197.20 +{
197.21 + char *to, *from, ch;
197.22 + int v;
197.23 +
197.24 + to = from = str;
197.25 +
197.26 + for (to = from = (char *) str;
197.27 + *from && *from != '"'; to++, from++) {
197.28 + if (*from == '\\') {
197.29 + ch = *(++from);
197.30 + switch (ch) {
197.31 + case 'a':
197.32 + *to = '\a';
197.33 + break;
197.34 + case 'b':
197.35 + *to = '\b';
197.36 + break;
197.37 + case 'f':
197.38 + *to = '\f';
197.39 + break;
197.40 + case 'n':
197.41 + *to = '\n';
197.42 + break;
197.43 + case 't':
197.44 + *to = '\t';
197.45 + break;
197.46 + case 'v':
197.47 + *to = '\v';
197.48 + break;
197.49 + case 'x':
197.50 + ch = *(from + 1);
197.51 + if (ch >= 'a' && ch <= 'f')
197.52 + ch = ch - 'a' + 'A';
197.53 + if (ch >= '0' && ch <= '9')
197.54 + v = ch - '0';
197.55 + else if (ch >= 'A' && ch <= 'F')
197.56 + v = ch + 10 - 'A';
197.57 + else {
197.58 + *to = 'x';
197.59 + break;
197.60 + }
197.61 + from++;
197.62 + ch = *(from + 1);
197.63 + if (ch >= 'a' && ch <= 'f')
197.64 + ch = ch - 'a' + 'A';
197.65 + if (ch >= '0' && ch <= '9')
197.66 + v = (v * 16) + (ch - '0');
197.67 + else if (ch >= 'A' && ch <= 'F')
197.68 + v = (v * 16) + (ch + 10 - 'A');
197.69 + else {
197.70 + *to = 'x';
197.71 + from--;
197.72 + break;
197.73 + }
197.74 + from++;
197.75 + *to = v;
197.76 + break;
197.77 + default:
197.78 + if (ch >= '0' && ch <= '9') {
197.79 + v = ch - '0';
197.80 + ch = *(from + 1);
197.81 + if (ch >= '0' && ch <= '9') {
197.82 + from++;
197.83 + v = (8 * v) + (ch - '0');
197.84 + ch = *(from + 1);
197.85 + if (ch >= '0' && ch <= '9') {
197.86 + from++;
197.87 + v = (8 * v) + (ch - '0');
197.88 + }
197.89 + }
197.90 + ch = v;
197.91 + }
197.92 + *to = ch;
197.93 + }
197.94 + continue;
197.95 + }
197.96 + *to = *from;
197.97 + }
197.98 + *to = '\0';
197.99 + return to - (char *) str;
197.100 +}
197.101 +
197.102 +void print_c_string(FILE *f, const char *cp, int len)
197.103 +{
197.104 + unsigned char ch;
197.105 +
197.106 + if (len < 0)
197.107 + len = strlen(cp);
197.108 +
197.109 + while (len--) {
197.110 + ch = *cp++;
197.111 + if (ch == '\a')
197.112 + fputs("\\a", f);
197.113 + else if (ch == '\b')
197.114 + fputs("\\b", f);
197.115 + else if (ch == '\f')
197.116 + fputs("\\f", f);
197.117 + else if (ch == '\n')
197.118 + fputs("\\n", f);
197.119 + else if (ch == '\t')
197.120 + fputs("\\t", f);
197.121 + else if (ch == '\v')
197.122 + fputs("\\v", f);
197.123 + else if (ch == '\\')
197.124 + fputs("\\\\", f);
197.125 + else if (ch == '\'')
197.126 + fputs("\\\'", f);
197.127 + else if (ch == '\"')
197.128 + fputs("\\\"", f);
197.129 + else if ((ch < 32) || (ch > 126))
197.130 + fprintf(f, "\\%03o", ch);
197.131 + else
197.132 + fputc(ch, f);
197.133 + }
197.134 +}
197.135 +
197.136 +#ifdef DEBUG_PROGRAM
197.137 +int main(int argc, char **argv)
197.138 +{
197.139 + char buf[4096];
197.140 + int c, raw = 0;
197.141 +
197.142 + while ((c = getopt(argc, argv, "r")) != EOF) {
197.143 + switch (c) {
197.144 + case 'r':
197.145 + raw++;
197.146 + break;
197.147 + default:
197.148 + fprintf(stderr, "Usage: %s [-r]\n", argv[0]);
197.149 + exit(1);
197.150 + }
197.151 + }
197.152 +
197.153 + while (!feof(stdin)) {
197.154 + if (fgets(buf, sizeof(buf), stdin) == NULL)
197.155 + break;
197.156 + c = parse_c_string(buf);
197.157 + if (raw)
197.158 + fputs(buf, stdout);
197.159 + else {
197.160 + print_c_string(stdout, buf, c);
197.161 + printf(" <%d>\n", c);
197.162 + }
197.163 + }
197.164 +}
197.165 +#endif
198.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
198.2 +++ b/libext2fs/lib/libsupport/cstring.h Wed Aug 25 01:28:08 2021 +0200
198.3 @@ -0,0 +1,6 @@
198.4 +/*
198.5 + * cstring.h -- header file for C string parse/print utilities
198.6 + */
198.7 +
198.8 +extern int parse_c_string(char *str);
198.9 +extern void print_c_string(FILE *f, const char *cp, int len);
199.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
199.2 +++ b/libext2fs/lib/libsupport/dict.c Wed Aug 25 01:28:08 2021 +0200
199.3 @@ -0,0 +1,1531 @@
199.4 +/*
199.5 + * Dictionary Abstract Data Type
199.6 + * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
199.7 + *
199.8 + * Free Software License:
199.9 + *
199.10 + * All rights are reserved by the author, with the following exceptions:
199.11 + * Permission is granted to freely reproduce and distribute this software,
199.12 + * possibly in exchange for a fee, provided that this copyright notice appears
199.13 + * intact. Permission is also granted to adapt this software to produce
199.14 + * derivative works, as long as the modified versions carry this copyright
199.15 + * notice and additional notices stating that the work has been modified.
199.16 + * This source code may be translated into executable form and incorporated
199.17 + * into proprietary software; there is no requirement for such software to
199.18 + * contain a copyright notice related to this source.
199.19 + *
199.20 + * $Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz Exp $
199.21 + * $Name: kazlib_1_20 $
199.22 + */
199.23 +
199.24 +#define DICT_NODEBUG
199.25 +
199.26 +#ifdef __GNUC__
199.27 +#define EXT2FS_ATTR(x) __attribute__(x)
199.28 +#else
199.29 +#define EXT2FS_ATTR(x)
199.30 +#endif
199.31 +
199.32 +#include "config.h"
199.33 +#include <stdlib.h>
199.34 +#include <stddef.h>
199.35 +#ifdef DICT_NODEBUG
199.36 +#define dict_assert(x)
199.37 +#else
199.38 +#include <assert.h>
199.39 +#define dict_assert(x) assert(x)
199.40 +#endif
199.41 +#define DICT_IMPLEMENTATION
199.42 +#include "dict.h"
199.43 +
199.44 +#ifdef KAZLIB_RCSID
199.45 +static const char rcsid[] = "$Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz Exp $";
199.46 +#endif
199.47 +
199.48 +/*
199.49 + * These macros provide short convenient names for structure members,
199.50 + * which are embellished with dict_ prefixes so that they are
199.51 + * properly confined to the documented namespace. It's legal for a
199.52 + * program which uses dict to define, for instance, a macro called ``parent''.
199.53 + * Such a macro would interfere with the dnode_t struct definition.
199.54 + * In general, highly portable and reusable C modules which expose their
199.55 + * structures need to confine structure member names to well-defined spaces.
199.56 + * The resulting identifiers aren't necessarily convenient to use, nor
199.57 + * readable, in the implementation, however!
199.58 + */
199.59 +
199.60 +#define left dict_left
199.61 +#define right dict_right
199.62 +#define parent dict_parent
199.63 +#define color dict_color
199.64 +#define key dict_key
199.65 +#define data dict_data
199.66 +
199.67 +#define nilnode dict_nilnode
199.68 +#define nodecount dict_nodecount
199.69 +#define maxcount dict_maxcount
199.70 +#define compare dict_compare
199.71 +#define allocnode dict_allocnode
199.72 +#define freenode dict_freenode
199.73 +#define context dict_context
199.74 +#define dupes dict_dupes
199.75 +
199.76 +#define dictptr dict_dictptr
199.77 +
199.78 +#define dict_root(D) ((D)->nilnode.left)
199.79 +#define dict_nil(D) (&(D)->nilnode)
199.80 +#define DICT_DEPTH_MAX 64
199.81 +
199.82 +static dnode_t *dnode_alloc(void *context);
199.83 +static void dnode_free(dnode_t *node, void *context);
199.84 +
199.85 +/*
199.86 + * Perform a ``left rotation'' adjustment on the tree. The given node P and
199.87 + * its right child C are rearranged so that the P instead becomes the left
199.88 + * child of C. The left subtree of C is inherited as the new right subtree
199.89 + * for P. The ordering of the keys within the tree is thus preserved.
199.90 + */
199.91 +
199.92 +static void rotate_left(dnode_t *upper)
199.93 +{
199.94 + dnode_t *lower, *lowleft, *upparent;
199.95 +
199.96 + lower = upper->right;
199.97 + upper->right = lowleft = lower->left;
199.98 + lowleft->parent = upper;
199.99 +
199.100 + lower->parent = upparent = upper->parent;
199.101 +
199.102 + /* don't need to check for root node here because root->parent is
199.103 + the sentinel nil node, and root->parent->left points back to root */
199.104 +
199.105 + if (upper == upparent->left) {
199.106 + upparent->left = lower;
199.107 + } else {
199.108 + dict_assert (upper == upparent->right);
199.109 + upparent->right = lower;
199.110 + }
199.111 +
199.112 + lower->left = upper;
199.113 + upper->parent = lower;
199.114 +}
199.115 +
199.116 +/*
199.117 + * This operation is the ``mirror'' image of rotate_left. It is
199.118 + * the same procedure, but with left and right interchanged.
199.119 + */
199.120 +
199.121 +static void rotate_right(dnode_t *upper)
199.122 +{
199.123 + dnode_t *lower, *lowright, *upparent;
199.124 +
199.125 + lower = upper->left;
199.126 + upper->left = lowright = lower->right;
199.127 + lowright->parent = upper;
199.128 +
199.129 + lower->parent = upparent = upper->parent;
199.130 +
199.131 + if (upper == upparent->right) {
199.132 + upparent->right = lower;
199.133 + } else {
199.134 + dict_assert (upper == upparent->left);
199.135 + upparent->left = lower;
199.136 + }
199.137 +
199.138 + lower->right = upper;
199.139 + upper->parent = lower;
199.140 +}
199.141 +
199.142 +/*
199.143 + * Do a postorder traversal of the tree rooted at the specified
199.144 + * node and free everything under it. Used by dict_free().
199.145 + */
199.146 +
199.147 +static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
199.148 +{
199.149 + if (node == nil)
199.150 + return;
199.151 + free_nodes(dict, node->left, nil);
199.152 + free_nodes(dict, node->right, nil);
199.153 + dict->freenode(node, dict->context);
199.154 +}
199.155 +
199.156 +/*
199.157 + * This procedure performs a verification that the given subtree is a binary
199.158 + * search tree. It performs an inorder traversal of the tree using the
199.159 + * dict_next() successor function, verifying that the key of each node is
199.160 + * strictly lower than that of its successor, if duplicates are not allowed,
199.161 + * or lower or equal if duplicates are allowed. This function is used for
199.162 + * debugging purposes.
199.163 + */
199.164 +#ifndef DICT_NODEBUG
199.165 +static int verify_bintree(dict_t *dict)
199.166 +{
199.167 + dnode_t *first, *next;
199.168 +
199.169 + first = dict_first(dict);
199.170 +
199.171 + if (dict->dupes) {
199.172 + while (first && (next = dict_next(dict, first))) {
199.173 + if (dict->compare(first->key, next->key) > 0)
199.174 + return 0;
199.175 + first = next;
199.176 + }
199.177 + } else {
199.178 + while (first && (next = dict_next(dict, first))) {
199.179 + if (dict->compare(first->key, next->key) >= 0)
199.180 + return 0;
199.181 + first = next;
199.182 + }
199.183 + }
199.184 + return 1;
199.185 +}
199.186 +
199.187 +/*
199.188 + * This function recursively verifies that the given binary subtree satisfies
199.189 + * three of the red black properties. It checks that every red node has only
199.190 + * black children. It makes sure that each node is either red or black. And it
199.191 + * checks that every path has the same count of black nodes from root to leaf.
199.192 + * It returns the blackheight of the given subtree; this allows blackheights to
199.193 + * be computed recursively and compared for left and right siblings for
199.194 + * mismatches. It does not check for every nil node being black, because there
199.195 + * is only one sentinel nil node. The return value of this function is the
199.196 + * black height of the subtree rooted at the node ``root'', or zero if the
199.197 + * subtree is not red-black.
199.198 + */
199.199 +
199.200 +static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
199.201 +{
199.202 + unsigned height_left, height_right;
199.203 +
199.204 + if (root != nil) {
199.205 + height_left = verify_redblack(nil, root->left);
199.206 + height_right = verify_redblack(nil, root->right);
199.207 + if (height_left == 0 || height_right == 0)
199.208 + return 0;
199.209 + if (height_left != height_right)
199.210 + return 0;
199.211 + if (root->color == dnode_red) {
199.212 + if (root->left->color != dnode_black)
199.213 + return 0;
199.214 + if (root->right->color != dnode_black)
199.215 + return 0;
199.216 + return height_left;
199.217 + }
199.218 + if (root->color != dnode_black)
199.219 + return 0;
199.220 + return height_left + 1;
199.221 + }
199.222 + return 1;
199.223 +}
199.224 +
199.225 +/*
199.226 + * Compute the actual count of nodes by traversing the tree and
199.227 + * return it. This could be compared against the stored count to
199.228 + * detect a mismatch.
199.229 + */
199.230 +
199.231 +static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
199.232 +{
199.233 + if (root == nil)
199.234 + return 0;
199.235 + else
199.236 + return 1 + verify_node_count(nil, root->left)
199.237 + + verify_node_count(nil, root->right);
199.238 +}
199.239 +#endif
199.240 +
199.241 +/*
199.242 + * Verify that the tree contains the given node. This is done by
199.243 + * traversing all of the nodes and comparing their pointers to the
199.244 + * given pointer. Returns 1 if the node is found, otherwise
199.245 + * returns zero. It is intended for debugging purposes.
199.246 + */
199.247 +
199.248 +static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
199.249 +{
199.250 + if (root != nil) {
199.251 + return root == node
199.252 + || verify_dict_has_node(nil, root->left, node)
199.253 + || verify_dict_has_node(nil, root->right, node);
199.254 + }
199.255 + return 0;
199.256 +}
199.257 +
199.258 +
199.259 +#ifdef E2FSCK_NOTUSED
199.260 +/*
199.261 + * Dynamically allocate and initialize a dictionary object.
199.262 + */
199.263 +
199.264 +dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp)
199.265 +{
199.266 + dict_t *new = malloc(sizeof *new);
199.267 +
199.268 + if (new) {
199.269 + new->compare = comp;
199.270 + new->allocnode = dnode_alloc;
199.271 + new->freenode = dnode_free;
199.272 + new->context = NULL;
199.273 + new->nodecount = 0;
199.274 + new->maxcount = maxcount;
199.275 + new->nilnode.left = &new->nilnode;
199.276 + new->nilnode.right = &new->nilnode;
199.277 + new->nilnode.parent = &new->nilnode;
199.278 + new->nilnode.color = dnode_black;
199.279 + new->dupes = 0;
199.280 + }
199.281 + return new;
199.282 +}
199.283 +#endif /* E2FSCK_NOTUSED */
199.284 +
199.285 +/*
199.286 + * Select a different set of node allocator routines.
199.287 + */
199.288 +
199.289 +void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
199.290 + dnode_free_t fr, void *context)
199.291 +{
199.292 + dict_assert (dict_count(dict) == 0);
199.293 + dict_assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL));
199.294 +
199.295 + dict->allocnode = al ? al : dnode_alloc;
199.296 + dict->freenode = fr ? fr : dnode_free;
199.297 + dict->context = context;
199.298 +}
199.299 +
199.300 +#ifdef E2FSCK_NOTUSED
199.301 +/*
199.302 + * Free a dynamically allocated dictionary object. Removing the nodes
199.303 + * from the tree before deleting it is required.
199.304 + */
199.305 +
199.306 +void dict_destroy(dict_t *dict)
199.307 +{
199.308 + dict_assert (dict_isempty(dict));
199.309 + free(dict);
199.310 +}
199.311 +#endif
199.312 +
199.313 +/*
199.314 + * Free all the nodes in the dictionary by using the dictionary's
199.315 + * installed free routine. The dictionary is emptied.
199.316 + */
199.317 +
199.318 +void dict_free_nodes(dict_t *dict)
199.319 +{
199.320 + dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
199.321 + free_nodes(dict, root, nil);
199.322 + dict->nodecount = 0;
199.323 + dict->nilnode.left = &dict->nilnode;
199.324 + dict->nilnode.right = &dict->nilnode;
199.325 +}
199.326 +
199.327 +#ifdef E2FSCK_NOTUSED
199.328 +/*
199.329 + * Obsolescent function, equivalent to dict_free_nodes
199.330 + */
199.331 +void dict_free(dict_t *dict)
199.332 +{
199.333 +#ifdef KAZLIB_OBSOLESCENT_DEBUG
199.334 + dict_assert ("call to obsolescent function dict_free()" && 0);
199.335 +#endif
199.336 + dict_free_nodes(dict);
199.337 +}
199.338 +#endif
199.339 +
199.340 +/*
199.341 + * Initialize a user-supplied dictionary object.
199.342 + */
199.343 +
199.344 +dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
199.345 +{
199.346 + dict->compare = comp;
199.347 + dict->allocnode = dnode_alloc;
199.348 + dict->freenode = dnode_free;
199.349 + dict->context = NULL;
199.350 + dict->nodecount = 0;
199.351 + dict->maxcount = maxcount;
199.352 + dict->nilnode.left = &dict->nilnode;
199.353 + dict->nilnode.right = &dict->nilnode;
199.354 + dict->nilnode.parent = &dict->nilnode;
199.355 + dict->nilnode.color = dnode_black;
199.356 + dict->dupes = 0;
199.357 + return dict;
199.358 +}
199.359 +
199.360 +#ifdef E2FSCK_NOTUSED
199.361 +/*
199.362 + * Initialize a dictionary in the likeness of another dictionary
199.363 + */
199.364 +
199.365 +void dict_init_like(dict_t *dict, const dict_t *template)
199.366 +{
199.367 + dict->compare = template->compare;
199.368 + dict->allocnode = template->allocnode;
199.369 + dict->freenode = template->freenode;
199.370 + dict->context = template->context;
199.371 + dict->nodecount = 0;
199.372 + dict->maxcount = template->maxcount;
199.373 + dict->nilnode.left = &dict->nilnode;
199.374 + dict->nilnode.right = &dict->nilnode;
199.375 + dict->nilnode.parent = &dict->nilnode;
199.376 + dict->nilnode.color = dnode_black;
199.377 + dict->dupes = template->dupes;
199.378 +
199.379 + dict_assert (dict_similar(dict, template));
199.380 +}
199.381 +
199.382 +/*
199.383 + * Remove all nodes from the dictionary (without freeing them in any way).
199.384 + */
199.385 +
199.386 +static void dict_clear(dict_t *dict)
199.387 +{
199.388 + dict->nodecount = 0;
199.389 + dict->nilnode.left = &dict->nilnode;
199.390 + dict->nilnode.right = &dict->nilnode;
199.391 + dict->nilnode.parent = &dict->nilnode;
199.392 + dict_assert (dict->nilnode.color == dnode_black);
199.393 +}
199.394 +#endif /* E2FSCK_NOTUSED */
199.395 +
199.396 +
199.397 +/*
199.398 + * Verify the integrity of the dictionary structure. This is provided for
199.399 + * debugging purposes, and should be placed in assert statements. Just because
199.400 + * this function succeeds doesn't mean that the tree is not corrupt. Certain
199.401 + * corruptions in the tree may simply cause undefined behavior.
199.402 + */
199.403 +#ifndef DICT_NODEBUG
199.404 +int dict_verify(dict_t *dict)
199.405 +{
199.406 + dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
199.407 +
199.408 + /* check that the sentinel node and root node are black */
199.409 + if (root->color != dnode_black)
199.410 + return 0;
199.411 + if (nil->color != dnode_black)
199.412 + return 0;
199.413 + if (nil->right != nil)
199.414 + return 0;
199.415 + /* nil->left is the root node; check that its parent pointer is nil */
199.416 + if (nil->left->parent != nil)
199.417 + return 0;
199.418 + /* perform a weak test that the tree is a binary search tree */
199.419 + if (!verify_bintree(dict))
199.420 + return 0;
199.421 + /* verify that the tree is a red-black tree */
199.422 + if (!verify_redblack(nil, root))
199.423 + return 0;
199.424 + if (verify_node_count(nil, root) != dict_count(dict))
199.425 + return 0;
199.426 + return 1;
199.427 +}
199.428 +#endif /* DICT_NODEBUG */
199.429 +
199.430 +#ifdef E2FSCK_NOTUSED
199.431 +/*
199.432 + * Determine whether two dictionaries are similar: have the same comparison and
199.433 + * allocator functions, and same status as to whether duplicates are allowed.
199.434 + */
199.435 +int dict_similar(const dict_t *left, const dict_t *right)
199.436 +{
199.437 + if (left->compare != right->compare)
199.438 + return 0;
199.439 +
199.440 + if (left->allocnode != right->allocnode)
199.441 + return 0;
199.442 +
199.443 + if (left->freenode != right->freenode)
199.444 + return 0;
199.445 +
199.446 + if (left->context != right->context)
199.447 + return 0;
199.448 +
199.449 + if (left->dupes != right->dupes)
199.450 + return 0;
199.451 +
199.452 + return 1;
199.453 +}
199.454 +#endif /* E2FSCK_NOTUSED */
199.455 +
199.456 +/*
199.457 + * Locate a node in the dictionary having the given key.
199.458 + * If the node is not found, a null a pointer is returned (rather than
199.459 + * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
199.460 + * located node is returned.
199.461 + */
199.462 +
199.463 +dnode_t *dict_lookup(dict_t *dict, const void *key)
199.464 +{
199.465 + dnode_t *root = dict_root(dict);
199.466 + dnode_t *nil = dict_nil(dict);
199.467 + dnode_t *saved;
199.468 + int result;
199.469 +
199.470 + /* simple binary search adapted for trees that contain duplicate keys */
199.471 +
199.472 + while (root != nil) {
199.473 + result = dict->compare(key, root->key);
199.474 + if (result < 0)
199.475 + root = root->left;
199.476 + else if (result > 0)
199.477 + root = root->right;
199.478 + else {
199.479 + if (!dict->dupes) { /* no duplicates, return match */
199.480 + return root;
199.481 + } else { /* could be dupes, find leftmost one */
199.482 + do {
199.483 + saved = root;
199.484 + root = root->left;
199.485 + while (root != nil && dict->compare(key, root->key))
199.486 + root = root->right;
199.487 + } while (root != nil);
199.488 + return saved;
199.489 + }
199.490 + }
199.491 + }
199.492 +
199.493 + return NULL;
199.494 +}
199.495 +
199.496 +#ifdef E2FSCK_NOTUSED
199.497 +/*
199.498 + * Look for the node corresponding to the lowest key that is equal to or
199.499 + * greater than the given key. If there is no such node, return null.
199.500 + */
199.501 +
199.502 +dnode_t *dict_lower_bound(dict_t *dict, const void *key)
199.503 +{
199.504 + dnode_t *root = dict_root(dict);
199.505 + dnode_t *nil = dict_nil(dict);
199.506 + dnode_t *tentative = 0;
199.507 +
199.508 + while (root != nil) {
199.509 + int result = dict->compare(key, root->key);
199.510 +
199.511 + if (result > 0) {
199.512 + root = root->right;
199.513 + } else if (result < 0) {
199.514 + tentative = root;
199.515 + root = root->left;
199.516 + } else {
199.517 + if (!dict->dupes) {
199.518 + return root;
199.519 + } else {
199.520 + tentative = root;
199.521 + root = root->left;
199.522 + }
199.523 + }
199.524 + }
199.525 +
199.526 + return tentative;
199.527 +}
199.528 +
199.529 +/*
199.530 + * Look for the node corresponding to the greatest key that is equal to or
199.531 + * lower than the given key. If there is no such node, return null.
199.532 + */
199.533 +
199.534 +dnode_t *dict_upper_bound(dict_t *dict, const void *key)
199.535 +{
199.536 + dnode_t *root = dict_root(dict);
199.537 + dnode_t *nil = dict_nil(dict);
199.538 + dnode_t *tentative = 0;
199.539 +
199.540 + while (root != nil) {
199.541 + int result = dict->compare(key, root->key);
199.542 +
199.543 + if (result < 0) {
199.544 + root = root->left;
199.545 + } else if (result > 0) {
199.546 + tentative = root;
199.547 + root = root->right;
199.548 + } else {
199.549 + if (!dict->dupes) {
199.550 + return root;
199.551 + } else {
199.552 + tentative = root;
199.553 + root = root->right;
199.554 + }
199.555 + }
199.556 + }
199.557 +
199.558 + return tentative;
199.559 +}
199.560 +#endif
199.561 +
199.562 +/*
199.563 + * Insert a node into the dictionary. The node should have been
199.564 + * initialized with a data field. All other fields are ignored.
199.565 + * The behavior is undefined if the user attempts to insert into
199.566 + * a dictionary that is already full (for which the dict_isfull()
199.567 + * function returns true).
199.568 + */
199.569 +
199.570 +void dict_insert(dict_t *dict, dnode_t *node, const void *key)
199.571 +{
199.572 + dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
199.573 + dnode_t *parent = nil, *uncle, *grandpa;
199.574 + int result = -1;
199.575 +
199.576 + node->key = key;
199.577 +
199.578 + dict_assert (!dict_isfull(dict));
199.579 + dict_assert (!dict_contains(dict, node));
199.580 + dict_assert (!dnode_is_in_a_dict(node));
199.581 +
199.582 + /* basic binary tree insert */
199.583 +
199.584 + while (where != nil) {
199.585 + parent = where;
199.586 + result = dict->compare(key, where->key);
199.587 + /* trap attempts at duplicate key insertion unless it's explicitly allowed */
199.588 + dict_assert (dict->dupes || result != 0);
199.589 + if (result < 0)
199.590 + where = where->left;
199.591 + else
199.592 + where = where->right;
199.593 + }
199.594 +
199.595 + dict_assert (where == nil);
199.596 +
199.597 + if (result < 0)
199.598 + parent->left = node;
199.599 + else
199.600 + parent->right = node;
199.601 +
199.602 + node->parent = parent;
199.603 + node->left = nil;
199.604 + node->right = nil;
199.605 +
199.606 + dict->nodecount++;
199.607 +
199.608 + /* red black adjustments */
199.609 +
199.610 + node->color = dnode_red;
199.611 +
199.612 + while (parent->color == dnode_red) {
199.613 + grandpa = parent->parent;
199.614 + if (parent == grandpa->left) {
199.615 + uncle = grandpa->right;
199.616 + if (uncle->color == dnode_red) { /* red parent, red uncle */
199.617 + parent->color = dnode_black;
199.618 + uncle->color = dnode_black;
199.619 + grandpa->color = dnode_red;
199.620 + node = grandpa;
199.621 + parent = grandpa->parent;
199.622 + } else { /* red parent, black uncle */
199.623 + if (node == parent->right) {
199.624 + rotate_left(parent);
199.625 + parent = node;
199.626 + dict_assert (grandpa == parent->parent);
199.627 + /* rotation between parent and child preserves grandpa */
199.628 + }
199.629 + parent->color = dnode_black;
199.630 + grandpa->color = dnode_red;
199.631 + rotate_right(grandpa);
199.632 + break;
199.633 + }
199.634 + } else { /* symmetric cases: parent == parent->parent->right */
199.635 + uncle = grandpa->left;
199.636 + if (uncle->color == dnode_red) {
199.637 + parent->color = dnode_black;
199.638 + uncle->color = dnode_black;
199.639 + grandpa->color = dnode_red;
199.640 + node = grandpa;
199.641 + parent = grandpa->parent;
199.642 + } else {
199.643 + if (node == parent->left) {
199.644 + rotate_right(parent);
199.645 + parent = node;
199.646 + dict_assert (grandpa == parent->parent);
199.647 + }
199.648 + parent->color = dnode_black;
199.649 + grandpa->color = dnode_red;
199.650 + rotate_left(grandpa);
199.651 + break;
199.652 + }
199.653 + }
199.654 + }
199.655 +
199.656 + dict_root(dict)->color = dnode_black;
199.657 +
199.658 + dict_assert (dict_verify(dict));
199.659 +}
199.660 +
199.661 +#ifdef E2FSCK_NOTUSED
199.662 +/*
199.663 + * Delete the given node from the dictionary. If the given node does not belong
199.664 + * to the given dictionary, undefined behavior results. A pointer to the
199.665 + * deleted node is returned.
199.666 + */
199.667 +
199.668 +dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
199.669 +{
199.670 + dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent;
199.671 +
199.672 + /* basic deletion */
199.673 +
199.674 + dict_assert (!dict_isempty(dict));
199.675 + dict_assert (dict_contains(dict, delete));
199.676 +
199.677 + /*
199.678 + * If the node being deleted has two children, then we replace it with its
199.679 + * successor (i.e. the leftmost node in the right subtree.) By doing this,
199.680 + * we avoid the traditional algorithm under which the successor's key and
199.681 + * value *only* move to the deleted node and the successor is spliced out
199.682 + * from the tree. We cannot use this approach because the user may hold
199.683 + * pointers to the successor, or nodes may be inextricably tied to some
199.684 + * other structures by way of embedding, etc. So we must splice out the
199.685 + * node we are given, not some other node, and must not move contents from
199.686 + * one node to another behind the user's back.
199.687 + */
199.688 +
199.689 + if (delete->left != nil && delete->right != nil) {
199.690 + dnode_t *next = dict_next(dict, delete);
199.691 + dnode_t *nextparent = next->parent;
199.692 + dnode_color_t nextcolor = next->color;
199.693 +
199.694 + dict_assert (next != nil);
199.695 + dict_assert (next->parent != nil);
199.696 + dict_assert (next->left == nil);
199.697 +
199.698 + /*
199.699 + * First, splice out the successor from the tree completely, by
199.700 + * moving up its right child into its place.
199.701 + */
199.702 +
199.703 + child = next->right;
199.704 + child->parent = nextparent;
199.705 +
199.706 + if (nextparent->left == next) {
199.707 + nextparent->left = child;
199.708 + } else {
199.709 + dict_assert (nextparent->right == next);
199.710 + nextparent->right = child;
199.711 + }
199.712 +
199.713 + /*
199.714 + * Now that the successor has been extricated from the tree, install it
199.715 + * in place of the node that we want deleted.
199.716 + */
199.717 +
199.718 + next->parent = delparent;
199.719 + next->left = delete->left;
199.720 + next->right = delete->right;
199.721 + next->left->parent = next;
199.722 + next->right->parent = next;
199.723 + next->color = delete->color;
199.724 + delete->color = nextcolor;
199.725 +
199.726 + if (delparent->left == delete) {
199.727 + delparent->left = next;
199.728 + } else {
199.729 + dict_assert (delparent->right == delete);
199.730 + delparent->right = next;
199.731 + }
199.732 +
199.733 + } else {
199.734 + dict_assert (delete != nil);
199.735 + dict_assert (delete->left == nil || delete->right == nil);
199.736 +
199.737 + child = (delete->left != nil) ? delete->left : delete->right;
199.738 +
199.739 + child->parent = delparent = delete->parent;
199.740 +
199.741 + if (delete == delparent->left) {
199.742 + delparent->left = child;
199.743 + } else {
199.744 + dict_assert (delete == delparent->right);
199.745 + delparent->right = child;
199.746 + }
199.747 + }
199.748 +
199.749 + delete->parent = NULL;
199.750 + delete->right = NULL;
199.751 + delete->left = NULL;
199.752 +
199.753 + dict->nodecount--;
199.754 +
199.755 + dict_assert (verify_bintree(dict));
199.756 +
199.757 + /* red-black adjustments */
199.758 +
199.759 + if (delete->color == dnode_black) {
199.760 + dnode_t *parent, *sister;
199.761 +
199.762 + dict_root(dict)->color = dnode_red;
199.763 +
199.764 + while (child->color == dnode_black) {
199.765 + parent = child->parent;
199.766 + if (child == parent->left) {
199.767 + sister = parent->right;
199.768 + dict_assert (sister != nil);
199.769 + if (sister->color == dnode_red) {
199.770 + sister->color = dnode_black;
199.771 + parent->color = dnode_red;
199.772 + rotate_left(parent);
199.773 + sister = parent->right;
199.774 + dict_assert (sister != nil);
199.775 + }
199.776 + if (sister->left->color == dnode_black
199.777 + && sister->right->color == dnode_black) {
199.778 + sister->color = dnode_red;
199.779 + child = parent;
199.780 + } else {
199.781 + if (sister->right->color == dnode_black) {
199.782 + dict_assert (sister->left->color == dnode_red);
199.783 + sister->left->color = dnode_black;
199.784 + sister->color = dnode_red;
199.785 + rotate_right(sister);
199.786 + sister = parent->right;
199.787 + dict_assert (sister != nil);
199.788 + }
199.789 + sister->color = parent->color;
199.790 + sister->right->color = dnode_black;
199.791 + parent->color = dnode_black;
199.792 + rotate_left(parent);
199.793 + break;
199.794 + }
199.795 + } else { /* symmetric case: child == child->parent->right */
199.796 + dict_assert (child == parent->right);
199.797 + sister = parent->left;
199.798 + dict_assert (sister != nil);
199.799 + if (sister->color == dnode_red) {
199.800 + sister->color = dnode_black;
199.801 + parent->color = dnode_red;
199.802 + rotate_right(parent);
199.803 + sister = parent->left;
199.804 + dict_assert (sister != nil);
199.805 + }
199.806 + if (sister->right->color == dnode_black
199.807 + && sister->left->color == dnode_black) {
199.808 + sister->color = dnode_red;
199.809 + child = parent;
199.810 + } else {
199.811 + if (sister->left->color == dnode_black) {
199.812 + dict_assert (sister->right->color == dnode_red);
199.813 + sister->right->color = dnode_black;
199.814 + sister->color = dnode_red;
199.815 + rotate_left(sister);
199.816 + sister = parent->left;
199.817 + dict_assert (sister != nil);
199.818 + }
199.819 + sister->color = parent->color;
199.820 + sister->left->color = dnode_black;
199.821 + parent->color = dnode_black;
199.822 + rotate_right(parent);
199.823 + break;
199.824 + }
199.825 + }
199.826 + }
199.827 +
199.828 + child->color = dnode_black;
199.829 + dict_root(dict)->color = dnode_black;
199.830 + }
199.831 +
199.832 + dict_assert (dict_verify(dict));
199.833 +
199.834 + return delete;
199.835 +}
199.836 +#endif /* E2FSCK_NOTUSED */
199.837 +
199.838 +/*
199.839 + * Allocate a node using the dictionary's allocator routine, give it
199.840 + * the data item.
199.841 + */
199.842 +
199.843 +int dict_alloc_insert(dict_t *dict, const void *key, void *data)
199.844 +{
199.845 + dnode_t *node = dict->allocnode(dict->context);
199.846 +
199.847 + if (node) {
199.848 + dnode_init(node, data);
199.849 + dict_insert(dict, node, key);
199.850 + return 1;
199.851 + }
199.852 + return 0;
199.853 +}
199.854 +
199.855 +#ifdef E2FSCK_NOTUSED
199.856 +void dict_delete_free(dict_t *dict, dnode_t *node)
199.857 +{
199.858 + dict_delete(dict, node);
199.859 + dict->freenode(node, dict->context);
199.860 +}
199.861 +#endif
199.862 +
199.863 +/*
199.864 + * Return the node with the lowest (leftmost) key. If the dictionary is empty
199.865 + * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
199.866 + */
199.867 +
199.868 +dnode_t *dict_first(dict_t *dict)
199.869 +{
199.870 + dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
199.871 +
199.872 + if (root != nil)
199.873 + while ((left = root->left) != nil)
199.874 + root = left;
199.875 +
199.876 + return (root == nil) ? NULL : root;
199.877 +}
199.878 +
199.879 +/*
199.880 + * Return the node with the highest (rightmost) key. If the dictionary is empty
199.881 + * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
199.882 + */
199.883 +
199.884 +dnode_t *dict_last(dict_t *dict)
199.885 +{
199.886 + dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right;
199.887 +
199.888 + if (root != nil)
199.889 + while ((right = root->right) != nil)
199.890 + root = right;
199.891 +
199.892 + return (root == nil) ? NULL : root;
199.893 +}
199.894 +
199.895 +/*
199.896 + * Return the given node's successor node---the node which has the
199.897 + * next key in the the left to right ordering. If the node has
199.898 + * no successor, a null pointer is returned rather than a pointer to
199.899 + * the nil node.
199.900 + */
199.901 +
199.902 +dnode_t *dict_next(dict_t *dict, dnode_t *curr)
199.903 +{
199.904 + dnode_t *nil = dict_nil(dict), *parent, *left;
199.905 +
199.906 + if (curr->right != nil) {
199.907 + curr = curr->right;
199.908 + while ((left = curr->left) != nil)
199.909 + curr = left;
199.910 + return curr;
199.911 + }
199.912 +
199.913 + parent = curr->parent;
199.914 +
199.915 + while (parent != nil && curr == parent->right) {
199.916 + curr = parent;
199.917 + parent = curr->parent;
199.918 + }
199.919 +
199.920 + return (parent == nil) ? NULL : parent;
199.921 +}
199.922 +
199.923 +/*
199.924 + * Return the given node's predecessor, in the key order.
199.925 + * The nil sentinel node is returned if there is no predecessor.
199.926 + */
199.927 +
199.928 +dnode_t *dict_prev(dict_t *dict, dnode_t *curr)
199.929 +{
199.930 + dnode_t *nil = dict_nil(dict), *parent, *right;
199.931 +
199.932 + if (curr->left != nil) {
199.933 + curr = curr->left;
199.934 + while ((right = curr->right) != nil)
199.935 + curr = right;
199.936 + return curr;
199.937 + }
199.938 +
199.939 + parent = curr->parent;
199.940 +
199.941 + while (parent != nil && curr == parent->left) {
199.942 + curr = parent;
199.943 + parent = curr->parent;
199.944 + }
199.945 +
199.946 + return (parent == nil) ? NULL : parent;
199.947 +}
199.948 +
199.949 +void dict_allow_dupes(dict_t *dict)
199.950 +{
199.951 + dict->dupes = 1;
199.952 +}
199.953 +
199.954 +#undef dict_count
199.955 +#undef dict_isempty
199.956 +#undef dict_isfull
199.957 +#undef dnode_get
199.958 +#undef dnode_put
199.959 +#undef dnode_getkey
199.960 +
199.961 +dictcount_t dict_count(dict_t *dict)
199.962 +{
199.963 + return dict->nodecount;
199.964 +}
199.965 +
199.966 +int dict_isempty(dict_t *dict)
199.967 +{
199.968 + return dict->nodecount == 0;
199.969 +}
199.970 +
199.971 +int dict_isfull(dict_t *dict)
199.972 +{
199.973 + return dict->nodecount == dict->maxcount;
199.974 +}
199.975 +
199.976 +int dict_contains(dict_t *dict, dnode_t *node)
199.977 +{
199.978 + return verify_dict_has_node(dict_nil(dict), dict_root(dict), node);
199.979 +}
199.980 +
199.981 +static dnode_t *dnode_alloc(void *context EXT2FS_ATTR((unused)))
199.982 +{
199.983 + return malloc(sizeof *dnode_alloc(NULL));
199.984 +}
199.985 +
199.986 +static void dnode_free(dnode_t *node, void *context EXT2FS_ATTR((unused)))
199.987 +{
199.988 + free(node);
199.989 +}
199.990 +
199.991 +dnode_t *dnode_create(void *data)
199.992 +{
199.993 + dnode_t *new = malloc(sizeof *new);
199.994 + if (new) {
199.995 + new->data = data;
199.996 + new->parent = NULL;
199.997 + new->left = NULL;
199.998 + new->right = NULL;
199.999 + }
199.1000 + return new;
199.1001 +}
199.1002 +
199.1003 +dnode_t *dnode_init(dnode_t *dnode, void *data)
199.1004 +{
199.1005 + dnode->data = data;
199.1006 + dnode->parent = NULL;
199.1007 + dnode->left = NULL;
199.1008 + dnode->right = NULL;
199.1009 + return dnode;
199.1010 +}
199.1011 +
199.1012 +void dnode_destroy(dnode_t *dnode)
199.1013 +{
199.1014 + dict_assert (!dnode_is_in_a_dict(dnode));
199.1015 + free(dnode);
199.1016 +}
199.1017 +
199.1018 +void *dnode_get(dnode_t *dnode)
199.1019 +{
199.1020 + return dnode->data;
199.1021 +}
199.1022 +
199.1023 +const void *dnode_getkey(dnode_t *dnode)
199.1024 +{
199.1025 + return dnode->key;
199.1026 +}
199.1027 +
199.1028 +#ifdef E2FSCK_NOTUSED
199.1029 +void dnode_put(dnode_t *dnode, void *data)
199.1030 +{
199.1031 + dnode->data = data;
199.1032 +}
199.1033 +#endif
199.1034 +
199.1035 +#ifndef DICT_NODEBUG
199.1036 +int dnode_is_in_a_dict(dnode_t *dnode)
199.1037 +{
199.1038 + return (dnode->parent && dnode->left && dnode->right);
199.1039 +}
199.1040 +#endif
199.1041 +
199.1042 +#ifdef E2FSCK_NOTUSED
199.1043 +void dict_process(dict_t *dict, void *context, dnode_process_t function)
199.1044 +{
199.1045 + dnode_t *node = dict_first(dict), *next;
199.1046 +
199.1047 + while (node != NULL) {
199.1048 + /* check for callback function deleting */
199.1049 + /* the next node from under us */
199.1050 + dict_assert (dict_contains(dict, node));
199.1051 + next = dict_next(dict, node);
199.1052 + function(dict, node, context);
199.1053 + node = next;
199.1054 + }
199.1055 +}
199.1056 +
199.1057 +static void load_begin_internal(dict_load_t *load, dict_t *dict)
199.1058 +{
199.1059 + load->dictptr = dict;
199.1060 + load->nilnode.left = &load->nilnode;
199.1061 + load->nilnode.right = &load->nilnode;
199.1062 +}
199.1063 +
199.1064 +void dict_load_begin(dict_load_t *load, dict_t *dict)
199.1065 +{
199.1066 + dict_assert (dict_isempty(dict));
199.1067 + load_begin_internal(load, dict);
199.1068 +}
199.1069 +
199.1070 +void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key)
199.1071 +{
199.1072 + dict_t *dict = load->dictptr;
199.1073 + dnode_t *nil = &load->nilnode;
199.1074 +
199.1075 + dict_assert (!dnode_is_in_a_dict(newnode));
199.1076 + dict_assert (dict->nodecount < dict->maxcount);
199.1077 +
199.1078 +#ifndef DICT_NODEBUG
199.1079 + if (dict->nodecount > 0) {
199.1080 + if (dict->dupes)
199.1081 + dict_assert (dict->compare(nil->left->key, key) <= 0);
199.1082 + else
199.1083 + dict_assert (dict->compare(nil->left->key, key) < 0);
199.1084 + }
199.1085 +#endif
199.1086 +
199.1087 + newnode->key = key;
199.1088 + nil->right->left = newnode;
199.1089 + nil->right = newnode;
199.1090 + newnode->left = nil;
199.1091 + dict->nodecount++;
199.1092 +}
199.1093 +
199.1094 +void dict_load_end(dict_load_t *load)
199.1095 +{
199.1096 + dict_t *dict = load->dictptr;
199.1097 + dnode_t *tree[DICT_DEPTH_MAX] = { 0 };
199.1098 + dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next;
199.1099 + dnode_t *complete = 0;
199.1100 + dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount;
199.1101 + dictcount_t botrowcount;
199.1102 + unsigned baselevel = 0, level = 0, i;
199.1103 +
199.1104 + dict_assert (dnode_red == 0 && dnode_black == 1);
199.1105 +
199.1106 + while (fullcount >= nodecount && fullcount)
199.1107 + fullcount >>= 1;
199.1108 +
199.1109 + botrowcount = nodecount - fullcount;
199.1110 +
199.1111 + for (curr = loadnil->left; curr != loadnil; curr = next) {
199.1112 + next = curr->left;
199.1113 +
199.1114 + if (complete == NULL && botrowcount-- == 0) {
199.1115 + dict_assert (baselevel == 0);
199.1116 + dict_assert (level == 0);
199.1117 + baselevel = level = 1;
199.1118 + complete = tree[0];
199.1119 +
199.1120 + if (complete != 0) {
199.1121 + tree[0] = 0;
199.1122 + complete->right = dictnil;
199.1123 + while (tree[level] != 0) {
199.1124 + tree[level]->right = complete;
199.1125 + complete->parent = tree[level];
199.1126 + complete = tree[level];
199.1127 + tree[level++] = 0;
199.1128 + }
199.1129 + }
199.1130 + }
199.1131 +
199.1132 + if (complete == NULL) {
199.1133 + curr->left = dictnil;
199.1134 + curr->right = dictnil;
199.1135 + curr->color = level % 2;
199.1136 + complete = curr;
199.1137 +
199.1138 + dict_assert (level == baselevel);
199.1139 + while (tree[level] != 0) {
199.1140 + tree[level]->right = complete;
199.1141 + complete->parent = tree[level];
199.1142 + complete = tree[level];
199.1143 + tree[level++] = 0;
199.1144 + }
199.1145 + } else {
199.1146 + curr->left = complete;
199.1147 + curr->color = (level + 1) % 2;
199.1148 + complete->parent = curr;
199.1149 + tree[level] = curr;
199.1150 + complete = 0;
199.1151 + level = baselevel;
199.1152 + }
199.1153 + }
199.1154 +
199.1155 + if (complete == NULL)
199.1156 + complete = dictnil;
199.1157 +
199.1158 + for (i = 0; i < DICT_DEPTH_MAX; i++) {
199.1159 + if (tree[i] != 0) {
199.1160 + tree[i]->right = complete;
199.1161 + complete->parent = tree[i];
199.1162 + complete = tree[i];
199.1163 + }
199.1164 + }
199.1165 +
199.1166 + dictnil->color = dnode_black;
199.1167 + dictnil->right = dictnil;
199.1168 + complete->parent = dictnil;
199.1169 + complete->color = dnode_black;
199.1170 + dict_root(dict) = complete;
199.1171 +
199.1172 + dict_assert (dict_verify(dict));
199.1173 +}
199.1174 +
199.1175 +void dict_merge(dict_t *dest, dict_t *source)
199.1176 +{
199.1177 + dict_load_t load;
199.1178 + dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source);
199.1179 +
199.1180 + dict_assert (dict_similar(dest, source));
199.1181 +
199.1182 + if (source == dest)
199.1183 + return;
199.1184 +
199.1185 + dest->nodecount = 0;
199.1186 + load_begin_internal(&load, dest);
199.1187 +
199.1188 + for (;;) {
199.1189 + if (leftnode != NULL && rightnode != NULL) {
199.1190 + if (dest->compare(leftnode->key, rightnode->key) < 0)
199.1191 + goto copyleft;
199.1192 + else
199.1193 + goto copyright;
199.1194 + } else if (leftnode != NULL) {
199.1195 + goto copyleft;
199.1196 + } else if (rightnode != NULL) {
199.1197 + goto copyright;
199.1198 + } else {
199.1199 + dict_assert (leftnode == NULL && rightnode == NULL);
199.1200 + break;
199.1201 + }
199.1202 +
199.1203 + copyleft:
199.1204 + {
199.1205 + dnode_t *next = dict_next(dest, leftnode);
199.1206 +#ifndef DICT_NODEBUG
199.1207 + leftnode->left = NULL; /* suppress assertion in dict_load_next */
199.1208 +#endif
199.1209 + dict_load_next(&load, leftnode, leftnode->key);
199.1210 + leftnode = next;
199.1211 + continue;
199.1212 + }
199.1213 +
199.1214 + copyright:
199.1215 + {
199.1216 + dnode_t *next = dict_next(source, rightnode);
199.1217 +#ifndef DICT_NODEBUG
199.1218 + rightnode->left = NULL;
199.1219 +#endif
199.1220 + dict_load_next(&load, rightnode, rightnode->key);
199.1221 + rightnode = next;
199.1222 + continue;
199.1223 + }
199.1224 + }
199.1225 +
199.1226 + dict_clear(source);
199.1227 + dict_load_end(&load);
199.1228 +}
199.1229 +#endif /* E2FSCK_NOTUSED */
199.1230 +
199.1231 +#ifdef KAZLIB_TEST_MAIN
199.1232 +
199.1233 +#include <stdio.h>
199.1234 +#include <string.h>
199.1235 +#include <ctype.h>
199.1236 +#include <stdarg.h>
199.1237 +
199.1238 +typedef char input_t[256];
199.1239 +
199.1240 +static int tokenize(char *string, ...)
199.1241 +{
199.1242 + char **tokptr;
199.1243 + va_list arglist;
199.1244 + int tokcount = 0;
199.1245 +
199.1246 + va_start(arglist, string);
199.1247 + tokptr = va_arg(arglist, char **);
199.1248 + while (tokptr) {
199.1249 + while (*string && isspace((unsigned char) *string))
199.1250 + string++;
199.1251 + if (!*string)
199.1252 + break;
199.1253 + *tokptr = string;
199.1254 + while (*string && !isspace((unsigned char) *string))
199.1255 + string++;
199.1256 + tokptr = va_arg(arglist, char **);
199.1257 + tokcount++;
199.1258 + if (!*string)
199.1259 + break;
199.1260 + *string++ = 0;
199.1261 + }
199.1262 + va_end(arglist);
199.1263 +
199.1264 + return tokcount;
199.1265 +}
199.1266 +
199.1267 +static int comparef(const void *key1, const void *key2)
199.1268 +{
199.1269 + return strcmp(key1, key2);
199.1270 +}
199.1271 +
199.1272 +static char *dupstring(char *str)
199.1273 +{
199.1274 + int sz = strlen(str) + 1;
199.1275 + char *new = malloc(sz);
199.1276 + if (new)
199.1277 + memcpy(new, str, sz);
199.1278 + return new;
199.1279 +}
199.1280 +
199.1281 +static dnode_t *new_node(void *c)
199.1282 +{
199.1283 + static dnode_t few[5];
199.1284 + static int count;
199.1285 +
199.1286 + if (count < 5)
199.1287 + return few + count++;
199.1288 +
199.1289 + return NULL;
199.1290 +}
199.1291 +
199.1292 +static void del_node(dnode_t *n, void *c)
199.1293 +{
199.1294 +}
199.1295 +
199.1296 +static int prompt = 0;
199.1297 +
199.1298 +static void construct(dict_t *d)
199.1299 +{
199.1300 + input_t in;
199.1301 + int done = 0;
199.1302 + dict_load_t dl;
199.1303 + dnode_t *dn;
199.1304 + char *tok1, *tok2, *val;
199.1305 + const char *key;
199.1306 + char *help =
199.1307 + "p turn prompt on\n"
199.1308 + "q finish construction\n"
199.1309 + "a <key> <val> add new entry\n";
199.1310 +
199.1311 + if (!dict_isempty(d))
199.1312 + puts("warning: dictionary not empty!");
199.1313 +
199.1314 + dict_load_begin(&dl, d);
199.1315 +
199.1316 + while (!done) {
199.1317 + if (prompt)
199.1318 + putchar('>');
199.1319 + fflush(stdout);
199.1320 +
199.1321 + if (!fgets(in, sizeof(input_t), stdin))
199.1322 + break;
199.1323 +
199.1324 + switch (in[0]) {
199.1325 + case '?':
199.1326 + puts(help);
199.1327 + break;
199.1328 + case 'p':
199.1329 + prompt = 1;
199.1330 + break;
199.1331 + case 'q':
199.1332 + done = 1;
199.1333 + break;
199.1334 + case 'a':
199.1335 + if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
199.1336 + puts("what?");
199.1337 + break;
199.1338 + }
199.1339 + key = dupstring(tok1);
199.1340 + val = dupstring(tok2);
199.1341 + dn = dnode_create(val);
199.1342 +
199.1343 + if (!key || !val || !dn) {
199.1344 + puts("out of memory");
199.1345 + free((void *) key);
199.1346 + free(val);
199.1347 + if (dn)
199.1348 + dnode_destroy(dn);
199.1349 + }
199.1350 +
199.1351 + dict_load_next(&dl, dn, key);
199.1352 + break;
199.1353 + default:
199.1354 + putchar('?');
199.1355 + putchar('\n');
199.1356 + break;
199.1357 + }
199.1358 + }
199.1359 +
199.1360 + dict_load_end(&dl);
199.1361 +}
199.1362 +
199.1363 +int main(void)
199.1364 +{
199.1365 + input_t in;
199.1366 + dict_t darray[10];
199.1367 + dict_t *d = &darray[0];
199.1368 + dnode_t *dn;
199.1369 + int i;
199.1370 + char *tok1, *tok2, *val;
199.1371 + const char *key;
199.1372 +
199.1373 + char *help =
199.1374 + "a <key> <val> add value to dictionary\n"
199.1375 + "d <key> delete value from dictionary\n"
199.1376 + "l <key> lookup value in dictionary\n"
199.1377 + "( <key> lookup lower bound\n"
199.1378 + ") <key> lookup upper bound\n"
199.1379 + "# <num> switch to alternate dictionary (0-9)\n"
199.1380 + "j <num> <num> merge two dictionaries\n"
199.1381 + "f free the whole dictionary\n"
199.1382 + "k allow duplicate keys\n"
199.1383 + "c show number of entries\n"
199.1384 + "t dump whole dictionary in sort order\n"
199.1385 + "m make dictionary out of sorted items\n"
199.1386 + "p turn prompt on\n"
199.1387 + "s switch to non-functioning allocator\n"
199.1388 + "q quit";
199.1389 +
199.1390 + for (i = 0; i < sizeof darray / sizeof *darray; i++)
199.1391 + dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
199.1392 +
199.1393 + for (;;) {
199.1394 + if (prompt)
199.1395 + putchar('>');
199.1396 + fflush(stdout);
199.1397 +
199.1398 + if (!fgets(in, sizeof(input_t), stdin))
199.1399 + break;
199.1400 +
199.1401 + switch(in[0]) {
199.1402 + case '?':
199.1403 + puts(help);
199.1404 + break;
199.1405 + case 'a':
199.1406 + if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
199.1407 + puts("what?");
199.1408 + break;
199.1409 + }
199.1410 + key = dupstring(tok1);
199.1411 + val = dupstring(tok2);
199.1412 +
199.1413 + if (!key || !val) {
199.1414 + puts("out of memory");
199.1415 + free((void *) key);
199.1416 + free(val);
199.1417 + }
199.1418 +
199.1419 + if (!dict_alloc_insert(d, key, val)) {
199.1420 + puts("dict_alloc_insert failed");
199.1421 + free((void *) key);
199.1422 + free(val);
199.1423 + break;
199.1424 + }
199.1425 + break;
199.1426 + case 'd':
199.1427 + if (tokenize(in+1, &tok1, (char **) 0) != 1) {
199.1428 + puts("what?");
199.1429 + break;
199.1430 + }
199.1431 + dn = dict_lookup(d, tok1);
199.1432 + if (!dn) {
199.1433 + puts("dict_lookup failed");
199.1434 + break;
199.1435 + }
199.1436 + val = dnode_get(dn);
199.1437 + key = dnode_getkey(dn);
199.1438 + dict_delete_free(d, dn);
199.1439 +
199.1440 + free(val);
199.1441 + free((void *) key);
199.1442 + break;
199.1443 + case 'f':
199.1444 + dict_free(d);
199.1445 + break;
199.1446 + case 'l':
199.1447 + case '(':
199.1448 + case ')':
199.1449 + if (tokenize(in+1, &tok1, (char **) 0) != 1) {
199.1450 + puts("what?");
199.1451 + break;
199.1452 + }
199.1453 + dn = 0;
199.1454 + switch (in[0]) {
199.1455 + case 'l':
199.1456 + dn = dict_lookup(d, tok1);
199.1457 + break;
199.1458 + case '(':
199.1459 + dn = dict_lower_bound(d, tok1);
199.1460 + break;
199.1461 + case ')':
199.1462 + dn = dict_upper_bound(d, tok1);
199.1463 + break;
199.1464 + }
199.1465 + if (!dn) {
199.1466 + puts("lookup failed");
199.1467 + break;
199.1468 + }
199.1469 + val = dnode_get(dn);
199.1470 + puts(val);
199.1471 + break;
199.1472 + case 'm':
199.1473 + construct(d);
199.1474 + break;
199.1475 + case 'k':
199.1476 + dict_allow_dupes(d);
199.1477 + break;
199.1478 + case 'c':
199.1479 + printf("%lu\n", (unsigned long) dict_count(d));
199.1480 + break;
199.1481 + case 't':
199.1482 + for (dn = dict_first(d); dn; dn = dict_next(d, dn)) {
199.1483 + printf("%s\t%s\n", (char *) dnode_getkey(dn),
199.1484 + (char *) dnode_get(dn));
199.1485 + }
199.1486 + break;
199.1487 + case 'q':
199.1488 + exit(0);
199.1489 + break;
199.1490 + case '\0':
199.1491 + break;
199.1492 + case 'p':
199.1493 + prompt = 1;
199.1494 + break;
199.1495 + case 's':
199.1496 + dict_set_allocator(d, new_node, del_node, NULL);
199.1497 + break;
199.1498 + case '#':
199.1499 + if (tokenize(in+1, &tok1, (char **) 0) != 1) {
199.1500 + puts("what?");
199.1501 + break;
199.1502 + } else {
199.1503 + int dictnum = atoi(tok1);
199.1504 + if (dictnum < 0 || dictnum > 9) {
199.1505 + puts("invalid number");
199.1506 + break;
199.1507 + }
199.1508 + d = &darray[dictnum];
199.1509 + }
199.1510 + break;
199.1511 + case 'j':
199.1512 + if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
199.1513 + puts("what?");
199.1514 + break;
199.1515 + } else {
199.1516 + int dict1 = atoi(tok1), dict2 = atoi(tok2);
199.1517 + if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) {
199.1518 + puts("invalid number");
199.1519 + break;
199.1520 + }
199.1521 + dict_merge(&darray[dict1], &darray[dict2]);
199.1522 + }
199.1523 + break;
199.1524 + default:
199.1525 + putchar('?');
199.1526 + putchar('\n');
199.1527 + break;
199.1528 + }
199.1529 + }
199.1530 +
199.1531 + return 0;
199.1532 +}
199.1533 +
199.1534 +#endif
200.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
200.2 +++ b/libext2fs/lib/libsupport/dict.h Wed Aug 25 01:28:08 2021 +0200
200.3 @@ -0,0 +1,144 @@
200.4 +/*
200.5 + * Dictionary Abstract Data Type
200.6 + * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
200.7 + *
200.8 + * Free Software License:
200.9 + *
200.10 + * All rights are reserved by the author, with the following exceptions:
200.11 + * Permission is granted to freely reproduce and distribute this software,
200.12 + * possibly in exchange for a fee, provided that this copyright notice appears
200.13 + * intact. Permission is also granted to adapt this software to produce
200.14 + * derivative works, as long as the modified versions carry this copyright
200.15 + * notice and additional notices stating that the work has been modified.
200.16 + * This source code may be translated into executable form and incorporated
200.17 + * into proprietary software; there is no requirement for such software to
200.18 + * contain a copyright notice related to this source.
200.19 + *
200.20 + * $Id: dict.h,v 1.22.2.6 2000/11/13 01:36:44 kaz Exp $
200.21 + * $Name: kazlib_1_20 $
200.22 + */
200.23 +
200.24 +#ifndef DICT_H
200.25 +#define DICT_H
200.26 +
200.27 +#include <limits.h>
200.28 +#ifdef KAZLIB_SIDEEFFECT_DEBUG
200.29 +#include "sfx.h"
200.30 +#endif
200.31 +
200.32 +/*
200.33 + * Blurb for inclusion into C++ translation units
200.34 + */
200.35 +
200.36 +#ifdef __cplusplus
200.37 +extern "C" {
200.38 +#endif
200.39 +
200.40 +typedef unsigned long dictcount_t;
200.41 +#define DICTCOUNT_T_MAX ULONG_MAX
200.42 +
200.43 +/*
200.44 + * The dictionary is implemented as a red-black tree
200.45 + */
200.46 +
200.47 +typedef enum { dnode_red, dnode_black } dnode_color_t;
200.48 +
200.49 +typedef struct dnode_t {
200.50 +#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
200.51 + struct dnode_t *dict_left;
200.52 + struct dnode_t *dict_right;
200.53 + struct dnode_t *dict_parent;
200.54 + dnode_color_t dict_color;
200.55 + const void *dict_key;
200.56 + void *dict_data;
200.57 +#else
200.58 + int dict_dummy;
200.59 +#endif
200.60 +} dnode_t;
200.61 +
200.62 +typedef int (*dict_comp_t)(const void *, const void *);
200.63 +typedef dnode_t *(*dnode_alloc_t)(void *);
200.64 +typedef void (*dnode_free_t)(dnode_t *, void *);
200.65 +
200.66 +typedef struct dict_t {
200.67 +#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
200.68 + dnode_t dict_nilnode;
200.69 + dictcount_t dict_nodecount;
200.70 + dictcount_t dict_maxcount;
200.71 + dict_comp_t dict_compare;
200.72 + dnode_alloc_t dict_allocnode;
200.73 + dnode_free_t dict_freenode;
200.74 + void *dict_context;
200.75 + int dict_dupes;
200.76 +#else
200.77 + int dict_dummmy;
200.78 +#endif
200.79 +} dict_t;
200.80 +
200.81 +typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
200.82 +
200.83 +typedef struct dict_load_t {
200.84 +#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
200.85 + dict_t *dict_dictptr;
200.86 + dnode_t dict_nilnode;
200.87 +#else
200.88 + int dict_dummmy;
200.89 +#endif
200.90 +} dict_load_t;
200.91 +
200.92 +extern dict_t *dict_create(dictcount_t, dict_comp_t);
200.93 +extern void dict_set_allocator(dict_t *, dnode_alloc_t, dnode_free_t, void *);
200.94 +extern void dict_destroy(dict_t *);
200.95 +extern void dict_free_nodes(dict_t *);
200.96 +extern void dict_free(dict_t *);
200.97 +extern dict_t *dict_init(dict_t *, dictcount_t, dict_comp_t);
200.98 +extern void dict_init_like(dict_t *, const dict_t *);
200.99 +extern int dict_verify(dict_t *);
200.100 +extern int dict_similar(const dict_t *, const dict_t *);
200.101 +extern dnode_t *dict_lookup(dict_t *, const void *);
200.102 +extern dnode_t *dict_lower_bound(dict_t *, const void *);
200.103 +extern dnode_t *dict_upper_bound(dict_t *, const void *);
200.104 +extern void dict_insert(dict_t *, dnode_t *, const void *);
200.105 +extern dnode_t *dict_delete(dict_t *, dnode_t *);
200.106 +extern int dict_alloc_insert(dict_t *, const void *, void *);
200.107 +extern void dict_delete_free(dict_t *, dnode_t *);
200.108 +extern dnode_t *dict_first(dict_t *);
200.109 +extern dnode_t *dict_last(dict_t *);
200.110 +extern dnode_t *dict_next(dict_t *, dnode_t *);
200.111 +extern dnode_t *dict_prev(dict_t *, dnode_t *);
200.112 +extern dictcount_t dict_count(dict_t *);
200.113 +extern int dict_isempty(dict_t *);
200.114 +extern int dict_isfull(dict_t *);
200.115 +extern int dict_contains(dict_t *, dnode_t *);
200.116 +extern void dict_allow_dupes(dict_t *);
200.117 +extern int dnode_is_in_a_dict(dnode_t *);
200.118 +extern dnode_t *dnode_create(void *);
200.119 +extern dnode_t *dnode_init(dnode_t *, void *);
200.120 +extern void dnode_destroy(dnode_t *);
200.121 +extern void *dnode_get(dnode_t *);
200.122 +extern const void *dnode_getkey(dnode_t *);
200.123 +extern void dnode_put(dnode_t *, void *);
200.124 +extern void dict_process(dict_t *, void *, dnode_process_t);
200.125 +extern void dict_load_begin(dict_load_t *, dict_t *);
200.126 +extern void dict_load_next(dict_load_t *, dnode_t *, const void *);
200.127 +extern void dict_load_end(dict_load_t *);
200.128 +extern void dict_merge(dict_t *, dict_t *);
200.129 +
200.130 +#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
200.131 +#ifdef KAZLIB_SIDEEFFECT_DEBUG
200.132 +#define dict_isfull(D) (SFX_CHECK(D)->dict_nodecount == (D)->dict_maxcount)
200.133 +#else
200.134 +#define dict_isfull(D) ((D)->dict_nodecount == (D)->dict_maxcount)
200.135 +#endif
200.136 +#define dict_count(D) ((D)->dict_nodecount)
200.137 +#define dict_isempty(D) ((D)->dict_nodecount == 0)
200.138 +#define dnode_get(N) ((N)->dict_data)
200.139 +#define dnode_getkey(N) ((N)->dict_key)
200.140 +#define dnode_put(N, X) ((N)->dict_data = (X))
200.141 +#endif
200.142 +
200.143 +#ifdef __cplusplus
200.144 +}
200.145 +#endif
200.146 +
200.147 +#endif
201.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
201.2 +++ b/libext2fs/lib/libsupport/dqblk_v2.h Wed Aug 25 01:28:08 2021 +0200
201.3 @@ -0,0 +1,31 @@
201.4 +/*
201.5 + * Header file for disk format of new quotafile format
201.6 + *
201.7 + * Jan Kara <jack@suse.cz> - sponsored by SuSE CR
201.8 + */
201.9 +
201.10 +#ifndef __QUOTA_DQBLK_V2_H__
201.11 +#define __QUOTA_DQBLK_V2_H__
201.12 +
201.13 +#include "quotaio_tree.h"
201.14 +
201.15 +/* Structure for format specific information */
201.16 +struct v2_mem_dqinfo {
201.17 + struct qtree_mem_dqinfo dqi_qtree;
201.18 + unsigned int dqi_flags; /* Flags set in quotafile */
201.19 + unsigned int dqi_used_entries; /* Number of entries in file -
201.20 + updated by scan_dquots */
201.21 + unsigned int dqi_data_blocks; /* Number of data blocks in file -
201.22 + updated by scan_dquots */
201.23 +};
201.24 +
201.25 +struct v2_mem_dqblk {
201.26 + long long dqb_off; /* Offset of dquot in file */
201.27 +};
201.28 +
201.29 +struct quotafile_ops; /* Will be defined later in quotaio.h */
201.30 +
201.31 +/* Operations above this format */
201.32 +extern struct quotafile_ops quotafile_ops_2;
201.33 +
201.34 +#endif /* __QUOTA_DQBLK_V2_H__ */
202.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
202.2 +++ b/libext2fs/lib/libsupport/mkquota.c Wed Aug 25 01:28:08 2021 +0200
202.3 @@ -0,0 +1,727 @@
202.4 +/*
202.5 + * mkquota.c --- create quota files for a filesystem
202.6 + *
202.7 + * Aditya Kali <adityakali@google.com>
202.8 + */
202.9 +#include "config.h"
202.10 +#include <sys/types.h>
202.11 +#include <sys/stat.h>
202.12 +#include <unistd.h>
202.13 +#include <errno.h>
202.14 +#include <string.h>
202.15 +#include <fcntl.h>
202.16 +
202.17 +#include "ext2fs/ext2_fs.h"
202.18 +#include "ext2fs/ext2fs.h"
202.19 +#include "e2p/e2p.h"
202.20 +
202.21 +#include "quotaio.h"
202.22 +#include "quotaio_v2.h"
202.23 +#include "quotaio_tree.h"
202.24 +#include "common.h"
202.25 +#include "dict.h"
202.26 +
202.27 +/* Needed for architectures where sizeof(int) != sizeof(void *) */
202.28 +#define UINT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
202.29 +#define VOIDPTR_TO_UINT(ptr) ((unsigned int)(intptr_t)(ptr))
202.30 +
202.31 +#if DEBUG_QUOTA
202.32 +static void print_inode(struct ext2_inode *inode)
202.33 +{
202.34 + if (!inode)
202.35 + return;
202.36 +
202.37 + fprintf(stderr, " i_mode = %d\n", inode->i_mode);
202.38 + fprintf(stderr, " i_uid = %d\n", inode->i_uid);
202.39 + fprintf(stderr, " i_size = %d\n", inode->i_size);
202.40 + fprintf(stderr, " i_atime = %d\n", inode->i_atime);
202.41 + fprintf(stderr, " i_ctime = %d\n", inode->i_ctime);
202.42 + fprintf(stderr, " i_mtime = %d\n", inode->i_mtime);
202.43 + fprintf(stderr, " i_dtime = %d\n", inode->i_dtime);
202.44 + fprintf(stderr, " i_gid = %d\n", inode->i_gid);
202.45 + fprintf(stderr, " i_links_count = %d\n", inode->i_links_count);
202.46 + fprintf(stderr, " i_blocks = %d\n", inode->i_blocks);
202.47 + fprintf(stderr, " i_flags = %d\n", inode->i_flags);
202.48 +
202.49 + return;
202.50 +}
202.51 +
202.52 +static void print_dquot(const char *desc, struct dquot *dq)
202.53 +{
202.54 + if (desc)
202.55 + fprintf(stderr, "%s: ", desc);
202.56 + fprintf(stderr, "%u %lld:%lld:%lld %lld:%lld:%lld\n",
202.57 + dq->dq_id, (long long) dq->dq_dqb.dqb_curspace,
202.58 + (long long) dq->dq_dqb.dqb_bsoftlimit,
202.59 + (long long) dq->dq_dqb.dqb_bhardlimit,
202.60 + (long long) dq->dq_dqb.dqb_curinodes,
202.61 + (long long) dq->dq_dqb.dqb_isoftlimit,
202.62 + (long long) dq->dq_dqb.dqb_ihardlimit);
202.63 +}
202.64 +#else
202.65 +static void print_dquot(const char *desc EXT2FS_ATTR((unused)),
202.66 + struct dquot *dq EXT2FS_ATTR((unused)))
202.67 +{
202.68 +}
202.69 +#endif
202.70 +
202.71 +/*
202.72 + * Returns 0 if not able to find the quota file, otherwise returns its
202.73 + * inode number.
202.74 + */
202.75 +int quota_file_exists(ext2_filsys fs, enum quota_type qtype)
202.76 +{
202.77 + char qf_name[256];
202.78 + errcode_t ret;
202.79 + ext2_ino_t ino;
202.80 +
202.81 + if (qtype >= MAXQUOTAS)
202.82 + return -EINVAL;
202.83 +
202.84 + quota_get_qf_name(qtype, QFMT_VFS_V1, qf_name);
202.85 +
202.86 + ret = ext2fs_lookup(fs, EXT2_ROOT_INO, qf_name, strlen(qf_name), 0,
202.87 + &ino);
202.88 + if (ret)
202.89 + return 0;
202.90 +
202.91 + return ino;
202.92 +}
202.93 +
202.94 +/*
202.95 + * Set the value for reserved quota inode number field in superblock.
202.96 + */
202.97 +void quota_set_sb_inum(ext2_filsys fs, ext2_ino_t ino, enum quota_type qtype)
202.98 +{
202.99 + ext2_ino_t *inump;
202.100 +
202.101 + inump = quota_sb_inump(fs->super, qtype);
202.102 +
202.103 + log_debug("setting quota ino in superblock: ino=%u, type=%d", ino,
202.104 + qtype);
202.105 + *inump = ino;
202.106 + ext2fs_mark_super_dirty(fs);
202.107 +}
202.108 +
202.109 +errcode_t quota_remove_inode(ext2_filsys fs, enum quota_type qtype)
202.110 +{
202.111 + ext2_ino_t qf_ino;
202.112 + errcode_t retval;
202.113 +
202.114 + retval = ext2fs_read_bitmaps(fs);
202.115 + if (retval) {
202.116 + log_debug("Couldn't read bitmaps: %s", error_message(retval));
202.117 + return retval;
202.118 + }
202.119 +
202.120 + qf_ino = *quota_sb_inump(fs->super, qtype);
202.121 + if (qf_ino == 0)
202.122 + return 0;
202.123 + retval = quota_inode_truncate(fs, qf_ino);
202.124 + if (retval)
202.125 + return retval;
202.126 + if (qf_ino >= EXT2_FIRST_INODE(fs->super)) {
202.127 + struct ext2_inode inode;
202.128 +
202.129 + retval = ext2fs_read_inode(fs, qf_ino, &inode);
202.130 + if (!retval) {
202.131 + memset(&inode, 0, sizeof(struct ext2_inode));
202.132 + ext2fs_write_inode(fs, qf_ino, &inode);
202.133 + }
202.134 + ext2fs_inode_alloc_stats2(fs, qf_ino, -1, 0);
202.135 + ext2fs_mark_ib_dirty(fs);
202.136 +
202.137 + }
202.138 + quota_set_sb_inum(fs, 0, qtype);
202.139 +
202.140 + ext2fs_mark_super_dirty(fs);
202.141 + fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
202.142 + retval = ext2fs_write_bitmaps(fs);
202.143 + if (retval) {
202.144 + log_debug("Couldn't write bitmaps: %s", error_message(retval));
202.145 + return retval;
202.146 + }
202.147 + return 0;
202.148 +}
202.149 +
202.150 +static void write_dquots(dict_t *dict, struct quota_handle *qh)
202.151 +{
202.152 + dnode_t *n;
202.153 + struct dquot *dq;
202.154 +
202.155 + for (n = dict_first(dict); n; n = dict_next(dict, n)) {
202.156 + dq = dnode_get(n);
202.157 + if (dq) {
202.158 + print_dquot("write", dq);
202.159 + dq->dq_h = qh;
202.160 + update_grace_times(dq);
202.161 + qh->qh_ops->commit_dquot(dq);
202.162 + }
202.163 + }
202.164 +}
202.165 +
202.166 +errcode_t quota_write_inode(quota_ctx_t qctx, unsigned int qtype_bits)
202.167 +{
202.168 + int retval = 0;
202.169 + enum quota_type qtype;
202.170 + dict_t *dict;
202.171 + ext2_filsys fs;
202.172 + struct quota_handle *h = NULL;
202.173 + int fmt = QFMT_VFS_V1;
202.174 +
202.175 + if (!qctx)
202.176 + return 0;
202.177 +
202.178 + fs = qctx->fs;
202.179 + retval = ext2fs_get_mem(sizeof(struct quota_handle), &h);
202.180 + if (retval) {
202.181 + log_debug("Unable to allocate quota handle: %s",
202.182 + error_message(retval));
202.183 + goto out;
202.184 + }
202.185 +
202.186 + retval = ext2fs_read_bitmaps(fs);
202.187 + if (retval) {
202.188 + log_debug("Couldn't read bitmaps: %s", error_message(retval));
202.189 + goto out;
202.190 + }
202.191 +
202.192 + for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
202.193 + if (((1 << qtype) & qtype_bits) == 0)
202.194 + continue;
202.195 +
202.196 + dict = qctx->quota_dict[qtype];
202.197 + if (!dict)
202.198 + continue;
202.199 +
202.200 + retval = quota_file_create(h, fs, qtype, fmt);
202.201 + if (retval) {
202.202 + log_debug("Cannot initialize io on quotafile: %s",
202.203 + error_message(retval));
202.204 + goto out;
202.205 + }
202.206 +
202.207 + write_dquots(dict, h);
202.208 + retval = quota_file_close(qctx, h);
202.209 + if (retval) {
202.210 + log_debug("Cannot finish IO on new quotafile: %s",
202.211 + strerror(errno));
202.212 + if (h->qh_qf.e2_file)
202.213 + ext2fs_file_close(h->qh_qf.e2_file);
202.214 + (void) quota_inode_truncate(fs, h->qh_qf.ino);
202.215 + goto out;
202.216 + }
202.217 +
202.218 + /* Set quota inode numbers in superblock. */
202.219 + quota_set_sb_inum(fs, h->qh_qf.ino, qtype);
202.220 + ext2fs_mark_super_dirty(fs);
202.221 + ext2fs_mark_bb_dirty(fs);
202.222 + fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
202.223 + }
202.224 +
202.225 + retval = ext2fs_write_bitmaps(fs);
202.226 + if (retval) {
202.227 + log_debug("Couldn't write bitmaps: %s", error_message(retval));
202.228 + goto out;
202.229 + }
202.230 +out:
202.231 + if (h)
202.232 + ext2fs_free_mem(&h);
202.233 + return retval;
202.234 +}
202.235 +
202.236 +/******************************************************************/
202.237 +/* Helper functions for computing quota in memory. */
202.238 +/******************************************************************/
202.239 +
202.240 +static int dict_uint_cmp(const void *a, const void *b)
202.241 +{
202.242 + unsigned int c, d;
202.243 +
202.244 + c = VOIDPTR_TO_UINT(a);
202.245 + d = VOIDPTR_TO_UINT(b);
202.246 +
202.247 + if (c == d)
202.248 + return 0;
202.249 + else if (c > d)
202.250 + return 1;
202.251 + else
202.252 + return -1;
202.253 +}
202.254 +
202.255 +static inline int project_quota_valid(quota_ctx_t qctx)
202.256 +{
202.257 + return (EXT2_INODE_SIZE(qctx->fs->super) > EXT2_GOOD_OLD_INODE_SIZE);
202.258 +}
202.259 +
202.260 +static inline qid_t get_qid(struct ext2_inode_large *inode, enum quota_type qtype)
202.261 +{
202.262 + unsigned int inode_size;
202.263 +
202.264 + switch (qtype) {
202.265 + case USRQUOTA:
202.266 + return inode_uid(*inode);
202.267 + case GRPQUOTA:
202.268 + return inode_gid(*inode);
202.269 + case PRJQUOTA:
202.270 + inode_size = EXT2_GOOD_OLD_INODE_SIZE +
202.271 + inode->i_extra_isize;
202.272 + if (inode_includes(inode_size, i_projid))
202.273 + return inode_projid(*inode);
202.274 + return 0;
202.275 + default:
202.276 + return 0;
202.277 + }
202.278 +
202.279 + return 0;
202.280 +}
202.281 +
202.282 +static void quota_dnode_free(dnode_t *node,
202.283 + void *context EXT2FS_ATTR((unused)))
202.284 +{
202.285 + void *ptr = node ? dnode_get(node) : 0;
202.286 +
202.287 + ext2fs_free_mem(&ptr);
202.288 + free(node);
202.289 +}
202.290 +
202.291 +/*
202.292 + * Set up the quota tracking data structures.
202.293 + */
202.294 +errcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs,
202.295 + unsigned int qtype_bits)
202.296 +{
202.297 + errcode_t err;
202.298 + dict_t *dict;
202.299 + quota_ctx_t ctx;
202.300 + enum quota_type qtype;
202.301 +
202.302 + err = ext2fs_get_mem(sizeof(struct quota_ctx), &ctx);
202.303 + if (err) {
202.304 + log_debug("Failed to allocate quota context");
202.305 + return err;
202.306 + }
202.307 +
202.308 + memset(ctx, 0, sizeof(struct quota_ctx));
202.309 + for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
202.310 + ctx->quota_file[qtype] = NULL;
202.311 + if (qtype_bits) {
202.312 + if (((1 << qtype) & qtype_bits) == 0)
202.313 + continue;
202.314 + } else {
202.315 + if (*quota_sb_inump(fs->super, qtype) == 0)
202.316 + continue;
202.317 + }
202.318 + err = ext2fs_get_mem(sizeof(dict_t), &dict);
202.319 + if (err) {
202.320 + log_debug("Failed to allocate dictionary");
202.321 + quota_release_context(&ctx);
202.322 + return err;
202.323 + }
202.324 + ctx->quota_dict[qtype] = dict;
202.325 + dict_init(dict, DICTCOUNT_T_MAX, dict_uint_cmp);
202.326 + dict_set_allocator(dict, NULL, quota_dnode_free, NULL);
202.327 + }
202.328 +
202.329 + ctx->fs = fs;
202.330 + *qctx = ctx;
202.331 + return 0;
202.332 +}
202.333 +
202.334 +void quota_release_context(quota_ctx_t *qctx)
202.335 +{
202.336 + errcode_t err;
202.337 + dict_t *dict;
202.338 + enum quota_type qtype;
202.339 + quota_ctx_t ctx;
202.340 +
202.341 + if (!qctx)
202.342 + return;
202.343 +
202.344 + ctx = *qctx;
202.345 + for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
202.346 + dict = ctx->quota_dict[qtype];
202.347 + ctx->quota_dict[qtype] = 0;
202.348 + if (dict) {
202.349 + dict_free_nodes(dict);
202.350 + free(dict);
202.351 + }
202.352 + if (ctx->quota_file[qtype]) {
202.353 + err = quota_file_close(ctx, ctx->quota_file[qtype]);
202.354 + if (err) {
202.355 + log_err("Cannot close quotafile: %s",
202.356 + strerror(errno));
202.357 + ext2fs_free_mem(&ctx->quota_file[qtype]);
202.358 + }
202.359 + }
202.360 + }
202.361 + *qctx = NULL;
202.362 + free(ctx);
202.363 +}
202.364 +
202.365 +static struct dquot *get_dq(dict_t *dict, __u32 key)
202.366 +{
202.367 + struct dquot *dq;
202.368 + dnode_t *n;
202.369 +
202.370 + n = dict_lookup(dict, UINT_TO_VOIDPTR(key));
202.371 + if (n)
202.372 + dq = dnode_get(n);
202.373 + else {
202.374 + if (ext2fs_get_mem(sizeof(struct dquot), &dq)) {
202.375 + log_err("Unable to allocate dquot");
202.376 + return NULL;
202.377 + }
202.378 + memset(dq, 0, sizeof(struct dquot));
202.379 + dict_alloc_insert(dict, UINT_TO_VOIDPTR(key), dq);
202.380 + dq->dq_id = key;
202.381 + }
202.382 + return dq;
202.383 +}
202.384 +
202.385 +
202.386 +/*
202.387 + * Called to update the blocks used by a particular inode
202.388 + */
202.389 +void quota_data_add(quota_ctx_t qctx, struct ext2_inode_large *inode,
202.390 + ext2_ino_t ino EXT2FS_ATTR((unused)),
202.391 + qsize_t space)
202.392 +{
202.393 + struct dquot *dq;
202.394 + dict_t *dict;
202.395 + enum quota_type qtype;
202.396 +
202.397 + if (!qctx)
202.398 + return;
202.399 +
202.400 + log_debug("ADD_DATA: Inode: %u, UID/GID: %u/%u, space: %ld", ino,
202.401 + inode_uid(*inode),
202.402 + inode_gid(*inode), space);
202.403 + for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
202.404 + if (qtype == PRJQUOTA && !project_quota_valid(qctx))
202.405 + continue;
202.406 + dict = qctx->quota_dict[qtype];
202.407 + if (dict) {
202.408 + dq = get_dq(dict, get_qid(inode, qtype));
202.409 + if (dq)
202.410 + dq->dq_dqb.dqb_curspace += space;
202.411 + }
202.412 + }
202.413 +}
202.414 +
202.415 +/*
202.416 + * Called to remove some blocks used by a particular inode
202.417 + */
202.418 +void quota_data_sub(quota_ctx_t qctx, struct ext2_inode_large *inode,
202.419 + ext2_ino_t ino EXT2FS_ATTR((unused)),
202.420 + qsize_t space)
202.421 +{
202.422 + struct dquot *dq;
202.423 + dict_t *dict;
202.424 + enum quota_type qtype;
202.425 +
202.426 + if (!qctx)
202.427 + return;
202.428 +
202.429 + log_debug("SUB_DATA: Inode: %u, UID/GID: %u/%u, space: %ld", ino,
202.430 + inode_uid(*inode),
202.431 + inode_gid(*inode), space);
202.432 + for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
202.433 + if (qtype == PRJQUOTA && !project_quota_valid(qctx))
202.434 + continue;
202.435 + dict = qctx->quota_dict[qtype];
202.436 + if (dict) {
202.437 + dq = get_dq(dict, get_qid(inode, qtype));
202.438 + dq->dq_dqb.dqb_curspace -= space;
202.439 + }
202.440 + }
202.441 +}
202.442 +
202.443 +/*
202.444 + * Called to count the files used by an inode's user/group
202.445 + */
202.446 +void quota_data_inodes(quota_ctx_t qctx, struct ext2_inode_large *inode,
202.447 + ext2_ino_t ino EXT2FS_ATTR((unused)), int adjust)
202.448 +{
202.449 + struct dquot *dq;
202.450 + dict_t *dict;
202.451 + enum quota_type qtype;
202.452 +
202.453 + if (!qctx)
202.454 + return;
202.455 +
202.456 + log_debug("ADJ_INODE: Inode: %u, UID/GID: %u/%u, adjust: %d", ino,
202.457 + inode_uid(*inode),
202.458 + inode_gid(*inode), adjust);
202.459 + for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
202.460 + if (qtype == PRJQUOTA && !project_quota_valid(qctx))
202.461 + continue;
202.462 + dict = qctx->quota_dict[qtype];
202.463 + if (dict) {
202.464 + dq = get_dq(dict, get_qid(inode, qtype));
202.465 + dq->dq_dqb.dqb_curinodes += adjust;
202.466 + }
202.467 + }
202.468 +}
202.469 +
202.470 +errcode_t quota_compute_usage(quota_ctx_t qctx)
202.471 +{
202.472 + ext2_filsys fs;
202.473 + ext2_ino_t ino;
202.474 + errcode_t ret;
202.475 + struct ext2_inode_large *inode;
202.476 + int inode_size;
202.477 + qsize_t space;
202.478 + ext2_inode_scan scan;
202.479 +
202.480 + if (!qctx)
202.481 + return 0;
202.482 +
202.483 + fs = qctx->fs;
202.484 + ret = ext2fs_open_inode_scan(fs, 0, &scan);
202.485 + if (ret) {
202.486 + log_err("while opening inode scan. ret=%ld", ret);
202.487 + return ret;
202.488 + }
202.489 + inode_size = fs->super->s_inode_size;
202.490 + inode = malloc(inode_size);
202.491 + if (!inode) {
202.492 + ext2fs_close_inode_scan(scan);
202.493 + return ENOMEM;
202.494 + }
202.495 + while (1) {
202.496 + ret = ext2fs_get_next_inode_full(scan, &ino,
202.497 + EXT2_INODE(inode), inode_size);
202.498 + if (ret) {
202.499 + log_err("while getting next inode. ret=%ld", ret);
202.500 + ext2fs_close_inode_scan(scan);
202.501 + free(inode);
202.502 + return ret;
202.503 + }
202.504 + if (ino == 0)
202.505 + break;
202.506 + if (inode->i_links_count &&
202.507 + (ino == EXT2_ROOT_INO ||
202.508 + ino >= EXT2_FIRST_INODE(fs->super))) {
202.509 + space = ext2fs_inode_i_blocks(fs,
202.510 + EXT2_INODE(inode)) << 9;
202.511 + quota_data_add(qctx, inode, ino, space);
202.512 + quota_data_inodes(qctx, inode, ino, +1);
202.513 + }
202.514 + }
202.515 +
202.516 + ext2fs_close_inode_scan(scan);
202.517 + free(inode);
202.518 + return 0;
202.519 +}
202.520 +
202.521 +struct scan_dquots_data {
202.522 + dict_t *quota_dict;
202.523 + int update_limits; /* update limits from disk */
202.524 + int update_usage;
202.525 + int check_consistency;
202.526 + int usage_is_inconsistent;
202.527 +};
202.528 +
202.529 +static int scan_dquots_callback(struct dquot *dquot, void *cb_data)
202.530 +{
202.531 + struct scan_dquots_data *scan_data = cb_data;
202.532 + dict_t *quota_dict = scan_data->quota_dict;
202.533 + struct dquot *dq;
202.534 +
202.535 + dq = get_dq(quota_dict, dquot->dq_id);
202.536 + dq->dq_id = dquot->dq_id;
202.537 + dq->dq_flags |= DQF_SEEN;
202.538 +
202.539 + print_dquot("mem", dq);
202.540 + print_dquot("dsk", dquot);
202.541 +
202.542 + /* Check if there is inconsistency */
202.543 + if (scan_data->check_consistency &&
202.544 + (dq->dq_dqb.dqb_curspace != dquot->dq_dqb.dqb_curspace ||
202.545 + dq->dq_dqb.dqb_curinodes != dquot->dq_dqb.dqb_curinodes)) {
202.546 + scan_data->usage_is_inconsistent = 1;
202.547 + fprintf(stderr, "[QUOTA WARNING] Usage inconsistent for ID %u:"
202.548 + "actual (%lld, %lld) != expected (%lld, %lld)\n",
202.549 + dq->dq_id, (long long) dq->dq_dqb.dqb_curspace,
202.550 + (long long) dq->dq_dqb.dqb_curinodes,
202.551 + (long long) dquot->dq_dqb.dqb_curspace,
202.552 + (long long) dquot->dq_dqb.dqb_curinodes);
202.553 + }
202.554 +
202.555 + if (scan_data->update_limits) {
202.556 + dq->dq_dqb.dqb_ihardlimit = dquot->dq_dqb.dqb_ihardlimit;
202.557 + dq->dq_dqb.dqb_isoftlimit = dquot->dq_dqb.dqb_isoftlimit;
202.558 + dq->dq_dqb.dqb_bhardlimit = dquot->dq_dqb.dqb_bhardlimit;
202.559 + dq->dq_dqb.dqb_bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit;
202.560 + }
202.561 +
202.562 + if (scan_data->update_usage) {
202.563 + dq->dq_dqb.dqb_curspace = dquot->dq_dqb.dqb_curspace;
202.564 + dq->dq_dqb.dqb_curinodes = dquot->dq_dqb.dqb_curinodes;
202.565 + }
202.566 +
202.567 + return 0;
202.568 +}
202.569 +
202.570 +/*
202.571 + * Read all dquots from quota file into memory
202.572 + */
202.573 +static errcode_t quota_read_all_dquots(struct quota_handle *qh,
202.574 + quota_ctx_t qctx,
202.575 + int update_limits EXT2FS_ATTR((unused)))
202.576 +{
202.577 + struct scan_dquots_data scan_data;
202.578 +
202.579 + scan_data.quota_dict = qctx->quota_dict[qh->qh_type];
202.580 + scan_data.check_consistency = 0;
202.581 + scan_data.update_limits = 0;
202.582 + scan_data.update_usage = 1;
202.583 +
202.584 + return qh->qh_ops->scan_dquots(qh, scan_dquots_callback, &scan_data);
202.585 +}
202.586 +
202.587 +/*
202.588 + * Write all memory dquots into quota file
202.589 + */
202.590 +#if 0 /* currently unused, but may be useful in the future? */
202.591 +static errcode_t quota_write_all_dquots(struct quota_handle *qh,
202.592 + quota_ctx_t qctx)
202.593 +{
202.594 + errcode_t err;
202.595 +
202.596 + err = ext2fs_read_bitmaps(qctx->fs);
202.597 + if (err)
202.598 + return err;
202.599 + write_dquots(qctx->quota_dict[qh->qh_type], qh);
202.600 + ext2fs_mark_bb_dirty(qctx->fs);
202.601 + qctx->fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
202.602 + ext2fs_write_bitmaps(qctx->fs);
202.603 + return 0;
202.604 +}
202.605 +#endif
202.606 +
202.607 +/*
202.608 + * Updates the in-memory quota limits from the given quota inode.
202.609 + */
202.610 +errcode_t quota_update_limits(quota_ctx_t qctx, ext2_ino_t qf_ino,
202.611 + enum quota_type qtype)
202.612 +{
202.613 + struct quota_handle *qh;
202.614 + errcode_t err;
202.615 +
202.616 + if (!qctx)
202.617 + return 0;
202.618 +
202.619 + err = ext2fs_get_mem(sizeof(struct quota_handle), &qh);
202.620 + if (err) {
202.621 + log_debug("Unable to allocate quota handle");
202.622 + return err;
202.623 + }
202.624 +
202.625 + err = quota_file_open(qctx, qh, qf_ino, qtype, -1, 0);
202.626 + if (err) {
202.627 + log_debug("Open quota file failed");
202.628 + goto out;
202.629 + }
202.630 +
202.631 + quota_read_all_dquots(qh, qctx, 1);
202.632 +
202.633 + err = quota_file_close(qctx, qh);
202.634 + if (err) {
202.635 + log_debug("Cannot finish IO on new quotafile: %s",
202.636 + strerror(errno));
202.637 + if (qh->qh_qf.e2_file)
202.638 + ext2fs_file_close(qh->qh_qf.e2_file);
202.639 + }
202.640 +out:
202.641 + ext2fs_free_mem(&qh);
202.642 + return err;
202.643 +}
202.644 +
202.645 +/*
202.646 + * Compares the measured quota in qctx->quota_dict with that in the quota inode
202.647 + * on disk and updates the limits in qctx->quota_dict. 'usage_inconsistent' is
202.648 + * set to 1 if the supplied and on-disk quota usage values are not identical.
202.649 + */
202.650 +errcode_t quota_compare_and_update(quota_ctx_t qctx, enum quota_type qtype,
202.651 + int *usage_inconsistent)
202.652 +{
202.653 + struct quota_handle qh;
202.654 + struct scan_dquots_data scan_data;
202.655 + struct dquot *dq;
202.656 + dnode_t *n;
202.657 + dict_t *dict = qctx->quota_dict[qtype];
202.658 + errcode_t err = 0;
202.659 +
202.660 + if (!dict)
202.661 + goto out;
202.662 +
202.663 + err = quota_file_open(qctx, &qh, 0, qtype, -1, 0);
202.664 + if (err) {
202.665 + log_debug("Open quota file failed");
202.666 + goto out;
202.667 + }
202.668 +
202.669 + scan_data.quota_dict = qctx->quota_dict[qtype];
202.670 + scan_data.update_limits = 1;
202.671 + scan_data.update_usage = 0;
202.672 + scan_data.check_consistency = 1;
202.673 + scan_data.usage_is_inconsistent = 0;
202.674 + err = qh.qh_ops->scan_dquots(&qh, scan_dquots_callback, &scan_data);
202.675 + if (err) {
202.676 + log_debug("Error scanning dquots");
202.677 + goto out_close_qh;
202.678 + }
202.679 +
202.680 + for (n = dict_first(dict); n; n = dict_next(dict, n)) {
202.681 + dq = dnode_get(n);
202.682 + if (!dq)
202.683 + continue;
202.684 + if ((dq->dq_flags & DQF_SEEN) == 0) {
202.685 + fprintf(stderr, "[QUOTA WARNING] "
202.686 + "Missing quota entry ID %d\n", dq->dq_id);
202.687 + scan_data.usage_is_inconsistent = 1;
202.688 + }
202.689 + }
202.690 + *usage_inconsistent = scan_data.usage_is_inconsistent;
202.691 +
202.692 +out_close_qh:
202.693 + err = quota_file_close(qctx, &qh);
202.694 + if (err) {
202.695 + log_debug("Cannot close quotafile: %s", error_message(errno));
202.696 + if (qh.qh_qf.e2_file)
202.697 + ext2fs_file_close(qh.qh_qf.e2_file);
202.698 + }
202.699 +out:
202.700 + return err;
202.701 +}
202.702 +
202.703 +int parse_quota_opts(const char *opts, int (*func)(char *))
202.704 +{
202.705 + char *buf, *token, *next, *p;
202.706 + int len;
202.707 + int ret = 0;
202.708 +
202.709 + len = strlen(opts);
202.710 + buf = malloc(len + 1);
202.711 + if (!buf) {
202.712 + fprintf(stderr,
202.713 + "Couldn't allocate memory to parse quota options!\n");
202.714 + return -ENOMEM;
202.715 + }
202.716 + strcpy(buf, opts);
202.717 + for (token = buf; token && *token; token = next) {
202.718 + p = strchr(token, ',');
202.719 + next = 0;
202.720 + if (p) {
202.721 + *p = 0;
202.722 + next = p + 1;
202.723 + }
202.724 + ret = func(token);
202.725 + if (ret)
202.726 + break;
202.727 + }
202.728 + free(buf);
202.729 + return ret;
202.730 +}
203.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
203.2 +++ b/libext2fs/lib/libsupport/nls-enable.h Wed Aug 25 01:28:08 2021 +0200
203.3 @@ -0,0 +1,21 @@
203.4 +#if defined(ENABLE_NLS) && !defined(DEBUGFS)
203.5 +#include <libintl.h>
203.6 +#include <locale.h>
203.7 +#define _(a) (gettext (a))
203.8 +#ifdef gettext_noop
203.9 +#define N_(a) gettext_noop (a)
203.10 +#else
203.11 +#define N_(a) (a)
203.12 +#endif
203.13 +#define P_(singular, plural, n) (ngettext (singular, plural, n))
203.14 +#ifndef NLS_CAT_NAME
203.15 +#define NLS_CAT_NAME "e2fsprogs"
203.16 +#endif
203.17 +#ifndef LOCALEDIR
203.18 +#define LOCALEDIR "/usr/share/locale"
203.19 +#endif
203.20 +#else
203.21 +#define _(a) (a)
203.22 +#define N_(a) a
203.23 +#define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural))
203.24 +#endif
204.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
204.2 +++ b/libext2fs/lib/libsupport/parse_qtype.c Wed Aug 25 01:28:08 2021 +0200
204.3 @@ -0,0 +1,90 @@
204.4 +/*
204.5 + * parse_qtype.c
204.6 + */
204.7 +
204.8 +#include "config.h"
204.9 +#include <sys/types.h>
204.10 +#include <sys/stat.h>
204.11 +#include <unistd.h>
204.12 +#include <errno.h>
204.13 +#include <string.h>
204.14 +#include <fcntl.h>
204.15 +
204.16 +#include "quotaio.h"
204.17 +
204.18 +#define PARSE_DELIM ":,"
204.19 +
204.20 +int parse_quota_types(const char *in_str, unsigned int *qtype_bits,
204.21 + char **err_token)
204.22 +{
204.23 + char *buf, *token, *next, *tmp;
204.24 + unsigned int qtype = *qtype_bits;
204.25 + int len, ret = 0;
204.26 +
204.27 + if (!in_str)
204.28 + return 0;
204.29 +
204.30 + len = strlen(in_str);
204.31 + buf = malloc(len + 1);
204.32 + if (!buf)
204.33 + return ENOMEM;
204.34 + strcpy(buf, in_str);
204.35 +
204.36 + for (token = buf, next = strtok_r(buf, PARSE_DELIM, &tmp);
204.37 + token && *token; token = next) {
204.38 + int not = 0;
204.39 + char *p = token;
204.40 +
204.41 + if (*p == '^') {
204.42 + not = 1;
204.43 + p++;
204.44 + }
204.45 + if (!strcmp(p, "usr") || !strcmp(p, "usrquota")) {
204.46 + if (not)
204.47 + qtype &= ~QUOTA_USR_BIT;
204.48 + else
204.49 + qtype |= QUOTA_USR_BIT;
204.50 + } else if (!strcmp(p, "grp") || !strcmp(p, "grpquota")) {
204.51 + if (not)
204.52 + qtype &= ~QUOTA_GRP_BIT;
204.53 + else
204.54 + qtype |= QUOTA_GRP_BIT;
204.55 + } else if (!strcmp(p, "prj") || !strcmp(p, "prjquota")) {
204.56 + if (not)
204.57 + qtype &= ~QUOTA_PRJ_BIT;
204.58 + else
204.59 + qtype |= QUOTA_PRJ_BIT;
204.60 + } else {
204.61 + if (err_token) {
204.62 + *err_token = malloc(strlen(token) + 1);
204.63 + if (*err_token)
204.64 + strcpy(*err_token, token);
204.65 + }
204.66 + ret = EINVAL;
204.67 + goto errout;
204.68 + }
204.69 +#ifdef DEBUG_PROGRAM
204.70 + printf("word: %s\n", token);
204.71 +#endif
204.72 + next = strtok_r(NULL, PARSE_DELIM, &tmp);
204.73 + }
204.74 + *qtype_bits = qtype;
204.75 +errout:
204.76 + free(buf);
204.77 + return ret;
204.78 +}
204.79 +
204.80 +#ifdef DEBUG_PROGRAM
204.81 +int main(int argc, char **argv)
204.82 +{
204.83 + unsigned int qtype_bits = 0;
204.84 + int ret;
204.85 + char *err_token = 0;
204.86 +
204.87 + ret = parse_quota_types(argv[1], &qtype_bits, &err_token);
204.88 + printf("parse_quota_types returns %d, %d\n", ret, qtype_bits);
204.89 + if (err_token)
204.90 + printf("err_token is %s\n", err_token);
204.91 + return 0;
204.92 +}
204.93 +#endif
205.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
205.2 +++ b/libext2fs/lib/libsupport/plausible.c Wed Aug 25 01:28:08 2021 +0200
205.3 @@ -0,0 +1,291 @@
205.4 +/*
205.5 + * plausible.c --- Figure out if a pathname is ext* or something else.
205.6 + *
205.7 + * Copyright 2014, Oracle, Inc.
205.8 + *
205.9 + * Some parts are:
205.10 + * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
205.11 + *
205.12 + * %Begin-Header%
205.13 + * This file may be redistributed under the terms of the GNU Public
205.14 + * License.
205.15 + * %End-Header%
205.16 + */
205.17 +
205.18 +#ifndef _LARGEFILE_SOURCE
205.19 +#define _LARGEFILE_SOURCE
205.20 +#endif
205.21 +#ifndef _LARGEFILE64_SOURCE
205.22 +#define _LARGEFILE64_SOURCE
205.23 +#endif
205.24 +
205.25 +#include "config.h"
205.26 +#include <fcntl.h>
205.27 +#include <time.h>
205.28 +#include <sys/types.h>
205.29 +#ifdef HAVE_SYS_STAT_H
205.30 +#include <sys/stat.h>
205.31 +#endif
205.32 +#ifdef HAVE_UNISTD_H
205.33 +#include <unistd.h>
205.34 +#endif
205.35 +#ifdef HAVE_MAGIC_H
205.36 +#include <magic.h>
205.37 +#endif
205.38 +#include "plausible.h"
205.39 +#include "ext2fs/ext2fs.h"
205.40 +#include "nls-enable.h"
205.41 +#include "blkid/blkid.h"
205.42 +
205.43 +#ifdef HAVE_MAGIC_H
205.44 +static magic_t (*dl_magic_open)(int);
205.45 +static const char *(*dl_magic_file)(magic_t, const char *);
205.46 +static int (*dl_magic_load)(magic_t, const char *);
205.47 +static void (*dl_magic_close)(magic_t);
205.48 +
205.49 +/*
205.50 + * NO_CHECK functionality was only added in file 4.20.
205.51 + * Older systems like RHEL 5.x still have file 4.17
205.52 + */
205.53 +#ifndef MAGIC_NO_CHECK_COMPRESS
205.54 +#define MAGIC_NO_CHECK_COMPRESS 0x0001000
205.55 +#endif
205.56 +#ifndef MAGIC_NO_CHECK_ELF
205.57 +#define MAGIC_NO_CHECK_ELF 0x0010000
205.58 +#endif
205.59 +
205.60 +#ifdef HAVE_DLOPEN
205.61 +#include <dlfcn.h>
205.62 +
205.63 +static void *magic_handle;
205.64 +
205.65 +static int magic_library_available(void)
205.66 +{
205.67 + if (!magic_handle) {
205.68 + magic_handle = dlopen("libmagic.so.1", RTLD_NOW);
205.69 + if (!magic_handle)
205.70 + return 0;
205.71 +
205.72 + dl_magic_open = (magic_t (*)(int))
205.73 + dlsym(magic_handle, "magic_open");
205.74 + dl_magic_file = (const char *(*)(magic_t, const char *))
205.75 + dlsym(magic_handle, "magic_file");
205.76 + dl_magic_load = (int (*)(magic_t, const char *))
205.77 + dlsym(magic_handle, "magic_load");
205.78 + dl_magic_close = (void (*)(magic_t))
205.79 + dlsym(magic_handle, "magic_close");
205.80 + }
205.81 +
205.82 + if (!dl_magic_open || !dl_magic_file ||
205.83 + !dl_magic_load || !dl_magic_close)
205.84 + return 0;
205.85 + return 1;
205.86 +}
205.87 +#else
205.88 +static int magic_library_available(void)
205.89 +{
205.90 + dl_magic_open = magic_open;
205.91 + dl_magic_file = magic_file;
205.92 + dl_magic_load = magic_load;
205.93 + dl_magic_close = magic_close;
205.94 +
205.95 + return 1;
205.96 +}
205.97 +#endif
205.98 +#endif
205.99 +
205.100 +static void print_ext2_info(const char *device)
205.101 +
205.102 +{
205.103 + struct ext2_super_block *sb;
205.104 + ext2_filsys fs;
205.105 + errcode_t retval;
205.106 + time_t tm;
205.107 + char buf[80];
205.108 +
205.109 + retval = ext2fs_open2(device, 0, EXT2_FLAG_64BITS, 0, 0,
205.110 + unix_io_manager, &fs);
205.111 + if (retval)
205.112 + return;
205.113 + sb = fs->super;
205.114 +
205.115 + if (sb->s_mtime) {
205.116 + tm = sb->s_mtime;
205.117 + if (sb->s_last_mounted[0]) {
205.118 + memset(buf, 0, sizeof(buf));
205.119 + strncpy(buf, sb->s_last_mounted,
205.120 + sizeof(sb->s_last_mounted));
205.121 + printf(_("\tlast mounted on %s on %s"), buf,
205.122 + ctime(&tm));
205.123 + } else
205.124 + printf(_("\tlast mounted on %s"), ctime(&tm));
205.125 + } else if (sb->s_mkfs_time) {
205.126 + tm = sb->s_mkfs_time;
205.127 + printf(_("\tcreated on %s"), ctime(&tm));
205.128 + } else if (sb->s_wtime) {
205.129 + tm = sb->s_wtime;
205.130 + printf(_("\tlast modified on %s"), ctime(&tm));
205.131 + }
205.132 + ext2fs_close_free(&fs);
205.133 +}
205.134 +
205.135 +/*
205.136 + * return 1 if there is no partition table, 0 if a partition table is
205.137 + * detected, and -1 on an error.
205.138 + */
205.139 +#ifdef HAVE_BLKID_PROBE_ENABLE_PARTITIONS
205.140 +static int check_partition_table(const char *device)
205.141 +{
205.142 + blkid_probe pr;
205.143 + const char *value;
205.144 + int ret;
205.145 +
205.146 + pr = blkid_new_probe_from_filename(device);
205.147 + if (!pr)
205.148 + return -1;
205.149 +
205.150 + ret = blkid_probe_enable_partitions(pr, 1);
205.151 + if (ret < 0)
205.152 + goto errout;
205.153 +
205.154 + ret = blkid_probe_enable_superblocks(pr, 0);
205.155 + if (ret < 0)
205.156 + goto errout;
205.157 +
205.158 + ret = blkid_do_fullprobe(pr);
205.159 + if (ret < 0)
205.160 + goto errout;
205.161 +
205.162 + ret = blkid_probe_lookup_value(pr, "PTTYPE", &value, NULL);
205.163 + if (ret == 0)
205.164 + fprintf(stderr, _("Found a %s partition table in %s\n"),
205.165 + value, device);
205.166 + else
205.167 + ret = 1;
205.168 +
205.169 +errout:
205.170 + blkid_free_probe(pr);
205.171 + return ret;
205.172 +}
205.173 +#else
205.174 +static int check_partition_table(const char *device EXT2FS_ATTR((unused)))
205.175 +{
205.176 + return -1;
205.177 +}
205.178 +#endif
205.179 +
205.180 +/*
205.181 + * return 1 if the device looks plausible, creating the file if necessary
205.182 + */
205.183 +int check_plausibility(const char *device, int flags, int *ret_is_dev)
205.184 +{
205.185 + int fd, ret, is_dev = 0;
205.186 + ext2fs_struct_stat s;
205.187 + int fl = O_RDONLY;
205.188 + blkid_cache cache = NULL;
205.189 + char *fs_type = NULL;
205.190 + char *fs_label = NULL;
205.191 +
205.192 + fd = ext2fs_open_file(device, fl, 0666);
205.193 + if ((fd < 0) && (errno == ENOENT) && (flags & NO_SIZE)) {
205.194 + fprintf(stderr, _("The file %s does not exist and no "
205.195 + "size was specified.\n"), device);
205.196 + exit(1);
205.197 + }
205.198 + if ((fd < 0) && (errno == ENOENT) && (flags & CREATE_FILE)) {
205.199 + fl |= O_CREAT;
205.200 + fd = ext2fs_open_file(device, fl, 0666);
205.201 + if (fd >= 0 && (flags & VERBOSE_CREATE))
205.202 + printf(_("Creating regular file %s\n"), device);
205.203 + }
205.204 + if (fd < 0) {
205.205 + fprintf(stderr, _("Could not open %s: %s\n"),
205.206 + device, error_message(errno));
205.207 + if (errno == ENOENT)
205.208 + fputs(_("\nThe device apparently does not exist; "
205.209 + "did you specify it correctly?\n"), stderr);
205.210 + exit(1);
205.211 + }
205.212 +
205.213 + if (ext2fs_fstat(fd, &s) < 0) {
205.214 + perror("stat");
205.215 + exit(1);
205.216 + }
205.217 + close(fd);
205.218 +
205.219 + if (S_ISBLK(s.st_mode))
205.220 + is_dev = 1;
205.221 +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
205.222 + /* On FreeBSD, all disk devices are character specials */
205.223 + if (S_ISCHR(s.st_mode))
205.224 + is_dev = 1;
205.225 +#endif
205.226 + if (ret_is_dev)
205.227 + *ret_is_dev = is_dev;
205.228 +
205.229 + if ((flags & CHECK_BLOCK_DEV) && !is_dev) {
205.230 + printf(_("%s is not a block special device.\n"), device);
205.231 + return 0;
205.232 + }
205.233 +
205.234 + /*
205.235 + * Note: we use the older-style blkid API's here because we
205.236 + * want as much functionality to be available when using the
205.237 + * internal blkid library, when e2fsprogs is compiled for
205.238 + * non-Linux systems that will probably not have the libraries
205.239 + * from util-linux available. We only use the newer
205.240 + * blkid-probe interfaces to access functionality not
205.241 + * available in the original blkid library.
205.242 + */
205.243 + if ((flags & CHECK_FS_EXIST) && blkid_get_cache(&cache, NULL) >= 0) {
205.244 + fs_type = blkid_get_tag_value(cache, "TYPE", device);
205.245 + if (fs_type)
205.246 + fs_label = blkid_get_tag_value(cache, "LABEL", device);
205.247 + blkid_put_cache(cache);
205.248 + }
205.249 +
205.250 + if (fs_type) {
205.251 + if (fs_label)
205.252 + printf(_("%s contains a %s file system labelled '%s'\n"),
205.253 + device, fs_type, fs_label);
205.254 + else
205.255 + printf(_("%s contains a %s file system\n"), device,
205.256 + fs_type);
205.257 + if (strncmp(fs_type, "ext", 3) == 0)
205.258 + print_ext2_info(device);
205.259 + free(fs_type);
205.260 + free(fs_label);
205.261 + return 0;
205.262 + }
205.263 +
205.264 +#ifdef HAVE_MAGIC_H
205.265 + if ((flags & CHECK_FS_EXIST) &&
205.266 + !getenv("E2FSPROGS_LIBMAGIC_SUPPRESS") &&
205.267 + magic_library_available()) {
205.268 + const char *msg;
205.269 + magic_t mag;
205.270 + int has_magic = 0;
205.271 +
205.272 + mag = dl_magic_open(MAGIC_RAW | MAGIC_SYMLINK | MAGIC_DEVICES |
205.273 + MAGIC_ERROR | MAGIC_NO_CHECK_ELF |
205.274 + MAGIC_NO_CHECK_COMPRESS);
205.275 + dl_magic_load(mag, NULL);
205.276 +
205.277 + msg = dl_magic_file(mag, device);
205.278 + if (msg && strcmp(msg, "data") && strcmp(msg, "empty")) {
205.279 + printf(_("%s contains `%s' data\n"), device, msg);
205.280 + has_magic = 1;
205.281 + }
205.282 +
205.283 + dl_magic_close(mag);
205.284 + return !has_magic;
205.285 + }
205.286 +#endif
205.287 +
205.288 + ret = check_partition_table(device);
205.289 + if (ret >= 0)
205.290 + return ret;
205.291 +
205.292 + return 1;
205.293 +}
205.294 +
206.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
206.2 +++ b/libext2fs/lib/libsupport/plausible.h Wed Aug 25 01:28:08 2021 +0200
206.3 @@ -0,0 +1,29 @@
206.4 +/*
206.5 + * plausible.h --- header file defining prototypes for helper functions
206.6 + * used by tune2fs and mke2fs
206.7 + *
206.8 + * Copyright 2014 by Oracle, Inc.
206.9 + *
206.10 + * %Begin-Header%
206.11 + * This file may be redistributed under the terms of the GNU Public
206.12 + * License.
206.13 + * %End-Header%
206.14 + */
206.15 +
206.16 +#ifndef PLAUSIBLE_H_
206.17 +#define PLAUSIBLE_H_
206.18 +
206.19 +/*
206.20 + * Flags for check_plausibility()
206.21 + */
206.22 +#define CHECK_BLOCK_DEV 0x0001
206.23 +#define CREATE_FILE 0x0002
206.24 +#define CHECK_FS_EXIST 0x0004
206.25 +#define VERBOSE_CREATE 0x0008
206.26 +#define NO_SIZE 0x0010
206.27 +#define QUIET_CHECK 0x0020
206.28 +
206.29 +extern int check_plausibility(const char *device, int flags,
206.30 + int *ret_is_dev);
206.31 +
206.32 +#endif /* PLAUSIBLE_H_ */
207.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
207.2 +++ b/libext2fs/lib/libsupport/prof_err.c Wed Aug 25 01:28:08 2021 +0200
207.3 @@ -0,0 +1,85 @@
207.4 +/*
207.5 + * prof_err.c:
207.6 + * This file is automatically generated; please do not edit it.
207.7 + */
207.8 +
207.9 +#include <stdlib.h>
207.10 +
207.11 +#define N_(a) a
207.12 +
207.13 +static const char * const text[] = {
207.14 + N_("Profile version 0.0"),
207.15 + N_("Bad magic value in profile_node"),
207.16 + N_("Profile section not found"),
207.17 + N_("Profile relation not found"),
207.18 + N_( "Attempt to add a relation to node which is not a section"),
207.19 + N_( "A profile section header has a non-zero value"),
207.20 + N_("Bad linked list in profile structures"),
207.21 + N_("Bad group level in profile structures"),
207.22 + N_( "Bad parent pointer in profile structures"),
207.23 + N_("Bad magic value in profile iterator"),
207.24 + N_("Can't set value on section node"),
207.25 + N_("Invalid argument passed to profile library"),
207.26 + N_("Attempt to modify read-only profile"),
207.27 + N_("Profile section header not at top level"),
207.28 + N_("Syntax error in profile section header"),
207.29 + N_("Syntax error in profile relation"),
207.30 + N_("Extra closing brace in profile"),
207.31 + N_("Missing open brace in profile"),
207.32 + N_("Bad magic value in profile_t"),
207.33 + N_("Bad magic value in profile_section_t"),
207.34 + N_( "Iteration through all top level section not supported"),
207.35 + N_("Invalid profile_section object"),
207.36 + N_("No more sections"),
207.37 + N_("Bad nameset passed to query routine"),
207.38 + N_("No profile file open"),
207.39 + N_("Bad magic value in profile_file_t"),
207.40 + N_("Couldn't open profile file"),
207.41 + N_("Section already exists"),
207.42 + N_("Invalid boolean value"),
207.43 + N_("Invalid integer value"),
207.44 + N_("Bad magic value in profile_file_data_t"),
207.45 + 0
207.46 +};
207.47 +
207.48 +struct error_table {
207.49 + char const * const * msgs;
207.50 + long base;
207.51 + int n_msgs;
207.52 +};
207.53 +struct et_list {
207.54 + struct et_list *next;
207.55 + const struct error_table * table;
207.56 +};
207.57 +extern struct et_list *_et_list;
207.58 +
207.59 +const struct error_table et_prof_error_table = { text, -1429577728L, 31 };
207.60 +
207.61 +static struct et_list link = { 0, 0 };
207.62 +
207.63 +void initialize_prof_error_table_r(struct et_list **list);
207.64 +void initialize_prof_error_table(void);
207.65 +
207.66 +void initialize_prof_error_table(void) {
207.67 + initialize_prof_error_table_r(&_et_list);
207.68 +}
207.69 +
207.70 +/* For Heimdal compatibility */
207.71 +void initialize_prof_error_table_r(struct et_list **list)
207.72 +{
207.73 + struct et_list *et, **end;
207.74 +
207.75 + for (end = list, et = *list; et; end = &et->next, et = et->next)
207.76 + if (et->table->msgs == text)
207.77 + return;
207.78 + et = malloc(sizeof(struct et_list));
207.79 + if (et == 0) {
207.80 + if (!link.table)
207.81 + et = &link;
207.82 + else
207.83 + return;
207.84 + }
207.85 + et->table = &et_prof_error_table;
207.86 + et->next = 0;
207.87 + *end = et;
207.88 +}
208.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
208.2 +++ b/libext2fs/lib/libsupport/prof_err.h Wed Aug 25 01:28:08 2021 +0200
208.3 @@ -0,0 +1,49 @@
208.4 +/*
208.5 + * prof_err.h:
208.6 + * This file is automatically generated; please do not edit it.
208.7 + */
208.8 +
208.9 +#include <et/com_err.h>
208.10 +
208.11 +#define PROF_VERSION (-1429577728L)
208.12 +#define PROF_MAGIC_NODE (-1429577727L)
208.13 +#define PROF_NO_SECTION (-1429577726L)
208.14 +#define PROF_NO_RELATION (-1429577725L)
208.15 +#define PROF_ADD_NOT_SECTION (-1429577724L)
208.16 +#define PROF_SECTION_WITH_VALUE (-1429577723L)
208.17 +#define PROF_BAD_LINK_LIST (-1429577722L)
208.18 +#define PROF_BAD_GROUP_LVL (-1429577721L)
208.19 +#define PROF_BAD_PARENT_PTR (-1429577720L)
208.20 +#define PROF_MAGIC_ITERATOR (-1429577719L)
208.21 +#define PROF_SET_SECTION_VALUE (-1429577718L)
208.22 +#define PROF_EINVAL (-1429577717L)
208.23 +#define PROF_READ_ONLY (-1429577716L)
208.24 +#define PROF_SECTION_NOTOP (-1429577715L)
208.25 +#define PROF_SECTION_SYNTAX (-1429577714L)
208.26 +#define PROF_RELATION_SYNTAX (-1429577713L)
208.27 +#define PROF_EXTRA_CBRACE (-1429577712L)
208.28 +#define PROF_MISSING_OBRACE (-1429577711L)
208.29 +#define PROF_MAGIC_PROFILE (-1429577710L)
208.30 +#define PROF_MAGIC_SECTION (-1429577709L)
208.31 +#define PROF_TOPSECTION_ITER_NOSUPP (-1429577708L)
208.32 +#define PROF_INVALID_SECTION (-1429577707L)
208.33 +#define PROF_END_OF_SECTIONS (-1429577706L)
208.34 +#define PROF_BAD_NAMESET (-1429577705L)
208.35 +#define PROF_NO_PROFILE (-1429577704L)
208.36 +#define PROF_MAGIC_FILE (-1429577703L)
208.37 +#define PROF_FAIL_OPEN (-1429577702L)
208.38 +#define PROF_EXISTS (-1429577701L)
208.39 +#define PROF_BAD_BOOLEAN (-1429577700L)
208.40 +#define PROF_BAD_INTEGER (-1429577699L)
208.41 +#define PROF_MAGIC_FILE_DATA (-1429577698L)
208.42 +extern const struct error_table et_prof_error_table;
208.43 +extern void initialize_prof_error_table(void);
208.44 +
208.45 +/* For compatibility with Heimdal */
208.46 +extern void initialize_prof_error_table_r(struct et_list **list);
208.47 +
208.48 +#define ERROR_TABLE_BASE_prof (-1429577728L)
208.49 +
208.50 +/* for compatibility with older versions... */
208.51 +#define init_prof_err_tbl initialize_prof_error_table
208.52 +#define prof_err_base ERROR_TABLE_BASE_prof
209.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
209.2 +++ b/libext2fs/lib/libsupport/profile.c Wed Aug 25 01:28:08 2021 +0200
209.3 @@ -0,0 +1,1910 @@
209.4 +/*
209.5 + * profile.c -- A simple configuration file parsing "library in a file"
209.6 + *
209.7 + * The profile library was originally written by Theodore Ts'o in 1995
209.8 + * for use in the MIT Kerberos v5 library. It has been
209.9 + * modified/enhanced/bug-fixed over time by other members of the MIT
209.10 + * Kerberos team. This version was originally taken from the Kerberos
209.11 + * v5 distribution, version 1.4.2, and radically simplified for use in
209.12 + * e2fsprogs. (Support for locking for multi-threaded operations,
209.13 + * being able to modify and update the configuration file
209.14 + * programmatically, and Mac/Windows portability have been removed.
209.15 + * It has been folded into a single C source file to make it easier to
209.16 + * fold into an application program.)
209.17 + *
209.18 + * Copyright (C) 2005, 2006 by Theodore Ts'o.
209.19 + *
209.20 + * %Begin-Header%
209.21 + * This file may be redistributed under the terms of the GNU Public
209.22 + * License.
209.23 + * %End-Header%
209.24 + *
209.25 + * Copyright (C) 1985-2005 by the Massachusetts Institute of Technology.
209.26 + *
209.27 + * All rights reserved.
209.28 + *
209.29 + * Export of this software from the United States of America may require
209.30 + * a specific license from the United States Government. It is the
209.31 + * responsibility of any person or organization contemplating export to
209.32 + * obtain such a license before exporting.
209.33 + *
209.34 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
209.35 + * distribute this software and its documentation for any purpose and
209.36 + * without fee is hereby granted, provided that the above copyright
209.37 + * notice appear in all copies and that both that copyright notice and
209.38 + * this permission notice appear in supporting documentation, and that
209.39 + * the name of M.I.T. not be used in advertising or publicity pertaining
209.40 + * to distribution of the software without specific, written prior
209.41 + * permission. Furthermore if you modify this software you must label
209.42 + * your software as modified software and not distribute it in such a
209.43 + * fashion that it might be confused with the original MIT software.
209.44 + * M.I.T. makes no representations about the suitability of this software
209.45 + * for any purpose. It is provided "as is" without express or implied
209.46 + * warranty.
209.47 + *
209.48 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
209.49 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
209.50 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
209.51 + *
209.52 + */
209.53 +
209.54 +#include "config.h"
209.55 +#ifdef HAVE_UNISTD_H
209.56 +#include <unistd.h>
209.57 +#endif
209.58 +#include <stdio.h>
209.59 +#ifdef HAVE_STDLIB_H
209.60 +#include <stdlib.h>
209.61 +#endif
209.62 +#include <time.h>
209.63 +#include <string.h>
209.64 +#include <strings.h>
209.65 +#include <errno.h>
209.66 +#include <ctype.h>
209.67 +#include <limits.h>
209.68 +#include <stddef.h>
209.69 +#include <sys/types.h>
209.70 +#include <sys/stat.h>
209.71 +#include <dirent.h>
209.72 +#ifdef HAVE_PWD_H
209.73 +#include <pwd.h>
209.74 +#endif
209.75 +
209.76 +#include <et/com_err.h>
209.77 +#include "profile.h"
209.78 +#include "prof_err.h"
209.79 +
209.80 +#undef STAT_ONCE_PER_SECOND
209.81 +#undef HAVE_STAT
209.82 +
209.83 +/*
209.84 + * prof_int.h
209.85 + */
209.86 +
209.87 +typedef long prf_magic_t;
209.88 +
209.89 +/*
209.90 + * This is the structure which stores the profile information for a
209.91 + * particular configuration file.
209.92 + */
209.93 +struct _prf_file_t {
209.94 + prf_magic_t magic;
209.95 + char *filespec;
209.96 +#ifdef STAT_ONCE_PER_SECOND
209.97 + time_t last_stat;
209.98 +#endif
209.99 + time_t timestamp; /* time tree was last updated from file */
209.100 + int flags; /* r/w, dirty */
209.101 + int upd_serial; /* incremented when data changes */
209.102 + struct profile_node *root;
209.103 + struct _prf_file_t *next;
209.104 +};
209.105 +
209.106 +typedef struct _prf_file_t *prf_file_t;
209.107 +
209.108 +/*
209.109 + * The profile flags
209.110 + */
209.111 +#define PROFILE_FILE_RW 0x0001
209.112 +#define PROFILE_FILE_DIRTY 0x0002
209.113 +#define PROFILE_FILE_NO_RELOAD 0x0004
209.114 +
209.115 +/*
209.116 + * This structure defines the high-level, user visible profile_t
209.117 + * object, which is used as a handle by users who need to query some
209.118 + * configuration file(s)
209.119 + */
209.120 +struct _profile_t {
209.121 + prf_magic_t magic;
209.122 + prf_file_t first_file;
209.123 +};
209.124 +
209.125 +/*
209.126 + * Used by the profile iterator in prof_get.c
209.127 + */
209.128 +#define PROFILE_ITER_LIST_SECTION 0x0001
209.129 +#define PROFILE_ITER_SECTIONS_ONLY 0x0002
209.130 +#define PROFILE_ITER_RELATIONS_ONLY 0x0004
209.131 +
209.132 +#define PROFILE_ITER_FINAL_SEEN 0x0100
209.133 +
209.134 +/*
209.135 + * Check if a filespec is last in a list (NULL on UNIX, invalid FSSpec on MacOS
209.136 + */
209.137 +
209.138 +#define PROFILE_LAST_FILESPEC(x) (((x) == NULL) || ((x)[0] == '\0'))
209.139 +
209.140 +struct profile_node {
209.141 + errcode_t magic;
209.142 + char *name;
209.143 + char *value;
209.144 + int group_level;
209.145 + unsigned int final:1; /* Indicate don't search next file */
209.146 + unsigned int deleted:1;
209.147 + struct profile_node *first_child;
209.148 + struct profile_node *parent;
209.149 + struct profile_node *next, *prev;
209.150 +};
209.151 +
209.152 +#define CHECK_MAGIC(node) \
209.153 + if ((node)->magic != PROF_MAGIC_NODE) \
209.154 + return PROF_MAGIC_NODE;
209.155 +
209.156 +/* profile parser declarations */
209.157 +struct parse_state {
209.158 + int state;
209.159 + int group_level;
209.160 + int line_num;
209.161 + struct profile_node *root_section;
209.162 + struct profile_node *current_section;
209.163 +};
209.164 +
209.165 +static const char *default_filename = "<default>";
209.166 +
209.167 +static profile_syntax_err_cb_t syntax_err_cb;
209.168 +
209.169 +static errcode_t parse_line(char *line, struct parse_state *state);
209.170 +
209.171 +#ifdef DEBUG_PROGRAM
209.172 +static errcode_t profile_write_tree_file
209.173 + (struct profile_node *root, FILE *dstfile);
209.174 +
209.175 +static errcode_t profile_write_tree_to_buffer
209.176 + (struct profile_node *root, char **buf);
209.177 +#endif
209.178 +
209.179 +
209.180 +static void profile_free_node
209.181 + (struct profile_node *relation);
209.182 +
209.183 +static errcode_t profile_create_node
209.184 + (const char *name, const char *value,
209.185 + struct profile_node **ret_node);
209.186 +
209.187 +#ifdef DEBUG_PROGRAM
209.188 +static errcode_t profile_verify_node
209.189 + (struct profile_node *node);
209.190 +#endif
209.191 +
209.192 +static errcode_t profile_add_node
209.193 + (struct profile_node *section,
209.194 + const char *name, const char *value,
209.195 + struct profile_node **ret_node);
209.196 +
209.197 +static errcode_t profile_find_node
209.198 + (struct profile_node *section,
209.199 + const char *name, const char *value,
209.200 + int section_flag, void **state,
209.201 + struct profile_node **node);
209.202 +
209.203 +static errcode_t profile_node_iterator
209.204 + (void **iter_p, struct profile_node **ret_node,
209.205 + char **ret_name, char **ret_value);
209.206 +
209.207 +static errcode_t profile_open_file
209.208 + (const char * file, prf_file_t *ret_prof);
209.209 +
209.210 +static errcode_t profile_update_file
209.211 + (prf_file_t prf);
209.212 +
209.213 +static void profile_free_file
209.214 + (prf_file_t profile);
209.215 +
209.216 +static errcode_t profile_get_value(profile_t profile, const char *name,
209.217 + const char *subname, const char *subsubname,
209.218 + const char **ret_value);
209.219 +
209.220 +
209.221 +/*
209.222 + * prof_init.c --- routines that manipulate the user-visible profile_t
209.223 + * object.
209.224 + */
209.225 +
209.226 +static int compstr(const void *m1, const void *m2)
209.227 +{
209.228 + const char *s1 = *((const char * const *) m1);
209.229 + const char *s2 = *((const char * const *) m2);
209.230 +
209.231 + return strcmp(s1, s2);
209.232 +}
209.233 +
209.234 +static void free_list(char **list)
209.235 +{
209.236 + char **cp;
209.237 +
209.238 + if (list == 0)
209.239 + return;
209.240 +
209.241 + for (cp = list; *cp; cp++)
209.242 + free(*cp);
209.243 + free(list);
209.244 +}
209.245 +
209.246 +static errcode_t get_dirlist(const char *dirname, char***ret_array)
209.247 +{
209.248 + DIR *dir;
209.249 + struct dirent *de;
209.250 + struct stat st;
209.251 + errcode_t retval;
209.252 + char *fn, *cp;
209.253 + char **array = 0, **new_array;
209.254 + int max = 0, num = 0;
209.255 +
209.256 + dir = opendir(dirname);
209.257 + if (!dir)
209.258 + return errno;
209.259 +
209.260 + while ((de = readdir(dir)) != NULL) {
209.261 + for (cp = de->d_name; *cp; cp++) {
209.262 + if (!isalnum(*cp) &&
209.263 + (*cp != '-') &&
209.264 + (*cp != '_'))
209.265 + break;
209.266 + }
209.267 + if (*cp)
209.268 + continue;
209.269 + fn = malloc(strlen(dirname) + strlen(de->d_name) + 2);
209.270 + if (!fn) {
209.271 + retval = ENOMEM;
209.272 + goto errout;
209.273 + }
209.274 + sprintf(fn, "%s/%s", dirname, de->d_name);
209.275 + if ((stat(fn, &st) < 0) || !S_ISREG(st.st_mode)) {
209.276 + free(fn);
209.277 + continue;
209.278 + }
209.279 + if (num >= max) {
209.280 + max += 10;
209.281 + new_array = realloc(array, sizeof(char *) * (max+1));
209.282 + if (!new_array) {
209.283 + retval = ENOMEM;
209.284 + free(fn);
209.285 + goto errout;
209.286 + }
209.287 + array = new_array;
209.288 + }
209.289 + array[num++] = fn;
209.290 + }
209.291 + if (array) {
209.292 + qsort(array, num, sizeof(char *), compstr);
209.293 + array[num++] = 0;
209.294 + }
209.295 + *ret_array = array;
209.296 + closedir(dir);
209.297 + return 0;
209.298 +errout:
209.299 + if (array)
209.300 + array[num] = 0;
209.301 + closedir(dir);
209.302 + free_list(array);
209.303 + return retval;
209.304 +}
209.305 +
209.306 +errcode_t
209.307 +profile_init(const char * const *files, profile_t *ret_profile)
209.308 +{
209.309 + const char * const *fs;
209.310 + profile_t profile;
209.311 + prf_file_t new_file, *last;
209.312 + errcode_t retval = 0;
209.313 + char **cpp, *cp, **array = 0;
209.314 +
209.315 + profile = malloc(sizeof(struct _profile_t));
209.316 + if (!profile)
209.317 + return ENOMEM;
209.318 + memset(profile, 0, sizeof(struct _profile_t));
209.319 + profile->magic = PROF_MAGIC_PROFILE;
209.320 + last = &profile->first_file;
209.321 +
209.322 + /* if the filenames list is not specified return an empty profile */
209.323 + if ( files ) {
209.324 + for (fs = files; !PROFILE_LAST_FILESPEC(*fs); fs++) {
209.325 + if (array)
209.326 + free_list(array);
209.327 + array = NULL;
209.328 + retval = get_dirlist(*fs, &array);
209.329 + if (retval == 0) {
209.330 + if (!array)
209.331 + continue;
209.332 + for (cpp = array; (cp = *cpp); cpp++) {
209.333 + retval = profile_open_file(cp, &new_file);
209.334 + if (retval == EACCES)
209.335 + continue;
209.336 + if (retval)
209.337 + goto errout;
209.338 + *last = new_file;
209.339 + last = &new_file->next;
209.340 + }
209.341 + } else if ((retval != ENOTDIR) &&
209.342 + strcmp(*fs, default_filename))
209.343 + goto errout;
209.344 +
209.345 + retval = profile_open_file(*fs, &new_file);
209.346 + /* if this file is missing, skip to the next */
209.347 + if (retval == ENOENT || retval == EACCES) {
209.348 + continue;
209.349 + }
209.350 + if (retval)
209.351 + goto errout;
209.352 + *last = new_file;
209.353 + last = &new_file->next;
209.354 + }
209.355 + /*
209.356 + * If all the files were not found, return the appropriate error.
209.357 + */
209.358 + if (!profile->first_file) {
209.359 + retval = ENOENT;
209.360 + goto errout;
209.361 + }
209.362 + }
209.363 +
209.364 + free_list(array);
209.365 + *ret_profile = profile;
209.366 + return 0;
209.367 +errout:
209.368 + free_list(array);
209.369 + profile_release(profile);
209.370 + return retval;
209.371 +}
209.372 +
209.373 +void
209.374 +profile_release(profile_t profile)
209.375 +{
209.376 + prf_file_t p, next;
209.377 +
209.378 + if (!profile || profile->magic != PROF_MAGIC_PROFILE)
209.379 + return;
209.380 +
209.381 + for (p = profile->first_file; p; p = next) {
209.382 + next = p->next;
209.383 + profile_free_file(p);
209.384 + }
209.385 + profile->magic = 0;
209.386 + free(profile);
209.387 +}
209.388 +
209.389 +/*
209.390 + * This function sets the value of the pseudo file "<default>". If
209.391 + * the file "<default>" had previously been passed to profile_init(),
209.392 + * then def_string parameter will be parsed and used as the profile
209.393 + * information for the "<default>" file.
209.394 + */
209.395 +errcode_t profile_set_default(profile_t profile, const char *def_string)
209.396 +{
209.397 + struct parse_state state;
209.398 + prf_file_t prf;
209.399 + errcode_t retval;
209.400 + const char *in;
209.401 + char *line, *p, *end;
209.402 + int line_size, len;
209.403 +
209.404 + if (!def_string || !profile || profile->magic != PROF_MAGIC_PROFILE)
209.405 + return PROF_MAGIC_PROFILE;
209.406 +
209.407 + for (prf = profile->first_file; prf; prf = prf->next) {
209.408 + if (strcmp(prf->filespec, default_filename) == 0)
209.409 + break;
209.410 + }
209.411 + if (!prf)
209.412 + return 0;
209.413 +
209.414 + if (prf->root) {
209.415 + profile_free_node(prf->root);
209.416 + prf->root = 0;
209.417 + }
209.418 +
209.419 + memset(&state, 0, sizeof(struct parse_state));
209.420 + retval = profile_create_node("(root)", 0, &state.root_section);
209.421 + if (retval)
209.422 + return retval;
209.423 +
209.424 + line = 0;
209.425 + line_size = 0;
209.426 + in = def_string;
209.427 + while (*in) {
209.428 + end = strchr(in, '\n');
209.429 + len = end ? (end - in) : (int) strlen(in);
209.430 + if (len >= line_size) {
209.431 + line_size = len+1;
209.432 + p = realloc(line, line_size);
209.433 + if (!p) {
209.434 + retval = ENOMEM;
209.435 + goto errout;
209.436 + }
209.437 + line = p;
209.438 + }
209.439 + memcpy(line, in, len);
209.440 + line[len] = 0;
209.441 + retval = parse_line(line, &state);
209.442 + if (retval) {
209.443 + errout:
209.444 + if (syntax_err_cb)
209.445 + (syntax_err_cb)(prf->filespec, retval,
209.446 + state.line_num);
209.447 + free(line);
209.448 + if (prf->root)
209.449 + profile_free_node(prf->root);
209.450 + return retval;
209.451 + }
209.452 + if (!end)
209.453 + break;
209.454 + in = end+1;
209.455 + }
209.456 + prf->root = state.root_section;
209.457 + free(line);
209.458 +
209.459 + return 0;
209.460 +}
209.461 +
209.462 +/*
209.463 + * prof_file.c ---- routines that manipulate an individual profile file.
209.464 + */
209.465 +
209.466 +errcode_t profile_open_file(const char * filespec,
209.467 + prf_file_t *ret_prof)
209.468 +{
209.469 + prf_file_t prf;
209.470 + errcode_t retval;
209.471 + char *home_env = 0;
209.472 + unsigned int len;
209.473 + char *expanded_filename;
209.474 +
209.475 + prf = malloc(sizeof(struct _prf_file_t));
209.476 + if (!prf)
209.477 + return ENOMEM;
209.478 + memset(prf, 0, sizeof(struct _prf_file_t));
209.479 + prf->magic = PROF_MAGIC_FILE;
209.480 +
209.481 + len = strlen(filespec)+1;
209.482 + if (filespec[0] == '~' && filespec[1] == '/') {
209.483 + home_env = getenv("HOME");
209.484 +#ifdef HAVE_PWD_H
209.485 + if (home_env == NULL) {
209.486 +#ifdef HAVE_GETWUID_R
209.487 + struct passwd *pw, pwx;
209.488 + uid_t uid;
209.489 + char pwbuf[BUFSIZ];
209.490 +
209.491 + uid = getuid();
209.492 + if (!getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw)
209.493 + && pw != NULL && pw->pw_dir[0] != 0)
209.494 + home_env = pw->pw_dir;
209.495 +#else
209.496 + struct passwd *pw;
209.497 +
209.498 + pw = getpwuid(getuid());
209.499 + home_env = pw->pw_dir;
209.500 +#endif
209.501 + }
209.502 +#endif
209.503 + if (home_env)
209.504 + len += strlen(home_env);
209.505 + }
209.506 + expanded_filename = malloc(len);
209.507 + if (expanded_filename == 0) {
209.508 + profile_free_file(prf);
209.509 + return errno;
209.510 + }
209.511 + if (home_env) {
209.512 + strcpy(expanded_filename, home_env);
209.513 + strcat(expanded_filename, filespec+1);
209.514 + } else
209.515 + memcpy(expanded_filename, filespec, len);
209.516 +
209.517 + prf->filespec = expanded_filename;
209.518 +
209.519 + if (strcmp(prf->filespec, default_filename) != 0) {
209.520 + retval = profile_update_file(prf);
209.521 + if (retval) {
209.522 + profile_free_file(prf);
209.523 + return retval;
209.524 + }
209.525 + }
209.526 +
209.527 + *ret_prof = prf;
209.528 + return 0;
209.529 +}
209.530 +
209.531 +errcode_t profile_update_file(prf_file_t prf)
209.532 +{
209.533 + errcode_t retval;
209.534 +#ifdef HAVE_STAT
209.535 + struct stat st;
209.536 +#ifdef STAT_ONCE_PER_SECOND
209.537 + time_t now;
209.538 +#endif
209.539 +#endif
209.540 + FILE *f;
209.541 + char buf[2048];
209.542 + struct parse_state state;
209.543 +
209.544 + if (prf->flags & PROFILE_FILE_NO_RELOAD)
209.545 + return 0;
209.546 +
209.547 +#ifdef HAVE_STAT
209.548 +#ifdef STAT_ONCE_PER_SECOND
209.549 + now = time(0);
209.550 + if (now == prf->last_stat && prf->root != NULL) {
209.551 + return 0;
209.552 + }
209.553 +#endif
209.554 + if (stat(prf->filespec, &st)) {
209.555 + retval = errno;
209.556 + return retval;
209.557 + }
209.558 +#ifdef STAT_ONCE_PER_SECOND
209.559 + prf->last_stat = now;
209.560 +#endif
209.561 + if (st.st_mtime == prf->timestamp && prf->root != NULL) {
209.562 + return 0;
209.563 + }
209.564 + if (prf->root) {
209.565 + profile_free_node(prf->root);
209.566 + prf->root = 0;
209.567 + }
209.568 +#else
209.569 + /*
209.570 + * If we don't have the stat() call, assume that our in-core
209.571 + * memory image is correct. That is, we won't reread the
209.572 + * profile file if it changes.
209.573 + */
209.574 + if (prf->root) {
209.575 + return 0;
209.576 + }
209.577 +#endif
209.578 + memset(&state, 0, sizeof(struct parse_state));
209.579 + retval = profile_create_node("(root)", 0, &state.root_section);
209.580 + if (retval)
209.581 + return retval;
209.582 + errno = 0;
209.583 + f = fopen(prf->filespec, "r");
209.584 + if (f == NULL) {
209.585 + retval = errno;
209.586 + if (retval == 0)
209.587 + retval = ENOENT;
209.588 + return retval;
209.589 + }
209.590 + prf->upd_serial++;
209.591 + while (!feof(f)) {
209.592 + if (fgets(buf, sizeof(buf), f) == NULL)
209.593 + break;
209.594 + retval = parse_line(buf, &state);
209.595 + if (retval) {
209.596 + if (syntax_err_cb)
209.597 + (syntax_err_cb)(prf->filespec, retval,
209.598 + state.line_num);
209.599 + fclose(f);
209.600 + return retval;
209.601 + }
209.602 + }
209.603 + prf->root = state.root_section;
209.604 +
209.605 + fclose(f);
209.606 +
209.607 +#ifdef HAVE_STAT
209.608 + prf->timestamp = st.st_mtime;
209.609 +#endif
209.610 + return 0;
209.611 +}
209.612 +
209.613 +void profile_free_file(prf_file_t prf)
209.614 +{
209.615 + if (prf->root)
209.616 + profile_free_node(prf->root);
209.617 + free(prf->filespec);
209.618 + free(prf);
209.619 +}
209.620 +
209.621 +/* Begin the profile parser */
209.622 +
209.623 +profile_syntax_err_cb_t profile_set_syntax_err_cb(profile_syntax_err_cb_t hook)
209.624 +{
209.625 + profile_syntax_err_cb_t old;
209.626 +
209.627 + old = syntax_err_cb;
209.628 + syntax_err_cb = hook;
209.629 + return(old);
209.630 +}
209.631 +
209.632 +#define STATE_INIT_COMMENT 0
209.633 +#define STATE_STD_LINE 1
209.634 +#define STATE_GET_OBRACE 2
209.635 +
209.636 +static char *skip_over_blanks(char *cp)
209.637 +{
209.638 + while (*cp && isspace((int) (*cp)))
209.639 + cp++;
209.640 + return cp;
209.641 +}
209.642 +
209.643 +static int end_or_comment(char ch)
209.644 +{
209.645 + return (ch == 0 || ch == '#' || ch == ';');
209.646 +}
209.647 +
209.648 +static char *skip_over_nonblanks(char *cp)
209.649 +{
209.650 + while (!end_or_comment(*cp) && !isspace(*cp))
209.651 + cp++;
209.652 + return cp;
209.653 +}
209.654 +
209.655 +static void strip_line(char *line)
209.656 +{
209.657 + char *p = line + strlen(line);
209.658 + while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
209.659 + *p-- = 0;
209.660 +}
209.661 +
209.662 +static void parse_quoted_string(char *str)
209.663 +{
209.664 + char *to, *from;
209.665 +
209.666 + to = from = str;
209.667 +
209.668 + for (to = from = str; *from && *from != '"'; to++, from++) {
209.669 + if (*from == '\\') {
209.670 + from++;
209.671 + switch (*from) {
209.672 + case 'n':
209.673 + *to = '\n';
209.674 + break;
209.675 + case 't':
209.676 + *to = '\t';
209.677 + break;
209.678 + case 'b':
209.679 + *to = '\b';
209.680 + break;
209.681 + default:
209.682 + *to = *from;
209.683 + }
209.684 + continue;
209.685 + }
209.686 + *to = *from;
209.687 + }
209.688 + *to = '\0';
209.689 +}
209.690 +
209.691 +static errcode_t parse_line(char *line, struct parse_state *state)
209.692 +{
209.693 + char *cp, ch, *tag, *value;
209.694 + char *p;
209.695 + errcode_t retval;
209.696 + struct profile_node *node;
209.697 + int do_subsection = 0;
209.698 + void *iter = 0;
209.699 +
209.700 + state->line_num++;
209.701 + if (state->state == STATE_GET_OBRACE) {
209.702 + cp = skip_over_blanks(line);
209.703 + if (*cp != '{')
209.704 + return PROF_MISSING_OBRACE;
209.705 + state->state = STATE_STD_LINE;
209.706 + return 0;
209.707 + }
209.708 + if (state->state == STATE_INIT_COMMENT) {
209.709 + if (line[0] != '[')
209.710 + return 0;
209.711 + state->state = STATE_STD_LINE;
209.712 + }
209.713 +
209.714 + if (*line == 0)
209.715 + return 0;
209.716 + strip_line(line);
209.717 + cp = skip_over_blanks(line);
209.718 + ch = *cp;
209.719 + if (end_or_comment(ch))
209.720 + return 0;
209.721 + if (ch == '[') {
209.722 + if (state->group_level > 0)
209.723 + return PROF_SECTION_NOTOP;
209.724 + cp++;
209.725 + cp = skip_over_blanks(cp);
209.726 + p = strchr(cp, ']');
209.727 + if (p == NULL)
209.728 + return PROF_SECTION_SYNTAX;
209.729 + if (*cp == '"') {
209.730 + cp++;
209.731 + parse_quoted_string(cp);
209.732 + } else {
209.733 + *p-- = '\0';
209.734 + while (isspace(*p) && (p > cp))
209.735 + *p-- = '\0';
209.736 + if (*cp == 0)
209.737 + return PROF_SECTION_SYNTAX;
209.738 + }
209.739 + retval = profile_find_node(state->root_section, cp, 0, 1,
209.740 + &iter, &state->current_section);
209.741 + if (retval == PROF_NO_SECTION) {
209.742 + retval = profile_add_node(state->root_section,
209.743 + cp, 0,
209.744 + &state->current_section);
209.745 + if (retval)
209.746 + return retval;
209.747 + } else if (retval)
209.748 + return retval;
209.749 +
209.750 + /*
209.751 + * Finish off the rest of the line.
209.752 + */
209.753 + cp = p+1;
209.754 + if (*cp == '*') {
209.755 + state->current_section->final = 1;
209.756 + cp++;
209.757 + }
209.758 + /*
209.759 + * Spaces or comments after ']' should not be fatal
209.760 + */
209.761 + cp = skip_over_blanks(cp);
209.762 + if (!end_or_comment(*cp))
209.763 + return PROF_SECTION_SYNTAX;
209.764 + return 0;
209.765 + }
209.766 + if (ch == '}') {
209.767 + if (state->group_level == 0)
209.768 + return PROF_EXTRA_CBRACE;
209.769 + if (*(cp+1) == '*')
209.770 + state->current_section->final = 1;
209.771 + state->current_section = state->current_section->parent;
209.772 + state->group_level--;
209.773 + return 0;
209.774 + }
209.775 + /*
209.776 + * Parse the relations
209.777 + */
209.778 + tag = cp;
209.779 + cp = strchr(cp, '=');
209.780 + if (!cp)
209.781 + return PROF_RELATION_SYNTAX;
209.782 + if (cp == tag)
209.783 + return PROF_RELATION_SYNTAX;
209.784 + *cp = '\0';
209.785 + if (*tag == '"') {
209.786 + tag++;
209.787 + parse_quoted_string(tag);
209.788 + } else {
209.789 + /* Look for whitespace on left-hand side. */
209.790 + p = skip_over_nonblanks(tag);
209.791 + if (*p)
209.792 + *p++ = 0;
209.793 + p = skip_over_blanks(p);
209.794 + /* If we have more non-whitespace, it's an error. */
209.795 + if (*p)
209.796 + return PROF_RELATION_SYNTAX;
209.797 + }
209.798 +
209.799 + cp = skip_over_blanks(cp+1);
209.800 + value = cp;
209.801 + ch = value[0];
209.802 + if (ch == '"') {
209.803 + value++;
209.804 + parse_quoted_string(value);
209.805 + } else if (end_or_comment(ch)) {
209.806 + do_subsection++;
209.807 + state->state = STATE_GET_OBRACE;
209.808 + } else if (value[0] == '{') {
209.809 + cp = skip_over_blanks(value+1);
209.810 + ch = *cp;
209.811 + if (end_or_comment(ch))
209.812 + do_subsection++;
209.813 + else
209.814 + return PROF_RELATION_SYNTAX;
209.815 + } else {
209.816 + cp = skip_over_nonblanks(value);
209.817 + p = skip_over_blanks(cp);
209.818 + ch = *p;
209.819 + *cp = 0;
209.820 + if (!end_or_comment(ch))
209.821 + return PROF_RELATION_SYNTAX;
209.822 + }
209.823 + if (do_subsection) {
209.824 + p = strchr(tag, '*');
209.825 + if (p)
209.826 + *p = '\0';
209.827 + retval = profile_add_node(state->current_section,
209.828 + tag, 0, &state->current_section);
209.829 + if (retval)
209.830 + return retval;
209.831 + if (p)
209.832 + state->current_section->final = 1;
209.833 + state->group_level++;
209.834 + return 0;
209.835 + }
209.836 + p = strchr(tag, '*');
209.837 + if (p)
209.838 + *p = '\0';
209.839 + profile_add_node(state->current_section, tag, value, &node);
209.840 + if (p)
209.841 + node->final = 1;
209.842 + return 0;
209.843 +}
209.844 +
209.845 +#ifdef DEBUG_PROGRAM
209.846 +/*
209.847 + * Return TRUE if the string begins or ends with whitespace
209.848 + */
209.849 +static int need_double_quotes(char *str)
209.850 +{
209.851 + if (!str || !*str)
209.852 + return 0;
209.853 + if (isspace((int) (*str)) ||isspace((int) (*(str + strlen(str) - 1))))
209.854 + return 1;
209.855 + if (strchr(str, '\n') || strchr(str, '\t') || strchr(str, '\b') ||
209.856 + strchr(str, ' ') || strchr(str, '#') || strchr(str, ';'))
209.857 + return 1;
209.858 + return 0;
209.859 +}
209.860 +
209.861 +/*
209.862 + * Output a string with double quotes, doing appropriate backquoting
209.863 + * of characters as necessary.
209.864 + */
209.865 +static void output_quoted_string(char *str, void (*cb)(const char *,void *),
209.866 + void *data)
209.867 +{
209.868 + char ch;
209.869 + char buf[2];
209.870 +
209.871 + cb("\"", data);
209.872 + if (!str) {
209.873 + cb("\"", data);
209.874 + return;
209.875 + }
209.876 + buf[1] = 0;
209.877 + while ((ch = *str++)) {
209.878 + switch (ch) {
209.879 + case '\\':
209.880 + cb("\\\\", data);
209.881 + break;
209.882 + case '\n':
209.883 + cb("\\n", data);
209.884 + break;
209.885 + case '\t':
209.886 + cb("\\t", data);
209.887 + break;
209.888 + case '\b':
209.889 + cb("\\b", data);
209.890 + break;
209.891 + default:
209.892 + /* This would be a lot faster if we scanned
209.893 + forward for the next "interesting"
209.894 + character. */
209.895 + buf[0] = ch;
209.896 + cb(buf, data);
209.897 + break;
209.898 + }
209.899 + }
209.900 + cb("\"", data);
209.901 +}
209.902 +
209.903 +#ifndef EOL
209.904 +#define EOL "\n"
209.905 +#endif
209.906 +
209.907 +/* Errors should be returned, not ignored! */
209.908 +static void dump_profile(struct profile_node *root, int level,
209.909 + void (*cb)(const char *, void *), void *data)
209.910 +{
209.911 + int i;
209.912 + struct profile_node *p;
209.913 + void *iter;
209.914 + long retval;
209.915 +
209.916 + iter = 0;
209.917 + do {
209.918 + retval = profile_find_node(root, 0, 0, 0, &iter, &p);
209.919 + if (retval)
209.920 + break;
209.921 + for (i=0; i < level; i++)
209.922 + cb("\t", data);
209.923 + if (need_double_quotes(p->name))
209.924 + output_quoted_string(p->name, cb, data);
209.925 + else
209.926 + cb(p->name, data);
209.927 + cb(" = ", data);
209.928 + if (need_double_quotes(p->value))
209.929 + output_quoted_string(p->value, cb, data);
209.930 + else
209.931 + cb(p->value, data);
209.932 + cb(EOL, data);
209.933 + } while (iter != 0);
209.934 +
209.935 + iter = 0;
209.936 + do {
209.937 + retval = profile_find_node(root, 0, 0, 1, &iter, &p);
209.938 + if (retval)
209.939 + break;
209.940 + if (level == 0) { /* [xxx] */
209.941 + cb("[", data);
209.942 + if (need_double_quotes(p->name))
209.943 + output_quoted_string(p->name, cb, data);
209.944 + else
209.945 + cb(p->name, data);
209.946 + cb("]", data);
209.947 + cb(p->final ? "*" : "", data);
209.948 + cb(EOL, data);
209.949 + dump_profile(p, level+1, cb, data);
209.950 + cb(EOL, data);
209.951 + } else { /* xxx = { ... } */
209.952 + for (i=0; i < level; i++)
209.953 + cb("\t", data);
209.954 + if (need_double_quotes(p->name))
209.955 + output_quoted_string(p->name, cb, data);
209.956 + else
209.957 + cb(p->name, data);
209.958 + cb(" = {", data);
209.959 + cb(EOL, data);
209.960 + dump_profile(p, level+1, cb, data);
209.961 + for (i=0; i < level; i++)
209.962 + cb("\t", data);
209.963 + cb("}", data);
209.964 + cb(p->final ? "*" : "", data);
209.965 + cb(EOL, data);
209.966 + }
209.967 + } while (iter != 0);
209.968 +}
209.969 +
209.970 +static void dump_profile_to_file_cb(const char *str, void *data)
209.971 +{
209.972 + fputs(str, data);
209.973 +}
209.974 +
209.975 +errcode_t profile_write_tree_file(struct profile_node *root, FILE *dstfile)
209.976 +{
209.977 + dump_profile(root, 0, dump_profile_to_file_cb, dstfile);
209.978 + return 0;
209.979 +}
209.980 +
209.981 +struct prof_buf {
209.982 + char *base;
209.983 + size_t cur, max;
209.984 + int err;
209.985 +};
209.986 +
209.987 +static void add_data_to_buffer(struct prof_buf *b, const void *d, size_t len)
209.988 +{
209.989 + if (b->err)
209.990 + return;
209.991 + if (b->max - b->cur < len) {
209.992 + size_t newsize;
209.993 + char *newptr;
209.994 +
209.995 + newsize = b->max + (b->max >> 1) + len + 1024;
209.996 + newptr = realloc(b->base, newsize);
209.997 + if (newptr == NULL) {
209.998 + b->err = 1;
209.999 + return;
209.1000 + }
209.1001 + b->base = newptr;
209.1002 + b->max = newsize;
209.1003 + }
209.1004 + memcpy(b->base + b->cur, d, len);
209.1005 + b->cur += len; /* ignore overflow */
209.1006 +}
209.1007 +
209.1008 +static void dump_profile_to_buffer_cb(const char *str, void *data)
209.1009 +{
209.1010 + add_data_to_buffer((struct prof_buf *)data, str, strlen(str));
209.1011 +}
209.1012 +
209.1013 +errcode_t profile_write_tree_to_buffer(struct profile_node *root,
209.1014 + char **buf)
209.1015 +{
209.1016 + struct prof_buf prof_buf = { 0, 0, 0, 0 };
209.1017 +
209.1018 + dump_profile(root, 0, dump_profile_to_buffer_cb, &prof_buf);
209.1019 + if (prof_buf.err) {
209.1020 + *buf = NULL;
209.1021 + return ENOMEM;
209.1022 + }
209.1023 + add_data_to_buffer(&prof_buf, "", 1); /* append nul */
209.1024 + if (prof_buf.max - prof_buf.cur > (prof_buf.max >> 3)) {
209.1025 + char *newptr = realloc(prof_buf.base, prof_buf.cur);
209.1026 + if (newptr)
209.1027 + prof_buf.base = newptr;
209.1028 + }
209.1029 + *buf = prof_buf.base;
209.1030 + return 0;
209.1031 +}
209.1032 +#endif
209.1033 +
209.1034 +/*
209.1035 + * prof_tree.c --- these routines maintain the parse tree of the
209.1036 + * config file.
209.1037 + *
209.1038 + * All of the details of how the tree is stored is abstracted away in
209.1039 + * this file; all of the other profile routines build, access, and
209.1040 + * modify the tree via the accessor functions found in this file.
209.1041 + *
209.1042 + * Each node may represent either a relation or a section header.
209.1043 + *
209.1044 + * A section header must have its value field set to 0, and may a one
209.1045 + * or more child nodes, pointed to by first_child.
209.1046 + *
209.1047 + * A relation has as its value a pointer to allocated memory
209.1048 + * containing a string. Its first_child pointer must be null.
209.1049 + *
209.1050 + */
209.1051 +
209.1052 +/*
209.1053 + * Free a node, and any children
209.1054 + */
209.1055 +void profile_free_node(struct profile_node *node)
209.1056 +{
209.1057 + struct profile_node *child, *next;
209.1058 +
209.1059 + if (node->magic != PROF_MAGIC_NODE)
209.1060 + return;
209.1061 +
209.1062 + free(node->name);
209.1063 + free(node->value);
209.1064 +
209.1065 + for (child=node->first_child; child; child = next) {
209.1066 + next = child->next;
209.1067 + profile_free_node(child);
209.1068 + }
209.1069 + node->magic = 0;
209.1070 +
209.1071 + free(node);
209.1072 +}
209.1073 +
209.1074 +#ifndef HAVE_STRDUP
209.1075 +#undef strdup
209.1076 +#define strdup MYstrdup
209.1077 +static char *MYstrdup (const char *s)
209.1078 +{
209.1079 + size_t sz = strlen(s) + 1;
209.1080 + char *p = malloc(sz);
209.1081 + if (p != 0)
209.1082 + memcpy(p, s, sz);
209.1083 + return p;
209.1084 +}
209.1085 +#endif
209.1086 +
209.1087 +/*
209.1088 + * Create a node
209.1089 + */
209.1090 +errcode_t profile_create_node(const char *name, const char *value,
209.1091 + struct profile_node **ret_node)
209.1092 +{
209.1093 + struct profile_node *new;
209.1094 +
209.1095 + new = malloc(sizeof(struct profile_node));
209.1096 + if (!new)
209.1097 + return ENOMEM;
209.1098 + memset(new, 0, sizeof(struct profile_node));
209.1099 + new->name = strdup(name);
209.1100 + if (new->name == 0) {
209.1101 + profile_free_node(new);
209.1102 + return ENOMEM;
209.1103 + }
209.1104 + if (value) {
209.1105 + new->value = strdup(value);
209.1106 + if (new->value == 0) {
209.1107 + profile_free_node(new);
209.1108 + return ENOMEM;
209.1109 + }
209.1110 + }
209.1111 + new->magic = PROF_MAGIC_NODE;
209.1112 +
209.1113 + *ret_node = new;
209.1114 + return 0;
209.1115 +}
209.1116 +
209.1117 +/*
209.1118 + * This function verifies that all of the representation invariants of
209.1119 + * the profile are true. If not, we have a programming bug somewhere,
209.1120 + * probably in this file.
209.1121 + */
209.1122 +#ifdef DEBUG_PROGRAM
209.1123 +errcode_t profile_verify_node(struct profile_node *node)
209.1124 +{
209.1125 + struct profile_node *p, *last;
209.1126 + errcode_t retval;
209.1127 +
209.1128 + CHECK_MAGIC(node);
209.1129 +
209.1130 + if (node->value && node->first_child)
209.1131 + return PROF_SECTION_WITH_VALUE;
209.1132 +
209.1133 + last = 0;
209.1134 + for (p = node->first_child; p; last = p, p = p->next) {
209.1135 + if (p->prev != last)
209.1136 + return PROF_BAD_LINK_LIST;
209.1137 + if (last && (last->next != p))
209.1138 + return PROF_BAD_LINK_LIST;
209.1139 + if (node->group_level+1 != p->group_level)
209.1140 + return PROF_BAD_GROUP_LVL;
209.1141 + if (p->parent != node)
209.1142 + return PROF_BAD_PARENT_PTR;
209.1143 + retval = profile_verify_node(p);
209.1144 + if (retval)
209.1145 + return retval;
209.1146 + }
209.1147 + return 0;
209.1148 +}
209.1149 +#endif
209.1150 +
209.1151 +/*
209.1152 + * Add a node to a particular section
209.1153 + */
209.1154 +errcode_t profile_add_node(struct profile_node *section, const char *name,
209.1155 + const char *value, struct profile_node **ret_node)
209.1156 +{
209.1157 + errcode_t retval;
209.1158 + struct profile_node *p, *last, *new;
209.1159 +
209.1160 + CHECK_MAGIC(section);
209.1161 +
209.1162 + if (section->value)
209.1163 + return PROF_ADD_NOT_SECTION;
209.1164 +
209.1165 + /*
209.1166 + * Find the place to insert the new node. We look for the
209.1167 + * place *after* the last match of the node name, since
209.1168 + * order matters.
209.1169 + */
209.1170 + for (p=section->first_child, last = 0; p; last = p, p = p->next) {
209.1171 + int cmp;
209.1172 + cmp = strcmp(p->name, name);
209.1173 + if (cmp > 0)
209.1174 + break;
209.1175 + }
209.1176 + retval = profile_create_node(name, value, &new);
209.1177 + if (retval)
209.1178 + return retval;
209.1179 + new->group_level = section->group_level+1;
209.1180 + new->deleted = 0;
209.1181 + new->parent = section;
209.1182 + new->prev = last;
209.1183 + new->next = p;
209.1184 + if (p)
209.1185 + p->prev = new;
209.1186 + if (last)
209.1187 + last->next = new;
209.1188 + else
209.1189 + section->first_child = new;
209.1190 + if (ret_node)
209.1191 + *ret_node = new;
209.1192 + return 0;
209.1193 +}
209.1194 +
209.1195 +/*
209.1196 + * Iterate through the section, returning the nodes which match
209.1197 + * the given name. If name is NULL, then interate through all the
209.1198 + * nodes in the section. If section_flag is non-zero, only return the
209.1199 + * section which matches the name; don't return relations. If value
209.1200 + * is non-NULL, then only return relations which match the requested
209.1201 + * value. (The value argument is ignored if section_flag is non-zero.)
209.1202 + *
209.1203 + * The first time this routine is called, the state pointer must be
209.1204 + * null. When this profile_find_node_relation() returns, if the state
209.1205 + * pointer is non-NULL, then this routine should be called again.
209.1206 + * (This won't happen if section_flag is non-zero, obviously.)
209.1207 + *
209.1208 + */
209.1209 +errcode_t profile_find_node(struct profile_node *section, const char *name,
209.1210 + const char *value, int section_flag, void **state,
209.1211 + struct profile_node **node)
209.1212 +{
209.1213 + struct profile_node *p;
209.1214 +
209.1215 + CHECK_MAGIC(section);
209.1216 + p = *state;
209.1217 + if (p) {
209.1218 + CHECK_MAGIC(p);
209.1219 + } else
209.1220 + p = section->first_child;
209.1221 +
209.1222 + for (; p; p = p->next) {
209.1223 + if (name && (strcmp(p->name, name)))
209.1224 + continue;
209.1225 + if (section_flag) {
209.1226 + if (p->value)
209.1227 + continue;
209.1228 + } else {
209.1229 + if (!p->value)
209.1230 + continue;
209.1231 + if (value && (strcmp(p->value, value)))
209.1232 + continue;
209.1233 + }
209.1234 + if (p->deleted)
209.1235 + continue;
209.1236 + /* A match! */
209.1237 + if (node)
209.1238 + *node = p;
209.1239 + break;
209.1240 + }
209.1241 + if (p == 0) {
209.1242 + *state = 0;
209.1243 + return section_flag ? PROF_NO_SECTION : PROF_NO_RELATION;
209.1244 + }
209.1245 + /*
209.1246 + * OK, we've found one match; now let's try to find another
209.1247 + * one. This way, if we return a non-zero state pointer,
209.1248 + * there's guaranteed to be another match that's returned.
209.1249 + */
209.1250 + for (p = p->next; p; p = p->next) {
209.1251 + if (name && (strcmp(p->name, name)))
209.1252 + continue;
209.1253 + if (section_flag) {
209.1254 + if (p->value)
209.1255 + continue;
209.1256 + } else {
209.1257 + if (!p->value)
209.1258 + continue;
209.1259 + if (value && (strcmp(p->value, value)))
209.1260 + continue;
209.1261 + }
209.1262 + /* A match! */
209.1263 + break;
209.1264 + }
209.1265 + *state = p;
209.1266 + return 0;
209.1267 +}
209.1268 +
209.1269 +/*
209.1270 + * This is a general-purpose iterator for returning all nodes that
209.1271 + * match the specified name array.
209.1272 + */
209.1273 +struct profile_iterator {
209.1274 + prf_magic_t magic;
209.1275 + profile_t profile;
209.1276 + int flags;
209.1277 + const char *const *names;
209.1278 + const char *name;
209.1279 + prf_file_t file;
209.1280 + int file_serial;
209.1281 + int done_idx;
209.1282 + struct profile_node *node;
209.1283 + int num;
209.1284 +};
209.1285 +
209.1286 +errcode_t
209.1287 +profile_iterator_create(profile_t profile, const char *const *names, int flags,
209.1288 + void **ret_iter)
209.1289 +{
209.1290 + struct profile_iterator *iter;
209.1291 + int done_idx = 0;
209.1292 +
209.1293 + if (profile == 0)
209.1294 + return PROF_NO_PROFILE;
209.1295 + if (profile->magic != PROF_MAGIC_PROFILE)
209.1296 + return PROF_MAGIC_PROFILE;
209.1297 + if (!names)
209.1298 + return PROF_BAD_NAMESET;
209.1299 + if (!(flags & PROFILE_ITER_LIST_SECTION)) {
209.1300 + if (!names[0])
209.1301 + return PROF_BAD_NAMESET;
209.1302 + done_idx = 1;
209.1303 + }
209.1304 +
209.1305 + if ((iter = malloc(sizeof(struct profile_iterator))) == NULL)
209.1306 + return ENOMEM;
209.1307 +
209.1308 + iter->magic = PROF_MAGIC_ITERATOR;
209.1309 + iter->profile = profile;
209.1310 + iter->names = names;
209.1311 + iter->flags = flags;
209.1312 + iter->file = profile->first_file;
209.1313 + iter->done_idx = done_idx;
209.1314 + iter->node = 0;
209.1315 + iter->num = 0;
209.1316 + *ret_iter = iter;
209.1317 + return 0;
209.1318 +}
209.1319 +
209.1320 +void profile_iterator_free(void **iter_p)
209.1321 +{
209.1322 + struct profile_iterator *iter;
209.1323 +
209.1324 + if (!iter_p)
209.1325 + return;
209.1326 + iter = *iter_p;
209.1327 + if (!iter || iter->magic != PROF_MAGIC_ITERATOR)
209.1328 + return;
209.1329 + free(iter);
209.1330 + *iter_p = 0;
209.1331 +}
209.1332 +
209.1333 +/*
209.1334 + * Note: the returned character strings in ret_name and ret_value
209.1335 + * points to the stored character string in the parse string. Before
209.1336 + * this string value is returned to a calling application
209.1337 + * (profile_node_iterator is not an exported interface), it should be
209.1338 + * strdup()'ed.
209.1339 + */
209.1340 +errcode_t profile_node_iterator(void **iter_p, struct profile_node **ret_node,
209.1341 + char **ret_name, char **ret_value)
209.1342 +{
209.1343 + struct profile_iterator *iter = *iter_p;
209.1344 + struct profile_node *section, *p;
209.1345 + const char *const *cpp;
209.1346 + errcode_t retval;
209.1347 + int skip_num = 0;
209.1348 +
209.1349 + if (!iter || iter->magic != PROF_MAGIC_ITERATOR)
209.1350 + return PROF_MAGIC_ITERATOR;
209.1351 + if (iter->file && iter->file->magic != PROF_MAGIC_FILE)
209.1352 + return PROF_MAGIC_FILE;
209.1353 + /*
209.1354 + * If the file has changed, then the node pointer is invalid,
209.1355 + * so we'll have search the file again looking for it.
209.1356 + */
209.1357 + if (iter->node && (iter->file &&
209.1358 + iter->file->upd_serial != iter->file_serial)) {
209.1359 + iter->flags &= ~PROFILE_ITER_FINAL_SEEN;
209.1360 + skip_num = iter->num;
209.1361 + iter->node = 0;
209.1362 + }
209.1363 + if (iter->node && iter->node->magic != PROF_MAGIC_NODE) {
209.1364 + return PROF_MAGIC_NODE;
209.1365 + }
209.1366 +get_new_file:
209.1367 + if (iter->node == 0) {
209.1368 + if (iter->file == NULL ||
209.1369 + (iter->flags & PROFILE_ITER_FINAL_SEEN)) {
209.1370 + profile_iterator_free(iter_p);
209.1371 + if (ret_node)
209.1372 + *ret_node = 0;
209.1373 + if (ret_name)
209.1374 + *ret_name = 0;
209.1375 + if (ret_value)
209.1376 + *ret_value =0;
209.1377 + return 0;
209.1378 + }
209.1379 + if ((retval = profile_update_file(iter->file))) {
209.1380 + if (retval == ENOENT || retval == EACCES) {
209.1381 + /* XXX memory leak? */
209.1382 + if (iter->file)
209.1383 + iter->file = iter->file->next;
209.1384 + skip_num = 0;
209.1385 + retval = 0;
209.1386 + goto get_new_file;
209.1387 + } else {
209.1388 + profile_iterator_free(iter_p);
209.1389 + return retval;
209.1390 + }
209.1391 + }
209.1392 + iter->file_serial = iter->file->upd_serial;
209.1393 + /*
209.1394 + * Find the section to list if we are a LIST_SECTION,
209.1395 + * or find the containing section if not.
209.1396 + */
209.1397 + section = iter->file->root;
209.1398 + for (cpp = iter->names; cpp[iter->done_idx]; cpp++) {
209.1399 + for (p=section->first_child; p; p = p->next) {
209.1400 + if (!strcmp(p->name, *cpp) && !p->value)
209.1401 + break;
209.1402 + }
209.1403 + if (!p) {
209.1404 + section = 0;
209.1405 + break;
209.1406 + }
209.1407 + section = p;
209.1408 + if (p->final)
209.1409 + iter->flags |= PROFILE_ITER_FINAL_SEEN;
209.1410 + }
209.1411 + if (!section) {
209.1412 + if (iter->file)
209.1413 + iter->file = iter->file->next;
209.1414 + skip_num = 0;
209.1415 + goto get_new_file;
209.1416 + }
209.1417 + iter->name = *cpp;
209.1418 + iter->node = section->first_child;
209.1419 + }
209.1420 + /*
209.1421 + * OK, now we know iter->node is set up correctly. Let's do
209.1422 + * the search.
209.1423 + */
209.1424 + for (p = iter->node; p; p = p->next) {
209.1425 + if (iter->name && strcmp(p->name, iter->name))
209.1426 + continue;
209.1427 + if ((iter->flags & PROFILE_ITER_SECTIONS_ONLY) &&
209.1428 + p->value)
209.1429 + continue;
209.1430 + if ((iter->flags & PROFILE_ITER_RELATIONS_ONLY) &&
209.1431 + !p->value)
209.1432 + continue;
209.1433 + if (skip_num > 0) {
209.1434 + skip_num--;
209.1435 + continue;
209.1436 + }
209.1437 + if (p->deleted)
209.1438 + continue;
209.1439 + break;
209.1440 + }
209.1441 + iter->num++;
209.1442 + if (!p) {
209.1443 + if (iter->file)
209.1444 + iter->file = iter->file->next;
209.1445 + iter->node = 0;
209.1446 + skip_num = 0;
209.1447 + goto get_new_file;
209.1448 + }
209.1449 + if ((iter->node = p->next) == NULL)
209.1450 + if (iter->file)
209.1451 + iter->file = iter->file->next;
209.1452 + if (ret_node)
209.1453 + *ret_node = p;
209.1454 + if (ret_name)
209.1455 + *ret_name = p->name;
209.1456 + if (ret_value)
209.1457 + *ret_value = p->value;
209.1458 + return 0;
209.1459 +}
209.1460 +
209.1461 +
209.1462 +/*
209.1463 + * prof_get.c --- routines that expose the public interfaces for
209.1464 + * querying items from the profile.
209.1465 + *
209.1466 + */
209.1467 +
209.1468 +/*
209.1469 + * This function only gets the first value from the file; it is a
209.1470 + * helper function for profile_get_string, profile_get_integer, etc.
209.1471 + */
209.1472 +errcode_t profile_get_value(profile_t profile, const char *name,
209.1473 + const char *subname, const char *subsubname,
209.1474 + const char **ret_value)
209.1475 +{
209.1476 + errcode_t retval;
209.1477 + void *state;
209.1478 + char *value;
209.1479 + const char *names[4];
209.1480 +
209.1481 + names[0] = name;
209.1482 + names[1] = subname;
209.1483 + names[2] = subsubname;
209.1484 + names[3] = 0;
209.1485 +
209.1486 + if ((retval = profile_iterator_create(profile, names,
209.1487 + PROFILE_ITER_RELATIONS_ONLY,
209.1488 + &state)))
209.1489 + return retval;
209.1490 +
209.1491 + if ((retval = profile_node_iterator(&state, 0, 0, &value)))
209.1492 + goto cleanup;
209.1493 +
209.1494 + if (value)
209.1495 + *ret_value = value;
209.1496 + else
209.1497 + retval = PROF_NO_RELATION;
209.1498 +
209.1499 +cleanup:
209.1500 + profile_iterator_free(&state);
209.1501 + return retval;
209.1502 +}
209.1503 +
209.1504 +errcode_t
209.1505 +profile_get_string(profile_t profile, const char *name, const char *subname,
209.1506 + const char *subsubname, const char *def_val,
209.1507 + char **ret_string)
209.1508 +{
209.1509 + const char *value;
209.1510 + errcode_t retval;
209.1511 +
209.1512 + if (profile) {
209.1513 + retval = profile_get_value(profile, name, subname,
209.1514 + subsubname, &value);
209.1515 + if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION)
209.1516 + value = def_val;
209.1517 + else if (retval)
209.1518 + return retval;
209.1519 + } else
209.1520 + value = def_val;
209.1521 +
209.1522 + if (value) {
209.1523 + *ret_string = malloc(strlen(value)+1);
209.1524 + if (*ret_string == 0)
209.1525 + return ENOMEM;
209.1526 + strcpy(*ret_string, value);
209.1527 + } else
209.1528 + *ret_string = 0;
209.1529 + return 0;
209.1530 +}
209.1531 +
209.1532 +errcode_t
209.1533 +profile_get_integer(profile_t profile, const char *name, const char *subname,
209.1534 + const char *subsubname, int def_val, int *ret_int)
209.1535 +{
209.1536 + const char *value;
209.1537 + errcode_t retval;
209.1538 + char *end_value;
209.1539 + long ret_long;
209.1540 +
209.1541 + *ret_int = def_val;
209.1542 + if (profile == 0)
209.1543 + return 0;
209.1544 +
209.1545 + retval = profile_get_value(profile, name, subname, subsubname, &value);
209.1546 + if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) {
209.1547 + *ret_int = def_val;
209.1548 + return 0;
209.1549 + } else if (retval)
209.1550 + return retval;
209.1551 +
209.1552 + if (value[0] == 0)
209.1553 + /* Empty string is no good. */
209.1554 + return PROF_BAD_INTEGER;
209.1555 + errno = 0;
209.1556 + ret_long = strtol(value, &end_value, 0);
209.1557 +
209.1558 + /* Overflow or underflow. */
209.1559 + if ((ret_long == LONG_MIN || ret_long == LONG_MAX) && errno != 0)
209.1560 + return PROF_BAD_INTEGER;
209.1561 + /* Value outside "int" range. */
209.1562 + if ((long) (int) ret_long != ret_long)
209.1563 + return PROF_BAD_INTEGER;
209.1564 + /* Garbage in string. */
209.1565 + if (end_value != value + strlen (value))
209.1566 + return PROF_BAD_INTEGER;
209.1567 +
209.1568 +
209.1569 + *ret_int = ret_long;
209.1570 + return 0;
209.1571 +}
209.1572 +
209.1573 +errcode_t
209.1574 +profile_get_uint(profile_t profile, const char *name, const char *subname,
209.1575 + const char *subsubname, unsigned int def_val,
209.1576 + unsigned int *ret_int)
209.1577 +{
209.1578 + const char *value;
209.1579 + errcode_t retval;
209.1580 + char *end_value;
209.1581 + unsigned long ret_long;
209.1582 +
209.1583 + *ret_int = def_val;
209.1584 + if (profile == 0)
209.1585 + return 0;
209.1586 +
209.1587 + retval = profile_get_value(profile, name, subname, subsubname, &value);
209.1588 + if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) {
209.1589 + *ret_int = def_val;
209.1590 + return 0;
209.1591 + } else if (retval)
209.1592 + return retval;
209.1593 +
209.1594 + if (value[0] == 0)
209.1595 + /* Empty string is no good. */
209.1596 + return PROF_BAD_INTEGER;
209.1597 + errno = 0;
209.1598 + ret_long = strtoul(value, &end_value, 0);
209.1599 +
209.1600 + /* Overflow or underflow. */
209.1601 + if ((ret_long == ULONG_MAX) && errno != 0)
209.1602 + return PROF_BAD_INTEGER;
209.1603 + /* Value outside "int" range. */
209.1604 + if ((unsigned long) (unsigned int) ret_long != ret_long)
209.1605 + return PROF_BAD_INTEGER;
209.1606 + /* Garbage in string. */
209.1607 + if (end_value != value + strlen (value))
209.1608 + return PROF_BAD_INTEGER;
209.1609 +
209.1610 + *ret_int = ret_long;
209.1611 + return 0;
209.1612 +}
209.1613 +
209.1614 +errcode_t
209.1615 +profile_get_double(profile_t profile, const char *name, const char *subname,
209.1616 + const char *subsubname, double def_val, double *ret_double)
209.1617 +{
209.1618 + const char *value;
209.1619 + errcode_t retval;
209.1620 + char *end_value;
209.1621 + double double_val;
209.1622 +
209.1623 + *ret_double = def_val;
209.1624 + if (profile == 0)
209.1625 + return 0;
209.1626 +
209.1627 + retval = profile_get_value(profile, name, subname, subsubname, &value);
209.1628 + if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) {
209.1629 + *ret_double = def_val;
209.1630 + return 0;
209.1631 + } else if (retval)
209.1632 + return retval;
209.1633 +
209.1634 + if (value[0] == 0)
209.1635 + /* Empty string is no good. */
209.1636 + return PROF_BAD_INTEGER;
209.1637 + errno = 0;
209.1638 + double_val = strtod(value, &end_value);
209.1639 +
209.1640 + /* Overflow or underflow. */
209.1641 + if (errno != 0)
209.1642 + return PROF_BAD_INTEGER;
209.1643 + /* Garbage in string. */
209.1644 + if (end_value != value + strlen(value))
209.1645 + return PROF_BAD_INTEGER;
209.1646 +
209.1647 + *ret_double = double_val;
209.1648 + return 0;
209.1649 +}
209.1650 +
209.1651 +static const char *const conf_yes[] = {
209.1652 + "y", "yes", "true", "t", "1", "on",
209.1653 + 0,
209.1654 +};
209.1655 +
209.1656 +static const char *const conf_no[] = {
209.1657 + "n", "no", "false", "nil", "0", "off",
209.1658 + 0,
209.1659 +};
209.1660 +
209.1661 +static errcode_t
209.1662 +profile_parse_boolean(const char *s, int *ret_boolean)
209.1663 +{
209.1664 + const char *const *p;
209.1665 +
209.1666 + if (ret_boolean == NULL)
209.1667 + return PROF_EINVAL;
209.1668 +
209.1669 + for(p=conf_yes; *p; p++) {
209.1670 + if (!strcasecmp(*p,s)) {
209.1671 + *ret_boolean = 1;
209.1672 + return 0;
209.1673 + }
209.1674 + }
209.1675 +
209.1676 + for(p=conf_no; *p; p++) {
209.1677 + if (!strcasecmp(*p,s)) {
209.1678 + *ret_boolean = 0;
209.1679 + return 0;
209.1680 + }
209.1681 + }
209.1682 +
209.1683 + return PROF_BAD_BOOLEAN;
209.1684 +}
209.1685 +
209.1686 +errcode_t
209.1687 +profile_get_boolean(profile_t profile, const char *name, const char *subname,
209.1688 + const char *subsubname, int def_val, int *ret_boolean)
209.1689 +{
209.1690 + const char *value;
209.1691 + errcode_t retval;
209.1692 +
209.1693 + if (profile == 0) {
209.1694 + *ret_boolean = def_val;
209.1695 + return 0;
209.1696 + }
209.1697 +
209.1698 + retval = profile_get_value(profile, name, subname, subsubname, &value);
209.1699 + if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) {
209.1700 + *ret_boolean = def_val;
209.1701 + return 0;
209.1702 + } else if (retval)
209.1703 + return retval;
209.1704 +
209.1705 + return profile_parse_boolean (value, ret_boolean);
209.1706 +}
209.1707 +
209.1708 +errcode_t
209.1709 +profile_iterator(void **iter_p, char **ret_name, char **ret_value)
209.1710 +{
209.1711 + char *name, *value;
209.1712 + errcode_t retval;
209.1713 +
209.1714 + retval = profile_node_iterator(iter_p, 0, &name, &value);
209.1715 + if (retval)
209.1716 + return retval;
209.1717 +
209.1718 + if (ret_name) {
209.1719 + if (name) {
209.1720 + *ret_name = malloc(strlen(name)+1);
209.1721 + if (!*ret_name)
209.1722 + return ENOMEM;
209.1723 + strcpy(*ret_name, name);
209.1724 + } else
209.1725 + *ret_name = 0;
209.1726 + }
209.1727 + if (ret_value) {
209.1728 + if (value) {
209.1729 + *ret_value = malloc(strlen(value)+1);
209.1730 + if (!*ret_value) {
209.1731 + if (ret_name) {
209.1732 + free(*ret_name);
209.1733 + *ret_name = 0;
209.1734 + }
209.1735 + return ENOMEM;
209.1736 + }
209.1737 + strcpy(*ret_value, value);
209.1738 + } else
209.1739 + *ret_value = 0;
209.1740 + }
209.1741 + return 0;
209.1742 +}
209.1743 +
209.1744 +#ifdef DEBUG_PROGRAM
209.1745 +
209.1746 +/*
209.1747 + * test_profile.c --- testing program for the profile routine
209.1748 + */
209.1749 +
209.1750 +#include "argv_parse.h"
209.1751 +#include "profile_helpers.h"
209.1752 +
209.1753 +const char *program_name = "test_profile";
209.1754 +
209.1755 +#define PRINT_VALUE 1
209.1756 +#define PRINT_VALUES 2
209.1757 +
209.1758 +static void do_cmd(profile_t profile, char **argv)
209.1759 +{
209.1760 + errcode_t retval;
209.1761 + const char **names, *value;
209.1762 + char **values, **cpp;
209.1763 + char *cmd;
209.1764 + int print_status;
209.1765 +
209.1766 + cmd = *(argv);
209.1767 + names = (const char **) argv + 1;
209.1768 + print_status = 0;
209.1769 + retval = 0;
209.1770 + if (cmd == 0)
209.1771 + return;
209.1772 + if (!strcmp(cmd, "query")) {
209.1773 + retval = profile_get_values(profile, names, &values);
209.1774 + print_status = PRINT_VALUES;
209.1775 + } else if (!strcmp(cmd, "query1")) {
209.1776 + const char *name = 0;
209.1777 + const char *subname = 0;
209.1778 + const char *subsubname = 0;
209.1779 +
209.1780 + name = names[0];
209.1781 + if (name)
209.1782 + subname = names[1];
209.1783 + if (subname)
209.1784 + subsubname = names[2];
209.1785 + if (subsubname && names[3]) {
209.1786 + fprintf(stderr,
209.1787 + "Only 3 levels are allowed with query1\n");
209.1788 + retval = EINVAL;
209.1789 + } else
209.1790 + retval = profile_get_value(profile, name, subname,
209.1791 + subsubname, &value);
209.1792 + print_status = PRINT_VALUE;
209.1793 + } else if (!strcmp(cmd, "list_sections")) {
209.1794 + retval = profile_get_subsection_names(profile, names,
209.1795 + &values);
209.1796 + print_status = PRINT_VALUES;
209.1797 + } else if (!strcmp(cmd, "list_relations")) {
209.1798 + retval = profile_get_relation_names(profile, names,
209.1799 + &values);
209.1800 + print_status = PRINT_VALUES;
209.1801 + } else if (!strcmp(cmd, "dump")) {
209.1802 + retval = profile_write_tree_file
209.1803 + (profile->first_file->root, stdout);
209.1804 +#if 0
209.1805 + } else if (!strcmp(cmd, "clear")) {
209.1806 + retval = profile_clear_relation(profile, names);
209.1807 + } else if (!strcmp(cmd, "update")) {
209.1808 + retval = profile_update_relation(profile, names+2,
209.1809 + *names, *(names+1));
209.1810 +#endif
209.1811 + } else if (!strcmp(cmd, "verify")) {
209.1812 + retval = profile_verify_node
209.1813 + (profile->first_file->root);
209.1814 +#if 0
209.1815 + } else if (!strcmp(cmd, "rename_section")) {
209.1816 + retval = profile_rename_section(profile, names+1, *names);
209.1817 + } else if (!strcmp(cmd, "add")) {
209.1818 + value = *names;
209.1819 + if (strcmp(value, "NULL") == 0)
209.1820 + value = NULL;
209.1821 + retval = profile_add_relation(profile, names+1, value);
209.1822 + } else if (!strcmp(cmd, "flush")) {
209.1823 + retval = profile_flush(profile);
209.1824 +#endif
209.1825 + } else {
209.1826 + printf("Invalid command.\n");
209.1827 + }
209.1828 + if (retval) {
209.1829 + com_err(cmd, retval, "");
209.1830 + print_status = 0;
209.1831 + }
209.1832 + switch (print_status) {
209.1833 + case PRINT_VALUE:
209.1834 + printf("%s\n", value);
209.1835 + break;
209.1836 + case PRINT_VALUES:
209.1837 + for (cpp = values; *cpp; cpp++)
209.1838 + printf("%s\n", *cpp);
209.1839 + profile_free_list(values);
209.1840 + break;
209.1841 + }
209.1842 +}
209.1843 +
209.1844 +static void do_batchmode(profile_t profile)
209.1845 +{
209.1846 + int argc, ret;
209.1847 + char **argv;
209.1848 + char buf[256];
209.1849 +
209.1850 + while (!feof(stdin)) {
209.1851 + if (fgets(buf, sizeof(buf), stdin) == NULL)
209.1852 + break;
209.1853 + printf(">%s", buf);
209.1854 + ret = argv_parse(buf, &argc, &argv);
209.1855 + if (ret != 0) {
209.1856 + printf("Argv_parse returned %d!\n", ret);
209.1857 + continue;
209.1858 + }
209.1859 + do_cmd(profile, argv);
209.1860 + printf("\n");
209.1861 + argv_free(argv);
209.1862 + }
209.1863 + profile_release(profile);
209.1864 + exit(0);
209.1865 +
209.1866 +}
209.1867 +
209.1868 +void syntax_err_report(const char *filename, long err, int line_num)
209.1869 +{
209.1870 + fprintf(stderr, "Syntax error in %s, line number %d: %s\n",
209.1871 + filename, line_num, error_message(err));
209.1872 + exit(1);
209.1873 +}
209.1874 +
209.1875 +const char *default_str = "[foo]\n\tbar=quux\n\tsub = {\n\t\twin = true\n}\n";
209.1876 +
209.1877 +int main(int argc, char **argv)
209.1878 +{
209.1879 + profile_t profile;
209.1880 + long retval;
209.1881 + char *cmd;
209.1882 +
209.1883 + if (argc < 2) {
209.1884 + fprintf(stderr, "Usage: %s filename [cmd argset]\n", program_name);
209.1885 + exit(1);
209.1886 + }
209.1887 +
209.1888 + initialize_prof_error_table();
209.1889 +
209.1890 + profile_set_syntax_err_cb(syntax_err_report);
209.1891 +
209.1892 + retval = profile_init_path(argv[1], &profile);
209.1893 + if (retval) {
209.1894 + com_err(program_name, retval, "while initializing profile");
209.1895 + exit(1);
209.1896 + }
209.1897 + retval = profile_set_default(profile, default_str);
209.1898 + if (retval) {
209.1899 + com_err(program_name, retval, "while setting default");
209.1900 + exit(1);
209.1901 + }
209.1902 +
209.1903 + cmd = *(argv+2);
209.1904 + if (!cmd || !strcmp(cmd, "batch"))
209.1905 + do_batchmode(profile);
209.1906 + else
209.1907 + do_cmd(profile, argv+2);
209.1908 + profile_release(profile);
209.1909 +
209.1910 + return 0;
209.1911 +}
209.1912 +
209.1913 +#endif
210.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
210.2 +++ b/libext2fs/lib/libsupport/profile.h Wed Aug 25 01:28:08 2021 +0200
210.3 @@ -0,0 +1,107 @@
210.4 +/*
210.5 + * profile.h
210.6 + *
210.7 + * Copyright (C) 2005 by Theodore Ts'o.
210.8 + *
210.9 + * %Begin-Header%
210.10 + * This file may be redistributed under the terms of the GNU Public
210.11 + * License.
210.12 + * %End-Header%
210.13 + *
210.14 + * Copyright (C) 1985-2005 by the Massachusetts Institute of Technology.
210.15 + *
210.16 + * All rights reserved.
210.17 + *
210.18 + * Export of this software from the United States of America may require
210.19 + * a specific license from the United States Government. It is the
210.20 + * responsibility of any person or organization contemplating export to
210.21 + * obtain such a license before exporting.
210.22 + *
210.23 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
210.24 + * distribute this software and its documentation for any purpose and
210.25 + * without fee is hereby granted, provided that the above copyright
210.26 + * notice appear in all copies and that both that copyright notice and
210.27 + * this permission notice appear in supporting documentation, and that
210.28 + * the name of M.I.T. not be used in advertising or publicity pertaining
210.29 + * to distribution of the software without specific, written prior
210.30 + * permission. Furthermore if you modify this software you must label
210.31 + * your software as modified software and not distribute it in such a
210.32 + * fashion that it might be confused with the original MIT software.
210.33 + * M.I.T. makes no representations about the suitability of this software
210.34 + * for any purpose. It is provided "as is" without express or implied
210.35 + * warranty.
210.36 + *
210.37 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
210.38 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
210.39 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
210.40 + */
210.41 +
210.42 +#ifndef _PROFILE_H
210.43 +#define _PROFILE_H
210.44 +
210.45 +typedef struct _profile_t *profile_t;
210.46 +
210.47 +typedef void (*profile_syntax_err_cb_t)(const char *file, long err,
210.48 + int line_num);
210.49 +
210.50 +/*
210.51 + * Used by the profile iterator in prof_get.c
210.52 + */
210.53 +#define PROFILE_ITER_LIST_SECTION 0x0001
210.54 +#define PROFILE_ITER_SECTIONS_ONLY 0x0002
210.55 +#define PROFILE_ITER_RELATIONS_ONLY 0x0004
210.56 +
210.57 +#ifdef __cplusplus
210.58 +extern "C" {
210.59 +#endif /* __cplusplus */
210.60 +
210.61 +long profile_init
210.62 + (const char * const *files, profile_t *ret_profile);
210.63 +
210.64 +void profile_release
210.65 + (profile_t profile);
210.66 +
210.67 +long profile_set_default
210.68 + (profile_t profile, const char *def_string);
210.69 +
210.70 +long profile_get_string
210.71 + (profile_t profile, const char *name, const char *subname,
210.72 + const char *subsubname, const char *def_val,
210.73 + char **ret_string);
210.74 +long profile_get_integer
210.75 + (profile_t profile, const char *name, const char *subname,
210.76 + const char *subsubname, int def_val,
210.77 + int *ret_default);
210.78 +
210.79 +long profile_get_uint
210.80 + (profile_t profile, const char *name, const char *subname,
210.81 + const char *subsubname, unsigned int def_val,
210.82 + unsigned int *ret_int);
210.83 +
210.84 +long profile_get_double
210.85 + (profile_t profile, const char *name, const char *subname,
210.86 + const char *subsubname, double def_val,
210.87 + double *ret_float);
210.88 +
210.89 +long profile_get_boolean
210.90 + (profile_t profile, const char *name, const char *subname,
210.91 + const char *subsubname, int def_val,
210.92 + int *ret_default);
210.93 +
210.94 +long profile_iterator_create
210.95 + (profile_t profile, const char *const *names,
210.96 + int flags, void **ret_iter);
210.97 +
210.98 +void profile_iterator_free
210.99 + (void **iter_p);
210.100 +
210.101 +long profile_iterator
210.102 + (void **iter_p, char **ret_name, char **ret_value);
210.103 +
210.104 +profile_syntax_err_cb_t profile_set_syntax_err_cb(profile_syntax_err_cb_t hook);
210.105 +
210.106 +#ifdef __cplusplus
210.107 +}
210.108 +#endif /* __cplusplus */
210.109 +
210.110 +#endif /* _KRB5_H */
211.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
211.2 +++ b/libext2fs/lib/libsupport/profile_helpers.c Wed Aug 25 01:28:08 2021 +0200
211.3 @@ -0,0 +1,317 @@
211.4 +/*
211.5 + * profile_helpers.c -- Helper functions for the profile library
211.6 + *
211.7 + * These functions are not part of the "core" profile library, and do
211.8 + * not require access to the internal functions and data structures of
211.9 + * the profile library. They are mainly convenience functions for
211.10 + * programs that want to do something unusual such as obtaining the
211.11 + * list of sections or relations, or accessing multiple values from a
211.12 + * relation that is listed more than once. This functionality can all
211.13 + * be done using the profile_iterator abstraction, but it is less
211.14 + * convenient.
211.15 + *
211.16 + * Copyright (C) 2006 by Theodore Ts'o.
211.17 + *
211.18 + * %Begin-Header%
211.19 + * This file may be redistributed under the terms of the GNU Public
211.20 + * License.
211.21 + * %End-Header%
211.22 + */
211.23 +
211.24 +#include "config.h"
211.25 +#include <stdlib.h>
211.26 +#include <string.h>
211.27 +#include <errno.h>
211.28 +
211.29 +#include <et/com_err.h>
211.30 +#include "profile.h"
211.31 +#include "profile_helpers.h"
211.32 +#include "prof_err.h"
211.33 +
211.34 +/*
211.35 + * These functions --- init_list(), end_list(), and add_to_list() are
211.36 + * internal functions used to build up a null-terminated char ** list
211.37 + * of strings to be returned by functions like profile_get_values.
211.38 + *
211.39 + * The profile_string_list structure is used for internal booking
211.40 + * purposes to build up the list, which is returned in *ret_list by
211.41 + * the end_list() function.
211.42 + *
211.43 + * The publicly exported interface for freeing char** list is
211.44 + * profile_free_list().
211.45 + */
211.46 +
211.47 +struct profile_string_list {
211.48 + char **list;
211.49 + int num;
211.50 + int max;
211.51 +};
211.52 +
211.53 +/*
211.54 + * Initialize the string list abstraction.
211.55 + */
211.56 +static errcode_t init_list(struct profile_string_list *list)
211.57 +{
211.58 + list->num = 0;
211.59 + list->max = 10;
211.60 + list->list = malloc(list->max * sizeof(char *));
211.61 + if (list->list == 0)
211.62 + return ENOMEM;
211.63 + list->list[0] = 0;
211.64 + return 0;
211.65 +}
211.66 +
211.67 +/*
211.68 + * Free any memory left over in the string abstraction, returning the
211.69 + * built up list in *ret_list if it is non-null.
211.70 + */
211.71 +static void end_list(struct profile_string_list *list, char ***ret_list)
211.72 +{
211.73 + char **cp;
211.74 +
211.75 + if (list == 0)
211.76 + return;
211.77 +
211.78 + if (ret_list) {
211.79 + *ret_list = list->list;
211.80 + return;
211.81 + } else {
211.82 + for (cp = list->list; *cp; cp++)
211.83 + free(*cp);
211.84 + free(list->list);
211.85 + }
211.86 + list->num = list->max = 0;
211.87 + list->list = 0;
211.88 +}
211.89 +
211.90 +/*
211.91 + * Add a string to the list.
211.92 + */
211.93 +static errcode_t add_to_list(struct profile_string_list *list, char *str)
211.94 +{
211.95 + char **newlist;
211.96 + int newmax;
211.97 +
211.98 + if (list->num+1 >= list->max) {
211.99 + newmax = list->max + 10;
211.100 + newlist = realloc(list->list, newmax * sizeof(char *));
211.101 + if (newlist == 0)
211.102 + return ENOMEM;
211.103 + list->max = newmax;
211.104 + list->list = newlist;
211.105 + }
211.106 +
211.107 + list->list[list->num++] = str;
211.108 + list->list[list->num] = 0;
211.109 + return 0;
211.110 +}
211.111 +
211.112 +/*
211.113 + * Return TRUE if the string is already a member of the list.
211.114 + */
211.115 +static int is_list_member(struct profile_string_list *list, const char *str)
211.116 +{
211.117 + char **cpp;
211.118 +
211.119 + if (!list->list)
211.120 + return 0;
211.121 +
211.122 + for (cpp = list->list; *cpp; cpp++) {
211.123 + if (!strcmp(*cpp, str))
211.124 + return 1;
211.125 + }
211.126 + return 0;
211.127 +}
211.128 +
211.129 +/*
211.130 + * This function frees a null-terminated list as returned by
211.131 + * profile_get_values.
211.132 + */
211.133 +void profile_free_list(char **list)
211.134 +{
211.135 + char **cp;
211.136 +
211.137 + if (list == 0)
211.138 + return;
211.139 +
211.140 + for (cp = list; *cp; cp++)
211.141 + free(*cp);
211.142 + free(list);
211.143 +}
211.144 +
211.145 +errcode_t
211.146 +profile_get_values(profile_t profile, const char *const *names,
211.147 + char ***ret_values)
211.148 +{
211.149 + errcode_t retval;
211.150 + void *state;
211.151 + char *value;
211.152 + struct profile_string_list values;
211.153 +
211.154 + if ((retval = profile_iterator_create(profile, names,
211.155 + PROFILE_ITER_RELATIONS_ONLY,
211.156 + &state)))
211.157 + return retval;
211.158 +
211.159 + if ((retval = init_list(&values)))
211.160 + goto cleanup_iterator;
211.161 +
211.162 + do {
211.163 + if ((retval = profile_iterator(&state, 0, &value)))
211.164 + goto cleanup;
211.165 + if (value)
211.166 + add_to_list(&values, value);
211.167 + } while (state);
211.168 +
211.169 + if (values.num == 0) {
211.170 + retval = PROF_NO_RELATION;
211.171 + goto cleanup;
211.172 + }
211.173 +
211.174 + end_list(&values, ret_values);
211.175 + return 0;
211.176 +
211.177 +cleanup:
211.178 + end_list(&values, 0);
211.179 +cleanup_iterator:
211.180 + profile_iterator_free(&state);
211.181 + return retval;
211.182 +}
211.183 +
211.184 +/*
211.185 + * This function will return the list of the names of subsections in the
211.186 + * under the specified section name.
211.187 + */
211.188 +errcode_t
211.189 +profile_get_subsection_names(profile_t profile, const char **names,
211.190 + char ***ret_names)
211.191 +{
211.192 + errcode_t retval;
211.193 + void *state;
211.194 + char *name;
211.195 + struct profile_string_list values;
211.196 +
211.197 + if ((retval = profile_iterator_create(profile, names,
211.198 + PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY,
211.199 + &state)))
211.200 + return retval;
211.201 +
211.202 + if ((retval = init_list(&values)))
211.203 + goto cleanup_iterator;
211.204 +
211.205 + do {
211.206 + if ((retval = profile_iterator(&state, &name, 0)))
211.207 + goto cleanup;
211.208 + if (name)
211.209 + add_to_list(&values, name);
211.210 + } while (state);
211.211 +
211.212 + end_list(&values, ret_names);
211.213 + return 0;
211.214 +
211.215 +cleanup:
211.216 + end_list(&values, 0);
211.217 +cleanup_iterator:
211.218 + profile_iterator_free(&state);
211.219 + return retval;
211.220 +}
211.221 +
211.222 +/*
211.223 + * This function will return the list of the names of relations in the
211.224 + * under the specified section name.
211.225 + */
211.226 +errcode_t
211.227 +profile_get_relation_names(profile_t profile, const char **names,
211.228 + char ***ret_names)
211.229 +{
211.230 + errcode_t retval;
211.231 + void *state;
211.232 + char *name;
211.233 + struct profile_string_list values;
211.234 +
211.235 + if ((retval = profile_iterator_create(profile, names,
211.236 + PROFILE_ITER_LIST_SECTION | PROFILE_ITER_RELATIONS_ONLY,
211.237 + &state)))
211.238 + return retval;
211.239 +
211.240 + if ((retval = init_list(&values)))
211.241 + goto cleanup_iterator;
211.242 +
211.243 + do {
211.244 + if ((retval = profile_iterator(&state, &name, 0)))
211.245 + goto cleanup;
211.246 + if (name) {
211.247 + if (is_list_member(&values, name))
211.248 + free(name);
211.249 + else
211.250 + add_to_list(&values, name);
211.251 + }
211.252 + } while (state);
211.253 +
211.254 + end_list(&values, ret_names);
211.255 + return 0;
211.256 +
211.257 +cleanup:
211.258 + end_list(&values, 0);
211.259 +cleanup_iterator:
211.260 + profile_iterator_free(&state);
211.261 + return retval;
211.262 +}
211.263 +
211.264 +
211.265 +void
211.266 +profile_release_string(char *str)
211.267 +{
211.268 + free(str);
211.269 +}
211.270 +
211.271 +errcode_t
211.272 +profile_init_path(const char * filepath,
211.273 + profile_t *ret_profile)
211.274 +{
211.275 + int n_entries, i;
211.276 + unsigned int ent_len;
211.277 + const char *s, *t;
211.278 + char **filenames;
211.279 + errcode_t retval;
211.280 +
211.281 + /* count the distinct filename components */
211.282 + for(s = filepath, n_entries = 1; *s; s++) {
211.283 + if (*s == ':')
211.284 + n_entries++;
211.285 + }
211.286 +
211.287 + /* the array is NULL terminated */
211.288 + filenames = (char **) malloc((n_entries+1) * sizeof(char*));
211.289 + if (filenames == 0)
211.290 + return ENOMEM;
211.291 +
211.292 + /* measure, copy, and skip each one */
211.293 + for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++) {
211.294 + ent_len = t-s;
211.295 + filenames[i] = (char*) malloc(ent_len + 1);
211.296 + if (filenames[i] == 0) {
211.297 + /* if malloc fails, free the ones that worked */
211.298 + while(--i >= 0) free(filenames[i]);
211.299 + free(filenames);
211.300 + return ENOMEM;
211.301 + }
211.302 + strncpy(filenames[i], s, ent_len);
211.303 + filenames[i][ent_len] = 0;
211.304 + if (*t == 0) {
211.305 + i++;
211.306 + break;
211.307 + }
211.308 + }
211.309 + /* cap the array */
211.310 + filenames[i] = 0;
211.311 +
211.312 + retval = profile_init((const char * const *) filenames,
211.313 + ret_profile);
211.314 +
211.315 + /* count back down and free the entries */
211.316 + while(--i >= 0) free(filenames[i]);
211.317 + free(filenames);
211.318 +
211.319 + return retval;
211.320 +}
212.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
212.2 +++ b/libext2fs/lib/libsupport/profile_helpers.h Wed Aug 25 01:28:08 2021 +0200
212.3 @@ -0,0 +1,28 @@
212.4 +/*
212.5 + * profile_helpers.h -- Function prototypes for profile helper functions
212.6 + *
212.7 + * Copyright (C) 2006 by Theodore Ts'o.
212.8 + *
212.9 + * %Begin-Header%
212.10 + * This file may be redistributed under the terms of the GNU Public
212.11 + * License.
212.12 + * %End-Header%
212.13 + */
212.14 +
212.15 +long profile_get_values
212.16 + (profile_t profile, const char *const *names, char ***ret_values);
212.17 +
212.18 +void profile_free_list
212.19 + (char **list);
212.20 +
212.21 +long profile_get_relation_names
212.22 + (profile_t profile, const char **names, char ***ret_names);
212.23 +
212.24 +long profile_get_subsection_names
212.25 + (profile_t profile, const char **names, char ***ret_names);
212.26 +
212.27 +void profile_release_string (char *str);
212.28 +
212.29 +long profile_init_path
212.30 + (const char * filelist, profile_t *ret_profile);
212.31 +
213.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
213.2 +++ b/libext2fs/lib/libsupport/quotaio.c Wed Aug 25 01:28:08 2021 +0200
213.3 @@ -0,0 +1,446 @@
213.4 +/** quotaio.c
213.5 + *
213.6 + * Generic IO operations on quotafiles
213.7 + * Jan Kara <jack@suse.cz> - sponsored by SuSE CR
213.8 + * Aditya Kali <adityakali@google.com> - Ported to e2fsprogs
213.9 + */
213.10 +
213.11 +#include "config.h"
213.12 +#include <stdio.h>
213.13 +#include <errno.h>
213.14 +#include <string.h>
213.15 +#include <unistd.h>
213.16 +#include <stdlib.h>
213.17 +#include <time.h>
213.18 +#include <sys/types.h>
213.19 +#include <sys/stat.h>
213.20 +#include <sys/file.h>
213.21 +#include <assert.h>
213.22 +
213.23 +#include "common.h"
213.24 +#include "quotaio.h"
213.25 +
213.26 +static const char * const extensions[MAXQUOTAS] = {
213.27 + [USRQUOTA] = "user",
213.28 + [GRPQUOTA] = "group",
213.29 + [PRJQUOTA] = "project",
213.30 +};
213.31 +static const char * const basenames[] = {
213.32 + "", /* undefined */
213.33 + "quota", /* QFMT_VFS_OLD */
213.34 + "aquota", /* QFMT_VFS_V0 */
213.35 + "", /* QFMT_OCFS2 */
213.36 + "aquota" /* QFMT_VFS_V1 */
213.37 +};
213.38 +
213.39 +/* Header in all newer quotafiles */
213.40 +struct disk_dqheader {
213.41 + __le32 dqh_magic;
213.42 + __le32 dqh_version;
213.43 +} __attribute__ ((packed));
213.44 +
213.45 +/**
213.46 + * Convert type of quota to written representation
213.47 + */
213.48 +const char *quota_type2name(enum quota_type qtype)
213.49 +{
213.50 + if (qtype >= MAXQUOTAS)
213.51 + return "unknown";
213.52 + return extensions[qtype];
213.53 +}
213.54 +
213.55 +ext2_ino_t quota_type2inum(enum quota_type qtype,
213.56 + struct ext2_super_block *sb)
213.57 +{
213.58 + switch (qtype) {
213.59 + case USRQUOTA:
213.60 + return EXT4_USR_QUOTA_INO;
213.61 + case GRPQUOTA:
213.62 + return EXT4_GRP_QUOTA_INO;
213.63 + case PRJQUOTA:
213.64 + return sb->s_prj_quota_inum;
213.65 + default:
213.66 + return 0;
213.67 + }
213.68 + return 0;
213.69 +}
213.70 +
213.71 +/**
213.72 + * Creates a quota file name for given type and format.
213.73 + */
213.74 +const char *quota_get_qf_name(enum quota_type type, int fmt, char *buf)
213.75 +{
213.76 + if (!buf)
213.77 + return NULL;
213.78 + snprintf(buf, QUOTA_NAME_LEN, "%s.%s",
213.79 + basenames[fmt], extensions[type]);
213.80 +
213.81 + return buf;
213.82 +}
213.83 +
213.84 +/*
213.85 + * Set grace time if needed
213.86 + */
213.87 +void update_grace_times(struct dquot *q)
213.88 +{
213.89 + time_t now;
213.90 +
213.91 + time(&now);
213.92 + if (q->dq_dqb.dqb_bsoftlimit && toqb(q->dq_dqb.dqb_curspace) >
213.93 + q->dq_dqb.dqb_bsoftlimit) {
213.94 + if (!q->dq_dqb.dqb_btime)
213.95 + q->dq_dqb.dqb_btime =
213.96 + now + q->dq_h->qh_info.dqi_bgrace;
213.97 + } else {
213.98 + q->dq_dqb.dqb_btime = 0;
213.99 + }
213.100 +
213.101 + if (q->dq_dqb.dqb_isoftlimit && q->dq_dqb.dqb_curinodes >
213.102 + q->dq_dqb.dqb_isoftlimit) {
213.103 + if (!q->dq_dqb.dqb_itime)
213.104 + q->dq_dqb.dqb_itime =
213.105 + now + q->dq_h->qh_info.dqi_igrace;
213.106 + } else {
213.107 + q->dq_dqb.dqb_itime = 0;
213.108 + }
213.109 +}
213.110 +
213.111 +static int compute_num_blocks_proc(ext2_filsys fs EXT2FS_ATTR((unused)),
213.112 + blk64_t *blocknr EXT2FS_ATTR((unused)),
213.113 + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
213.114 + blk64_t ref_block EXT2FS_ATTR((unused)),
213.115 + int ref_offset EXT2FS_ATTR((unused)),
213.116 + void *private)
213.117 +{
213.118 + blk64_t *num_blocks = private;
213.119 +
213.120 + *num_blocks += 1;
213.121 + return 0;
213.122 +}
213.123 +
213.124 +errcode_t quota_inode_truncate(ext2_filsys fs, ext2_ino_t ino)
213.125 +{
213.126 + struct ext2_inode inode;
213.127 + errcode_t err;
213.128 + enum quota_type qtype;
213.129 +
213.130 + if ((err = ext2fs_read_inode(fs, ino, &inode)))
213.131 + return err;
213.132 +
213.133 + for (qtype = 0; qtype < MAXQUOTAS; qtype++)
213.134 + if (ino == quota_type2inum(qtype, fs->super))
213.135 + break;
213.136 +
213.137 + if (qtype != MAXQUOTAS) {
213.138 + inode.i_dtime = fs->now ? fs->now : time(0);
213.139 + if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
213.140 + return 0;
213.141 + err = ext2fs_punch(fs, ino, &inode, NULL, 0, ~0ULL);
213.142 + if (err)
213.143 + return err;
213.144 + fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
213.145 + memset(&inode, 0, sizeof(struct ext2_inode));
213.146 + } else {
213.147 + inode.i_flags &= ~EXT2_IMMUTABLE_FL;
213.148 + }
213.149 + err = ext2fs_write_inode(fs, ino, &inode);
213.150 + return err;
213.151 +}
213.152 +
213.153 +static ext2_off64_t compute_inode_size(ext2_filsys fs, ext2_ino_t ino)
213.154 +{
213.155 + blk64_t num_blocks = 0;
213.156 +
213.157 + ext2fs_block_iterate3(fs, ino,
213.158 + BLOCK_FLAG_READ_ONLY,
213.159 + NULL,
213.160 + compute_num_blocks_proc,
213.161 + &num_blocks);
213.162 + return num_blocks * fs->blocksize;
213.163 +}
213.164 +
213.165 +/* Functions to read/write quota file. */
213.166 +static unsigned int quota_write_nomount(struct quota_file *qf,
213.167 + ext2_loff_t offset,
213.168 + void *buf, unsigned int size)
213.169 +{
213.170 + ext2_file_t e2_file = qf->e2_file;
213.171 + unsigned int bytes_written = 0;
213.172 + errcode_t err;
213.173 +
213.174 + err = ext2fs_file_llseek(e2_file, offset, EXT2_SEEK_SET, NULL);
213.175 + if (err) {
213.176 + log_err("ext2fs_file_llseek failed: %ld", err);
213.177 + return 0;
213.178 + }
213.179 +
213.180 + err = ext2fs_file_write(e2_file, buf, size, &bytes_written);
213.181 + if (err) {
213.182 + log_err("ext2fs_file_write failed: %ld", err);
213.183 + return 0;
213.184 + }
213.185 +
213.186 + /* Correct inode.i_size is set in end_io. */
213.187 + return bytes_written;
213.188 +}
213.189 +
213.190 +static unsigned int quota_read_nomount(struct quota_file *qf,
213.191 + ext2_loff_t offset,
213.192 + void *buf, unsigned int size)
213.193 +{
213.194 + ext2_file_t e2_file = qf->e2_file;
213.195 + unsigned int bytes_read = 0;
213.196 + errcode_t err;
213.197 +
213.198 + err = ext2fs_file_llseek(e2_file, offset, EXT2_SEEK_SET, NULL);
213.199 + if (err) {
213.200 + log_err("ext2fs_file_llseek failed: %ld", err);
213.201 + return 0;
213.202 + }
213.203 +
213.204 + err = ext2fs_file_read(e2_file, buf, size, &bytes_read);
213.205 + if (err) {
213.206 + log_err("ext2fs_file_read failed: %ld", err);
213.207 + return 0;
213.208 + }
213.209 +
213.210 + return bytes_read;
213.211 +}
213.212 +
213.213 +/*
213.214 + * Detect quota format and initialize quota IO
213.215 + */
213.216 +errcode_t quota_file_open(quota_ctx_t qctx, struct quota_handle *h,
213.217 + ext2_ino_t qf_ino, enum quota_type qtype,
213.218 + int fmt, int flags)
213.219 +{
213.220 + ext2_filsys fs = qctx->fs;
213.221 + ext2_file_t e2_file;
213.222 + errcode_t err;
213.223 + int allocated_handle = 0;
213.224 +
213.225 + if (qtype >= MAXQUOTAS)
213.226 + return EINVAL;
213.227 +
213.228 + if (fmt == -1)
213.229 + fmt = QFMT_VFS_V1;
213.230 +
213.231 + err = ext2fs_read_bitmaps(fs);
213.232 + if (err)
213.233 + return err;
213.234 +
213.235 + if (qf_ino == 0)
213.236 + qf_ino = *quota_sb_inump(fs->super, qtype);
213.237 +
213.238 + log_debug("Opening quota ino=%u, type=%d", qf_ino, qtype);
213.239 + err = ext2fs_file_open(fs, qf_ino, flags, &e2_file);
213.240 + if (err) {
213.241 + log_err("ext2fs_file_open failed: %s", error_message(err));
213.242 + return err;
213.243 + }
213.244 +
213.245 + if (!h) {
213.246 + if (qctx->quota_file[qtype]) {
213.247 + h = qctx->quota_file[qtype];
213.248 + if (((flags & EXT2_FILE_WRITE) == 0) ||
213.249 + (h->qh_file_flags & EXT2_FILE_WRITE)) {
213.250 + ext2fs_file_close(e2_file);
213.251 + return 0;
213.252 + }
213.253 + (void) quota_file_close(qctx, h);
213.254 + }
213.255 + err = ext2fs_get_mem(sizeof(struct quota_handle), &h);
213.256 + if (err) {
213.257 + log_err("Unable to allocate quota handle");
213.258 + ext2fs_file_close(e2_file);
213.259 + return err;
213.260 + }
213.261 + allocated_handle = 1;
213.262 + }
213.263 +
213.264 + h->qh_qf.e2_file = e2_file;
213.265 + h->qh_qf.fs = fs;
213.266 + h->qh_qf.ino = qf_ino;
213.267 + h->e2fs_write = quota_write_nomount;
213.268 + h->e2fs_read = quota_read_nomount;
213.269 + h->qh_file_flags = flags;
213.270 + h->qh_io_flags = 0;
213.271 + h->qh_type = qtype;
213.272 + h->qh_fmt = fmt;
213.273 + memset(&h->qh_info, 0, sizeof(h->qh_info));
213.274 + h->qh_ops = "afile_ops_2;
213.275 +
213.276 + if (h->qh_ops->check_file &&
213.277 + (h->qh_ops->check_file(h, qtype, fmt) == 0)) {
213.278 + log_err("qh_ops->check_file failed");
213.279 + err = EIO;
213.280 + goto errout;
213.281 + }
213.282 +
213.283 + if (h->qh_ops->init_io && (h->qh_ops->init_io(h) < 0)) {
213.284 + log_err("qh_ops->init_io failed");
213.285 + err = EIO;
213.286 + goto errout;
213.287 + }
213.288 + if (allocated_handle)
213.289 + qctx->quota_file[qtype] = h;
213.290 +
213.291 + return 0;
213.292 +errout:
213.293 + ext2fs_file_close(e2_file);
213.294 + if (allocated_handle)
213.295 + ext2fs_free_mem(&h);
213.296 + return err;
213.297 +}
213.298 +
213.299 +static errcode_t quota_inode_init_new(ext2_filsys fs, ext2_ino_t ino)
213.300 +{
213.301 + struct ext2_inode inode;
213.302 + errcode_t err = 0;
213.303 +
213.304 + err = ext2fs_read_inode(fs, ino, &inode);
213.305 + if (err) {
213.306 + log_err("ex2fs_read_inode failed");
213.307 + return err;
213.308 + }
213.309 +
213.310 + if (EXT2_I_SIZE(&inode)) {
213.311 + err = quota_inode_truncate(fs, ino);
213.312 + if (err)
213.313 + return err;
213.314 + }
213.315 +
213.316 + memset(&inode, 0, sizeof(struct ext2_inode));
213.317 + ext2fs_iblk_set(fs, &inode, 0);
213.318 + inode.i_atime = inode.i_mtime =
213.319 + inode.i_ctime = fs->now ? fs->now : time(0);
213.320 + inode.i_links_count = 1;
213.321 + inode.i_mode = LINUX_S_IFREG | 0600;
213.322 + inode.i_flags |= EXT2_IMMUTABLE_FL;
213.323 + if (ext2fs_has_feature_extents(fs->super))
213.324 + inode.i_flags |= EXT4_EXTENTS_FL;
213.325 +
213.326 + err = ext2fs_write_new_inode(fs, ino, &inode);
213.327 + if (err) {
213.328 + log_err("ext2fs_write_new_inode failed: %ld", err);
213.329 + return err;
213.330 + }
213.331 + return err;
213.332 +}
213.333 +
213.334 +/*
213.335 + * Create new quotafile of specified format on given filesystem
213.336 + */
213.337 +errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs,
213.338 + enum quota_type qtype, int fmt)
213.339 +{
213.340 + ext2_file_t e2_file;
213.341 + errcode_t err;
213.342 + ext2_ino_t qf_inum = 0;
213.343 +
213.344 + if (fmt == -1)
213.345 + fmt = QFMT_VFS_V1;
213.346 +
213.347 + h->qh_qf.fs = fs;
213.348 + qf_inum = quota_type2inum(qtype, fs->super);
213.349 + if (qf_inum == 0 && qtype == PRJQUOTA) {
213.350 + err = ext2fs_new_inode(fs, EXT2_ROOT_INO, LINUX_S_IFREG | 0600,
213.351 + 0, &qf_inum);
213.352 + if (err)
213.353 + return err;
213.354 + ext2fs_inode_alloc_stats2(fs, qf_inum, +1, 0);
213.355 + ext2fs_mark_ib_dirty(fs);
213.356 + } else if (qf_inum == 0) {
213.357 + return EXT2_ET_BAD_INODE_NUM;
213.358 + }
213.359 +
213.360 + err = ext2fs_read_bitmaps(fs);
213.361 + if (err)
213.362 + goto out_err;
213.363 +
213.364 + err = quota_inode_init_new(fs, qf_inum);
213.365 + if (err) {
213.366 + log_err("init_new_quota_inode failed");
213.367 + goto out_err;
213.368 + }
213.369 + h->qh_qf.ino = qf_inum;
213.370 + h->qh_file_flags = EXT2_FILE_WRITE | EXT2_FILE_CREATE;
213.371 + h->e2fs_write = quota_write_nomount;
213.372 + h->e2fs_read = quota_read_nomount;
213.373 +
213.374 + log_debug("Creating quota ino=%u, type=%d", qf_inum, qtype);
213.375 + err = ext2fs_file_open(fs, qf_inum, h->qh_file_flags, &e2_file);
213.376 + if (err) {
213.377 + log_err("ext2fs_file_open failed: %ld", err);
213.378 + goto out_err;
213.379 + }
213.380 + h->qh_qf.e2_file = e2_file;
213.381 +
213.382 + h->qh_io_flags = 0;
213.383 + h->qh_type = qtype;
213.384 + h->qh_fmt = fmt;
213.385 + memset(&h->qh_info, 0, sizeof(h->qh_info));
213.386 + h->qh_ops = "afile_ops_2;
213.387 +
213.388 + if (h->qh_ops->new_io && (h->qh_ops->new_io(h) < 0)) {
213.389 + log_err("qh_ops->new_io failed");
213.390 + err = EIO;
213.391 + goto out_err1;
213.392 + }
213.393 +
213.394 + return 0;
213.395 +
213.396 +out_err1:
213.397 + ext2fs_file_close(e2_file);
213.398 +out_err:
213.399 +
213.400 + if (qf_inum)
213.401 + quota_inode_truncate(fs, qf_inum);
213.402 +
213.403 + return err;
213.404 +}
213.405 +
213.406 +/*
213.407 + * Close quotafile and release handle
213.408 + */
213.409 +errcode_t quota_file_close(quota_ctx_t qctx, struct quota_handle *h)
213.410 +{
213.411 + if (h->qh_io_flags & IOFL_INFODIRTY) {
213.412 + if (h->qh_ops->write_info && h->qh_ops->write_info(h) < 0)
213.413 + return EIO;
213.414 + h->qh_io_flags &= ~IOFL_INFODIRTY;
213.415 + }
213.416 +
213.417 + if (h->qh_ops->end_io && h->qh_ops->end_io(h) < 0)
213.418 + return EIO;
213.419 + if (h->qh_qf.e2_file) {
213.420 + __u64 new_size, size;
213.421 +
213.422 + new_size = compute_inode_size(h->qh_qf.fs, h->qh_qf.ino);
213.423 + ext2fs_file_flush(h->qh_qf.e2_file);
213.424 + if (ext2fs_file_get_lsize(h->qh_qf.e2_file, &size))
213.425 + new_size = 0;
213.426 + if (size != new_size)
213.427 + ext2fs_file_set_size2(h->qh_qf.e2_file, new_size);
213.428 + ext2fs_file_close(h->qh_qf.e2_file);
213.429 + }
213.430 + if (qctx->quota_file[h->qh_type] == h)
213.431 + ext2fs_free_mem(&qctx->quota_file[h->qh_type]);
213.432 + return 0;
213.433 +}
213.434 +
213.435 +/*
213.436 + * Create empty quota structure
213.437 + */
213.438 +struct dquot *get_empty_dquot(void)
213.439 +{
213.440 + struct dquot *dquot;
213.441 +
213.442 + if (ext2fs_get_memzero(sizeof(struct dquot), &dquot)) {
213.443 + log_err("Failed to allocate dquot");
213.444 + return NULL;
213.445 + }
213.446 +
213.447 + dquot->dq_id = -1;
213.448 + return dquot;
213.449 +}
214.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
214.2 +++ b/libext2fs/lib/libsupport/quotaio_tree.c Wed Aug 25 01:28:08 2021 +0200
214.3 @@ -0,0 +1,664 @@
214.4 +/*
214.5 + * Implementation of new quotafile format
214.6 + *
214.7 + * Jan Kara <jack@suse.cz> - sponsored by SuSE CR
214.8 + */
214.9 +
214.10 +#include "config.h"
214.11 +#include <sys/types.h>
214.12 +#include <errno.h>
214.13 +#include <stdio.h>
214.14 +#include <stdlib.h>
214.15 +#include <string.h>
214.16 +#include <unistd.h>
214.17 +
214.18 +#include "common.h"
214.19 +#include "quotaio_tree.h"
214.20 +#include "quotaio.h"
214.21 +
214.22 +typedef char *dqbuf_t;
214.23 +
214.24 +#define freedqbuf(buf) ext2fs_free_mem(&buf)
214.25 +
214.26 +static inline dqbuf_t getdqbuf(void)
214.27 +{
214.28 + dqbuf_t buf;
214.29 + if (ext2fs_get_memzero(QT_BLKSIZE, &buf)) {
214.30 + log_err("Failed to allocate dqbuf");
214.31 + return NULL;
214.32 + }
214.33 +
214.34 + return buf;
214.35 +}
214.36 +
214.37 +/* Is given dquot empty? */
214.38 +int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk)
214.39 +{
214.40 + unsigned int i;
214.41 +
214.42 + for (i = 0; i < info->dqi_entry_size; i++)
214.43 + if (disk[i])
214.44 + return 0;
214.45 + return 1;
214.46 +}
214.47 +
214.48 +int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info)
214.49 +{
214.50 + return (QT_BLKSIZE - sizeof(struct qt_disk_dqdbheader)) /
214.51 + info->dqi_entry_size;
214.52 +}
214.53 +
214.54 +static int get_index(qid_t id, int depth)
214.55 +{
214.56 + return (id >> ((QT_TREEDEPTH - depth - 1) * 8)) & 0xff;
214.57 +}
214.58 +
214.59 +static inline void mark_quotafile_info_dirty(struct quota_handle *h)
214.60 +{
214.61 + h->qh_io_flags |= IOFL_INFODIRTY;
214.62 +}
214.63 +
214.64 +/* Read given block */
214.65 +static void read_blk(struct quota_handle *h, unsigned int blk, dqbuf_t buf)
214.66 +{
214.67 + int err;
214.68 +
214.69 + err = h->e2fs_read(&h->qh_qf, blk << QT_BLKSIZE_BITS, buf,
214.70 + QT_BLKSIZE);
214.71 + if (err < 0)
214.72 + log_err("Cannot read block %u: %s", blk, strerror(errno));
214.73 + else if (err != QT_BLKSIZE)
214.74 + memset(buf + err, 0, QT_BLKSIZE - err);
214.75 +}
214.76 +
214.77 +/* Write block */
214.78 +static int write_blk(struct quota_handle *h, unsigned int blk, dqbuf_t buf)
214.79 +{
214.80 + int err;
214.81 +
214.82 + err = h->e2fs_write(&h->qh_qf, blk << QT_BLKSIZE_BITS, buf,
214.83 + QT_BLKSIZE);
214.84 + if (err < 0 && errno != ENOSPC)
214.85 + log_err("Cannot write block (%u): %s", blk, strerror(errno));
214.86 + if (err != QT_BLKSIZE)
214.87 + return -ENOSPC;
214.88 + return 0;
214.89 +}
214.90 +
214.91 +/* Get free block in file (either from free list or create new one) */
214.92 +static int get_free_dqblk(struct quota_handle *h)
214.93 +{
214.94 + dqbuf_t buf = getdqbuf();
214.95 + struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
214.96 + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
214.97 + int blk;
214.98 +
214.99 + if (!buf)
214.100 + return -ENOMEM;
214.101 +
214.102 + if (info->dqi_free_blk) {
214.103 + blk = info->dqi_free_blk;
214.104 + read_blk(h, blk, buf);
214.105 + info->dqi_free_blk = ext2fs_le32_to_cpu(dh->dqdh_next_free);
214.106 + } else {
214.107 + memset(buf, 0, QT_BLKSIZE);
214.108 + /* Assure block allocation... */
214.109 + if (write_blk(h, info->dqi_blocks, buf) < 0) {
214.110 + freedqbuf(buf);
214.111 + log_err("Cannot allocate new quota block "
214.112 + "(out of disk space).");
214.113 + return -ENOSPC;
214.114 + }
214.115 + blk = info->dqi_blocks++;
214.116 + }
214.117 + mark_quotafile_info_dirty(h);
214.118 + freedqbuf(buf);
214.119 + return blk;
214.120 +}
214.121 +
214.122 +/* Put given block to free list */
214.123 +static void put_free_dqblk(struct quota_handle *h, dqbuf_t buf,
214.124 + unsigned int blk)
214.125 +{
214.126 + struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
214.127 + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
214.128 +
214.129 + dh->dqdh_next_free = ext2fs_cpu_to_le32(info->dqi_free_blk);
214.130 + dh->dqdh_prev_free = ext2fs_cpu_to_le32(0);
214.131 + dh->dqdh_entries = ext2fs_cpu_to_le16(0);
214.132 + info->dqi_free_blk = blk;
214.133 + mark_quotafile_info_dirty(h);
214.134 + write_blk(h, blk, buf);
214.135 +}
214.136 +
214.137 +/* Remove given block from the list of blocks with free entries */
214.138 +static void remove_free_dqentry(struct quota_handle *h, dqbuf_t buf,
214.139 + unsigned int blk)
214.140 +{
214.141 + dqbuf_t tmpbuf = getdqbuf();
214.142 + struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
214.143 + unsigned int nextblk = ext2fs_le32_to_cpu(dh->dqdh_next_free), prevblk =
214.144 +
214.145 + ext2fs_le32_to_cpu(dh->dqdh_prev_free);
214.146 +
214.147 + if (!tmpbuf)
214.148 + return;
214.149 +
214.150 + if (nextblk) {
214.151 + read_blk(h, nextblk, tmpbuf);
214.152 + ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
214.153 + dh->dqdh_prev_free;
214.154 + write_blk(h, nextblk, tmpbuf);
214.155 + }
214.156 + if (prevblk) {
214.157 + read_blk(h, prevblk, tmpbuf);
214.158 + ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_next_free =
214.159 + dh->dqdh_next_free;
214.160 + write_blk(h, prevblk, tmpbuf);
214.161 + } else {
214.162 + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_entry = nextblk;
214.163 + mark_quotafile_info_dirty(h);
214.164 + }
214.165 + freedqbuf(tmpbuf);
214.166 + dh->dqdh_next_free = dh->dqdh_prev_free = ext2fs_cpu_to_le32(0);
214.167 + write_blk(h, blk, buf); /* No matter whether write succeeds
214.168 + * block is out of list */
214.169 +}
214.170 +
214.171 +/* Insert given block to the beginning of list with free entries */
214.172 +static void insert_free_dqentry(struct quota_handle *h, dqbuf_t buf,
214.173 + unsigned int blk)
214.174 +{
214.175 + dqbuf_t tmpbuf = getdqbuf();
214.176 + struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
214.177 + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
214.178 +
214.179 + if (!tmpbuf)
214.180 + return;
214.181 +
214.182 + dh->dqdh_next_free = ext2fs_cpu_to_le32(info->dqi_free_entry);
214.183 + dh->dqdh_prev_free = ext2fs_cpu_to_le32(0);
214.184 + write_blk(h, blk, buf);
214.185 + if (info->dqi_free_entry) {
214.186 + read_blk(h, info->dqi_free_entry, tmpbuf);
214.187 + ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
214.188 + ext2fs_cpu_to_le32(blk);
214.189 + write_blk(h, info->dqi_free_entry, tmpbuf);
214.190 + }
214.191 + freedqbuf(tmpbuf);
214.192 + info->dqi_free_entry = blk;
214.193 + mark_quotafile_info_dirty(h);
214.194 +}
214.195 +
214.196 +/* Find space for dquot */
214.197 +static unsigned int find_free_dqentry(struct quota_handle *h,
214.198 + struct dquot *dquot, int *err)
214.199 +{
214.200 + int blk, i;
214.201 + struct qt_disk_dqdbheader *dh;
214.202 + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
214.203 + char *ddquot;
214.204 + dqbuf_t buf;
214.205 +
214.206 + *err = 0;
214.207 + buf = getdqbuf();
214.208 + if (!buf) {
214.209 + *err = -ENOMEM;
214.210 + return 0;
214.211 + }
214.212 +
214.213 + dh = (struct qt_disk_dqdbheader *)buf;
214.214 + if (info->dqi_free_entry) {
214.215 + blk = info->dqi_free_entry;
214.216 + read_blk(h, blk, buf);
214.217 + } else {
214.218 + blk = get_free_dqblk(h);
214.219 + if (blk < 0) {
214.220 + freedqbuf(buf);
214.221 + *err = blk;
214.222 + return 0;
214.223 + }
214.224 + memset(buf, 0, QT_BLKSIZE);
214.225 + info->dqi_free_entry = blk;
214.226 + mark_quotafile_info_dirty(h);
214.227 + }
214.228 +
214.229 + /* Block will be full? */
214.230 + if (ext2fs_le16_to_cpu(dh->dqdh_entries) + 1 >=
214.231 + qtree_dqstr_in_blk(info))
214.232 + remove_free_dqentry(h, buf, blk);
214.233 +
214.234 + dh->dqdh_entries =
214.235 + ext2fs_cpu_to_le16(ext2fs_le16_to_cpu(dh->dqdh_entries) + 1);
214.236 + /* Find free structure in block */
214.237 + ddquot = buf + sizeof(struct qt_disk_dqdbheader);
214.238 + for (i = 0;
214.239 + i < qtree_dqstr_in_blk(info) && !qtree_entry_unused(info, ddquot);
214.240 + i++)
214.241 + ddquot += info->dqi_entry_size;
214.242 +
214.243 + if (i == qtree_dqstr_in_blk(info))
214.244 + log_err("find_free_dqentry(): Data block full unexpectedly.");
214.245 +
214.246 + write_blk(h, blk, buf);
214.247 + dquot->dq_dqb.u.v2_mdqb.dqb_off =
214.248 + (blk << QT_BLKSIZE_BITS) + sizeof(struct qt_disk_dqdbheader) +
214.249 + i * info->dqi_entry_size;
214.250 + freedqbuf(buf);
214.251 + return blk;
214.252 +}
214.253 +
214.254 +/* Insert reference to structure into the trie */
214.255 +static int do_insert_tree(struct quota_handle *h, struct dquot *dquot,
214.256 + unsigned int * treeblk, int depth)
214.257 +{
214.258 + dqbuf_t buf;
214.259 + int newson = 0, newact = 0;
214.260 + __le32 *ref;
214.261 + unsigned int newblk;
214.262 + int ret = 0;
214.263 +
214.264 + log_debug("inserting in tree: treeblk=%u, depth=%d", *treeblk, depth);
214.265 + buf = getdqbuf();
214.266 + if (!buf)
214.267 + return -ENOMEM;
214.268 +
214.269 + if (!*treeblk) {
214.270 + ret = get_free_dqblk(h);
214.271 + if (ret < 0)
214.272 + goto out_buf;
214.273 + *treeblk = ret;
214.274 + memset(buf, 0, QT_BLKSIZE);
214.275 + newact = 1;
214.276 + } else {
214.277 + read_blk(h, *treeblk, buf);
214.278 + }
214.279 +
214.280 + ref = (__le32 *) buf;
214.281 + newblk = ext2fs_le32_to_cpu(ref[get_index(dquot->dq_id, depth)]);
214.282 + if (!newblk)
214.283 + newson = 1;
214.284 + if (depth == QT_TREEDEPTH - 1) {
214.285 + if (newblk)
214.286 + log_err("Inserting already present quota entry "
214.287 + "(block %u).",
214.288 + ref[get_index(dquot->dq_id, depth)]);
214.289 + newblk = find_free_dqentry(h, dquot, &ret);
214.290 + } else {
214.291 + ret = do_insert_tree(h, dquot, &newblk, depth + 1);
214.292 + }
214.293 +
214.294 + if (newson && ret >= 0) {
214.295 + ref[get_index(dquot->dq_id, depth)] =
214.296 + ext2fs_cpu_to_le32(newblk);
214.297 + write_blk(h, *treeblk, buf);
214.298 + } else if (newact && ret < 0) {
214.299 + put_free_dqblk(h, buf, *treeblk);
214.300 + }
214.301 +
214.302 +out_buf:
214.303 + freedqbuf(buf);
214.304 + return ret;
214.305 +}
214.306 +
214.307 +/* Wrapper for inserting quota structure into tree */
214.308 +static void dq_insert_tree(struct quota_handle *h, struct dquot *dquot)
214.309 +{
214.310 + unsigned int tmp = QT_TREEOFF;
214.311 +
214.312 + if (do_insert_tree(h, dquot, &tmp, 0) < 0)
214.313 + log_err("Cannot write quota (id %u): %s",
214.314 + (unsigned int) dquot->dq_id, strerror(errno));
214.315 +}
214.316 +
214.317 +/* Write dquot to file */
214.318 +void qtree_write_dquot(struct dquot *dquot)
214.319 +{
214.320 + errcode_t retval;
214.321 + unsigned int ret;
214.322 + char *ddquot;
214.323 + struct quota_handle *h = dquot->dq_h;
214.324 + struct qtree_mem_dqinfo *info =
214.325 + &dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree;
214.326 + log_debug("writing ddquot 1: off=%llu, info->dqi_entry_size=%u",
214.327 + dquot->dq_dqb.u.v2_mdqb.dqb_off,
214.328 + info->dqi_entry_size);
214.329 + retval = ext2fs_get_mem(info->dqi_entry_size, &ddquot);
214.330 + if (retval) {
214.331 + errno = ENOMEM;
214.332 + log_err("Quota write failed (id %u): %s",
214.333 + (unsigned int)dquot->dq_id, strerror(errno));
214.334 + return;
214.335 + }
214.336 + memset(ddquot, 0, info->dqi_entry_size);
214.337 +
214.338 + if (!dquot->dq_dqb.u.v2_mdqb.dqb_off)
214.339 + dq_insert_tree(dquot->dq_h, dquot);
214.340 + info->dqi_ops->mem2disk_dqblk(ddquot, dquot);
214.341 + log_debug("writing ddquot 2: off=%llu, info->dqi_entry_size=%u",
214.342 + dquot->dq_dqb.u.v2_mdqb.dqb_off,
214.343 + info->dqi_entry_size);
214.344 + ret = h->e2fs_write(&h->qh_qf, dquot->dq_dqb.u.v2_mdqb.dqb_off, ddquot,
214.345 + info->dqi_entry_size);
214.346 +
214.347 + if (ret != info->dqi_entry_size) {
214.348 + if (ret > 0)
214.349 + errno = ENOSPC;
214.350 + log_err("Quota write failed (id %u): %s",
214.351 + (unsigned int)dquot->dq_id, strerror(errno));
214.352 + }
214.353 + ext2fs_free_mem(&ddquot);
214.354 +}
214.355 +
214.356 +/* Free dquot entry in data block */
214.357 +static void free_dqentry(struct quota_handle *h, struct dquot *dquot,
214.358 + unsigned int blk)
214.359 +{
214.360 + struct qt_disk_dqdbheader *dh;
214.361 + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
214.362 + dqbuf_t buf = getdqbuf();
214.363 +
214.364 + if (!buf)
214.365 + return;
214.366 +
214.367 + if (dquot->dq_dqb.u.v2_mdqb.dqb_off >> QT_BLKSIZE_BITS != blk)
214.368 + log_err("Quota structure has offset to other block (%u) "
214.369 + "than it should (%u).", blk,
214.370 + (unsigned int) (dquot->dq_dqb.u.v2_mdqb.dqb_off >>
214.371 + QT_BLKSIZE_BITS));
214.372 +
214.373 + read_blk(h, blk, buf);
214.374 + dh = (struct qt_disk_dqdbheader *)buf;
214.375 + dh->dqdh_entries =
214.376 + ext2fs_cpu_to_le16(ext2fs_le16_to_cpu(dh->dqdh_entries) - 1);
214.377 +
214.378 + if (!ext2fs_le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */
214.379 + remove_free_dqentry(h, buf, blk);
214.380 + put_free_dqblk(h, buf, blk);
214.381 + } else {
214.382 + memset(buf + (dquot->dq_dqb.u.v2_mdqb.dqb_off &
214.383 + ((1 << QT_BLKSIZE_BITS) - 1)),
214.384 + 0, info->dqi_entry_size);
214.385 +
214.386 + /* First free entry? */
214.387 + if (ext2fs_le16_to_cpu(dh->dqdh_entries) ==
214.388 + qtree_dqstr_in_blk(info) - 1)
214.389 + /* This will also write data block */
214.390 + insert_free_dqentry(h, buf, blk);
214.391 + else
214.392 + write_blk(h, blk, buf);
214.393 + }
214.394 + dquot->dq_dqb.u.v2_mdqb.dqb_off = 0;
214.395 + freedqbuf(buf);
214.396 +}
214.397 +
214.398 +/* Remove reference to dquot from tree */
214.399 +static void remove_tree(struct quota_handle *h, struct dquot *dquot,
214.400 + unsigned int * blk, int depth)
214.401 +{
214.402 + dqbuf_t buf = getdqbuf();
214.403 + unsigned int newblk;
214.404 + __le32 *ref = (__le32 *) buf;
214.405 +
214.406 + if (!buf)
214.407 + return;
214.408 +
214.409 + read_blk(h, *blk, buf);
214.410 + newblk = ext2fs_le32_to_cpu(ref[get_index(dquot->dq_id, depth)]);
214.411 + if (depth == QT_TREEDEPTH - 1) {
214.412 + free_dqentry(h, dquot, newblk);
214.413 + newblk = 0;
214.414 + } else {
214.415 + remove_tree(h, dquot, &newblk, depth + 1);
214.416 + }
214.417 +
214.418 + if (!newblk) {
214.419 + int i;
214.420 +
214.421 + ref[get_index(dquot->dq_id, depth)] = ext2fs_cpu_to_le32(0);
214.422 +
214.423 + /* Block got empty? */
214.424 + for (i = 0; i < QT_BLKSIZE && !buf[i]; i++);
214.425 +
214.426 + /* Don't put the root block into the free block list */
214.427 + if (i == QT_BLKSIZE && *blk != QT_TREEOFF) {
214.428 + put_free_dqblk(h, buf, *blk);
214.429 + *blk = 0;
214.430 + } else {
214.431 + write_blk(h, *blk, buf);
214.432 + }
214.433 + }
214.434 + freedqbuf(buf);
214.435 +}
214.436 +
214.437 +/* Delete dquot from tree */
214.438 +void qtree_delete_dquot(struct dquot *dquot)
214.439 +{
214.440 + unsigned int tmp = QT_TREEOFF;
214.441 +
214.442 + if (!dquot->dq_dqb.u.v2_mdqb.dqb_off) /* Even not allocated? */
214.443 + return;
214.444 + remove_tree(dquot->dq_h, dquot, &tmp, 0);
214.445 +}
214.446 +
214.447 +/* Find entry in block */
214.448 +static ext2_loff_t find_block_dqentry(struct quota_handle *h,
214.449 + struct dquot *dquot, unsigned int blk)
214.450 +{
214.451 + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
214.452 + dqbuf_t buf = getdqbuf();
214.453 + int i;
214.454 + char *ddquot = buf + sizeof(struct qt_disk_dqdbheader);
214.455 +
214.456 + if (!buf)
214.457 + return -ENOMEM;
214.458 +
214.459 + read_blk(h, blk, buf);
214.460 + for (i = 0;
214.461 + i < qtree_dqstr_in_blk(info) && !info->dqi_ops->is_id(ddquot, dquot);
214.462 + i++)
214.463 + ddquot += info->dqi_entry_size;
214.464 +
214.465 + if (i == qtree_dqstr_in_blk(info))
214.466 + log_err("Quota for id %u referenced but not present.",
214.467 + dquot->dq_id);
214.468 + freedqbuf(buf);
214.469 + return (blk << QT_BLKSIZE_BITS) + sizeof(struct qt_disk_dqdbheader) +
214.470 + i * info->dqi_entry_size;
214.471 +}
214.472 +
214.473 +/* Find entry for given id in the tree */
214.474 +static ext2_loff_t find_tree_dqentry(struct quota_handle *h,
214.475 + struct dquot *dquot,
214.476 + unsigned int blk, int depth)
214.477 +{
214.478 + dqbuf_t buf = getdqbuf();
214.479 + ext2_loff_t ret = 0;
214.480 + __le32 *ref = (__le32 *) buf;
214.481 +
214.482 + if (!buf)
214.483 + return -ENOMEM;
214.484 +
214.485 + read_blk(h, blk, buf);
214.486 + ret = 0;
214.487 + blk = ext2fs_le32_to_cpu(ref[get_index(dquot->dq_id, depth)]);
214.488 + if (!blk) /* No reference? */
214.489 + goto out_buf;
214.490 + if (depth < QT_TREEDEPTH - 1)
214.491 + ret = find_tree_dqentry(h, dquot, blk, depth + 1);
214.492 + else
214.493 + ret = find_block_dqentry(h, dquot, blk);
214.494 +out_buf:
214.495 + freedqbuf(buf);
214.496 + return ret;
214.497 +}
214.498 +
214.499 +/* Find entry for given id in the tree - wrapper function */
214.500 +static inline ext2_loff_t find_dqentry(struct quota_handle *h,
214.501 + struct dquot *dquot)
214.502 +{
214.503 + return find_tree_dqentry(h, dquot, QT_TREEOFF, 0);
214.504 +}
214.505 +
214.506 +/*
214.507 + * Read dquot from disk.
214.508 + */
214.509 +struct dquot *qtree_read_dquot(struct quota_handle *h, qid_t id)
214.510 +{
214.511 + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
214.512 + ext2_loff_t offset;
214.513 + unsigned int ret;
214.514 + char *ddquot;
214.515 + struct dquot *dquot = get_empty_dquot();
214.516 +
214.517 + if (!dquot)
214.518 + return NULL;
214.519 + if (ext2fs_get_mem(info->dqi_entry_size, &ddquot)) {
214.520 + ext2fs_free_mem(&dquot);
214.521 + return NULL;
214.522 + }
214.523 +
214.524 + dquot->dq_id = id;
214.525 + dquot->dq_h = h;
214.526 + dquot->dq_dqb.u.v2_mdqb.dqb_off = 0;
214.527 + memset(&dquot->dq_dqb, 0, sizeof(struct util_dqblk));
214.528 +
214.529 + offset = find_dqentry(h, dquot);
214.530 + if (offset > 0) {
214.531 + dquot->dq_dqb.u.v2_mdqb.dqb_off = offset;
214.532 + ret = h->e2fs_read(&h->qh_qf, offset, ddquot,
214.533 + info->dqi_entry_size);
214.534 + if (ret != info->dqi_entry_size) {
214.535 + if (ret > 0)
214.536 + errno = EIO;
214.537 + log_err("Cannot read quota structure for id %u: %s",
214.538 + dquot->dq_id, strerror(errno));
214.539 + }
214.540 + info->dqi_ops->disk2mem_dqblk(dquot, ddquot);
214.541 + }
214.542 + ext2fs_free_mem(&ddquot);
214.543 + return dquot;
214.544 +}
214.545 +
214.546 +/*
214.547 + * Scan all dquots in file and call callback on each
214.548 + */
214.549 +#define set_bit(bmp, ind) ((bmp)[(ind) >> 3] |= (1 << ((ind) & 7)))
214.550 +#define get_bit(bmp, ind) ((bmp)[(ind) >> 3] & (1 << ((ind) & 7)))
214.551 +
214.552 +static int report_block(struct dquot *dquot, unsigned int blk, char *bitmap,
214.553 + int (*process_dquot) (struct dquot *, void *),
214.554 + void *data)
214.555 +{
214.556 + struct qtree_mem_dqinfo *info =
214.557 + &dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree;
214.558 + dqbuf_t buf = getdqbuf();
214.559 + struct qt_disk_dqdbheader *dh;
214.560 + char *ddata;
214.561 + int entries, i;
214.562 +
214.563 + if (!buf)
214.564 + return 0;
214.565 +
214.566 + set_bit(bitmap, blk);
214.567 + read_blk(dquot->dq_h, blk, buf);
214.568 + dh = (struct qt_disk_dqdbheader *)buf;
214.569 + ddata = buf + sizeof(struct qt_disk_dqdbheader);
214.570 + entries = ext2fs_le16_to_cpu(dh->dqdh_entries);
214.571 + for (i = 0; i < qtree_dqstr_in_blk(info);
214.572 + i++, ddata += info->dqi_entry_size)
214.573 + if (!qtree_entry_unused(info, ddata)) {
214.574 + dquot->dq_dqb.u.v2_mdqb.dqb_off =
214.575 + (blk << QT_BLKSIZE_BITS) +
214.576 + sizeof(struct qt_disk_dqdbheader) +
214.577 + i * info->dqi_entry_size;
214.578 + info->dqi_ops->disk2mem_dqblk(dquot, ddata);
214.579 + if (process_dquot(dquot, data) < 0)
214.580 + break;
214.581 + }
214.582 + freedqbuf(buf);
214.583 + return entries;
214.584 +}
214.585 +
214.586 +static void check_reference(struct quota_handle *h, unsigned int blk)
214.587 +{
214.588 + if (blk >= h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks)
214.589 + log_err("Illegal reference (%u >= %u) in %s quota file. "
214.590 + "Quota file is probably corrupted.\n"
214.591 + "Please run e2fsck (8) to fix it.",
214.592 + blk,
214.593 + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks,
214.594 + quota_type2name(h->qh_type));
214.595 +}
214.596 +
214.597 +static int report_tree(struct dquot *dquot, unsigned int blk, int depth,
214.598 + char *bitmap,
214.599 + int (*process_dquot) (struct dquot *, void *),
214.600 + void *data)
214.601 +{
214.602 + int entries = 0, i;
214.603 + dqbuf_t buf = getdqbuf();
214.604 + __le32 *ref = (__le32 *) buf;
214.605 +
214.606 + if (!buf)
214.607 + return 0;
214.608 +
214.609 + read_blk(dquot->dq_h, blk, buf);
214.610 + if (depth == QT_TREEDEPTH - 1) {
214.611 + for (i = 0; i < QT_BLKSIZE >> 2; i++) {
214.612 + blk = ext2fs_le32_to_cpu(ref[i]);
214.613 + check_reference(dquot->dq_h, blk);
214.614 + if (blk && !get_bit(bitmap, blk))
214.615 + entries += report_block(dquot, blk, bitmap,
214.616 + process_dquot, data);
214.617 + }
214.618 + } else {
214.619 + for (i = 0; i < QT_BLKSIZE >> 2; i++) {
214.620 + blk = ext2fs_le32_to_cpu(ref[i]);
214.621 + if (blk) {
214.622 + check_reference(dquot->dq_h, blk);
214.623 + entries += report_tree(dquot, blk, depth + 1,
214.624 + bitmap, process_dquot,
214.625 + data);
214.626 + }
214.627 + }
214.628 + }
214.629 + freedqbuf(buf);
214.630 + return entries;
214.631 +}
214.632 +
214.633 +static unsigned int find_set_bits(char *bmp, int blocks)
214.634 +{
214.635 + unsigned int used = 0;
214.636 + int i;
214.637 +
214.638 + for (i = 0; i < blocks; i++)
214.639 + if (get_bit(bmp, i))
214.640 + used++;
214.641 + return used;
214.642 +}
214.643 +
214.644 +int qtree_scan_dquots(struct quota_handle *h,
214.645 + int (*process_dquot) (struct dquot *, void *),
214.646 + void *data)
214.647 +{
214.648 + char *bitmap;
214.649 + struct v2_mem_dqinfo *v2info = &h->qh_info.u.v2_mdqi;
214.650 + struct qtree_mem_dqinfo *info = &v2info->dqi_qtree;
214.651 + struct dquot *dquot = get_empty_dquot();
214.652 +
214.653 + if (!dquot)
214.654 + return -1;
214.655 +
214.656 + dquot->dq_h = h;
214.657 + if (ext2fs_get_memzero((info->dqi_blocks + 7) >> 3, &bitmap)) {
214.658 + ext2fs_free_mem(&dquot);
214.659 + return -1;
214.660 + }
214.661 + v2info->dqi_used_entries = report_tree(dquot, QT_TREEOFF, 0, bitmap,
214.662 + process_dquot, data);
214.663 + v2info->dqi_data_blocks = find_set_bits(bitmap, info->dqi_blocks);
214.664 + ext2fs_free_mem(&bitmap);
214.665 + ext2fs_free_mem(&dquot);
214.666 + return 0;
214.667 +}
215.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
215.2 +++ b/libext2fs/lib/libsupport/quotaio_tree.h Wed Aug 25 01:28:08 2021 +0200
215.3 @@ -0,0 +1,64 @@
215.4 +/*
215.5 + * Definitions of structures for vfsv0 quota format
215.6 + */
215.7 +
215.8 +#ifndef _LINUX_QUOTA_TREE_H
215.9 +#define _LINUX_QUOTA_TREE_H
215.10 +
215.11 +#include <sys/types.h>
215.12 +
215.13 +typedef __u32 qid_t; /* Type in which we store ids in memory */
215.14 +
215.15 +#define QT_TREEOFF 1 /* Offset of tree in file in blocks */
215.16 +#define QT_TREEDEPTH 4 /* Depth of quota tree */
215.17 +#define QT_BLKSIZE_BITS 10
215.18 +#define QT_BLKSIZE (1 << QT_BLKSIZE_BITS) /* Size of block with quota
215.19 + * structures */
215.20 +
215.21 +/*
215.22 + * Structure of header of block with quota structures. It is padded to 16 bytes
215.23 + * so there will be space for exactly 21 quota-entries in a block
215.24 + */
215.25 +struct qt_disk_dqdbheader {
215.26 + __le32 dqdh_next_free; /* Number of next block with free
215.27 + * entry */
215.28 + __le32 dqdh_prev_free; /* Number of previous block with free
215.29 + * entry */
215.30 + __le16 dqdh_entries; /* Number of valid entries in block */
215.31 + __le16 dqdh_pad1;
215.32 + __le32 dqdh_pad2;
215.33 +} __attribute__ ((packed));
215.34 +
215.35 +struct dquot;
215.36 +struct quota_handle;
215.37 +
215.38 +/* Operations */
215.39 +struct qtree_fmt_operations {
215.40 + /* Convert given entry from in memory format to disk one */
215.41 + void (*mem2disk_dqblk)(void *disk, struct dquot *dquot);
215.42 + /* Convert given entry from disk format to in memory one */
215.43 + void (*disk2mem_dqblk)(struct dquot *dquot, void *disk);
215.44 + /* Is this structure for given id? */
215.45 + int (*is_id)(void *disk, struct dquot *dquot);
215.46 +};
215.47 +
215.48 +/* In-memory copy of version specific information */
215.49 +struct qtree_mem_dqinfo {
215.50 + unsigned int dqi_blocks; /* # of blocks in quota file */
215.51 + unsigned int dqi_free_blk; /* First block in list of free blocks */
215.52 + unsigned int dqi_free_entry; /* First block with free entry */
215.53 + unsigned int dqi_entry_size; /* Size of quota entry in quota file */
215.54 + struct qtree_fmt_operations *dqi_ops; /* Operations for entry
215.55 + * manipulation */
215.56 +};
215.57 +
215.58 +void qtree_write_dquot(struct dquot *dquot);
215.59 +struct dquot *qtree_read_dquot(struct quota_handle *h, qid_t id);
215.60 +void qtree_delete_dquot(struct dquot *dquot);
215.61 +int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk);
215.62 +int qtree_scan_dquots(struct quota_handle *h,
215.63 + int (*process_dquot) (struct dquot *, void *), void *data);
215.64 +
215.65 +int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info);
215.66 +
215.67 +#endif /* _LINUX_QUOTAIO_TREE_H */
216.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
216.2 +++ b/libext2fs/lib/libsupport/quotaio_v2.c Wed Aug 25 01:28:08 2021 +0200
216.3 @@ -0,0 +1,285 @@
216.4 +/*
216.5 + * Implementation of new quotafile format
216.6 + *
216.7 + * Jan Kara <jack@suse.cz> - sponsored by SuSE CR
216.8 + */
216.9 +
216.10 +#include "config.h"
216.11 +#include <sys/types.h>
216.12 +#include <errno.h>
216.13 +#include <stdio.h>
216.14 +#include <stdlib.h>
216.15 +#include <string.h>
216.16 +#include <unistd.h>
216.17 +
216.18 +#include "common.h"
216.19 +#include "quotaio_v2.h"
216.20 +#include "dqblk_v2.h"
216.21 +#include "quotaio.h"
216.22 +#include "quotaio_tree.h"
216.23 +
216.24 +static int v2_check_file(struct quota_handle *h, int type, int fmt);
216.25 +static int v2_init_io(struct quota_handle *h);
216.26 +static int v2_new_io(struct quota_handle *h);
216.27 +static int v2_write_info(struct quota_handle *h);
216.28 +static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id);
216.29 +static int v2_commit_dquot(struct dquot *dquot);
216.30 +static int v2_scan_dquots(struct quota_handle *h,
216.31 + int (*process_dquot) (struct dquot *dquot,
216.32 + void *data),
216.33 + void *data);
216.34 +static int v2_report(struct quota_handle *h, int verbose);
216.35 +
216.36 +struct quotafile_ops quotafile_ops_2 = {
216.37 + .check_file = v2_check_file,
216.38 + .init_io = v2_init_io,
216.39 + .new_io = v2_new_io,
216.40 + .write_info = v2_write_info,
216.41 + .read_dquot = v2_read_dquot,
216.42 + .commit_dquot = v2_commit_dquot,
216.43 + .scan_dquots = v2_scan_dquots,
216.44 + .report = v2_report,
216.45 +};
216.46 +
216.47 +/*
216.48 + * Copy dquot from disk to memory
216.49 + */
216.50 +static void v2r1_disk2memdqblk(struct dquot *dquot, void *dp)
216.51 +{
216.52 + struct util_dqblk *m = &dquot->dq_dqb;
216.53 + struct v2r1_disk_dqblk *d = dp, empty;
216.54 +
216.55 + dquot->dq_id = ext2fs_le32_to_cpu(d->dqb_id);
216.56 + m->dqb_ihardlimit = ext2fs_le64_to_cpu(d->dqb_ihardlimit);
216.57 + m->dqb_isoftlimit = ext2fs_le64_to_cpu(d->dqb_isoftlimit);
216.58 + m->dqb_bhardlimit = ext2fs_le64_to_cpu(d->dqb_bhardlimit);
216.59 + m->dqb_bsoftlimit = ext2fs_le64_to_cpu(d->dqb_bsoftlimit);
216.60 + m->dqb_curinodes = ext2fs_le64_to_cpu(d->dqb_curinodes);
216.61 + m->dqb_curspace = ext2fs_le64_to_cpu(d->dqb_curspace);
216.62 + m->dqb_itime = ext2fs_le64_to_cpu(d->dqb_itime);
216.63 + m->dqb_btime = ext2fs_le64_to_cpu(d->dqb_btime);
216.64 +
216.65 + memset(&empty, 0, sizeof(struct v2r1_disk_dqblk));
216.66 + empty.dqb_itime = ext2fs_cpu_to_le64(1);
216.67 + if (!memcmp(&empty, dp, sizeof(struct v2r1_disk_dqblk)))
216.68 + m->dqb_itime = 0;
216.69 +}
216.70 +
216.71 +/*
216.72 + * Copy dquot from memory to disk
216.73 + */
216.74 +static void v2r1_mem2diskdqblk(void *dp, struct dquot *dquot)
216.75 +{
216.76 + struct util_dqblk *m = &dquot->dq_dqb;
216.77 + struct v2r1_disk_dqblk *d = dp;
216.78 +
216.79 + d->dqb_ihardlimit = ext2fs_cpu_to_le64(m->dqb_ihardlimit);
216.80 + d->dqb_isoftlimit = ext2fs_cpu_to_le64(m->dqb_isoftlimit);
216.81 + d->dqb_bhardlimit = ext2fs_cpu_to_le64(m->dqb_bhardlimit);
216.82 + d->dqb_bsoftlimit = ext2fs_cpu_to_le64(m->dqb_bsoftlimit);
216.83 + d->dqb_curinodes = ext2fs_cpu_to_le64(m->dqb_curinodes);
216.84 + d->dqb_curspace = ext2fs_cpu_to_le64(m->dqb_curspace);
216.85 + d->dqb_itime = ext2fs_cpu_to_le64(m->dqb_itime);
216.86 + d->dqb_btime = ext2fs_cpu_to_le64(m->dqb_btime);
216.87 + d->dqb_id = ext2fs_cpu_to_le32(dquot->dq_id);
216.88 + if (qtree_entry_unused(&dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree, dp))
216.89 + d->dqb_itime = ext2fs_cpu_to_le64(1);
216.90 +}
216.91 +
216.92 +static int v2r1_is_id(void *dp, struct dquot *dquot)
216.93 +{
216.94 + struct v2r1_disk_dqblk *d = dp;
216.95 + struct qtree_mem_dqinfo *info =
216.96 + &dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree;
216.97 +
216.98 + if (qtree_entry_unused(info, dp))
216.99 + return 0;
216.100 + return ext2fs_le32_to_cpu(d->dqb_id) == dquot->dq_id;
216.101 +}
216.102 +
216.103 +static struct qtree_fmt_operations v2r1_fmt_ops = {
216.104 + .mem2disk_dqblk = v2r1_mem2diskdqblk,
216.105 + .disk2mem_dqblk = v2r1_disk2memdqblk,
216.106 + .is_id = v2r1_is_id,
216.107 +};
216.108 +
216.109 +/*
216.110 + * Copy dqinfo from disk to memory
216.111 + */
216.112 +static inline void v2_disk2memdqinfo(struct util_dqinfo *m,
216.113 + struct v2_disk_dqinfo *d)
216.114 +{
216.115 + m->dqi_bgrace = ext2fs_le32_to_cpu(d->dqi_bgrace);
216.116 + m->dqi_igrace = ext2fs_le32_to_cpu(d->dqi_igrace);
216.117 + m->u.v2_mdqi.dqi_flags = ext2fs_le32_to_cpu(d->dqi_flags) & V2_DQF_MASK;
216.118 + m->u.v2_mdqi.dqi_qtree.dqi_blocks = ext2fs_le32_to_cpu(d->dqi_blocks);
216.119 + m->u.v2_mdqi.dqi_qtree.dqi_free_blk =
216.120 + ext2fs_le32_to_cpu(d->dqi_free_blk);
216.121 + m->u.v2_mdqi.dqi_qtree.dqi_free_entry =
216.122 + ext2fs_le32_to_cpu(d->dqi_free_entry);
216.123 +}
216.124 +
216.125 +/*
216.126 + * Copy dqinfo from memory to disk
216.127 + */
216.128 +static inline void v2_mem2diskdqinfo(struct v2_disk_dqinfo *d,
216.129 + struct util_dqinfo *m)
216.130 +{
216.131 + d->dqi_bgrace = ext2fs_cpu_to_le32(m->dqi_bgrace);
216.132 + d->dqi_igrace = ext2fs_cpu_to_le32(m->dqi_igrace);
216.133 + d->dqi_flags = ext2fs_cpu_to_le32(m->u.v2_mdqi.dqi_flags & V2_DQF_MASK);
216.134 + d->dqi_blocks = ext2fs_cpu_to_le32(m->u.v2_mdqi.dqi_qtree.dqi_blocks);
216.135 + d->dqi_free_blk =
216.136 + ext2fs_cpu_to_le32(m->u.v2_mdqi.dqi_qtree.dqi_free_blk);
216.137 + d->dqi_free_entry =
216.138 + ext2fs_cpu_to_le32(m->u.v2_mdqi.dqi_qtree.dqi_free_entry);
216.139 +}
216.140 +
216.141 +static int v2_read_header(struct quota_handle *h, struct v2_disk_dqheader *dqh)
216.142 +{
216.143 + if (h->e2fs_read(&h->qh_qf, 0, dqh, sizeof(struct v2_disk_dqheader)) !=
216.144 + sizeof(struct v2_disk_dqheader))
216.145 + return 0;
216.146 +
216.147 + return 1;
216.148 +}
216.149 +
216.150 +/*
216.151 + * Check whether given quota file is in our format
216.152 + */
216.153 +static int v2_check_file(struct quota_handle *h, int type, int fmt)
216.154 +{
216.155 + struct v2_disk_dqheader dqh;
216.156 + int file_magics[] = INITQMAGICS;
216.157 + int be_magic;
216.158 +
216.159 + if (fmt != QFMT_VFS_V1)
216.160 + return 0;
216.161 +
216.162 + if (!v2_read_header(h, &dqh))
216.163 + return 0;
216.164 +
216.165 + be_magic = ext2fs_be32_to_cpu((__force __be32)dqh.dqh_magic);
216.166 + if (be_magic == file_magics[type]) {
216.167 + log_err("Your quota file is stored in wrong endianity");
216.168 + return 0;
216.169 + }
216.170 + if (V2_VERSION != ext2fs_le32_to_cpu(dqh.dqh_version))
216.171 + return 0;
216.172 + return 1;
216.173 +}
216.174 +
216.175 +/*
216.176 + * Open quotafile
216.177 + */
216.178 +static int v2_init_io(struct quota_handle *h)
216.179 +{
216.180 + struct v2_disk_dqinfo ddqinfo;
216.181 +
216.182 + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size =
216.183 + sizeof(struct v2r1_disk_dqblk);
216.184 + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r1_fmt_ops;
216.185 +
216.186 + /* Read information about quotafile */
216.187 + if (h->e2fs_read(&h->qh_qf, V2_DQINFOOFF, &ddqinfo,
216.188 + sizeof(ddqinfo)) != sizeof(ddqinfo))
216.189 + return -1;
216.190 + v2_disk2memdqinfo(&h->qh_info, &ddqinfo);
216.191 + return 0;
216.192 +}
216.193 +
216.194 +/*
216.195 + * Initialize new quotafile
216.196 + */
216.197 +static int v2_new_io(struct quota_handle *h)
216.198 +{
216.199 + int file_magics[] = INITQMAGICS;
216.200 + struct v2_disk_dqheader ddqheader;
216.201 + struct v2_disk_dqinfo ddqinfo;
216.202 +
216.203 + if (h->qh_fmt != QFMT_VFS_V1)
216.204 + return -1;
216.205 +
216.206 + /* Write basic quota header */
216.207 + ddqheader.dqh_magic = ext2fs_cpu_to_le32(file_magics[h->qh_type]);
216.208 + ddqheader.dqh_version = ext2fs_cpu_to_le32(V2_VERSION);
216.209 + if (h->e2fs_write(&h->qh_qf, 0, &ddqheader, sizeof(ddqheader)) !=
216.210 + sizeof(ddqheader))
216.211 + return -1;
216.212 +
216.213 + /* Write information about quotafile */
216.214 + h->qh_info.dqi_bgrace = MAX_DQ_TIME;
216.215 + h->qh_info.dqi_igrace = MAX_IQ_TIME;
216.216 + h->qh_info.u.v2_mdqi.dqi_flags = 0;
216.217 + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks = QT_TREEOFF + 1;
216.218 + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_blk = 0;
216.219 + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_entry = 0;
216.220 + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size =
216.221 + sizeof(struct v2r1_disk_dqblk);
216.222 + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r1_fmt_ops;
216.223 + v2_mem2diskdqinfo(&ddqinfo, &h->qh_info);
216.224 + if (h->e2fs_write(&h->qh_qf, V2_DQINFOOFF, &ddqinfo,
216.225 + sizeof(ddqinfo)) !=
216.226 + sizeof(ddqinfo))
216.227 + return -1;
216.228 +
216.229 + return 0;
216.230 +}
216.231 +
216.232 +/*
216.233 + * Write information (grace times to file)
216.234 + */
216.235 +static int v2_write_info(struct quota_handle *h)
216.236 +{
216.237 + struct v2_disk_dqinfo ddqinfo;
216.238 +
216.239 + v2_mem2diskdqinfo(&ddqinfo, &h->qh_info);
216.240 + if (h->e2fs_write(&h->qh_qf, V2_DQINFOOFF, &ddqinfo, sizeof(ddqinfo)) !=
216.241 + sizeof(ddqinfo))
216.242 + return -1;
216.243 +
216.244 + return 0;
216.245 +}
216.246 +
216.247 +/*
216.248 + * Read dquot from disk
216.249 + */
216.250 +static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id)
216.251 +{
216.252 + return qtree_read_dquot(h, id);
216.253 +}
216.254 +
216.255 +/*
216.256 + * Commit changes of dquot to disk - it might also mean deleting it when quota
216.257 + * became fake one and user has no blocks.
216.258 + * User can process use 'errno' to detect errstr.
216.259 + */
216.260 +static int v2_commit_dquot(struct dquot *dquot)
216.261 +{
216.262 + struct util_dqblk *b = &dquot->dq_dqb;
216.263 +
216.264 + if (!b->dqb_curspace && !b->dqb_curinodes && !b->dqb_bsoftlimit &&
216.265 + !b->dqb_isoftlimit && !b->dqb_bhardlimit && !b->dqb_ihardlimit)
216.266 + qtree_delete_dquot(dquot);
216.267 + else
216.268 + qtree_write_dquot(dquot);
216.269 + return 0;
216.270 +}
216.271 +
216.272 +static int v2_scan_dquots(struct quota_handle *h,
216.273 + int (*process_dquot) (struct dquot *, void *),
216.274 + void *data)
216.275 +{
216.276 + return qtree_scan_dquots(h, process_dquot, data);
216.277 +}
216.278 +
216.279 +/* Report information about quotafile.
216.280 + * TODO: Not used right now, but we should be able to use this when we add
216.281 + * support to debugfs to read quota files.
216.282 + */
216.283 +static int v2_report(struct quota_handle *h EXT2FS_ATTR((unused)),
216.284 + int verbose EXT2FS_ATTR((unused)))
216.285 +{
216.286 + log_err("Not Implemented.");
216.287 + return -1;
216.288 +}
217.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
217.2 +++ b/libext2fs/lib/libsupport/quotaio_v2.h Wed Aug 25 01:28:08 2021 +0200
217.3 @@ -0,0 +1,54 @@
217.4 +/*
217.5 + *
217.6 + * Header file for disk format of new quotafile format
217.7 + *
217.8 + */
217.9 +
217.10 +#ifndef GUARD_QUOTAIO_V2_H
217.11 +#define GUARD_QUOTAIO_V2_H
217.12 +
217.13 +#include <sys/types.h>
217.14 +#include "quotaio.h"
217.15 +
217.16 +/* Offset of info header in file */
217.17 +#define V2_DQINFOOFF sizeof(struct v2_disk_dqheader)
217.18 +/* Supported version of quota-tree format */
217.19 +#define V2_VERSION 1
217.20 +
217.21 +struct v2_disk_dqheader {
217.22 + __le32 dqh_magic; /* Magic number identifying file */
217.23 + __le32 dqh_version; /* File version */
217.24 +} __attribute__ ((packed));
217.25 +
217.26 +/* Flags for version specific files */
217.27 +#define V2_DQF_MASK 0x0000 /* Mask for all valid ondisk flags */
217.28 +
217.29 +/* Header with type and version specific information */
217.30 +struct v2_disk_dqinfo {
217.31 + __le32 dqi_bgrace; /* Time before block soft limit becomes
217.32 + * hard limit */
217.33 + __le32 dqi_igrace; /* Time before inode soft limit becomes
217.34 + * hard limit */
217.35 + __le32 dqi_flags; /* Flags for quotafile (DQF_*) */
217.36 + __le32 dqi_blocks; /* Number of blocks in file */
217.37 + __le32 dqi_free_blk; /* Number of first free block in the list */
217.38 + __le32 dqi_free_entry; /* Number of block with at least one
217.39 + * free entry */
217.40 +} __attribute__ ((packed));
217.41 +
217.42 +struct v2r1_disk_dqblk {
217.43 + __le32 dqb_id; /* id this quota applies to */
217.44 + __le32 dqb_pad;
217.45 + __le64 dqb_ihardlimit; /* absolute limit on allocated inodes */
217.46 + __le64 dqb_isoftlimit; /* preferred inode limit */
217.47 + __le64 dqb_curinodes; /* current # allocated inodes */
217.48 + __le64 dqb_bhardlimit; /* absolute limit on disk space
217.49 + * (in QUOTABLOCK_SIZE) */
217.50 + __le64 dqb_bsoftlimit; /* preferred limit on disk space
217.51 + * (in QUOTABLOCK_SIZE) */
217.52 + __le64 dqb_curspace; /* current space occupied (in bytes) */
217.53 + __le64 dqb_btime; /* time limit for excessive disk use */
217.54 + __le64 dqb_itime; /* time limit for excessive inode use */
217.55 +} __attribute__ ((packed));
217.56 +
217.57 +#endif
218.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
218.2 +++ b/libext2fs/lib/libuuid/Makefile Wed Aug 25 01:28:08 2021 +0200
218.3 @@ -0,0 +1,16 @@
218.4 +PKGDIR ?= ../..
218.5 +L4DIR ?= $(PKGDIR)/../../..
218.6 +
218.7 +TARGET = libuuid.a libuuid.so
218.8 +PC_FILENAME = libuuid
218.9 +SRC_C = \
218.10 + clear.c compare.c copy.c gen_uuid.c isnull.c pack.c \
218.11 + parse.c tst_uuid.c unpack.c unparse.c uuid_time.c
218.12 +
218.13 +PRIVATE_INCDIR += \
218.14 + $(PKGDIR)/lib $(PKGDIR)/lib/libuuid \
218.15 + $(PKGDIR)/include/libuuid
218.16 +
218.17 +CONTRIB_INCDIR = libuuid
218.18 +
218.19 +include $(L4DIR)/mk/lib.mk
219.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
219.2 +++ b/libext2fs/lib/libuuid/clear.c Wed Aug 25 01:28:08 2021 +0200
219.3 @@ -0,0 +1,44 @@
219.4 +/*
219.5 + * clear.c -- Clear a UUID
219.6 + *
219.7 + * Copyright (C) 1996, 1997 Theodore Ts'o.
219.8 + *
219.9 + * %Begin-Header%
219.10 + * Redistribution and use in source and binary forms, with or without
219.11 + * modification, are permitted provided that the following conditions
219.12 + * are met:
219.13 + * 1. Redistributions of source code must retain the above copyright
219.14 + * notice, and the entire permission notice in its entirety,
219.15 + * including the disclaimer of warranties.
219.16 + * 2. Redistributions in binary form must reproduce the above copyright
219.17 + * notice, this list of conditions and the following disclaimer in the
219.18 + * documentation and/or other materials provided with the distribution.
219.19 + * 3. The name of the author may not be used to endorse or promote
219.20 + * products derived from this software without specific prior
219.21 + * written permission.
219.22 + *
219.23 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
219.24 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
219.25 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
219.26 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
219.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
219.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
219.29 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
219.30 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
219.31 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
219.32 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
219.33 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
219.34 + * DAMAGE.
219.35 + * %End-Header%
219.36 + */
219.37 +
219.38 +#include "config.h"
219.39 +#include "string.h"
219.40 +
219.41 +#include "uuidP.h"
219.42 +
219.43 +void uuid_clear(uuid_t uu)
219.44 +{
219.45 + memset(uu, 0, 16);
219.46 +}
219.47 +
220.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
220.2 +++ b/libext2fs/lib/libuuid/compare.c Wed Aug 25 01:28:08 2021 +0200
220.3 @@ -0,0 +1,56 @@
220.4 +/*
220.5 + * compare.c --- compare whether or not two UUID's are the same
220.6 + *
220.7 + * Returns 0 if the two UUID's are different, and 1 if they are the same.
220.8 + *
220.9 + * Copyright (C) 1996, 1997 Theodore Ts'o.
220.10 + *
220.11 + * %Begin-Header%
220.12 + * Redistribution and use in source and binary forms, with or without
220.13 + * modification, are permitted provided that the following conditions
220.14 + * are met:
220.15 + * 1. Redistributions of source code must retain the above copyright
220.16 + * notice, and the entire permission notice in its entirety,
220.17 + * including the disclaimer of warranties.
220.18 + * 2. Redistributions in binary form must reproduce the above copyright
220.19 + * notice, this list of conditions and the following disclaimer in the
220.20 + * documentation and/or other materials provided with the distribution.
220.21 + * 3. The name of the author may not be used to endorse or promote
220.22 + * products derived from this software without specific prior
220.23 + * written permission.
220.24 + *
220.25 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
220.26 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
220.27 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
220.28 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
220.29 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
220.30 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
220.31 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
220.32 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
220.33 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
220.34 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
220.35 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
220.36 + * DAMAGE.
220.37 + * %End-Header%
220.38 + */
220.39 +
220.40 +#include "config.h"
220.41 +#include "uuidP.h"
220.42 +#include <string.h>
220.43 +
220.44 +#define UUCMP(u1,u2) if (u1 != u2) return((u1 < u2) ? -1 : 1);
220.45 +
220.46 +int uuid_compare(const uuid_t uu1, const uuid_t uu2)
220.47 +{
220.48 + struct uuid uuid1, uuid2;
220.49 +
220.50 + uuid_unpack(uu1, &uuid1);
220.51 + uuid_unpack(uu2, &uuid2);
220.52 +
220.53 + UUCMP(uuid1.time_low, uuid2.time_low);
220.54 + UUCMP(uuid1.time_mid, uuid2.time_mid);
220.55 + UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
220.56 + UUCMP(uuid1.clock_seq, uuid2.clock_seq);
220.57 + return memcmp(uuid1.node, uuid2.node, 6);
220.58 +}
220.59 +
221.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
221.2 +++ b/libext2fs/lib/libuuid/copy.c Wed Aug 25 01:28:08 2021 +0200
221.3 @@ -0,0 +1,46 @@
221.4 +/*
221.5 + * copy.c --- copy UUIDs
221.6 + *
221.7 + * Copyright (C) 1996, 1997 Theodore Ts'o.
221.8 + *
221.9 + * %Begin-Header%
221.10 + * Redistribution and use in source and binary forms, with or without
221.11 + * modification, are permitted provided that the following conditions
221.12 + * are met:
221.13 + * 1. Redistributions of source code must retain the above copyright
221.14 + * notice, and the entire permission notice in its entirety,
221.15 + * including the disclaimer of warranties.
221.16 + * 2. Redistributions in binary form must reproduce the above copyright
221.17 + * notice, this list of conditions and the following disclaimer in the
221.18 + * documentation and/or other materials provided with the distribution.
221.19 + * 3. The name of the author may not be used to endorse or promote
221.20 + * products derived from this software without specific prior
221.21 + * written permission.
221.22 + *
221.23 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
221.24 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
221.25 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
221.26 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
221.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
221.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
221.29 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
221.30 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
221.31 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
221.32 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
221.33 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
221.34 + * DAMAGE.
221.35 + * %End-Header%
221.36 + */
221.37 +
221.38 +#include "config.h"
221.39 +#include "uuidP.h"
221.40 +
221.41 +void uuid_copy(uuid_t dst, const uuid_t src)
221.42 +{
221.43 + unsigned char *cp1;
221.44 + const unsigned char *cp2;
221.45 + int i;
221.46 +
221.47 + for (i=0, cp1 = dst, cp2 = src; i < 16; i++)
221.48 + *cp1++ = *cp2++;
221.49 +}
222.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
222.2 +++ b/libext2fs/lib/libuuid/gen_uuid.c Wed Aug 25 01:28:08 2021 +0200
222.3 @@ -0,0 +1,694 @@
222.4 +/*
222.5 + * gen_uuid.c --- generate a DCE-compatible uuid
222.6 + *
222.7 + * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
222.8 + *
222.9 + * %Begin-Header%
222.10 + * Redistribution and use in source and binary forms, with or without
222.11 + * modification, are permitted provided that the following conditions
222.12 + * are met:
222.13 + * 1. Redistributions of source code must retain the above copyright
222.14 + * notice, and the entire permission notice in its entirety,
222.15 + * including the disclaimer of warranties.
222.16 + * 2. Redistributions in binary form must reproduce the above copyright
222.17 + * notice, this list of conditions and the following disclaimer in the
222.18 + * documentation and/or other materials provided with the distribution.
222.19 + * 3. The name of the author may not be used to endorse or promote
222.20 + * products derived from this software without specific prior
222.21 + * written permission.
222.22 + *
222.23 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
222.24 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
222.25 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
222.26 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
222.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
222.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
222.29 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
222.30 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
222.31 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
222.32 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
222.33 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
222.34 + * DAMAGE.
222.35 + * %End-Header%
222.36 + */
222.37 +
222.38 +/*
222.39 + * Force inclusion of SVID stuff since we need it if we're compiling in
222.40 + * gcc-wall wall mode
222.41 + */
222.42 +#define _SVID_SOURCE
222.43 +#define _DEFAULT_SOURCE /* since glibc 2.20 _SVID_SOURCE is deprecated */
222.44 +
222.45 +#include "config.h"
222.46 +
222.47 +#ifdef _WIN32
222.48 +#define _WIN32_WINNT 0x0500
222.49 +#include <windows.h>
222.50 +#define UUID MYUUID
222.51 +#endif
222.52 +#include <stdio.h>
222.53 +#ifdef HAVE_UNISTD_H
222.54 +#include <unistd.h>
222.55 +#endif
222.56 +#ifdef HAVE_STDLIB_H
222.57 +#include <stdlib.h>
222.58 +#endif
222.59 +#include <string.h>
222.60 +#include <fcntl.h>
222.61 +#include <errno.h>
222.62 +#include <sys/types.h>
222.63 +#ifdef HAVE_SYS_TIME_H
222.64 +#include <sys/time.h>
222.65 +#endif
222.66 +#ifdef HAVE_SYS_WAIT_H
222.67 +#include <sys/wait.h>
222.68 +#endif
222.69 +#include <sys/stat.h>
222.70 +#ifdef HAVE_SYS_FILE_H
222.71 +#include <sys/file.h>
222.72 +#endif
222.73 +#ifdef HAVE_SYS_IOCTL_H
222.74 +#include <sys/ioctl.h>
222.75 +#endif
222.76 +#ifdef HAVE_SYS_SOCKET_H
222.77 +#include <sys/socket.h>
222.78 +#endif
222.79 +#ifdef HAVE_SYS_UN_H
222.80 +#include <sys/un.h>
222.81 +#endif
222.82 +#ifdef HAVE_SYS_SOCKIO_H
222.83 +#include <sys/sockio.h>
222.84 +#endif
222.85 +#ifdef HAVE_NET_IF_H
222.86 +#include <net/if.h>
222.87 +#endif
222.88 +#ifdef HAVE_NETINET_IN_H
222.89 +#include <netinet/in.h>
222.90 +#endif
222.91 +#ifdef HAVE_NET_IF_DL_H
222.92 +#include <net/if_dl.h>
222.93 +#endif
222.94 +#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
222.95 +#include <sys/syscall.h>
222.96 +#endif
222.97 +#ifdef HAVE_SYS_RESOURCE_H
222.98 +#include <sys/resource.h>
222.99 +#endif
222.100 +
222.101 +#include "uuidP.h"
222.102 +#include "uuidd.h"
222.103 +
222.104 +#ifdef HAVE_SRANDOM
222.105 +#define srand(x) srandom(x)
222.106 +#define rand() random()
222.107 +#endif
222.108 +
222.109 +#ifdef TLS
222.110 +#define THREAD_LOCAL static TLS
222.111 +#else
222.112 +#define THREAD_LOCAL static
222.113 +#endif
222.114 +
222.115 +#if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48)
222.116 +#define DO_JRAND_MIX
222.117 +THREAD_LOCAL unsigned short jrand_seed[3];
222.118 +#endif
222.119 +
222.120 +#ifdef _WIN32
222.121 +#ifndef USE_MINGW
222.122 +static void gettimeofday (struct timeval *tv, void *dummy)
222.123 +{
222.124 + FILETIME ftime;
222.125 + uint64_t n;
222.126 +
222.127 + GetSystemTimeAsFileTime (&ftime);
222.128 + n = (((uint64_t) ftime.dwHighDateTime << 32)
222.129 + + (uint64_t) ftime.dwLowDateTime);
222.130 + if (n) {
222.131 + n /= 10;
222.132 + n -= ((369 * 365 + 89) * (uint64_t) 86400) * 1000000;
222.133 + }
222.134 +
222.135 + tv->tv_sec = n / 1000000;
222.136 + tv->tv_usec = n % 1000000;
222.137 +}
222.138 +#endif
222.139 +#endif
222.140 +
222.141 +static int get_random_fd(void)
222.142 +{
222.143 + struct timeval tv;
222.144 + static int fd = -2;
222.145 + int i;
222.146 +
222.147 + if (fd == -2) {
222.148 + gettimeofday(&tv, 0);
222.149 +#ifndef _WIN32
222.150 + fd = open("/dev/urandom", O_RDONLY);
222.151 + if (fd == -1)
222.152 + fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
222.153 + if (fd >= 0) {
222.154 + i = fcntl(fd, F_GETFD);
222.155 + if (i >= 0)
222.156 + fcntl(fd, F_SETFD, i | FD_CLOEXEC);
222.157 + }
222.158 +#endif
222.159 + srand(((unsigned)getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
222.160 +#ifdef DO_JRAND_MIX
222.161 + jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF);
222.162 + jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF);
222.163 + jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16;
222.164 +#endif
222.165 + }
222.166 + /* Crank the random number generator a few times */
222.167 + gettimeofday(&tv, 0);
222.168 + for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
222.169 + rand();
222.170 + return fd;
222.171 +}
222.172 +
222.173 +
222.174 +/*
222.175 + * Generate a series of random bytes. Use /dev/urandom if possible,
222.176 + * and if not, use srandom/random.
222.177 + */
222.178 +static void get_random_bytes(void *buf, int nbytes)
222.179 +{
222.180 + int i, n = nbytes, fd = get_random_fd();
222.181 + int lose_counter = 0;
222.182 + unsigned char *cp = buf;
222.183 +
222.184 + if (fd >= 0) {
222.185 + while (n > 0) {
222.186 + i = read(fd, cp, n);
222.187 + if (i <= 0) {
222.188 + if (lose_counter++ > 16)
222.189 + break;
222.190 + continue;
222.191 + }
222.192 + n -= i;
222.193 + cp += i;
222.194 + lose_counter = 0;
222.195 + }
222.196 + }
222.197 +
222.198 + /*
222.199 + * We do this all the time, but this is the only source of
222.200 + * randomness if /dev/random/urandom is out to lunch.
222.201 + */
222.202 + for (cp = buf, i = 0; i < nbytes; i++)
222.203 + *cp++ ^= (rand() >> 7) & 0xFF;
222.204 +#ifdef DO_JRAND_MIX
222.205 + {
222.206 + unsigned short tmp_seed[3];
222.207 +
222.208 + memcpy(tmp_seed, jrand_seed, sizeof(tmp_seed));
222.209 + jrand_seed[2] = jrand_seed[2] ^ syscall(__NR_gettid);
222.210 + for (cp = buf, i = 0; i < nbytes; i++)
222.211 + *cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF;
222.212 + memcpy(jrand_seed, tmp_seed,
222.213 + sizeof(jrand_seed) - sizeof(unsigned short));
222.214 + }
222.215 +#endif
222.216 +
222.217 + return;
222.218 +}
222.219 +
222.220 +/*
222.221 + * Get the ethernet hardware address, if we can find it...
222.222 + *
222.223 + * XXX for a windows version, probably should use GetAdaptersInfo:
222.224 + * http://www.codeguru.com/cpp/i-n/network/networkinformation/article.php/c5451
222.225 + * commenting out get_node_id just to get gen_uuid to compile under windows
222.226 + * is not the right way to go!
222.227 + */
222.228 +static int get_node_id(unsigned char *node_id)
222.229 +{
222.230 +#ifdef HAVE_NET_IF_H
222.231 + int sd;
222.232 + struct ifreq ifr, *ifrp;
222.233 + struct ifconf ifc;
222.234 + char buf[1024];
222.235 + int n, i;
222.236 + unsigned char *a;
222.237 +#ifdef HAVE_NET_IF_DL_H
222.238 + struct sockaddr_dl *sdlp;
222.239 +#endif
222.240 +
222.241 +/*
222.242 + * BSD 4.4 defines the size of an ifreq to be
222.243 + * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
222.244 + * However, under earlier systems, sa_len isn't present, so the size is
222.245 + * just sizeof(struct ifreq)
222.246 + */
222.247 +#ifdef HAVE_SA_LEN
222.248 +#ifndef max
222.249 +#define max(a,b) ((a) > (b) ? (a) : (b))
222.250 +#endif
222.251 +#define ifreq_size(i) max(sizeof(struct ifreq),\
222.252 + sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
222.253 +#else
222.254 +#define ifreq_size(i) sizeof(struct ifreq)
222.255 +#endif /* HAVE_SA_LEN*/
222.256 +
222.257 + sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
222.258 + if (sd < 0) {
222.259 + return -1;
222.260 + }
222.261 + memset(buf, 0, sizeof(buf));
222.262 + ifc.ifc_len = sizeof(buf);
222.263 + ifc.ifc_buf = buf;
222.264 + if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
222.265 + close(sd);
222.266 + return -1;
222.267 + }
222.268 + n = ifc.ifc_len;
222.269 + for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
222.270 + ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
222.271 + strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
222.272 +#ifdef SIOCGIFHWADDR
222.273 + if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
222.274 + continue;
222.275 + a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
222.276 +#else
222.277 +#ifdef SIOCGENADDR
222.278 + if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
222.279 + continue;
222.280 + a = (unsigned char *) ifr.ifr_enaddr;
222.281 +#else
222.282 +#ifdef HAVE_NET_IF_DL_H
222.283 + sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
222.284 + if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
222.285 + continue;
222.286 + a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
222.287 +#else
222.288 + /*
222.289 + * XXX we don't have a way of getting the hardware
222.290 + * address
222.291 + */
222.292 + close(sd);
222.293 + return 0;
222.294 +#endif /* HAVE_NET_IF_DL_H */
222.295 +#endif /* SIOCGENADDR */
222.296 +#endif /* SIOCGIFHWADDR */
222.297 + if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
222.298 + continue;
222.299 + if (node_id) {
222.300 + memcpy(node_id, a, 6);
222.301 + close(sd);
222.302 + return 1;
222.303 + }
222.304 + }
222.305 + close(sd);
222.306 +#endif
222.307 + return 0;
222.308 +}
222.309 +
222.310 +/* Assume that the gettimeofday() has microsecond granularity */
222.311 +#define MAX_ADJUSTMENT 10
222.312 +
222.313 +static int get_clock(uint32_t *clock_high, uint32_t *clock_low,
222.314 + uint16_t *ret_clock_seq, int *num)
222.315 +{
222.316 + THREAD_LOCAL int adjustment = 0;
222.317 + THREAD_LOCAL struct timeval last = {0, 0};
222.318 + THREAD_LOCAL int state_fd = -2;
222.319 + THREAD_LOCAL FILE *state_f;
222.320 + THREAD_LOCAL uint16_t clock_seq;
222.321 + struct timeval tv;
222.322 +#ifndef _WIN32
222.323 + struct flock fl;
222.324 +#endif
222.325 + uint64_t clock_reg;
222.326 + mode_t save_umask;
222.327 + int len;
222.328 +
222.329 + if (state_fd == -2) {
222.330 + save_umask = umask(0);
222.331 + state_fd = open("/var/lib/libuuid/clock.txt",
222.332 + O_RDWR|O_CREAT, 0660);
222.333 + (void) umask(save_umask);
222.334 + if (state_fd >= 0) {
222.335 + state_f = fdopen(state_fd, "r+");
222.336 + if (!state_f) {
222.337 + close(state_fd);
222.338 + state_fd = -1;
222.339 + }
222.340 + }
222.341 + }
222.342 +#ifndef _WIN32
222.343 + fl.l_type = F_WRLCK;
222.344 + fl.l_whence = SEEK_SET;
222.345 + fl.l_start = 0;
222.346 + fl.l_len = 0;
222.347 + fl.l_pid = 0;
222.348 + if (state_fd >= 0) {
222.349 + rewind(state_f);
222.350 + while (fcntl(state_fd, F_SETLKW, &fl) < 0) {
222.351 + if ((errno == EAGAIN) || (errno == EINTR))
222.352 + continue;
222.353 + fclose(state_f);
222.354 + state_fd = -1;
222.355 + break;
222.356 + }
222.357 + }
222.358 +#endif
222.359 + if (state_fd >= 0) {
222.360 + unsigned int cl;
222.361 + unsigned long tv1, tv2;
222.362 + int a;
222.363 +
222.364 + if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n",
222.365 + &cl, &tv1, &tv2, &a) == 4) {
222.366 + clock_seq = cl & 0x3FFF;
222.367 + last.tv_sec = tv1;
222.368 + last.tv_usec = tv2;
222.369 + adjustment = a;
222.370 + }
222.371 + }
222.372 +
222.373 + if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
222.374 + get_random_bytes(&clock_seq, sizeof(clock_seq));
222.375 + clock_seq &= 0x3FFF;
222.376 + gettimeofday(&last, 0);
222.377 + last.tv_sec--;
222.378 + }
222.379 +
222.380 +try_again:
222.381 + gettimeofday(&tv, 0);
222.382 + if ((tv.tv_sec < last.tv_sec) ||
222.383 + ((tv.tv_sec == last.tv_sec) &&
222.384 + (tv.tv_usec < last.tv_usec))) {
222.385 + clock_seq = (clock_seq+1) & 0x3FFF;
222.386 + adjustment = 0;
222.387 + last = tv;
222.388 + } else if ((tv.tv_sec == last.tv_sec) &&
222.389 + (tv.tv_usec == last.tv_usec)) {
222.390 + if (adjustment >= MAX_ADJUSTMENT)
222.391 + goto try_again;
222.392 + adjustment++;
222.393 + } else {
222.394 + adjustment = 0;
222.395 + last = tv;
222.396 + }
222.397 +
222.398 + clock_reg = tv.tv_usec*10 + adjustment;
222.399 + clock_reg += ((uint64_t) tv.tv_sec)*10000000;
222.400 + clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000;
222.401 +
222.402 + if (num && (*num > 1)) {
222.403 + adjustment += *num - 1;
222.404 + last.tv_usec += adjustment / 10;
222.405 + adjustment = adjustment % 10;
222.406 + last.tv_sec += last.tv_usec / 1000000;
222.407 + last.tv_usec = last.tv_usec % 1000000;
222.408 + }
222.409 +
222.410 + if (state_fd > 0) {
222.411 + rewind(state_f);
222.412 + len = fprintf(state_f,
222.413 + "clock: %04x tv: %016lu %08lu adj: %08d\n",
222.414 + clock_seq, last.tv_sec, (long)last.tv_usec,
222.415 + adjustment);
222.416 + fflush(state_f);
222.417 + if (ftruncate(state_fd, len) < 0) {
222.418 + fprintf(state_f, " \n");
222.419 + fflush(state_f);
222.420 + }
222.421 + rewind(state_f);
222.422 +#ifndef _WIN32
222.423 + fl.l_type = F_UNLCK;
222.424 + if (fcntl(state_fd, F_SETLK, &fl) < 0) {
222.425 + fclose(state_f);
222.426 + state_fd = -1;
222.427 + }
222.428 +#endif
222.429 + }
222.430 +
222.431 + *clock_high = clock_reg >> 32;
222.432 + *clock_low = clock_reg;
222.433 + *ret_clock_seq = clock_seq;
222.434 + return 0;
222.435 +}
222.436 +
222.437 +#if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
222.438 +static ssize_t read_all(int fd, char *buf, size_t count)
222.439 +{
222.440 + ssize_t ret;
222.441 + ssize_t c = 0;
222.442 + int tries = 0;
222.443 +
222.444 + memset(buf, 0, count);
222.445 + while (count > 0) {
222.446 + ret = read(fd, buf, count);
222.447 + if (ret <= 0) {
222.448 + if ((errno == EAGAIN || errno == EINTR || ret == 0) &&
222.449 + (tries++ < 5))
222.450 + continue;
222.451 + return c ? c : -1;
222.452 + }
222.453 + if (ret > 0)
222.454 + tries = 0;
222.455 + count -= ret;
222.456 + buf += ret;
222.457 + c += ret;
222.458 + }
222.459 + return c;
222.460 +}
222.461 +
222.462 +/*
222.463 + * Close all file descriptors
222.464 + */
222.465 +static void close_all_fds(void)
222.466 +{
222.467 + int i, max;
222.468 +
222.469 +#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
222.470 + max = sysconf(_SC_OPEN_MAX);
222.471 +#elif defined(HAVE_GETDTABLESIZE)
222.472 + max = getdtablesize();
222.473 +#elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
222.474 + struct rlimit rl;
222.475 +
222.476 + getrlimit(RLIMIT_NOFILE, &rl);
222.477 + max = rl.rlim_cur;
222.478 +#else
222.479 + max = OPEN_MAX;
222.480 +#endif
222.481 +
222.482 + for (i=0; i < max; i++) {
222.483 + close(i);
222.484 + if (i <= 2)
222.485 + open("/dev/null", O_RDWR);
222.486 + }
222.487 +}
222.488 +#endif /* defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) */
222.489 +
222.490 +#if __GNUC_PREREQ (4, 6)
222.491 +#pragma GCC diagnostic push
222.492 +#if !defined(USE_UUIDD) || !defined(HAVE_SYS_UN_H)
222.493 +#pragma GCC diagnostic ignored "-Wunused-parameter"
222.494 +#endif
222.495 +#endif
222.496 +/*
222.497 + * Try using the uuidd daemon to generate the UUID
222.498 + *
222.499 + * Returns 0 on success, non-zero on failure.
222.500 + */
222.501 +static int get_uuid_via_daemon(int op, uuid_t out, int *num)
222.502 +{
222.503 +#if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
222.504 + char op_buf[64];
222.505 + int op_len;
222.506 + int s;
222.507 + ssize_t ret;
222.508 + int32_t reply_len = 0, expected = 16;
222.509 + struct sockaddr_un srv_addr;
222.510 + struct stat st;
222.511 + pid_t pid;
222.512 + static const char *uuidd_path = UUIDD_PATH;
222.513 + static int access_ret = -2;
222.514 + static int start_attempts = 0;
222.515 +
222.516 + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
222.517 + return -1;
222.518 +
222.519 + srv_addr.sun_family = AF_UNIX;
222.520 + strcpy(srv_addr.sun_path, UUIDD_SOCKET_PATH);
222.521 +
222.522 + if (connect(s, (const struct sockaddr *) &srv_addr,
222.523 + sizeof(struct sockaddr_un)) < 0) {
222.524 + if (access_ret == -2)
222.525 + access_ret = access(uuidd_path, X_OK);
222.526 + if (access_ret == 0)
222.527 + access_ret = stat(uuidd_path, &st);
222.528 + if (access_ret == 0 && (st.st_mode & (S_ISUID | S_ISGID)) == 0)
222.529 + access_ret = access(UUIDD_DIR, W_OK);
222.530 + if (access_ret == 0 && start_attempts++ < 5) {
222.531 + if ((pid = fork()) == 0) {
222.532 + close_all_fds();
222.533 + execl(uuidd_path, "uuidd", "-qT", "300",
222.534 + (char *) NULL);
222.535 + exit(1);
222.536 + }
222.537 + (void) waitpid(pid, 0, 0);
222.538 + if (connect(s, (const struct sockaddr *) &srv_addr,
222.539 + sizeof(struct sockaddr_un)) < 0)
222.540 + goto fail;
222.541 + } else
222.542 + goto fail;
222.543 + }
222.544 + op_buf[0] = op;
222.545 + op_len = 1;
222.546 + if (op == UUIDD_OP_BULK_TIME_UUID) {
222.547 + memcpy(op_buf+1, num, sizeof(*num));
222.548 + op_len += sizeof(*num);
222.549 + expected += sizeof(*num);
222.550 + }
222.551 +
222.552 + ret = write(s, op_buf, op_len);
222.553 + if (ret < 1)
222.554 + goto fail;
222.555 +
222.556 + ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
222.557 + if (ret < 0)
222.558 + goto fail;
222.559 +
222.560 + if (reply_len != expected)
222.561 + goto fail;
222.562 +
222.563 + ret = read_all(s, op_buf, reply_len);
222.564 +
222.565 + if (op == UUIDD_OP_BULK_TIME_UUID)
222.566 + memcpy(op_buf+16, num, sizeof(int));
222.567 +
222.568 + memcpy(out, op_buf, 16);
222.569 +
222.570 + close(s);
222.571 + return ((ret == expected) ? 0 : -1);
222.572 +
222.573 +fail:
222.574 + close(s);
222.575 +#endif
222.576 + return -1;
222.577 +}
222.578 +#if __GNUC_PREREQ (4, 6)
222.579 +#pragma GCC diagnostic pop
222.580 +#endif
222.581 +
222.582 +void uuid__generate_time(uuid_t out, int *num)
222.583 +{
222.584 + static unsigned char node_id[6];
222.585 + static int has_init = 0;
222.586 + struct uuid uu;
222.587 + uint32_t clock_mid;
222.588 +
222.589 + if (!has_init) {
222.590 + if (get_node_id(node_id) <= 0) {
222.591 + get_random_bytes(node_id, 6);
222.592 + /*
222.593 + * Set multicast bit, to prevent conflicts
222.594 + * with IEEE 802 addresses obtained from
222.595 + * network cards
222.596 + */
222.597 + node_id[0] |= 0x01;
222.598 + }
222.599 + has_init = 1;
222.600 + }
222.601 + get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num);
222.602 + uu.clock_seq |= 0x8000;
222.603 + uu.time_mid = (uint16_t) clock_mid;
222.604 + uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000;
222.605 + memcpy(uu.node, node_id, 6);
222.606 + uuid_pack(&uu, out);
222.607 +}
222.608 +
222.609 +void uuid_generate_time(uuid_t out)
222.610 +{
222.611 +#ifdef TLS
222.612 + THREAD_LOCAL int num = 0;
222.613 + THREAD_LOCAL struct uuid uu;
222.614 + THREAD_LOCAL time_t last_time = 0;
222.615 + time_t now;
222.616 +
222.617 + if (num > 0) {
222.618 + now = time(0);
222.619 + if (now > last_time+1)
222.620 + num = 0;
222.621 + }
222.622 + if (num <= 0) {
222.623 + num = 1000;
222.624 + if (get_uuid_via_daemon(UUIDD_OP_BULK_TIME_UUID,
222.625 + out, &num) == 0) {
222.626 + last_time = time(0);
222.627 + uuid_unpack(out, &uu);
222.628 + num--;
222.629 + return;
222.630 + }
222.631 + num = 0;
222.632 + }
222.633 + if (num > 0) {
222.634 + uu.time_low++;
222.635 + if (uu.time_low == 0) {
222.636 + uu.time_mid++;
222.637 + if (uu.time_mid == 0)
222.638 + uu.time_hi_and_version++;
222.639 + }
222.640 + num--;
222.641 + uuid_pack(&uu, out);
222.642 + return;
222.643 + }
222.644 +#else
222.645 + if (get_uuid_via_daemon(UUIDD_OP_TIME_UUID, out, 0) == 0)
222.646 + return;
222.647 +#endif
222.648 +
222.649 + uuid__generate_time(out, 0);
222.650 +}
222.651 +
222.652 +
222.653 +void uuid__generate_random(uuid_t out, int *num)
222.654 +{
222.655 + uuid_t buf;
222.656 + struct uuid uu;
222.657 + int i, n;
222.658 +
222.659 + if (!num || !*num)
222.660 + n = 1;
222.661 + else
222.662 + n = *num;
222.663 +
222.664 + for (i = 0; i < n; i++) {
222.665 + get_random_bytes(buf, sizeof(buf));
222.666 + uuid_unpack(buf, &uu);
222.667 +
222.668 + uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
222.669 + uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF)
222.670 + | 0x4000;
222.671 + uuid_pack(&uu, out);
222.672 + out += sizeof(uuid_t);
222.673 + }
222.674 +}
222.675 +
222.676 +void uuid_generate_random(uuid_t out)
222.677 +{
222.678 + int num = 1;
222.679 + /* No real reason to use the daemon for random uuid's -- yet */
222.680 +
222.681 + uuid__generate_random(out, &num);
222.682 +}
222.683 +
222.684 +
222.685 +/*
222.686 + * This is the generic front-end to uuid_generate_random and
222.687 + * uuid_generate_time. It uses uuid_generate_random only if
222.688 + * /dev/urandom is available, since otherwise we won't have
222.689 + * high-quality randomness.
222.690 + */
222.691 +void uuid_generate(uuid_t out)
222.692 +{
222.693 + if (get_random_fd() >= 0)
222.694 + uuid_generate_random(out);
222.695 + else
222.696 + uuid_generate_time(out);
222.697 +}
223.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
223.2 +++ b/libext2fs/lib/libuuid/isnull.c Wed Aug 25 01:28:08 2021 +0200
223.3 @@ -0,0 +1,49 @@
223.4 +/*
223.5 + * isnull.c --- Check whether or not the UUID is null
223.6 + *
223.7 + * Copyright (C) 1996, 1997 Theodore Ts'o.
223.8 + *
223.9 + * %Begin-Header%
223.10 + * Redistribution and use in source and binary forms, with or without
223.11 + * modification, are permitted provided that the following conditions
223.12 + * are met:
223.13 + * 1. Redistributions of source code must retain the above copyright
223.14 + * notice, and the entire permission notice in its entirety,
223.15 + * including the disclaimer of warranties.
223.16 + * 2. Redistributions in binary form must reproduce the above copyright
223.17 + * notice, this list of conditions and the following disclaimer in the
223.18 + * documentation and/or other materials provided with the distribution.
223.19 + * 3. The name of the author may not be used to endorse or promote
223.20 + * products derived from this software without specific prior
223.21 + * written permission.
223.22 + *
223.23 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
223.24 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
223.25 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
223.26 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
223.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
223.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
223.29 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
223.30 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
223.31 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
223.32 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
223.33 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
223.34 + * DAMAGE.
223.35 + * %End-Header%
223.36 + */
223.37 +
223.38 +#include "config.h"
223.39 +#include "uuidP.h"
223.40 +
223.41 +/* Returns 1 if the uuid is the NULL uuid */
223.42 +int uuid_is_null(const uuid_t uu)
223.43 +{
223.44 + const unsigned char *cp;
223.45 + int i;
223.46 +
223.47 + for (i=0, cp = uu; i < 16; i++)
223.48 + if (*cp++)
223.49 + return 0;
223.50 + return 1;
223.51 +}
223.52 +
224.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
224.2 +++ b/libext2fs/lib/libuuid/pack.c Wed Aug 25 01:28:08 2021 +0200
224.3 @@ -0,0 +1,70 @@
224.4 +/*
224.5 + * Internal routine for packing UUID's
224.6 + *
224.7 + * Copyright (C) 1996, 1997 Theodore Ts'o.
224.8 + *
224.9 + * %Begin-Header%
224.10 + * Redistribution and use in source and binary forms, with or without
224.11 + * modification, are permitted provided that the following conditions
224.12 + * are met:
224.13 + * 1. Redistributions of source code must retain the above copyright
224.14 + * notice, and the entire permission notice in its entirety,
224.15 + * including the disclaimer of warranties.
224.16 + * 2. Redistributions in binary form must reproduce the above copyright
224.17 + * notice, this list of conditions and the following disclaimer in the
224.18 + * documentation and/or other materials provided with the distribution.
224.19 + * 3. The name of the author may not be used to endorse or promote
224.20 + * products derived from this software without specific prior
224.21 + * written permission.
224.22 + *
224.23 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
224.24 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
224.25 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
224.26 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
224.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
224.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
224.29 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
224.30 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
224.31 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
224.32 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
224.33 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
224.34 + * DAMAGE.
224.35 + * %End-Header%
224.36 + */
224.37 +
224.38 +#include "config.h"
224.39 +#include <string.h>
224.40 +#include "uuidP.h"
224.41 +
224.42 +void uuid_pack(const struct uuid *uu, uuid_t ptr)
224.43 +{
224.44 + uint32_t tmp;
224.45 + unsigned char *out = ptr;
224.46 +
224.47 + tmp = uu->time_low;
224.48 + out[3] = (unsigned char) tmp;
224.49 + tmp >>= 8;
224.50 + out[2] = (unsigned char) tmp;
224.51 + tmp >>= 8;
224.52 + out[1] = (unsigned char) tmp;
224.53 + tmp >>= 8;
224.54 + out[0] = (unsigned char) tmp;
224.55 +
224.56 + tmp = uu->time_mid;
224.57 + out[5] = (unsigned char) tmp;
224.58 + tmp >>= 8;
224.59 + out[4] = (unsigned char) tmp;
224.60 +
224.61 + tmp = uu->time_hi_and_version;
224.62 + out[7] = (unsigned char) tmp;
224.63 + tmp >>= 8;
224.64 + out[6] = (unsigned char) tmp;
224.65 +
224.66 + tmp = uu->clock_seq;
224.67 + out[9] = (unsigned char) tmp;
224.68 + tmp >>= 8;
224.69 + out[8] = (unsigned char) tmp;
224.70 +
224.71 + memcpy(out+10, uu->node, 6);
224.72 +}
224.73 +
225.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
225.2 +++ b/libext2fs/lib/libuuid/parse.c Wed Aug 25 01:28:08 2021 +0200
225.3 @@ -0,0 +1,80 @@
225.4 +/*
225.5 + * parse.c --- UUID parsing
225.6 + *
225.7 + * Copyright (C) 1996, 1997 Theodore Ts'o.
225.8 + *
225.9 + * %Begin-Header%
225.10 + * Redistribution and use in source and binary forms, with or without
225.11 + * modification, are permitted provided that the following conditions
225.12 + * are met:
225.13 + * 1. Redistributions of source code must retain the above copyright
225.14 + * notice, and the entire permission notice in its entirety,
225.15 + * including the disclaimer of warranties.
225.16 + * 2. Redistributions in binary form must reproduce the above copyright
225.17 + * notice, this list of conditions and the following disclaimer in the
225.18 + * documentation and/or other materials provided with the distribution.
225.19 + * 3. The name of the author may not be used to endorse or promote
225.20 + * products derived from this software without specific prior
225.21 + * written permission.
225.22 + *
225.23 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
225.24 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
225.25 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
225.26 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
225.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
225.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
225.29 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
225.30 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
225.31 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225.32 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
225.33 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
225.34 + * DAMAGE.
225.35 + * %End-Header%
225.36 + */
225.37 +
225.38 +#include "config.h"
225.39 +#include <stdlib.h>
225.40 +#include <stdio.h>
225.41 +#include <ctype.h>
225.42 +#include <string.h>
225.43 +
225.44 +#include "uuidP.h"
225.45 +
225.46 +int uuid_parse(const char *in, uuid_t uu)
225.47 +{
225.48 + struct uuid uuid;
225.49 + int i;
225.50 + const char *cp;
225.51 + char buf[3];
225.52 +
225.53 + if (strlen(in) != 36)
225.54 + return -1;
225.55 + for (i=0, cp = in; i <= 36; i++,cp++) {
225.56 + if ((i == 8) || (i == 13) || (i == 18) ||
225.57 + (i == 23)) {
225.58 + if (*cp == '-')
225.59 + continue;
225.60 + else
225.61 + return -1;
225.62 + }
225.63 + if (i== 36)
225.64 + if (*cp == 0)
225.65 + continue;
225.66 + if (!isxdigit(*cp))
225.67 + return -1;
225.68 + }
225.69 + uuid.time_low = strtoul(in, NULL, 16);
225.70 + uuid.time_mid = strtoul(in+9, NULL, 16);
225.71 + uuid.time_hi_and_version = strtoul(in+14, NULL, 16);
225.72 + uuid.clock_seq = strtoul(in+19, NULL, 16);
225.73 + cp = in+24;
225.74 + buf[2] = 0;
225.75 + for (i=0; i < 6; i++) {
225.76 + buf[0] = *cp++;
225.77 + buf[1] = *cp++;
225.78 + uuid.node[i] = strtoul(buf, NULL, 16);
225.79 + }
225.80 +
225.81 + uuid_pack(&uuid, uu);
225.82 + return 0;
225.83 +}
226.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
226.2 +++ b/libext2fs/lib/libuuid/tst_uuid.c Wed Aug 25 01:28:08 2021 +0200
226.3 @@ -0,0 +1,199 @@
226.4 +/*
226.5 + * tst_uuid.c --- test program from the UUID library
226.6 + *
226.7 + * Copyright (C) 1996, 1997, 1998 Theodore Ts'o.
226.8 + *
226.9 + * %Begin-Header%
226.10 + * Redistribution and use in source and binary forms, with or without
226.11 + * modification, are permitted provided that the following conditions
226.12 + * are met:
226.13 + * 1. Redistributions of source code must retain the above copyright
226.14 + * notice, and the entire permission notice in its entirety,
226.15 + * including the disclaimer of warranties.
226.16 + * 2. Redistributions in binary form must reproduce the above copyright
226.17 + * notice, this list of conditions and the following disclaimer in the
226.18 + * documentation and/or other materials provided with the distribution.
226.19 + * 3. The name of the author may not be used to endorse or promote
226.20 + * products derived from this software without specific prior
226.21 + * written permission.
226.22 + *
226.23 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
226.24 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
226.25 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
226.26 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
226.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
226.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
226.29 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
226.30 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
226.31 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
226.32 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
226.33 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
226.34 + * DAMAGE.
226.35 + * %End-Header%
226.36 + */
226.37 +
226.38 +#include "config.h"
226.39 +
226.40 +#ifdef _WIN32
226.41 +#define _WIN32_WINNT 0x0500
226.42 +#include <windows.h>
226.43 +#define UUID MYUUID
226.44 +#endif
226.45 +
226.46 +#include <stdio.h>
226.47 +#include <stdlib.h>
226.48 +
226.49 +#include <uuid/uuid.h>
226.50 +
226.51 +static int test_uuid(const char * uuid, int isValid)
226.52 +{
226.53 + static const char * validStr[2] = {"invalid", "valid"};
226.54 + uuid_t uuidBits;
226.55 + int parsedOk;
226.56 +
226.57 + parsedOk = uuid_parse(uuid, uuidBits) == 0;
226.58 +
226.59 + printf("%s is %s", uuid, validStr[isValid]);
226.60 + if (parsedOk != isValid) {
226.61 + printf(" but uuid_parse says %s\n", validStr[parsedOk]);
226.62 + return 1;
226.63 + }
226.64 + printf(", OK\n");
226.65 + return 0;
226.66 +}
226.67 +
226.68 +#ifdef __GNUC__
226.69 +#define ATTR(x) __attribute__(x)
226.70 +#else
226.71 +#define ATTR(x)
226.72 +#endif
226.73 +
226.74 +int
226.75 +main(int argc ATTR((unused)) , char **argv ATTR((unused)))
226.76 +{
226.77 + uuid_t buf, tst;
226.78 + char str[100];
226.79 + struct timeval tv;
226.80 + time_t time_reg, time_gen;
226.81 + unsigned char *cp;
226.82 + int i;
226.83 + int failed = 0;
226.84 + int type, variant;
226.85 +
226.86 + uuid_generate(buf);
226.87 + uuid_unparse(buf, str);
226.88 + printf("UUID generate = %s\n", str);
226.89 + printf("UUID: ");
226.90 + for (i=0, cp = (unsigned char *) &buf; i < 16; i++) {
226.91 + printf("%02x", *cp++);
226.92 + }
226.93 + printf("\n");
226.94 + type = uuid_type(buf); variant = uuid_variant(buf);
226.95 + printf("UUID type = %d, UUID variant = %d\n", type, variant);
226.96 + if (variant != UUID_VARIANT_DCE) {
226.97 + printf("Incorrect UUID Variant; was expecting DCE!\n");
226.98 + failed++;
226.99 + }
226.100 + printf("\n");
226.101 +
226.102 + uuid_generate_random(buf);
226.103 + uuid_unparse(buf, str);
226.104 + printf("UUID random string = %s\n", str);
226.105 + printf("UUID: ");
226.106 + for (i=0, cp = (unsigned char *) &buf; i < 16; i++) {
226.107 + printf("%02x", *cp++);
226.108 + }
226.109 + printf("\n");
226.110 + type = uuid_type(buf);
226.111 + variant = uuid_variant(buf);
226.112 + printf("UUID type = %d, UUID variant = %d\n", type, variant);
226.113 + if (variant != UUID_VARIANT_DCE) {
226.114 + printf("Incorrect UUID Variant; was expecting DCE!\n");
226.115 + failed++;
226.116 + }
226.117 + if (type != 4) {
226.118 + printf("Incorrect UUID type; was expecting "
226.119 + "4 (random type)!\n");
226.120 + failed++;
226.121 + }
226.122 + printf("\n");
226.123 +
226.124 + time_gen = time(0);
226.125 + uuid_generate_time(buf);
226.126 + uuid_unparse(buf, str);
226.127 + printf("UUID string = %s\n", str);
226.128 + printf("UUID time: ");
226.129 + for (i=0, cp = (unsigned char *) &buf; i < 16; i++) {
226.130 + printf("%02x", *cp++);
226.131 + }
226.132 + printf("\n");
226.133 + type = uuid_type(buf);
226.134 + variant = uuid_variant(buf);
226.135 + printf("UUID type = %d, UUID variant = %d\n", type, variant);
226.136 + if (variant != UUID_VARIANT_DCE) {
226.137 + printf("Incorrect UUID Variant; was expecting DCE!\n");
226.138 + failed++;
226.139 + }
226.140 + if (type != 1) {
226.141 + printf("Incorrect UUID type; was expecting "
226.142 + "1 (time-based type)!\\n");
226.143 + failed++;
226.144 + }
226.145 +
226.146 + tv.tv_sec = 0;
226.147 + tv.tv_usec = 0;
226.148 + time_reg = uuid_time(buf, &tv);
226.149 + printf("UUID generated at %lu reports %lu (%ld.%ld)\n",
226.150 + time_gen, time_reg, tv.tv_sec, (long)tv.tv_usec);
226.151 + /* allow 1s margin in case of rollover between sampling
226.152 + * the current time and when the UUID is generated. */
226.153 + if (time_reg > time_gen + 1) {
226.154 + printf("UUID time comparison failed!\n");
226.155 + failed++;
226.156 + } else {
226.157 + printf("UUID time comparison succeeded.\n");
226.158 + }
226.159 +
226.160 + if (uuid_parse(str, tst) < 0) {
226.161 + printf("UUID parse failed\n");
226.162 + failed++;
226.163 + }
226.164 + if (!uuid_compare(buf, tst)) {
226.165 + printf("UUID parse and compare succeeded.\n");
226.166 + } else {
226.167 + printf("UUID parse and compare failed!\n");
226.168 + failed++;
226.169 + }
226.170 + uuid_clear(tst);
226.171 + if (uuid_is_null(tst))
226.172 + printf("UUID clear and is null succeeded.\n");
226.173 + else {
226.174 + printf("UUID clear and is null failed!\n");
226.175 + failed++;
226.176 + }
226.177 + uuid_copy(buf, tst);
226.178 + if (!uuid_compare(buf, tst))
226.179 + printf("UUID copy and compare succeeded.\n");
226.180 + else {
226.181 + printf("UUID copy and compare failed!\n");
226.182 + failed++;
226.183 + }
226.184 +
226.185 + failed += test_uuid("84949cc5-4701-4a84-895b-354c584a981b", 1);
226.186 + failed += test_uuid("84949CC5-4701-4A84-895B-354C584A981B", 1);
226.187 + failed += test_uuid("84949cc5-4701-4a84-895b-354c584a981bc", 0);
226.188 + failed += test_uuid("84949cc5-4701-4a84-895b-354c584a981", 0);
226.189 + failed += test_uuid("84949cc5x4701-4a84-895b-354c584a981b", 0);
226.190 + failed += test_uuid("84949cc504701-4a84-895b-354c584a981b", 0);
226.191 + failed += test_uuid("84949cc5-470104a84-895b-354c584a981b", 0);
226.192 + failed += test_uuid("84949cc5-4701-4a840895b-354c584a981b", 0);
226.193 + failed += test_uuid("84949cc5-4701-4a84-895b0354c584a981b", 0);
226.194 + failed += test_uuid("g4949cc5-4701-4a84-895b-354c584a981b", 0);
226.195 + failed += test_uuid("84949cc5-4701-4a84-895b-354c584a981g", 0);
226.196 +
226.197 + if (failed) {
226.198 + printf("%d failures.\n", failed);
226.199 + exit(1);
226.200 + }
226.201 + return 0;
226.202 +}
227.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
227.2 +++ b/libext2fs/lib/libuuid/unpack.c Wed Aug 25 01:28:08 2021 +0200
227.3 @@ -0,0 +1,64 @@
227.4 +/*
227.5 + * Internal routine for unpacking UUID
227.6 + *
227.7 + * Copyright (C) 1996, 1997 Theodore Ts'o.
227.8 + *
227.9 + * %Begin-Header%
227.10 + * Redistribution and use in source and binary forms, with or without
227.11 + * modification, are permitted provided that the following conditions
227.12 + * are met:
227.13 + * 1. Redistributions of source code must retain the above copyright
227.14 + * notice, and the entire permission notice in its entirety,
227.15 + * including the disclaimer of warranties.
227.16 + * 2. Redistributions in binary form must reproduce the above copyright
227.17 + * notice, this list of conditions and the following disclaimer in the
227.18 + * documentation and/or other materials provided with the distribution.
227.19 + * 3. The name of the author may not be used to endorse or promote
227.20 + * products derived from this software without specific prior
227.21 + * written permission.
227.22 + *
227.23 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
227.24 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
227.25 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
227.26 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
227.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
227.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
227.29 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
227.30 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
227.31 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
227.32 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
227.33 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
227.34 + * DAMAGE.
227.35 + * %End-Header%
227.36 + */
227.37 +
227.38 +#include "config.h"
227.39 +#include <string.h>
227.40 +#include "uuidP.h"
227.41 +
227.42 +void uuid_unpack(const uuid_t in, struct uuid *uu)
227.43 +{
227.44 + const uint8_t *ptr = in;
227.45 + uint32_t tmp;
227.46 +
227.47 + tmp = *ptr++;
227.48 + tmp = (tmp << 8) | *ptr++;
227.49 + tmp = (tmp << 8) | *ptr++;
227.50 + tmp = (tmp << 8) | *ptr++;
227.51 + uu->time_low = tmp;
227.52 +
227.53 + tmp = *ptr++;
227.54 + tmp = (tmp << 8) | *ptr++;
227.55 + uu->time_mid = tmp;
227.56 +
227.57 + tmp = *ptr++;
227.58 + tmp = (tmp << 8) | *ptr++;
227.59 + uu->time_hi_and_version = tmp;
227.60 +
227.61 + tmp = *ptr++;
227.62 + tmp = (tmp << 8) | *ptr++;
227.63 + uu->clock_seq = tmp;
227.64 +
227.65 + memcpy(uu->node, ptr, 6);
227.66 +}
227.67 +
228.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
228.2 +++ b/libext2fs/lib/libuuid/unparse.c Wed Aug 25 01:28:08 2021 +0200
228.3 @@ -0,0 +1,77 @@
228.4 +/*
228.5 + * unparse.c -- convert a UUID to string
228.6 + *
228.7 + * Copyright (C) 1996, 1997 Theodore Ts'o.
228.8 + *
228.9 + * %Begin-Header%
228.10 + * Redistribution and use in source and binary forms, with or without
228.11 + * modification, are permitted provided that the following conditions
228.12 + * are met:
228.13 + * 1. Redistributions of source code must retain the above copyright
228.14 + * notice, and the entire permission notice in its entirety,
228.15 + * including the disclaimer of warranties.
228.16 + * 2. Redistributions in binary form must reproduce the above copyright
228.17 + * notice, this list of conditions and the following disclaimer in the
228.18 + * documentation and/or other materials provided with the distribution.
228.19 + * 3. The name of the author may not be used to endorse or promote
228.20 + * products derived from this software without specific prior
228.21 + * written permission.
228.22 + *
228.23 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
228.24 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
228.25 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
228.26 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
228.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
228.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
228.29 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
228.30 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
228.31 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228.32 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
228.33 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
228.34 + * DAMAGE.
228.35 + * %End-Header%
228.36 + */
228.37 +
228.38 +#include "config.h"
228.39 +#include <stdio.h>
228.40 +
228.41 +#include "uuidP.h"
228.42 +
228.43 +static const char *fmt_lower =
228.44 + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
228.45 +
228.46 +static const char *fmt_upper =
228.47 + "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X";
228.48 +
228.49 +#ifdef UUID_UNPARSE_DEFAULT_UPPER
228.50 +#define FMT_DEFAULT fmt_upper
228.51 +#else
228.52 +#define FMT_DEFAULT fmt_lower
228.53 +#endif
228.54 +
228.55 +static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt)
228.56 +{
228.57 + struct uuid uuid;
228.58 +
228.59 + uuid_unpack(uu, &uuid);
228.60 + sprintf(out, fmt,
228.61 + uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
228.62 + uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
228.63 + uuid.node[0], uuid.node[1], uuid.node[2],
228.64 + uuid.node[3], uuid.node[4], uuid.node[5]);
228.65 +}
228.66 +
228.67 +void uuid_unparse_lower(const uuid_t uu, char *out)
228.68 +{
228.69 + uuid_unparse_x(uu, out, fmt_lower);
228.70 +}
228.71 +
228.72 +void uuid_unparse_upper(const uuid_t uu, char *out)
228.73 +{
228.74 + uuid_unparse_x(uu, out, fmt_upper);
228.75 +}
228.76 +
228.77 +void uuid_unparse(const uuid_t uu, char *out)
228.78 +{
228.79 + uuid_unparse_x(uu, out, FMT_DEFAULT);
228.80 +}
229.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
229.2 +++ b/libext2fs/lib/libuuid/uuidP.h Wed Aug 25 01:28:08 2021 +0200
229.3 @@ -0,0 +1,74 @@
229.4 +/*
229.5 + * uuid.h -- private header file for uuids
229.6 + *
229.7 + * Copyright (C) 1996, 1997 Theodore Ts'o.
229.8 + *
229.9 + * %Begin-Header%
229.10 + * Redistribution and use in source and binary forms, with or without
229.11 + * modification, are permitted provided that the following conditions
229.12 + * are met:
229.13 + * 1. Redistributions of source code must retain the above copyright
229.14 + * notice, and the entire permission notice in its entirety,
229.15 + * including the disclaimer of warranties.
229.16 + * 2. Redistributions in binary form must reproduce the above copyright
229.17 + * notice, this list of conditions and the following disclaimer in the
229.18 + * documentation and/or other materials provided with the distribution.
229.19 + * 3. The name of the author may not be used to endorse or promote
229.20 + * products derived from this software without specific prior
229.21 + * written permission.
229.22 + *
229.23 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
229.24 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
229.25 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
229.26 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
229.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
229.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
229.29 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
229.30 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
229.31 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
229.32 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
229.33 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
229.34 + * DAMAGE.
229.35 + * %End-Header%
229.36 + */
229.37 +
229.38 +/* PAUL: Added here to avoid redefinition attempts. */
229.39 +#include <stdint.h>
229.40 +
229.41 +#ifdef HAVE_INTTYPES_H
229.42 +#include <inttypes.h>
229.43 +#else
229.44 +#include <uuid/uuid_types.h>
229.45 +#endif
229.46 +#include <sys/types.h>
229.47 +
229.48 +#include <uuid/uuid.h>
229.49 +
229.50 +/*
229.51 + * Offset between 15-Oct-1582 and 1-Jan-70
229.52 + */
229.53 +#define TIME_OFFSET_HIGH 0x01B21DD2
229.54 +#define TIME_OFFSET_LOW 0x13814000
229.55 +
229.56 +struct uuid {
229.57 + uint32_t time_low;
229.58 + uint16_t time_mid;
229.59 + uint16_t time_hi_and_version;
229.60 + uint16_t clock_seq;
229.61 + uint8_t node[6];
229.62 +};
229.63 +
229.64 +#ifndef __GNUC_PREREQ
229.65 +#if defined(__GNUC__) && defined(__GNUC_MINOR__)
229.66 +#define __GNUC_PREREQ(maj, min) \
229.67 + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
229.68 +#else
229.69 +#define __GNUC_PREREQ(maj, min) 0
229.70 +#endif
229.71 +#endif
229.72 +
229.73 +/*
229.74 + * prototypes
229.75 + */
229.76 +void uuid_pack(const struct uuid *uu, uuid_t ptr);
229.77 +void uuid_unpack(const uuid_t in, struct uuid *uu);
230.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
230.2 +++ b/libext2fs/lib/libuuid/uuid_time.c Wed Aug 25 01:28:08 2021 +0200
230.3 @@ -0,0 +1,173 @@
230.4 +/*
230.5 + * uuid_time.c --- Interpret the time field from a uuid. This program
230.6 + * violates the UUID abstraction barrier by reaching into the guts
230.7 + * of a UUID and interpreting it.
230.8 + *
230.9 + * Copyright (C) 1998, 1999 Theodore Ts'o.
230.10 + *
230.11 + * %Begin-Header%
230.12 + * Redistribution and use in source and binary forms, with or without
230.13 + * modification, are permitted provided that the following conditions
230.14 + * are met:
230.15 + * 1. Redistributions of source code must retain the above copyright
230.16 + * notice, and the entire permission notice in its entirety,
230.17 + * including the disclaimer of warranties.
230.18 + * 2. Redistributions in binary form must reproduce the above copyright
230.19 + * notice, this list of conditions and the following disclaimer in the
230.20 + * documentation and/or other materials provided with the distribution.
230.21 + * 3. The name of the author may not be used to endorse or promote
230.22 + * products derived from this software without specific prior
230.23 + * written permission.
230.24 + *
230.25 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
230.26 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
230.27 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
230.28 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
230.29 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
230.30 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
230.31 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
230.32 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
230.33 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
230.34 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
230.35 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
230.36 + * DAMAGE.
230.37 + * %End-Header%
230.38 + */
230.39 +
230.40 +#include "config.h"
230.41 +
230.42 +#ifdef _WIN32
230.43 +#define _WIN32_WINNT 0x0500
230.44 +#include <windows.h>
230.45 +#define UUID MYUUID
230.46 +#endif
230.47 +
230.48 +#include <stdio.h>
230.49 +#ifdef HAVE_UNISTD_H
230.50 +#include <unistd.h>
230.51 +#endif
230.52 +#include <stdlib.h>
230.53 +#include <sys/types.h>
230.54 +#ifdef HAVE_SYS_TIME_H
230.55 +#include <sys/time.h>
230.56 +#endif
230.57 +#include <time.h>
230.58 +
230.59 +#include "uuidP.h"
230.60 +
230.61 +time_t uuid_time(const uuid_t uu, struct timeval *ret_tv)
230.62 +{
230.63 + struct timeval tv;
230.64 + struct uuid uuid;
230.65 + uint32_t high;
230.66 + uint64_t clock_reg;
230.67 +
230.68 + uuid_unpack(uu, &uuid);
230.69 +
230.70 + high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16);
230.71 + clock_reg = uuid.time_low | ((uint64_t) high << 32);
230.72 +
230.73 + clock_reg -= (((uint64_t) 0x01B21DD2) << 32) + 0x13814000;
230.74 + tv.tv_sec = clock_reg / 10000000;
230.75 + tv.tv_usec = (clock_reg % 10000000) / 10;
230.76 +
230.77 + if (ret_tv)
230.78 + *ret_tv = tv;
230.79 +
230.80 + return tv.tv_sec;
230.81 +}
230.82 +
230.83 +int uuid_type(const uuid_t uu)
230.84 +{
230.85 + struct uuid uuid;
230.86 +
230.87 + uuid_unpack(uu, &uuid);
230.88 + return ((uuid.time_hi_and_version >> 12) & 0xF);
230.89 +}
230.90 +
230.91 +int uuid_variant(const uuid_t uu)
230.92 +{
230.93 + struct uuid uuid;
230.94 + int var;
230.95 +
230.96 + uuid_unpack(uu, &uuid);
230.97 + var = uuid.clock_seq;
230.98 +
230.99 + if ((var & 0x8000) == 0)
230.100 + return UUID_VARIANT_NCS;
230.101 + if ((var & 0x4000) == 0)
230.102 + return UUID_VARIANT_DCE;
230.103 + if ((var & 0x2000) == 0)
230.104 + return UUID_VARIANT_MICROSOFT;
230.105 + return UUID_VARIANT_OTHER;
230.106 +}
230.107 +
230.108 +#ifdef DEBUG
230.109 +static const char *variant_string(int variant)
230.110 +{
230.111 + switch (variant) {
230.112 + case UUID_VARIANT_NCS:
230.113 + return "NCS";
230.114 + case UUID_VARIANT_DCE:
230.115 + return "DCE";
230.116 + case UUID_VARIANT_MICROSOFT:
230.117 + return "Microsoft";
230.118 + default:
230.119 + return "Other";
230.120 + }
230.121 +}
230.122 +
230.123 +
230.124 +int
230.125 +main(int argc, char **argv)
230.126 +{
230.127 + uuid_t buf;
230.128 + time_t time_reg;
230.129 + struct timeval tv;
230.130 + int type, variant;
230.131 +
230.132 + if (argc != 2) {
230.133 + fprintf(stderr, "Usage: %s uuid\n", argv[0]);
230.134 + exit(1);
230.135 + }
230.136 + if (uuid_parse(argv[1], buf)) {
230.137 + fprintf(stderr, "Invalid UUID: %s\n", argv[1]);
230.138 + exit(1);
230.139 + }
230.140 + variant = uuid_variant(buf);
230.141 + type = uuid_type(buf);
230.142 + time_reg = uuid_time(buf, &tv);
230.143 +
230.144 + printf("UUID variant is %d (%s)\n", variant, variant_string(variant));
230.145 + if (variant != UUID_VARIANT_DCE) {
230.146 + printf("Warning: This program only knows how to interpret "
230.147 + "DCE UUIDs.\n\tThe rest of the output is likely "
230.148 + "to be incorrect!!\n");
230.149 + }
230.150 + printf("UUID type is %d", type);
230.151 + switch (type) {
230.152 + case 1:
230.153 + printf(" (time based)\n");
230.154 + break;
230.155 + case 2:
230.156 + printf(" (DCE)\n");
230.157 + break;
230.158 + case 3:
230.159 + printf(" (name-based)\n");
230.160 + break;
230.161 + case 4:
230.162 + printf(" (random)\n");
230.163 + break;
230.164 + default:
230.165 + printf("\n");
230.166 + }
230.167 + if (type != 1) {
230.168 + printf("Warning: not a time-based UUID, so UUID time "
230.169 + "decoding will likely not work!\n");
230.170 + }
230.171 + printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, (long)tv.tv_usec,
230.172 + ctime(&time_reg));
230.173 +
230.174 + return 0;
230.175 +}
230.176 +#endif
231.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
231.2 +++ b/libext2fs/lib/libuuid/uuidd.h Wed Aug 25 01:28:08 2021 +0200
231.3 @@ -0,0 +1,54 @@
231.4 +/*
231.5 + * Definitions used by the uuidd daemon
231.6 + *
231.7 + * Copyright (C) 2007 Theodore Ts'o.
231.8 + *
231.9 + * %Begin-Header%
231.10 + * Redistribution and use in source and binary forms, with or without
231.11 + * modification, are permitted provided that the following conditions
231.12 + * are met:
231.13 + * 1. Redistributions of source code must retain the above copyright
231.14 + * notice, and the entire permission notice in its entirety,
231.15 + * including the disclaimer of warranties.
231.16 + * 2. Redistributions in binary form must reproduce the above copyright
231.17 + * notice, this list of conditions and the following disclaimer in the
231.18 + * documentation and/or other materials provided with the distribution.
231.19 + * 3. The name of the author may not be used to endorse or promote
231.20 + * products derived from this software without specific prior
231.21 + * written permission.
231.22 + *
231.23 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
231.24 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
231.25 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
231.26 + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
231.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
231.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
231.29 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
231.30 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
231.31 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
231.32 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
231.33 + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
231.34 + * DAMAGE.
231.35 + * %End-Header%
231.36 + */
231.37 +
231.38 +#ifndef _UUID_UUIDD_H
231.39 +#define _UUID_UUIDD_H
231.40 +
231.41 +#define UUIDD_DIR "/var/lib/libuuid"
231.42 +#define UUIDD_SOCKET_PATH UUIDD_DIR "/request"
231.43 +#define UUIDD_PIDFILE_PATH UUIDD_DIR "/uuidd.pid"
231.44 +#define UUIDD_PATH "/usr/sbin/uuidd"
231.45 +
231.46 +#define UUIDD_OP_GETPID 0
231.47 +#define UUIDD_OP_GET_MAXOP 1
231.48 +#define UUIDD_OP_TIME_UUID 2
231.49 +#define UUIDD_OP_RANDOM_UUID 3
231.50 +#define UUIDD_OP_BULK_TIME_UUID 4
231.51 +#define UUIDD_OP_BULK_RANDOM_UUID 5
231.52 +#define UUIDD_MAX_OP UUIDD_OP_BULK_RANDOM_UUID
231.53 +
231.54 +extern void uuid__generate_time(uuid_t out, int *num);
231.55 +extern void uuid__generate_random(uuid_t out, int *num);
231.56 +
231.57 +#endif /* _UUID_UUID_H */
232.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
232.2 +++ b/libext2fs/lib/version.h Wed Aug 25 01:28:08 2021 +0200
232.3 @@ -0,0 +1,11 @@
232.4 +/*
232.5 + * version.h --- controls the version number printed by the e2fs
232.6 + * programs.
232.7 + *
232.8 + * Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
232.9 + * 2004, 2005, 2006, 2007, 2008, 2009, 2010 by Theodore Ts'o. This
232.10 + * file may be redistributed under the GNU Public License v2.
232.11 + */
232.12 +
232.13 +#define E2FSPROGS_VERSION "1.44.5"
232.14 +#define E2FSPROGS_DATE "15-Dec-2018"
233.1 --- a/libfsclient/lib/src/Makefile Sun Aug 22 22:37:55 2021 +0200
233.2 +++ b/libfsclient/lib/src/Makefile Wed Aug 25 01:28:08 2021 +0200
233.3 @@ -6,7 +6,7 @@
233.4
233.5 # Locations for interface input and generated output.
233.6
233.7 -IDL_DIR = $(L4DIR)/pkg/libsystypes/idl
233.8 +IDL_DIR = $(PKGDIR)/../libsystypes/idl
233.9 IDL_MK_DIR = $(L4DIR)/idl4re/mk
233.10 IDL_BUILD_DIR = .
233.11 IDL_EXPORT_DIR = .
234.1 --- a/libfsserver/lib/Makefile Sun Aug 22 22:37:55 2021 +0200
234.2 +++ b/libfsserver/lib/Makefile Wed Aug 25 01:28:08 2021 +0200
234.3 @@ -6,7 +6,7 @@
234.4
234.5 # Locations for interface input and generated output.
234.6
234.7 -IDL_DIR = $(L4DIR)/pkg/libsystypes/idl
234.8 +IDL_DIR = $(PKGDIR)/../libsystypes/idl
234.9 IDL_MK_DIR = $(L4DIR)/idl4re/mk
234.10 IDL_BUILD_DIR = .
234.11 IDL_EXPORT_DIR = $(OBJ_BASE)/include/contrib/$(CONTRIB_INCDIR)/fsserver
235.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
235.2 +++ b/libipc/Control Wed Aug 25 01:28:08 2021 +0200
235.3 @@ -0,0 +1,3 @@
235.4 +requires: libc libsystypes
235.5 +provides: libipc
235.6 +maintainer: paul@boddie.org.uk
236.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
236.2 +++ b/libipc/Makefile Wed Aug 25 01:28:08 2021 +0200
236.3 @@ -0,0 +1,4 @@
236.4 +PKGDIR ?= .
236.5 +L4DIR ?= $(PKGDIR)/../../..
236.6 +
236.7 +include $(L4DIR)/mk/subdir.mk
237.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
237.2 +++ b/libipc/docs/COPYING-GPL-2 Wed Aug 25 01:28:08 2021 +0200
237.3 @@ -0,0 +1,1 @@
237.4 +LICENCE.txt
237.5 \ No newline at end of file
238.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
238.2 +++ b/libipc/docs/COPYING.txt Wed Aug 25 01:28:08 2021 +0200
238.3 @@ -0,0 +1,22 @@
238.4 +Licence Agreement
238.5 +-----------------
238.6 +
238.7 +All original work in this distribution is covered by the following copyright
238.8 +and licensing information:
238.9 +
238.10 +Copyright (C) 2018, 2019 Paul Boddie <paul@boddie.org.uk>
238.11 +
238.12 +This software is free software; you can redistribute it and/or
238.13 +modify it under the terms of the GNU General Public License as
238.14 +published by the Free Software Foundation; either version 2 of
238.15 +the License, or (at your option) any later version.
238.16 +
238.17 +This software is distributed in the hope that it will be useful,
238.18 +but WITHOUT ANY WARRANTY; without even the implied warranty of
238.19 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
238.20 +GNU General Public License for more details.
238.21 +
238.22 +You should have received a copy of the GNU General Public
238.23 +License along with this library; see the file LICENCE.txt
238.24 +If not, write to the Free Software Foundation, Inc.,
238.25 +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
239.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
239.2 +++ b/libipc/docs/LICENCE.txt Wed Aug 25 01:28:08 2021 +0200
239.3 @@ -0,0 +1,339 @@
239.4 + GNU GENERAL PUBLIC LICENSE
239.5 + Version 2, June 1991
239.6 +
239.7 + Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
239.8 + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
239.9 + Everyone is permitted to copy and distribute verbatim copies
239.10 + of this license document, but changing it is not allowed.
239.11 +
239.12 + Preamble
239.13 +
239.14 + The licenses for most software are designed to take away your
239.15 +freedom to share and change it. By contrast, the GNU General Public
239.16 +License is intended to guarantee your freedom to share and change free
239.17 +software--to make sure the software is free for all its users. This
239.18 +General Public License applies to most of the Free Software
239.19 +Foundation's software and to any other program whose authors commit to
239.20 +using it. (Some other Free Software Foundation software is covered by
239.21 +the GNU Lesser General Public License instead.) You can apply it to
239.22 +your programs, too.
239.23 +
239.24 + When we speak of free software, we are referring to freedom, not
239.25 +price. Our General Public Licenses are designed to make sure that you
239.26 +have the freedom to distribute copies of free software (and charge for
239.27 +this service if you wish), that you receive source code or can get it
239.28 +if you want it, that you can change the software or use pieces of it
239.29 +in new free programs; and that you know you can do these things.
239.30 +
239.31 + To protect your rights, we need to make restrictions that forbid
239.32 +anyone to deny you these rights or to ask you to surrender the rights.
239.33 +These restrictions translate to certain responsibilities for you if you
239.34 +distribute copies of the software, or if you modify it.
239.35 +
239.36 + For example, if you distribute copies of such a program, whether
239.37 +gratis or for a fee, you must give the recipients all the rights that
239.38 +you have. You must make sure that they, too, receive or can get the
239.39 +source code. And you must show them these terms so they know their
239.40 +rights.
239.41 +
239.42 + We protect your rights with two steps: (1) copyright the software, and
239.43 +(2) offer you this license which gives you legal permission to copy,
239.44 +distribute and/or modify the software.
239.45 +
239.46 + Also, for each author's protection and ours, we want to make certain
239.47 +that everyone understands that there is no warranty for this free
239.48 +software. If the software is modified by someone else and passed on, we
239.49 +want its recipients to know that what they have is not the original, so
239.50 +that any problems introduced by others will not reflect on the original
239.51 +authors' reputations.
239.52 +
239.53 + Finally, any free program is threatened constantly by software
239.54 +patents. We wish to avoid the danger that redistributors of a free
239.55 +program will individually obtain patent licenses, in effect making the
239.56 +program proprietary. To prevent this, we have made it clear that any
239.57 +patent must be licensed for everyone's free use or not licensed at all.
239.58 +
239.59 + The precise terms and conditions for copying, distribution and
239.60 +modification follow.
239.61 +
239.62 + GNU GENERAL PUBLIC LICENSE
239.63 + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
239.64 +
239.65 + 0. This License applies to any program or other work which contains
239.66 +a notice placed by the copyright holder saying it may be distributed
239.67 +under the terms of this General Public License. The "Program", below,
239.68 +refers to any such program or work, and a "work based on the Program"
239.69 +means either the Program or any derivative work under copyright law:
239.70 +that is to say, a work containing the Program or a portion of it,
239.71 +either verbatim or with modifications and/or translated into another
239.72 +language. (Hereinafter, translation is included without limitation in
239.73 +the term "modification".) Each licensee is addressed as "you".
239.74 +
239.75 +Activities other than copying, distribution and modification are not
239.76 +covered by this License; they are outside its scope. The act of
239.77 +running the Program is not restricted, and the output from the Program
239.78 +is covered only if its contents constitute a work based on the
239.79 +Program (independent of having been made by running the Program).
239.80 +Whether that is true depends on what the Program does.
239.81 +
239.82 + 1. You may copy and distribute verbatim copies of the Program's
239.83 +source code as you receive it, in any medium, provided that you
239.84 +conspicuously and appropriately publish on each copy an appropriate
239.85 +copyright notice and disclaimer of warranty; keep intact all the
239.86 +notices that refer to this License and to the absence of any warranty;
239.87 +and give any other recipients of the Program a copy of this License
239.88 +along with the Program.
239.89 +
239.90 +You may charge a fee for the physical act of transferring a copy, and
239.91 +you may at your option offer warranty protection in exchange for a fee.
239.92 +
239.93 + 2. You may modify your copy or copies of the Program or any portion
239.94 +of it, thus forming a work based on the Program, and copy and
239.95 +distribute such modifications or work under the terms of Section 1
239.96 +above, provided that you also meet all of these conditions:
239.97 +
239.98 + a) You must cause the modified files to carry prominent notices
239.99 + stating that you changed the files and the date of any change.
239.100 +
239.101 + b) You must cause any work that you distribute or publish, that in
239.102 + whole or in part contains or is derived from the Program or any
239.103 + part thereof, to be licensed as a whole at no charge to all third
239.104 + parties under the terms of this License.
239.105 +
239.106 + c) If the modified program normally reads commands interactively
239.107 + when run, you must cause it, when started running for such
239.108 + interactive use in the most ordinary way, to print or display an
239.109 + announcement including an appropriate copyright notice and a
239.110 + notice that there is no warranty (or else, saying that you provide
239.111 + a warranty) and that users may redistribute the program under
239.112 + these conditions, and telling the user how to view a copy of this
239.113 + License. (Exception: if the Program itself is interactive but
239.114 + does not normally print such an announcement, your work based on
239.115 + the Program is not required to print an announcement.)
239.116 +
239.117 +These requirements apply to the modified work as a whole. If
239.118 +identifiable sections of that work are not derived from the Program,
239.119 +and can be reasonably considered independent and separate works in
239.120 +themselves, then this License, and its terms, do not apply to those
239.121 +sections when you distribute them as separate works. But when you
239.122 +distribute the same sections as part of a whole which is a work based
239.123 +on the Program, the distribution of the whole must be on the terms of
239.124 +this License, whose permissions for other licensees extend to the
239.125 +entire whole, and thus to each and every part regardless of who wrote it.
239.126 +
239.127 +Thus, it is not the intent of this section to claim rights or contest
239.128 +your rights to work written entirely by you; rather, the intent is to
239.129 +exercise the right to control the distribution of derivative or
239.130 +collective works based on the Program.
239.131 +
239.132 +In addition, mere aggregation of another work not based on the Program
239.133 +with the Program (or with a work based on the Program) on a volume of
239.134 +a storage or distribution medium does not bring the other work under
239.135 +the scope of this License.
239.136 +
239.137 + 3. You may copy and distribute the Program (or a work based on it,
239.138 +under Section 2) in object code or executable form under the terms of
239.139 +Sections 1 and 2 above provided that you also do one of the following:
239.140 +
239.141 + a) Accompany it with the complete corresponding machine-readable
239.142 + source code, which must be distributed under the terms of Sections
239.143 + 1 and 2 above on a medium customarily used for software interchange; or,
239.144 +
239.145 + b) Accompany it with a written offer, valid for at least three
239.146 + years, to give any third party, for a charge no more than your
239.147 + cost of physically performing source distribution, a complete
239.148 + machine-readable copy of the corresponding source code, to be
239.149 + distributed under the terms of Sections 1 and 2 above on a medium
239.150 + customarily used for software interchange; or,
239.151 +
239.152 + c) Accompany it with the information you received as to the offer
239.153 + to distribute corresponding source code. (This alternative is
239.154 + allowed only for noncommercial distribution and only if you
239.155 + received the program in object code or executable form with such
239.156 + an offer, in accord with Subsection b above.)
239.157 +
239.158 +The source code for a work means the preferred form of the work for
239.159 +making modifications to it. For an executable work, complete source
239.160 +code means all the source code for all modules it contains, plus any
239.161 +associated interface definition files, plus the scripts used to
239.162 +control compilation and installation of the executable. However, as a
239.163 +special exception, the source code distributed need not include
239.164 +anything that is normally distributed (in either source or binary
239.165 +form) with the major components (compiler, kernel, and so on) of the
239.166 +operating system on which the executable runs, unless that component
239.167 +itself accompanies the executable.
239.168 +
239.169 +If distribution of executable or object code is made by offering
239.170 +access to copy from a designated place, then offering equivalent
239.171 +access to copy the source code from the same place counts as
239.172 +distribution of the source code, even though third parties are not
239.173 +compelled to copy the source along with the object code.
239.174 +
239.175 + 4. You may not copy, modify, sublicense, or distribute the Program
239.176 +except as expressly provided under this License. Any attempt
239.177 +otherwise to copy, modify, sublicense or distribute the Program is
239.178 +void, and will automatically terminate your rights under this License.
239.179 +However, parties who have received copies, or rights, from you under
239.180 +this License will not have their licenses terminated so long as such
239.181 +parties remain in full compliance.
239.182 +
239.183 + 5. You are not required to accept this License, since you have not
239.184 +signed it. However, nothing else grants you permission to modify or
239.185 +distribute the Program or its derivative works. These actions are
239.186 +prohibited by law if you do not accept this License. Therefore, by
239.187 +modifying or distributing the Program (or any work based on the
239.188 +Program), you indicate your acceptance of this License to do so, and
239.189 +all its terms and conditions for copying, distributing or modifying
239.190 +the Program or works based on it.
239.191 +
239.192 + 6. Each time you redistribute the Program (or any work based on the
239.193 +Program), the recipient automatically receives a license from the
239.194 +original licensor to copy, distribute or modify the Program subject to
239.195 +these terms and conditions. You may not impose any further
239.196 +restrictions on the recipients' exercise of the rights granted herein.
239.197 +You are not responsible for enforcing compliance by third parties to
239.198 +this License.
239.199 +
239.200 + 7. If, as a consequence of a court judgment or allegation of patent
239.201 +infringement or for any other reason (not limited to patent issues),
239.202 +conditions are imposed on you (whether by court order, agreement or
239.203 +otherwise) that contradict the conditions of this License, they do not
239.204 +excuse you from the conditions of this License. If you cannot
239.205 +distribute so as to satisfy simultaneously your obligations under this
239.206 +License and any other pertinent obligations, then as a consequence you
239.207 +may not distribute the Program at all. For example, if a patent
239.208 +license would not permit royalty-free redistribution of the Program by
239.209 +all those who receive copies directly or indirectly through you, then
239.210 +the only way you could satisfy both it and this License would be to
239.211 +refrain entirely from distribution of the Program.
239.212 +
239.213 +If any portion of this section is held invalid or unenforceable under
239.214 +any particular circumstance, the balance of the section is intended to
239.215 +apply and the section as a whole is intended to apply in other
239.216 +circumstances.
239.217 +
239.218 +It is not the purpose of this section to induce you to infringe any
239.219 +patents or other property right claims or to contest validity of any
239.220 +such claims; this section has the sole purpose of protecting the
239.221 +integrity of the free software distribution system, which is
239.222 +implemented by public license practices. Many people have made
239.223 +generous contributions to the wide range of software distributed
239.224 +through that system in reliance on consistent application of that
239.225 +system; it is up to the author/donor to decide if he or she is willing
239.226 +to distribute software through any other system and a licensee cannot
239.227 +impose that choice.
239.228 +
239.229 +This section is intended to make thoroughly clear what is believed to
239.230 +be a consequence of the rest of this License.
239.231 +
239.232 + 8. If the distribution and/or use of the Program is restricted in
239.233 +certain countries either by patents or by copyrighted interfaces, the
239.234 +original copyright holder who places the Program under this License
239.235 +may add an explicit geographical distribution limitation excluding
239.236 +those countries, so that distribution is permitted only in or among
239.237 +countries not thus excluded. In such case, this License incorporates
239.238 +the limitation as if written in the body of this License.
239.239 +
239.240 + 9. The Free Software Foundation may publish revised and/or new versions
239.241 +of the General Public License from time to time. Such new versions will
239.242 +be similar in spirit to the present version, but may differ in detail to
239.243 +address new problems or concerns.
239.244 +
239.245 +Each version is given a distinguishing version number. If the Program
239.246 +specifies a version number of this License which applies to it and "any
239.247 +later version", you have the option of following the terms and conditions
239.248 +either of that version or of any later version published by the Free
239.249 +Software Foundation. If the Program does not specify a version number of
239.250 +this License, you may choose any version ever published by the Free Software
239.251 +Foundation.
239.252 +
239.253 + 10. If you wish to incorporate parts of the Program into other free
239.254 +programs whose distribution conditions are different, write to the author
239.255 +to ask for permission. For software which is copyrighted by the Free
239.256 +Software Foundation, write to the Free Software Foundation; we sometimes
239.257 +make exceptions for this. Our decision will be guided by the two goals
239.258 +of preserving the free status of all derivatives of our free software and
239.259 +of promoting the sharing and reuse of software generally.
239.260 +
239.261 + NO WARRANTY
239.262 +
239.263 + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
239.264 +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
239.265 +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
239.266 +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
239.267 +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
239.268 +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
239.269 +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
239.270 +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
239.271 +REPAIR OR CORRECTION.
239.272 +
239.273 + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
239.274 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
239.275 +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
239.276 +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
239.277 +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
239.278 +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
239.279 +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
239.280 +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
239.281 +POSSIBILITY OF SUCH DAMAGES.
239.282 +
239.283 + END OF TERMS AND CONDITIONS
239.284 +
239.285 + How to Apply These Terms to Your New Programs
239.286 +
239.287 + If you develop a new program, and you want it to be of the greatest
239.288 +possible use to the public, the best way to achieve this is to make it
239.289 +free software which everyone can redistribute and change under these terms.
239.290 +
239.291 + To do so, attach the following notices to the program. It is safest
239.292 +to attach them to the start of each source file to most effectively
239.293 +convey the exclusion of warranty; and each file should have at least
239.294 +the "copyright" line and a pointer to where the full notice is found.
239.295 +
239.296 + <one line to give the program's name and a brief idea of what it does.>
239.297 + Copyright (C) <year> <name of author>
239.298 +
239.299 + This program is free software; you can redistribute it and/or modify
239.300 + it under the terms of the GNU General Public License as published by
239.301 + the Free Software Foundation; either version 2 of the License, or
239.302 + (at your option) any later version.
239.303 +
239.304 + This program is distributed in the hope that it will be useful,
239.305 + but WITHOUT ANY WARRANTY; without even the implied warranty of
239.306 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
239.307 + GNU General Public License for more details.
239.308 +
239.309 + You should have received a copy of the GNU General Public License along
239.310 + with this program; if not, write to the Free Software Foundation, Inc.,
239.311 + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
239.312 +
239.313 +Also add information on how to contact you by electronic and paper mail.
239.314 +
239.315 +If the program is interactive, make it output a short notice like this
239.316 +when it starts in an interactive mode:
239.317 +
239.318 + Gnomovision version 69, Copyright (C) year name of author
239.319 + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
239.320 + This is free software, and you are welcome to redistribute it
239.321 + under certain conditions; type `show c' for details.
239.322 +
239.323 +The hypothetical commands `show w' and `show c' should show the appropriate
239.324 +parts of the General Public License. Of course, the commands you use may
239.325 +be called something other than `show w' and `show c'; they could even be
239.326 +mouse-clicks or menu items--whatever suits your program.
239.327 +
239.328 +You should also get your employer (if you work as a programmer) or your
239.329 +school, if any, to sign a "copyright disclaimer" for the program, if
239.330 +necessary. Here is a sample; alter the names:
239.331 +
239.332 + Yoyodyne, Inc., hereby disclaims all copyright interest in the program
239.333 + `Gnomovision' (which makes passes at compilers) written by James Hacker.
239.334 +
239.335 + <signature of Ty Coon>, 1 April 1989
239.336 + Ty Coon, President of Vice
239.337 +
239.338 +This General Public License does not permit incorporating your program into
239.339 +proprietary programs. If your program is a subroutine library, you may
239.340 +consider it more useful to permit linking proprietary applications with the
239.341 +library. If this is what you want to do, use the GNU Lesser General
239.342 +Public License instead of this License.
240.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
240.2 +++ b/libipc/include/Makefile Wed Aug 25 01:28:08 2021 +0200
240.3 @@ -0,0 +1,7 @@
240.4 +PKGDIR ?= ..
240.5 +L4DIR ?= $(PKGDIR)/../../..
240.6 +
240.7 +PKGNAME = libipc
240.8 +CONTRIB_HEADERS = 1
240.9 +
240.10 +include $(L4DIR)/mk/include.mk
241.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
241.2 +++ b/libipc/include/ipc/cap_alloc.h Wed Aug 25 01:28:08 2021 +0200
241.3 @@ -0,0 +1,32 @@
241.4 +/*
241.5 + * Capability allocation and management.
241.6 + *
241.7 + * Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk>
241.8 + *
241.9 + * This program is free software; you can redistribute it and/or
241.10 + * modify it under the terms of the GNU General Public License as
241.11 + * published by the Free Software Foundation; either version 2 of
241.12 + * the License, or (at your option) any later version.
241.13 + *
241.14 + * This program is distributed in the hope that it will be useful,
241.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
241.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
241.17 + * GNU General Public License for more details.
241.18 + *
241.19 + * You should have received a copy of the GNU General Public License
241.20 + * along with this program; if not, write to the Free Software
241.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
241.22 + * Boston, MA 02110-1301, USA
241.23 + */
241.24 +
241.25 +#pragma once
241.26 +
241.27 +#include <l4/sys/types.h>
241.28 +
241.29 +EXTERN_C_BEGIN
241.30 +
241.31 +l4_cap_idx_t ipc_cap_alloc(void);
241.32 +int ipc_cap_free(l4_cap_idx_t cap);
241.33 +int ipc_cap_free_um(l4_cap_idx_t cap);
241.34 +
241.35 +EXTERN_C_END
242.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
242.2 +++ b/libipc/include/ipc/direct.h Wed Aug 25 01:28:08 2021 +0200
242.3 @@ -0,0 +1,40 @@
242.4 +/*
242.5 + * Interprocess communication operations.
242.6 + *
242.7 + * Copyright (C) 2018, 2019 Paul Boddie <paul@boddie.org.uk>
242.8 + *
242.9 + * This program is free software; you can redistribute it and/or
242.10 + * modify it under the terms of the GNU General Public License as
242.11 + * published by the Free Software Foundation; either version 2 of
242.12 + * the License, or (at your option) any later version.
242.13 + *
242.14 + * This program is distributed in the hope that it will be useful,
242.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
242.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
242.17 + * GNU General Public License for more details.
242.18 + *
242.19 + * You should have received a copy of the GNU General Public License
242.20 + * along with this program; if not, write to the Free Software
242.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
242.22 + * Boston, MA 02110-1301, USA
242.23 + */
242.24 +
242.25 +#pragma once
242.26 +
242.27 +#include <l4/re/c/dataspace.h>
242.28 +#include <l4/sys/ipc.h>
242.29 +#include <l4/sys/types.h>
242.30 +
242.31 +
242.32 +
242.33 +EXTERN_C_BEGIN
242.34 +
242.35 +/* Direct operations. */
242.36 +
242.37 +long ipc_expect_capabilities(int number);
242.38 +long ipc_expect_capability(int item);
242.39 +void ipc_export_capability(l4_msgtag_t tag, int item, l4_cap_idx_t ref);
242.40 +long ipc_import_capability(l4_msgtag_t tag, int item, l4_cap_idx_t *ref);
242.41 +long ipc_import_dataspace(l4_msgtag_t tag, int item, l4re_ds_t *mem, l4_addr_t *addr);
242.42 +
242.43 +EXTERN_C_END
243.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
243.2 +++ b/libipc/include/ipc/factory.h Wed Aug 25 01:28:08 2021 +0200
243.3 @@ -0,0 +1,45 @@
243.4 +/*
243.5 + * Factory-related data types.
243.6 + *
243.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
243.8 + *
243.9 + * This program is free software; you can redistribute it and/or
243.10 + * modify it under the terms of the GNU General Public License as
243.11 + * published by the Free Software Foundation; either version 2 of
243.12 + * the License, or (at your option) any later version.
243.13 + *
243.14 + * This program is distributed in the hope that it will be useful,
243.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
243.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
243.17 + * GNU General Public License for more details.
243.18 + *
243.19 + * You should have received a copy of the GNU General Public License
243.20 + * along with this program; if not, write to the Free Software
243.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
243.22 + * Boston, MA 02110-1301, USA
243.23 + */
243.24 +
243.25 +#pragma once
243.26 +
243.27 +#include <l4/sys/types.h>
243.28 +
243.29 +#include <systypes/factory.h>
243.30 +
243.31 +
243.32 +
243.33 +EXTERN_C_BEGIN
243.34 +
243.35 +/* Supporting data types for factory invocations. */
243.36 +
243.37 +typedef unsigned long unsigned_long;
243.38 +
243.39 +ipc_varg_typedef(long, ipc_varg(long))
243.40 +ipc_varg_typedef(unsigned_long, ipc_varg(unsigned_long))
243.41 +
243.42 +#define ipc_varg_long(value) \
243.43 +ipc_varg_mword(ipc_varg(long), value)
243.44 +
243.45 +#define ipc_varg_unsigned_long(value) \
243.46 +ipc_varg_umword(ipc_varg(unsigned_long), value)
243.47 +
243.48 +EXTERN_C_END
244.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
244.2 +++ b/libipc/include/ipc/irq.h Wed Aug 25 01:28:08 2021 +0200
244.3 @@ -0,0 +1,37 @@
244.4 +/*
244.5 + * Interrupt request handling.
244.6 + *
244.7 + * Copyright (C) 2018, 2019 Paul Boddie <paul@boddie.org.uk>
244.8 + *
244.9 + * This program is free software; you can redistribute it and/or
244.10 + * modify it under the terms of the GNU General Public License as
244.11 + * published by the Free Software Foundation; either version 2 of
244.12 + * the License, or (at your option) any later version.
244.13 + *
244.14 + * This program is distributed in the hope that it will be useful,
244.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
244.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
244.17 + * GNU General Public License for more details.
244.18 + *
244.19 + * You should have received a copy of the GNU General Public License
244.20 + * along with this program; if not, write to the Free Software
244.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
244.22 + * Boston, MA 02110-1301, USA
244.23 + */
244.24 +
244.25 +#pragma once
244.26 +
244.27 +#include <l4/sys/ipc.h>
244.28 +#include <l4/sys/types.h>
244.29 +
244.30 +
244.31 +
244.32 +EXTERN_C_BEGIN
244.33 +
244.34 +/* IRQ operations. */
244.35 +
244.36 +long ipc_create_irq(l4_cap_idx_t *irq);
244.37 +l4_msgtag_t ipc_init_irq(l4_cap_idx_t irq);
244.38 +long ipc_bind_irq(l4_cap_idx_t irq, l4_umword_t id, l4_cap_idx_t thread);
244.39 +
244.40 +EXTERN_C_END
245.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
245.2 +++ b/libipc/include/ipc/macros_ipc.h Wed Aug 25 01:28:08 2021 +0200
245.3 @@ -0,0 +1,38 @@
245.4 +/*
245.5 + * Interprocess communication macros.
245.6 + *
245.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
245.8 + *
245.9 + * This program is free software; you can redistribute it and/or
245.10 + * modify it under the terms of the GNU General Public License as
245.11 + * published by the Free Software Foundation; either version 2 of
245.12 + * the License, or (at your option) any later version.
245.13 + *
245.14 + * This program is distributed in the hope that it will be useful,
245.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
245.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
245.17 + * GNU General Public License for more details.
245.18 + *
245.19 + * You should have received a copy of the GNU General Public License
245.20 + * along with this program; if not, write to the Free Software
245.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
245.22 + * Boston, MA 02110-1301, USA
245.23 + */
245.24 +
245.25 +#pragma once
245.26 +
245.27 +/* Count the size of an array. */
245.28 +
245.29 +#define VA_ARGCOUNT(TYPE, ARGS) (sizeof(ARGS) / sizeof(TYPE))
245.30 +
245.31 +/* Prepare an array from a variable argument list. */
245.32 +
245.33 +#define VA_ARGLIST(TYPE, ...) ((TYPE []) {__VA_ARGS__})
245.34 +
245.35 +/* Assign array members. */
245.36 +
245.37 +#define ARRAY_ASSIGN(TO, TYPE, ...) \
245.38 + memcpy(TO, VA_ARGLIST(TYPE, __VA_ARGS__), \
245.39 + sizeof(VA_ARGLIST(TYPE, __VA_ARGS__)))
245.40 +
245.41 +#define ipc_set_registers(TO, ...) ARRAY_ASSIGN(TO, l4_umword_t, __VA_ARGS__)
246.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
246.2 +++ b/libipc/include/ipc/mem_ipc.h Wed Aug 25 01:28:08 2021 +0200
246.3 @@ -0,0 +1,35 @@
246.4 +/*
246.5 + * Memory sharing abstractions.
246.6 + *
246.7 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
246.8 + *
246.9 + * This program is free software; you can redistribute it and/or
246.10 + * modify it under the terms of the GNU General Public License as
246.11 + * published by the Free Software Foundation; either version 2 of
246.12 + * the License, or (at your option) any later version.
246.13 + *
246.14 + * This program is distributed in the hope that it will be useful,
246.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
246.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
246.17 + * GNU General Public License for more details.
246.18 + *
246.19 + * You should have received a copy of the GNU General Public License
246.20 + * along with this program; if not, write to the Free Software
246.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
246.22 + * Boston, MA 02110-1301, USA
246.23 + */
246.24 +
246.25 +#pragma once
246.26 +
246.27 +#include <l4/re/c/dataspace.h>
246.28 +#include <l4/sys/types.h>
246.29 +
246.30 +EXTERN_C_BEGIN
246.31 +
246.32 +long ipc_allocate(unsigned long size, void **addr, l4re_ds_t *ds);
246.33 +long ipc_new_dataspace(l4_cap_idx_t cap, l4_mword_t size, l4_umword_t flags, l4_umword_t align);
246.34 +long ipc_attach_dataspace(l4re_ds_t ds, unsigned long size, void **addr);
246.35 +long ipc_detach_dataspace(void *addr);
246.36 +long ipc_dataspace_size(l4_cap_idx_t cap, unsigned long *size);
246.37 +
246.38 +EXTERN_C_END
247.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
247.2 +++ b/libipc/include/ipc/message.h Wed Aug 25 01:28:08 2021 +0200
247.3 @@ -0,0 +1,142 @@
247.4 +/*
247.5 + * Interprocess communication message abstraction.
247.6 + *
247.7 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
247.8 + *
247.9 + * This program is free software; you can redistribute it and/or
247.10 + * modify it under the terms of the GNU General Public License as
247.11 + * published by the Free Software Foundation; either version 2 of
247.12 + * the License, or (at your option) any later version.
247.13 + *
247.14 + * This program is distributed in the hope that it will be useful,
247.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
247.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
247.17 + * GNU General Public License for more details.
247.18 + *
247.19 + * You should have received a copy of the GNU General Public License
247.20 + * along with this program; if not, write to the Free Software
247.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
247.22 + * Boston, MA 02110-1301, USA
247.23 + */
247.24 +
247.25 +#pragma once
247.26 +
247.27 +#include <l4/re/c/dataspace.h>
247.28 +#include <l4/sys/ipc.h>
247.29 +#include <l4/sys/utcb.h>
247.30 +#include <l4/sys/types.h>
247.31 +
247.32 +#include <sys/types.h>
247.33 +
247.34 +
247.35 +
247.36 +EXTERN_C_BEGIN
247.37 +
247.38 +/* Message abstraction. */
247.39 +
247.40 +typedef struct
247.41 +{
247.42 + /* Common virtual registers. */
247.43 +
247.44 + l4_buf_regs_t bregs;
247.45 + l4_msg_regs_t mregs;
247.46 +
247.47 + /* Input details. */
247.48 +
247.49 + l4_msgtag_t tag;
247.50 + unsigned int expected_items;
247.51 +
247.52 + /* Output details. */
247.53 +
247.54 + unsigned int words;
247.55 + unsigned int items;
247.56 +
247.57 + /* Items transferred and not retained. */
247.58 +
247.59 + unsigned int discarded_items;
247.60 + l4_cap_idx_t to_discard[L4_UTCB_GENERIC_DATA_SIZE];
247.61 +
247.62 + /* Message label overriding. */
247.63 +
247.64 + l4_umword_t new_label;
247.65 +
247.66 + /* Server control. */
247.67 +
247.68 + int terminating;
247.69 +
247.70 +} ipc_message_t;
247.71 +
247.72 +
247.73 +
247.74 +/* Special status codes. */
247.75 +
247.76 +#define IPC_MESSAGE_SENT 0x01d10000
247.77 +
247.78 +/* Capability annotations. */
247.79 +
247.80 +#define IPC_DISCARD_CAP_FLAG (1 << (L4_CAP_SHIFT - 2))
247.81 +#define discard_cap(x) (x | IPC_DISCARD_CAP_FLAG)
247.82 +
247.83 +
247.84 +
247.85 +/* Message operations. */
247.86 +
247.87 +/* Lifecycle operations. */
247.88 +
247.89 +void ipc_message_new(ipc_message_t *msg);
247.90 +long ipc_message_expect(ipc_message_t *msg, unsigned int expected_items);
247.91 +void ipc_message_request(ipc_message_t *msg, int op, l4_cap_idx_t endpoint);
247.92 +void ipc_message_send(ipc_message_t *msg, int op, l4_cap_idx_t endpoint);
247.93 +void ipc_message_wait(ipc_message_t *msg, l4_umword_t *label);
247.94 +void ipc_message_reply(ipc_message_t *msg);
247.95 +void ipc_message_discard(ipc_message_t *msg);
247.96 +void ipc_message_free(ipc_message_t *msg);
247.97 +
247.98 +/* Helper operations. */
247.99 +
247.100 +void ipc_message_open(ipc_message_t *msg);
247.101 +void ipc_message_prepare(ipc_message_t *msg);
247.102 +void ipc_message_preserve_buffer_registers(ipc_message_t *msg);
247.103 +void ipc_message_preserve_message_registers(ipc_message_t *msg);
247.104 +void ipc_message_reset(ipc_message_t *msg);
247.105 +void ipc_message_restore_buffer_registers(ipc_message_t *msg);
247.106 +void ipc_message_restore_message_registers(ipc_message_t *msg);
247.107 +
247.108 +/* Population operations. */
247.109 +
247.110 +void ipc_message_add_capability(ipc_message_t *msg, l4_cap_idx_t cap);
247.111 +void ipc_message_add_data(ipc_message_t *msg, const char *value, size_t length);
247.112 +void ipc_message_add_item(ipc_message_t *msg, l4_cap_idx_t cap);
247.113 +void ipc_message_add_fpage(ipc_message_t *msg, l4_snd_fpage_t fpage);
247.114 +void ipc_message_add_page(ipc_message_t *msg, l4_umword_t hot_spot, l4_fpage_t fpage);
247.115 +void ipc_message_add_string(ipc_message_t *msg, const char *value);
247.116 +void ipc_message_add_word(ipc_message_t *msg, l4_umword_t value);
247.117 +void ipc_message_propagate_item(ipc_message_t *msg, l4_cap_idx_t cap);
247.118 +void *ipc_message_reserve_data(ipc_message_t *msg, size_t length);
247.119 +void *ipc_message_reserve_words(ipc_message_t *msg, size_t length);
247.120 +void ipc_message_send_error(ipc_message_t *msg, long error);
247.121 +
247.122 +/* Access operations. */
247.123 +
247.124 +l4_umword_t ipc_message_get_word(ipc_message_t *msg, unsigned int word);
247.125 +l4_umword_t *ipc_message_get_word_address(ipc_message_t *msg, unsigned int word);
247.126 +unsigned int ipc_message_number_of_items(ipc_message_t *msg);
247.127 +unsigned int ipc_message_number_of_words(ipc_message_t *msg);
247.128 +
247.129 +/* Supporting operations. */
247.130 +
247.131 +void ipc_message_discard_capability(ipc_message_t *msg, l4_cap_idx_t cap);
247.132 +void ipc_message_discard_dataspace(ipc_message_t *msg, l4re_ds_t mem, l4_addr_t addr);
247.133 +long ipc_message_expect_capabilities(ipc_message_t *msg, int number);
247.134 +long ipc_message_expect_capability(ipc_message_t *msg, int item);
247.135 +void ipc_message_export_capability(ipc_message_t *msg, int item, l4_cap_idx_t ref);
247.136 +void ipc_message_export_fpage(ipc_message_t *msg, int item, l4_snd_fpage_t fpage);
247.137 +void ipc_message_export_page(ipc_message_t *msg, int item, l4_umword_t hot_spot, l4_fpage_t fpage);
247.138 +long ipc_message_import_capability(ipc_message_t *msg, int item, l4_cap_idx_t *ref);
247.139 +long ipc_message_import_dataspace(ipc_message_t *msg, int item, l4re_ds_t *mem, l4_addr_t *addr);
247.140 +long ipc_message_import_fpage(ipc_message_t *msg, int item, l4_snd_fpage_t *fpage);
247.141 +void ipc_message_propagate_capability(ipc_message_t *msg, int item, l4_cap_idx_t ref);
247.142 +l4_msgtag_t ipc_message_reply_tag(ipc_message_t *msg);
247.143 +l4_msgtag_t ipc_message_request_tag(ipc_message_t *msg, int op);
247.144 +
247.145 +EXTERN_C_END
248.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
248.2 +++ b/libipc/include/ipc/semaphore.h Wed Aug 25 01:28:08 2021 +0200
248.3 @@ -0,0 +1,31 @@
248.4 +/*
248.5 + * Semaphore utilities.
248.6 + *
248.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk>
248.8 + *
248.9 + * This program is free software; you can redistribute it and/or
248.10 + * modify it under the terms of the GNU General Public License as
248.11 + * published by the Free Software Foundation; either version 2 of
248.12 + * the License, or (at your option) any later version.
248.13 + *
248.14 + * This program is distributed in the hope that it will be useful,
248.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
248.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
248.17 + * GNU General Public License for more details.
248.18 + *
248.19 + * You should have received a copy of the GNU General Public License
248.20 + * along with this program; if not, write to the Free Software
248.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
248.22 + * Boston, MA 02110-1301, USA
248.23 + */
248.24 +
248.25 +#pragma once
248.26 +
248.27 +#include <l4/sys/types.h>
248.28 +
248.29 +EXTERN_C_BEGIN
248.30 +
248.31 +long ipc_semaphore_down(l4_cap_idx_t cap);
248.32 +long ipc_semaphore_up(l4_cap_idx_t cap);
248.33 +
248.34 +EXTERN_C_END
249.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
249.2 +++ b/libipc/include/ipc/server.h Wed Aug 25 01:28:08 2021 +0200
249.3 @@ -0,0 +1,150 @@
249.4 +/*
249.5 + * Server binding/registration.
249.6 + *
249.7 + * Copyright (C) 2018, 2019, 2020, 2021 Paul Boddie <paul@boddie.org.uk>
249.8 + *
249.9 + * This program is free software; you can redistribute it and/or
249.10 + * modify it under the terms of the GNU General Public License as
249.11 + * published by the Free Software Foundation; either version 2 of
249.12 + * the License, or (at your option) any later version.
249.13 + *
249.14 + * This program is distributed in the hope that it will be useful,
249.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
249.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
249.17 + * GNU General Public License for more details.
249.18 + *
249.19 + * You should have received a copy of the GNU General Public License
249.20 + * along with this program; if not, write to the Free Software
249.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
249.22 + * Boston, MA 02110-1301, USA
249.23 + */
249.24 +
249.25 +#pragma once
249.26 +
249.27 +#include <l4/sys/types.h>
249.28 +
249.29 +#include <ipc/message.h>
249.30 +
249.31 +EXTERN_C_BEGIN
249.32 +
249.33 +/* A convenience macro for invoking the server mainloop. */
249.34 +
249.35 +#define ipc_server_loop_for(TYPE, POINTER) \
249.36 + ipc_server_loop(TYPE##_expected_items, (TYPE *) POINTER, \
249.37 + (ipc_server_handler_type) handle_##TYPE)
249.38 +
249.39 +/* A handler function type. */
249.40 +
249.41 +typedef void (*ipc_server_handler_type)(ipc_message_t *, void *);
249.42 +
249.43 +/* A finaliser function type. */
249.44 +
249.45 +struct ipc_server_config_type;
249.46 +
249.47 +typedef void (*ipc_server_finaliser_type)(struct ipc_server_config_type *);
249.48 +
249.49 +/* A server configuration type. */
249.50 +
249.51 +typedef struct ipc_server_config_type
249.52 +{
249.53 + /* Component object references. C++ objects may provide different references
249.54 + for the handler (providing access to the exposed interface) and the
249.55 + finaliser (providing access to a distinct control interface). */
249.56 +
249.57 + void *handler_obj;
249.58 + void *finaliser_obj;
249.59 +
249.60 + /* Expected capability item limit for incoming messages. */
249.61 +
249.62 + int expected_items;
249.63 +
249.64 + /* Handler for incoming messages and finaliser upon deletion. */
249.65 +
249.66 + ipc_server_handler_type handler;
249.67 + ipc_server_finaliser_type finaliser;
249.68 +
249.69 + /* Create a new thread. */
249.70 +
249.71 + int new_thread;
249.72 +
249.73 + /* Thread and IPC capabilities. */
249.74 +
249.75 + l4_cap_idx_t thread;
249.76 + l4_cap_idx_t server;
249.77 +
249.78 + /* Receive deletion notifications via an IRQ. */
249.79 +
249.80 + int notifications;
249.81 + l4_cap_idx_t irq;
249.82 +
249.83 +} ipc_server_config_type;
249.84 +
249.85 +
249.86 +
249.87 +/* Associate a notification IRQ with an IPC gate in the main thread. */
249.88 +
249.89 +long ipc_server_apply_irq(l4_cap_idx_t cap, l4_cap_idx_t *irq);
249.90 +
249.91 +/* Associate a notification IRQ with an IPC gate in the given thread. */
249.92 +
249.93 +long ipc_server_apply_irq_for_thread(l4_cap_idx_t cap, l4_cap_idx_t *irq, l4_cap_idx_t thread);
249.94 +
249.95 +/* Bind the main thread to a named IPC gate capability. */
249.96 +
249.97 +long ipc_server_bind(const char *name, l4_umword_t id, l4_cap_idx_t *server);
249.98 +
249.99 +/* Create a new IPC gate for the main thread. */
249.100 +
249.101 +long ipc_server_new(l4_cap_idx_t *cap, void *obj);
249.102 +
249.103 +/* Create a new IPC gate for the given thread. */
249.104 +
249.105 +long ipc_server_new_for_thread(l4_cap_idx_t *cap, void *obj, l4_cap_idx_t thread);
249.106 +
249.107 +/* Create an IPC gate for the main thread. */
249.108 +
249.109 +long ipc_server_new_gate(l4_cap_idx_t *ref, l4_umword_t id);
249.110 +
249.111 +/* Create an IPC gate for the indicated thread. */
249.112 +
249.113 +long ipc_server_new_gate_for_thread(l4_cap_idx_t *ref, l4_cap_idx_t thread, l4_umword_t id);
249.114 +
249.115 +
249.116 +
249.117 +/* Handle incoming messages for a server. */
249.118 +
249.119 +long ipc_server_loop(int expected_items, void *obj,
249.120 + ipc_server_handler_type handler);
249.121 +
249.122 +/* Handle incoming messages and IRQ notifications for a server. */
249.123 +
249.124 +long ipc_server_managed_loop(int expected_items, void *obj, l4_cap_idx_t irq,
249.125 + ipc_server_handler_type handler);
249.126 +
249.127 +/* A pthread-compatible mainloop initiation function. */
249.128 +
249.129 +void *ipc_server_start_mainloop(void *data);
249.130 +
249.131 +/* Wait for an incoming message via a dedicated IPC gate for a thread. */
249.132 +
249.133 +l4_msgtag_t ipc_server_wait(l4_umword_t id);
249.134 +
249.135 +
249.136 +
249.137 +/* Finalise a server configuration. */
249.138 +
249.139 +void ipc_server_finalise_config(ipc_server_config_type *config);
249.140 +
249.141 +/* Discard any thread created but not initiated. */
249.142 +
249.143 +void ipc_server_discard_thread(ipc_server_config_type *config);
249.144 +
249.145 +/* Initialise a server configuration. */
249.146 +
249.147 +void ipc_server_init_config(ipc_server_config_type *config);
249.148 +
249.149 +/* Initialise and start a server using the given configuration. */
249.150 +
249.151 +long ipc_server_start_config(ipc_server_config_type *config);
249.152 +
249.153 +EXTERN_C_END
250.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
250.2 +++ b/libipc/include/ipc/thread.h Wed Aug 25 01:28:08 2021 +0200
250.3 @@ -0,0 +1,35 @@
250.4 +/*
250.5 + * Thread-related initialisation.
250.6 + *
250.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk>
250.8 + *
250.9 + * This program is free software; you can redistribute it and/or
250.10 + * modify it under the terms of the GNU General Public License as
250.11 + * published by the Free Software Foundation; either version 2 of
250.12 + * the License, or (at your option) any later version.
250.13 + *
250.14 + * This program is distributed in the hope that it will be useful,
250.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
250.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
250.17 + * GNU General Public License for more details.
250.18 + *
250.19 + * You should have received a copy of the GNU General Public License
250.20 + * along with this program; if not, write to the Free Software
250.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
250.22 + * Boston, MA 02110-1301, USA
250.23 + */
250.24 +
250.25 +#pragma once
250.26 +
250.27 +#include <l4/sys/types.h>
250.28 +
250.29 +EXTERN_C_BEGIN
250.30 +
250.31 +long ipc_cap_alloc_init(void);
250.32 +long ipc_mem_init(void);
250.33 +
250.34 +/* Principal thread-related initialisation function. */
250.35 +
250.36 +long ipc_thread_init(void);
250.37 +
250.38 +EXTERN_C_END
251.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
251.2 +++ b/libipc/include/ipc/util_ipc.h Wed Aug 25 01:28:08 2021 +0200
251.3 @@ -0,0 +1,53 @@
251.4 +/*
251.5 + * Interprocess communication abstractions.
251.6 + *
251.7 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
251.8 + *
251.9 + * This program is free software; you can redistribute it and/or
251.10 + * modify it under the terms of the GNU General Public License as
251.11 + * published by the Free Software Foundation; either version 2 of
251.12 + * the License, or (at your option) any later version.
251.13 + *
251.14 + * This program is distributed in the hope that it will be useful,
251.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
251.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
251.17 + * GNU General Public License for more details.
251.18 + *
251.19 + * You should have received a copy of the GNU General Public License
251.20 + * along with this program; if not, write to the Free Software
251.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
251.22 + * Boston, MA 02110-1301, USA
251.23 + */
251.24 +
251.25 +#pragma once
251.26 +
251.27 +#include <l4/re/c/dataspace.h>
251.28 +#include <l4/sys/ipc.h>
251.29 +#include <l4/sys/utcb.h>
251.30 +#include <l4/sys/types.h>
251.31 +
251.32 +#include <sys/types.h>
251.33 +
251.34 +
251.35 +
251.36 +EXTERN_C_BEGIN
251.37 +
251.38 +/* Supporting operations. */
251.39 +
251.40 +long _expect_capabilities(l4_buf_regs_t *bregs, int number);
251.41 +long _expect_capability(l4_buf_regs_t *bregs, int item);
251.42 +void _export_capability(l4_msgtag_t tag, l4_msg_regs_t *mregs, int item, l4_cap_idx_t ref);
251.43 +void _export_fpage(l4_msgtag_t tag, l4_msg_regs_t *mregs, int item, l4_snd_fpage_t fpage);
251.44 +void _export_page(l4_msgtag_t tag, l4_msg_regs_t *mregs, int item, l4_umword_t hot_spot, l4_fpage_t fpage);
251.45 +void _free_expected_capabilities(l4_buf_regs_t *bregs, int number);
251.46 +long _import_capability(l4_msgtag_t tag, l4_buf_regs_t *bregs, l4_msg_regs_t *mregs, int item, l4_cap_idx_t *ref);
251.47 +long _import_dataspace(l4_msgtag_t tag, l4_buf_regs_t *bregs, l4_msg_regs_t *mregs, int item, l4re_ds_t *mem, l4_addr_t *addr);
251.48 +long _import_fpage(l4_msgtag_t tag, l4_buf_regs_t *bregs, l4_msg_regs_t *mregs, int item, l4_snd_fpage_t *fpage);
251.49 +
251.50 +/* Convenience operations. */
251.51 +
251.52 +l4_msgtag_t util_ipc_reply(l4_msgtag_t tag);
251.53 +l4_msgtag_t util_ipc_request(l4_msgtag_t tag, l4_cap_idx_t endpoint);
251.54 +l4_msgtag_t util_ipc_send(l4_msgtag_t tag, l4_cap_idx_t endpoint);
251.55 +
251.56 +EXTERN_C_END
252.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
252.2 +++ b/libipc/lib/Makefile Wed Aug 25 01:28:08 2021 +0200
252.3 @@ -0,0 +1,4 @@
252.4 +PKGDIR ?= ..
252.5 +L4DIR ?= $(PKGDIR)/../../..
252.6 +
252.7 +include $(L4DIR)/mk/subdir.mk
253.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
253.2 +++ b/libipc/lib/src/Makefile Wed Aug 25 01:28:08 2021 +0200
253.3 @@ -0,0 +1,12 @@
253.4 +PKGDIR ?= ../..
253.5 +L4DIR ?= $(PKGDIR)/../../..
253.6 +
253.7 +TARGET = libipc.a libipc.so
253.8 +PC_FILENAME = libipc
253.9 +SRC_C = cap_alloc.c direct.c irq.c mem_ipc.c message.c semaphore.c server.c thread.c util_ipc.c
253.10 +REQUIRES_LIBS = l4re_c-util
253.11 +
253.12 +PRIVATE_INCDIR += $(PKGDIR)/include/ipc
253.13 +CONTRIB_INCDIR = libipc
253.14 +
253.15 +include $(L4DIR)/mk/lib.mk
254.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
254.2 +++ b/libipc/lib/src/cap_alloc.c Wed Aug 25 01:28:08 2021 +0200
254.3 @@ -0,0 +1,89 @@
254.4 +/*
254.5 + * Capability allocation and management.
254.6 + *
254.7 + * Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk>
254.8 + *
254.9 + * This program is free software; you can redistribute it and/or
254.10 + * modify it under the terms of the GNU General Public License as
254.11 + * published by the Free Software Foundation; either version 2 of
254.12 + * the License, or (at your option) any later version.
254.13 + *
254.14 + * This program is distributed in the hope that it will be useful,
254.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
254.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
254.17 + * GNU General Public License for more details.
254.18 + *
254.19 + * You should have received a copy of the GNU General Public License
254.20 + * along with this program; if not, write to the Free Software
254.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
254.22 + * Boston, MA 02110-1301, USA
254.23 + */
254.24 +
254.25 +#include <l4/re/c/util/cap_alloc.h>
254.26 +
254.27 +#include "cap_alloc.h"
254.28 +#include "semaphore.h"
254.29 +
254.30 +
254.31 +
254.32 +/* Semaphore used if threading has been initialised by ipc_cap_alloc_init. */
254.33 +
254.34 +l4_cap_idx_t ipc_cap_alloc_semaphore = L4_INVALID_CAP;
254.35 +
254.36 +
254.37 +
254.38 +/* Reserve and return a capability index. */
254.39 +
254.40 +l4_cap_idx_t ipc_cap_alloc()
254.41 +{
254.42 + l4_cap_idx_t cap;
254.43 + long err;
254.44 +
254.45 + /* Allocate a capability in the critical section, then return. */
254.46 +
254.47 + err = ipc_semaphore_down(ipc_cap_alloc_semaphore);
254.48 + if (err)
254.49 + return L4_INVALID_CAP;
254.50 +
254.51 + cap = l4re_util_cap_alloc();
254.52 +
254.53 + ipc_semaphore_up(ipc_cap_alloc_semaphore);
254.54 +
254.55 + return cap;
254.56 +}
254.57 +
254.58 +/* Release a capability. */
254.59 +
254.60 +int ipc_cap_free(l4_cap_idx_t cap)
254.61 +{
254.62 + long err;
254.63 +
254.64 + err = ipc_semaphore_down(ipc_cap_alloc_semaphore);
254.65 + if (err)
254.66 + return 0;
254.67 +
254.68 + l4re_util_cap_free(cap);
254.69 +
254.70 + ipc_semaphore_up(ipc_cap_alloc_semaphore);
254.71 +
254.72 + return 1;
254.73 +}
254.74 +
254.75 +/* Free the indicated capability and unmap it. */
254.76 +
254.77 +int ipc_cap_free_um(l4_cap_idx_t cap)
254.78 +{
254.79 + long err;
254.80 +
254.81 + err = ipc_semaphore_down(ipc_cap_alloc_semaphore);
254.82 + if (err)
254.83 + return 0;
254.84 +
254.85 + l4re_util_cap_free_um(cap);
254.86 +
254.87 + ipc_semaphore_up(ipc_cap_alloc_semaphore);
254.88 +
254.89 + return 1;
254.90 +}
254.91 +
254.92 +// vim: tabstop=2 expandtab shiftwidth=2
255.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
255.2 +++ b/libipc/lib/src/direct.c Wed Aug 25 01:28:08 2021 +0200
255.3 @@ -0,0 +1,66 @@
255.4 +/*
255.5 + * Interprocess communication abstractions.
255.6 + *
255.7 + * Copyright (C) 2018, 2019 Paul Boddie <paul@boddie.org.uk>
255.8 + *
255.9 + * This program is free software; you can redistribute it and/or
255.10 + * modify it under the terms of the GNU General Public License as
255.11 + * published by the Free Software Foundation; either version 2 of
255.12 + * the License, or (at your option) any later version.
255.13 + *
255.14 + * This program is distributed in the hope that it will be useful,
255.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
255.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
255.17 + * GNU General Public License for more details.
255.18 + *
255.19 + * You should have received a copy of the GNU General Public License
255.20 + * along with this program; if not, write to the Free Software
255.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
255.22 + * Boston, MA 02110-1301, USA
255.23 + */
255.24 +
255.25 +#include <l4/sys/utcb.h>
255.26 +
255.27 +#include "direct.h"
255.28 +#include "util_ipc.h"
255.29 +
255.30 +
255.31 +
255.32 +/* Direct operations. */
255.33 +
255.34 +/* Reserve the given number of slots from zero for incoming capabilities. */
255.35 +
255.36 +long ipc_expect_capabilities(int number)
255.37 +{
255.38 + return _expect_capabilities(l4_utcb_br(), number);
255.39 +}
255.40 +
255.41 +/* Reserve a slot for an incoming capability. */
255.42 +
255.43 +long ipc_expect_capability(int item)
255.44 +{
255.45 + return _expect_capability(l4_utcb_br(), item);
255.46 +}
255.47 +
255.48 +/* Export a capability at the given position in the message. */
255.49 +
255.50 +void ipc_export_capability(l4_msgtag_t tag, int item, l4_cap_idx_t ref)
255.51 +{
255.52 + _export_capability(tag, l4_utcb_mr(), item, ref);
255.53 +}
255.54 +
255.55 +/* Import the capability at the given item position, updating the buffer
255.56 + registers for future capabilities. */
255.57 +
255.58 +long ipc_import_capability(l4_msgtag_t tag, int item, l4_cap_idx_t *ref)
255.59 +{
255.60 + return _import_capability(tag, l4_utcb_br(), l4_utcb_mr(), item, ref);
255.61 +}
255.62 +
255.63 +/* Import a dataspace, mapping it to an address, updating the buffer registers
255.64 + for future capabilities. */
255.65 +
255.66 +long ipc_import_dataspace(l4_msgtag_t tag, int item, l4re_ds_t *mem, l4_addr_t *addr)
255.67 +{
255.68 + return _import_dataspace(tag, l4_utcb_br(), l4_utcb_mr(), item, mem, addr);
255.69 +}
256.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
256.2 +++ b/libipc/lib/src/irq.c Wed Aug 25 01:28:08 2021 +0200
256.3 @@ -0,0 +1,73 @@
256.4 +/*
256.5 + * Interrupt request handling.
256.6 + *
256.7 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
256.8 + *
256.9 + * This program is free software; you can redistribute it and/or
256.10 + * modify it under the terms of the GNU General Public License as
256.11 + * published by the Free Software Foundation; either version 2 of
256.12 + * the License, or (at your option) any later version.
256.13 + *
256.14 + * This program is distributed in the hope that it will be useful,
256.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
256.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
256.17 + * GNU General Public License for more details.
256.18 + *
256.19 + * You should have received a copy of the GNU General Public License
256.20 + * along with this program; if not, write to the Free Software
256.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
256.22 + * Boston, MA 02110-1301, USA
256.23 + */
256.24 +
256.25 +#include <l4/re/env.h>
256.26 +#include <l4/sys/factory.h>
256.27 +#include <l4/sys/irq.h>
256.28 +#include <l4/sys/rcv_endpoint.h>
256.29 +
256.30 +#include "cap_alloc.h"
256.31 +#include "irq.h"
256.32 +
256.33 +
256.34 +
256.35 +/* IRQ operations. */
256.36 +
256.37 +/* Create an interrupt request object. */
256.38 +
256.39 +long ipc_create_irq(l4_cap_idx_t *irq)
256.40 +{
256.41 + long err;
256.42 +
256.43 + *irq = ipc_cap_alloc();
256.44 +
256.45 + if (l4_is_invalid_cap(*irq))
256.46 + return -L4_ENOENT;
256.47 +
256.48 + err = l4_error(l4_factory_create_irq(l4re_env()->factory, *irq));
256.49 +
256.50 + if (err)
256.51 + {
256.52 + ipc_cap_free_um(*irq);
256.53 + return err;
256.54 + }
256.55 +
256.56 + return L4_EOK;
256.57 +}
256.58 +
256.59 +/* Initialise an interrupt request object for subsequent notifications. */
256.60 +
256.61 +l4_msgtag_t ipc_init_irq(l4_cap_idx_t irq)
256.62 +{
256.63 + return l4_irq_unmask(irq);
256.64 +}
256.65 +
256.66 +/* Prepare a thread to receive IRQ object notifications. */
256.67 +
256.68 +long ipc_bind_irq(l4_cap_idx_t irq, l4_umword_t id, l4_cap_idx_t thread)
256.69 +{
256.70 + long err = l4_error(l4_rcv_ep_bind_thread(irq, thread, id));
256.71 +
256.72 + if (err)
256.73 + return err;
256.74 +
256.75 + return L4_EOK;
256.76 +}
257.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
257.2 +++ b/libipc/lib/src/mem_ipc.c Wed Aug 25 01:28:08 2021 +0200
257.3 @@ -0,0 +1,116 @@
257.4 +/*
257.5 + * Memory sharing abstractions.
257.6 + *
257.7 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
257.8 + *
257.9 + * This program is free software; you can redistribute it and/or
257.10 + * modify it under the terms of the GNU General Public License as
257.11 + * published by the Free Software Foundation; either version 2 of
257.12 + * the License, or (at your option) any later version.
257.13 + *
257.14 + * This program is distributed in the hope that it will be useful,
257.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
257.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
257.17 + * GNU General Public License for more details.
257.18 + *
257.19 + * You should have received a copy of the GNU General Public License
257.20 + * along with this program; if not, write to the Free Software
257.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
257.22 + * Boston, MA 02110-1301, USA
257.23 + */
257.24 +
257.25 +#include <l4/re/c/mem_alloc.h>
257.26 +#include <l4/re/c/rm.h>
257.27 +#include <l4/sys/err.h>
257.28 +#include <l4/sys/types.h>
257.29 +
257.30 +#include "cap_alloc.h"
257.31 +#include "mem_ipc.h"
257.32 +#include "semaphore.h"
257.33 +
257.34 +
257.35 +
257.36 +/* Semaphore used if threading has been initialised by ipc_mem_init. */
257.37 +
257.38 +l4_cap_idx_t ipc_mem_semaphore = L4_INVALID_CAP;
257.39 +
257.40 +
257.41 +
257.42 +/* Generic memory allocation. */
257.43 +
257.44 +long ipc_allocate(unsigned long size, void **addr, l4re_ds_t *ds)
257.45 +{
257.46 + /* Allocate a capability for the dataspace. */
257.47 +
257.48 + *ds = ipc_cap_alloc();
257.49 +
257.50 + if (l4_is_invalid_cap(*ds))
257.51 + return -L4_ENOENT;
257.52 +
257.53 + /* Allocate and attach the memory for the dataspace. */
257.54 +
257.55 + if (ipc_new_dataspace(*ds, size, 0, 0))
257.56 + {
257.57 + ipc_cap_free_um(*ds);
257.58 + return -L4_ENOMEM;
257.59 + }
257.60 +
257.61 + if (ipc_attach_dataspace(*ds, size, addr))
257.62 + {
257.63 + ipc_cap_free_um(*ds);
257.64 + return -L4_ENOMEM;
257.65 + }
257.66 +
257.67 + return L4_EOK;
257.68 +}
257.69 +
257.70 +/* Create a dataspace. Equivalent to l4re_ma_alloc_align. */
257.71 +
257.72 +long ipc_new_dataspace(l4_cap_idx_t cap, l4_mword_t size, l4_umword_t flags, l4_umword_t align)
257.73 +{
257.74 + return l4re_ma_alloc_align(size, cap, flags, align);
257.75 +}
257.76 +
257.77 +/* Attach a dataspace region. Similar to l4re_rm_attach. */
257.78 +
257.79 +long ipc_attach_dataspace(l4re_ds_t ds, unsigned long size, void **addr)
257.80 +{
257.81 + long err;
257.82 +
257.83 + err = ipc_semaphore_down(ipc_mem_semaphore);
257.84 + if (err)
257.85 + return err;
257.86 +
257.87 + err = l4re_rm_attach(addr, size, L4RE_RM_SEARCH_ADDR, ds, 0, L4_PAGESHIFT);
257.88 +
257.89 + ipc_semaphore_up(ipc_mem_semaphore);
257.90 +
257.91 + return err;
257.92 +}
257.93 +
257.94 +/* Detach a dataspace region. Equivalent to l4re_rm_detach_unmap. */
257.95 +
257.96 +long ipc_detach_dataspace(void *addr)
257.97 +{
257.98 + long err;
257.99 +
257.100 + err = ipc_semaphore_down(ipc_mem_semaphore);
257.101 + if (err)
257.102 + return err;
257.103 +
257.104 + err = l4re_rm_detach_unmap((l4_addr_t) addr, L4RE_THIS_TASK_CAP);
257.105 +
257.106 + ipc_semaphore_up(ipc_mem_semaphore);
257.107 +
257.108 + return err;
257.109 +}
257.110 +
257.111 +/* Obtain a dataspace size. Equivalent to l4re_ds_size. */
257.112 +
257.113 +long ipc_dataspace_size(l4_cap_idx_t cap, unsigned long *size)
257.114 +{
257.115 + *size = l4re_ds_size(cap);
257.116 + return L4_EOK;
257.117 +}
257.118 +
257.119 +// vim: tabstop=2 expandtab shiftwidth=2
258.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
258.2 +++ b/libipc/lib/src/message.c Wed Aug 25 01:28:08 2021 +0200
258.3 @@ -0,0 +1,485 @@
258.4 +/*
258.5 + * Interprocess communication message abstraction.
258.6 + *
258.7 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
258.8 + *
258.9 + * This program is free software; you can redistribute it and/or
258.10 + * modify it under the terms of the GNU General Public License as
258.11 + * published by the Free Software Foundation; either version 2 of
258.12 + * the License, or (at your option) any later version.
258.13 + *
258.14 + * This program is distributed in the hope that it will be useful,
258.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
258.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
258.17 + * GNU General Public License for more details.
258.18 + *
258.19 + * You should have received a copy of the GNU General Public License
258.20 + * along with this program; if not, write to the Free Software
258.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
258.22 + * Boston, MA 02110-1301, USA
258.23 + */
258.24 +
258.25 +#include <string.h>
258.26 +
258.27 +#include "cap_alloc.h"
258.28 +#include "message.h"
258.29 +#include "mem_ipc.h"
258.30 +#include "util_ipc.h"
258.31 +
258.32 +
258.33 +
258.34 +/* Calculate the given length rounded up to whole word increments. */
258.35 +
258.36 +static size_t get_size_in_words(size_t length)
258.37 +{
258.38 + size_t mask = sizeof(l4_umword_t) - 1;
258.39 + return (length + mask) & ~mask;
258.40 +}
258.41 +
258.42 +
258.43 +
258.44 +/* Message operations. */
258.45 +
258.46 +/* Discard capabilities for transfer to other tasks. */
258.47 +
258.48 +void ipc_message_discard(ipc_message_t *msg)
258.49 +{
258.50 + unsigned int i;
258.51 +
258.52 + for (i = 0; i < msg->discarded_items; i++)
258.53 + ipc_cap_free_um(msg->to_discard[i]);
258.54 +}
258.55 +
258.56 +/* Initialise a message structure with the given number of expected items. */
258.57 +
258.58 +long ipc_message_expect(ipc_message_t *msg, unsigned int expected_items)
258.59 +{
258.60 + long err = ipc_message_expect_capabilities(msg, expected_items);
258.61 +
258.62 + if (err)
258.63 + return err;
258.64 +
258.65 + /* Restore the buffer registers immediately. */
258.66 +
258.67 + ipc_message_restore_buffer_registers(msg);
258.68 +
258.69 + return L4_EOK;
258.70 +}
258.71 +
258.72 +/* Free capabilities expected in messages. */
258.73 +
258.74 +void ipc_message_free(ipc_message_t *msg)
258.75 +{
258.76 + _free_expected_capabilities(&msg->bregs, msg->expected_items);
258.77 +}
258.78 +
258.79 +/* Clear message attributes for sending and response handling. */
258.80 +
258.81 +void ipc_message_new(ipc_message_t *msg)
258.82 +{
258.83 + /* Set a default for expected items. */
258.84 +
258.85 + msg->expected_items = 0;
258.86 + ipc_message_reset(msg);
258.87 +}
258.88 +
258.89 +/* Open an incoming message by resetting sending state and preserving the
258.90 + message registers plus the buffer registers for the expected number of
258.91 + items. */
258.92 +
258.93 +void ipc_message_open(ipc_message_t *msg)
258.94 +{
258.95 + ipc_message_reset(msg);
258.96 + ipc_message_preserve_buffer_registers(msg);
258.97 + ipc_message_preserve_message_registers(msg);
258.98 +}
258.99 +
258.100 +/* Preserve the buffer registers. */
258.101 +
258.102 +void ipc_message_preserve_buffer_registers(ipc_message_t *msg)
258.103 +{
258.104 + unsigned int i;
258.105 +
258.106 + /* Reference the UTCB virtual registers. */
258.107 +
258.108 + l4_buf_regs_t *bregs = l4_utcb_br();
258.109 +
258.110 + msg->bregs.bdr = bregs->bdr;
258.111 +
258.112 + for (i = 0; i < msg->expected_items; i++)
258.113 + msg->bregs.br[i] = bregs->br[i];
258.114 +}
258.115 +
258.116 +/* Preserve the message registers. */
258.117 +
258.118 +void ipc_message_preserve_message_registers(ipc_message_t *msg)
258.119 +{
258.120 + /* Compute the number of message register words affected. */
258.121 +
258.122 + unsigned int i, affected_words = l4_msgtag_words(msg->tag) +
258.123 + 2 * l4_msgtag_items(msg->tag);
258.124 +
258.125 + /* Reference the UTCB virtual registers. */
258.126 +
258.127 + l4_msg_regs_t *mregs = l4_utcb_mr();
258.128 +
258.129 + /* Copy message register information. */
258.130 +
258.131 + for (i = 0; i < affected_words; i++)
258.132 + msg->mregs.mr[i] = mregs->mr[i];
258.133 +}
258.134 +
258.135 +/* Restore the message and buffer registers. */
258.136 +
258.137 +void ipc_message_prepare(ipc_message_t *msg)
258.138 +{
258.139 + ipc_message_restore_buffer_registers(msg);
258.140 + ipc_message_restore_message_registers(msg);
258.141 +}
258.142 +
258.143 +/* Restore buffer registers so that item expectations can be set. */
258.144 +
258.145 +void ipc_message_restore_buffer_registers(ipc_message_t *msg)
258.146 +{
258.147 + unsigned int i;
258.148 +
258.149 + /* Reference the UTCB virtual registers. */
258.150 +
258.151 + l4_buf_regs_t *bregs = l4_utcb_br();
258.152 +
258.153 + /* Restore buffer register information. */
258.154 +
258.155 + bregs->bdr = msg->bregs.bdr;
258.156 +
258.157 + for (i = 0; i < msg->expected_items; i++)
258.158 + bregs->br[i] = msg->bregs.br[i];
258.159 +}
258.160 +
258.161 +/* Restore message registers to communicate recorded data and items. */
258.162 +
258.163 +void ipc_message_restore_message_registers(ipc_message_t *msg)
258.164 +{
258.165 + /* Compute the number of message register words affected. */
258.166 +
258.167 + unsigned int i, affected_words = msg->words + 2 * msg->items;
258.168 +
258.169 + /* Reference the UTCB virtual registers. */
258.170 +
258.171 + l4_msg_regs_t *mregs = l4_utcb_mr();
258.172 +
258.173 + /* Restore message register information. */
258.174 +
258.175 + for (i = 0; i < affected_words; i++)
258.176 + mregs->mr[i] = msg->mregs.mr[i];
258.177 +}
258.178 +
258.179 +/* Prepare and send a reply using the message. */
258.180 +
258.181 +void ipc_message_reply(ipc_message_t *msg)
258.182 +{
258.183 + ipc_message_prepare(msg);
258.184 + msg->tag = util_ipc_reply(ipc_message_reply_tag(msg));
258.185 +}
258.186 +
258.187 +/* Prepare and send a request using the message, involving the given operation,
258.188 + directed at the indicated endpoint. Open a message for the reply. */
258.189 +
258.190 +void ipc_message_request(ipc_message_t *msg, int op, l4_cap_idx_t endpoint)
258.191 +{
258.192 + ipc_message_prepare(msg);
258.193 + msg->tag = util_ipc_request(ipc_message_request_tag(msg, op), endpoint);
258.194 + ipc_message_open(msg);
258.195 +}
258.196 +
258.197 +/* Prepare and send a message, involving the given operation, directed at the
258.198 + indicated endpoint. No reply is expected. */
258.199 +
258.200 +void ipc_message_send(ipc_message_t *msg, int op, l4_cap_idx_t endpoint)
258.201 +{
258.202 + ipc_message_prepare(msg);
258.203 + msg->tag = util_ipc_send(ipc_message_request_tag(msg, op), endpoint);
258.204 +}
258.205 +
258.206 +/* Reset the state of the message for sending purposes. */
258.207 +
258.208 +void ipc_message_reset(ipc_message_t *msg)
258.209 +{
258.210 + /* Initialise words and items for sending. */
258.211 +
258.212 + msg->discarded_items = 0;
258.213 + msg->words = 0;
258.214 + msg->items = 0;
258.215 +
258.216 + /* Message label overriding. */
258.217 +
258.218 + msg->new_label = 0;
258.219 +
258.220 + /* Server control. */
258.221 +
258.222 + msg->terminating = 0;
258.223 +}
258.224 +
258.225 +/* Wait for an incoming message. */
258.226 +
258.227 +void ipc_message_wait(ipc_message_t *msg, l4_umword_t *label)
258.228 +{
258.229 + msg->tag = l4_ipc_wait(l4_utcb(), label, L4_IPC_NEVER);
258.230 +}
258.231 +
258.232 +
258.233 +
258.234 +/* Add a capability to the message. */
258.235 +
258.236 +void ipc_message_add_capability(ipc_message_t *msg, l4_cap_idx_t cap)
258.237 +{
258.238 + ipc_message_export_capability(msg, msg->items++, cap);
258.239 + if (cap & IPC_DISCARD_CAP_FLAG)
258.240 + ipc_message_discard_capability(msg, cap & ~IPC_DISCARD_CAP_FLAG);
258.241 +}
258.242 +
258.243 +/* Add an item to the message. */
258.244 +
258.245 +void ipc_message_add_item(ipc_message_t *msg, l4_cap_idx_t cap)
258.246 +{
258.247 + ipc_message_export_capability(msg, msg->items++, cap);
258.248 + if (cap & IPC_DISCARD_CAP_FLAG)
258.249 + ipc_message_discard_capability(msg, cap & ~IPC_DISCARD_CAP_FLAG);
258.250 +}
258.251 +
258.252 +/* Add a flexpage to the message using a type to combine the "hot spot" and
258.253 + flexpage. */
258.254 +
258.255 +void ipc_message_add_fpage(ipc_message_t *msg, l4_snd_fpage_t fpage)
258.256 +{
258.257 + ipc_message_export_fpage(msg, msg->items++, fpage);
258.258 +}
258.259 +
258.260 +/* Add a flexpage to the message. */
258.261 +
258.262 +void ipc_message_add_page(ipc_message_t *msg, l4_umword_t hot_spot,
258.263 + l4_fpage_t fpage)
258.264 +{
258.265 + ipc_message_export_page(msg, msg->items++, hot_spot, fpage);
258.266 +}
258.267 +
258.268 +/* Add a word value to the message. */
258.269 +
258.270 +void ipc_message_add_word(ipc_message_t *msg, l4_umword_t value)
258.271 +{
258.272 + /* NOTE: Should raise an exception if there are items. */
258.273 +
258.274 + if (!msg->items)
258.275 + msg->mregs.mr[msg->words++] = value;
258.276 +}
258.277 +
258.278 +/* Add the given dimensioned data to the message. */
258.279 +
258.280 +void ipc_message_add_data(ipc_message_t *msg, const char *value, size_t length)
258.281 +{
258.282 + void *target = ipc_message_reserve_data(msg, length);
258.283 +
258.284 + memcpy(target, value, length);
258.285 +}
258.286 +
258.287 +/* Add the given null-terminated character string to the message. */
258.288 +
258.289 +void ipc_message_add_string(ipc_message_t *msg, const char *value)
258.290 +{
258.291 + ipc_message_add_data(msg, value, strlen(value) + 1);
258.292 +}
258.293 +
258.294 +/* Propagate the given item to the message. */
258.295 +
258.296 +void ipc_message_propagate_item(ipc_message_t *msg, l4_cap_idx_t cap)
258.297 +{
258.298 + ipc_message_propagate_capability(msg, msg->items++, cap);
258.299 +}
258.300 +
258.301 +/* Indicate an error condition in the message. */
258.302 +
258.303 +void ipc_message_send_error(ipc_message_t *msg, long error)
258.304 +{
258.305 + msg->new_label = error;
258.306 +}
258.307 +
258.308 +/* Return a word value from the message. */
258.309 +
258.310 +l4_umword_t ipc_message_get_word(ipc_message_t *msg, unsigned int word)
258.311 +{
258.312 + return msg->mregs.mr[word];
258.313 +}
258.314 +
258.315 +/* Return a pointer to a word in the message. */
258.316 +
258.317 +l4_umword_t *ipc_message_get_word_address(ipc_message_t *msg, unsigned int word)
258.318 +{
258.319 + return &msg->mregs.mr[word];
258.320 +}
258.321 +
258.322 +/* Return the number of received items. */
258.323 +
258.324 +unsigned int ipc_message_number_of_items(ipc_message_t *msg)
258.325 +{
258.326 + return l4_msgtag_items(msg->tag);
258.327 +}
258.328 +
258.329 +/* Return the number of received words. */
258.330 +
258.331 +unsigned int ipc_message_number_of_words(ipc_message_t *msg)
258.332 +{
258.333 + return l4_msgtag_words(msg->tag);
258.334 +}
258.335 +
258.336 +/* Message tag generation. */
258.337 +
258.338 +l4_msgtag_t ipc_message_reply_tag(ipc_message_t *msg)
258.339 +{
258.340 + return l4_msgtag(msg->new_label, msg->words, msg->items, 0);
258.341 +}
258.342 +
258.343 +l4_msgtag_t ipc_message_request_tag(ipc_message_t *msg, int op)
258.344 +{
258.345 + return l4_msgtag(op, msg->words, msg->items, 0);
258.346 +}
258.347 +
258.348 +/* Reserve space for dimensioned data, returning a pointer to use to add the
258.349 + data. The length of the data is incorporated into the message. */
258.350 +
258.351 +void *ipc_message_reserve_data(ipc_message_t *msg, size_t length)
258.352 +{
258.353 + /* Indicate the length of the data. */
258.354 +
258.355 + ipc_message_add_word(msg, length);
258.356 +
258.357 + /* Reserve the space. */
258.358 +
258.359 + return ipc_message_reserve_words(msg, length);
258.360 +}
258.361 +
258.362 +/* Reserve space for dimensioned data, returning a pointer to use to add the
258.363 + data. The length is not incorporated into the message. */
258.364 +
258.365 +void *ipc_message_reserve_words(ipc_message_t *msg, size_t length)
258.366 +{
258.367 + /* Calculate the rounded-up size of the data and the necessary padding. */
258.368 +
258.369 + size_t size = get_size_in_words(length);
258.370 + size_t padding = size - length;
258.371 + void *target;
258.372 +
258.373 + /* NOTE: Should test the length against the capacity of the message. */
258.374 +
258.375 + /* Obtain the location of the next word, where the data will be copied. */
258.376 +
258.377 + target = &msg->mregs.mr[msg->words];
258.378 +
258.379 + /* Pad the data and update the number of words. */
258.380 +
258.381 + memset(target + length, 0, padding);
258.382 + msg->words += size / sizeof(l4_umword_t);
258.383 +
258.384 + return target;
258.385 +}
258.386 +
258.387 +
258.388 +
258.389 +/* Discard a capability after replying. */
258.390 +
258.391 +void ipc_message_discard_capability(ipc_message_t *msg, l4_cap_idx_t cap)
258.392 +{
258.393 + msg->to_discard[msg->discarded_items++] = cap;
258.394 +}
258.395 +
258.396 +/* Discard a dataspace. */
258.397 +
258.398 +void ipc_message_discard_dataspace(ipc_message_t *msg, l4re_ds_t mem, l4_addr_t addr)
258.399 +{
258.400 + ipc_message_discard_capability(msg, mem);
258.401 + ipc_detach_dataspace((void *) addr);
258.402 +}
258.403 +
258.404 +/* Reserve the given number slots from zero for incoming capabilities. */
258.405 +
258.406 +long ipc_message_expect_capabilities(ipc_message_t *msg, int number)
258.407 +{
258.408 + msg->expected_items = number;
258.409 + return _expect_capabilities(&msg->bregs, number);
258.410 +}
258.411 +
258.412 +/* Reserve a slot for an incoming capability. */
258.413 +
258.414 +long ipc_message_expect_capability(ipc_message_t *msg, int item)
258.415 +{
258.416 + if (item >= (int) msg->expected_items)
258.417 + msg->expected_items = item + 1;
258.418 +
258.419 + return _expect_capability(&msg->bregs, item);
258.420 +}
258.421 +
258.422 +/* Export a capability at the given position in the message. */
258.423 +
258.424 +void ipc_message_export_capability(ipc_message_t *msg, int item, l4_cap_idx_t ref)
258.425 +{
258.426 + msg->mregs.mr[msg->words + item * 2] = 0 | L4_ITEM_MAP;
258.427 + msg->mregs.mr[msg->words + item * 2 + 1] = l4_obj_fpage(ref, 0, L4_FPAGE_RWX).raw;
258.428 +}
258.429 +
258.430 +/* Export a flexpage at the given position in the message. Here, the snd_base
258.431 + member of the flexpage structure is used to hold the "hot spot" value. */
258.432 +
258.433 +void ipc_message_export_fpage(ipc_message_t *msg, int item, l4_snd_fpage_t fpage)
258.434 +{
258.435 + msg->mregs.mr[msg->words + item * 2] = l4_map_control(fpage.snd_base, L4_FPAGE_CACHEABLE, 0);
258.436 + msg->mregs.mr[msg->words + item * 2 + 1] = fpage.fpage.raw;
258.437 +}
258.438 +
258.439 +/* Export a flexpage at the given position in the message. */
258.440 +
258.441 +void ipc_message_export_page(ipc_message_t *msg, int item, l4_umword_t hot_spot, l4_fpage_t fpage)
258.442 +{
258.443 + msg->mregs.mr[msg->words + item * 2] = l4_map_control(hot_spot, L4_FPAGE_CACHEABLE, 0);
258.444 + msg->mregs.mr[msg->words + item * 2 + 1] = fpage.raw;
258.445 +}
258.446 +
258.447 +/* Import from the message the capability at the given item position, updating
258.448 + the buffer registers for future capabilities. */
258.449 +
258.450 +long ipc_message_import_capability(ipc_message_t *msg, int item, l4_cap_idx_t *ref)
258.451 +{
258.452 + long err;
258.453 +
258.454 + err = _import_capability(msg->tag, &msg->bregs, &msg->mregs, item, ref);
258.455 + if (err)
258.456 + return err;
258.457 +
258.458 + return ipc_message_expect_capability(msg, item);
258.459 +}
258.460 +
258.461 +/* Import from the message a dataspace, mapping it to an address, updating the
258.462 + buffer registers for future capabilities. */
258.463 +
258.464 +long ipc_message_import_dataspace(ipc_message_t *msg, int item, l4re_ds_t *mem, l4_addr_t *addr)
258.465 +{
258.466 + long err;
258.467 +
258.468 + err = _import_dataspace(msg->tag, &msg->bregs, &msg->mregs, item, mem, addr);
258.469 + if (err)
258.470 + return err;
258.471 +
258.472 + return ipc_message_expect_capability(msg, item);
258.473 +}
258.474 +
258.475 +/* Import from the message the flexpage at the given item position. */
258.476 +
258.477 +long ipc_message_import_fpage(ipc_message_t *msg, int item, l4_snd_fpage_t *fpage)
258.478 +{
258.479 + return _import_fpage(msg->tag, &msg->bregs, &msg->mregs, item, fpage);
258.480 +}
258.481 +
258.482 +/* Export a capability, discarding it by propagating it to the recipient. */
258.483 +
258.484 +void ipc_message_propagate_capability(ipc_message_t *msg, int item, l4_cap_idx_t ref)
258.485 +{
258.486 + ipc_message_export_capability(msg, item, ref);
258.487 + ipc_message_discard_capability(msg, ref);
258.488 +}
259.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
259.2 +++ b/libipc/lib/src/semaphore.c Wed Aug 25 01:28:08 2021 +0200
259.3 @@ -0,0 +1,91 @@
259.4 +/*
259.5 + * Semaphore utilities.
259.6 + *
259.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk>
259.8 + *
259.9 + * This program is free software; you can redistribute it and/or
259.10 + * modify it under the terms of the GNU General Public License as
259.11 + * published by the Free Software Foundation; either version 2 of
259.12 + * the License, or (at your option) any later version.
259.13 + *
259.14 + * This program is distributed in the hope that it will be useful,
259.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
259.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
259.17 + * GNU General Public License for more details.
259.18 + *
259.19 + * You should have received a copy of the GNU General Public License
259.20 + * along with this program; if not, write to the Free Software
259.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
259.22 + * Boston, MA 02110-1301, USA
259.23 + */
259.24 +
259.25 +#include <l4/sys/err.h>
259.26 +#include <l4/sys/semaphore.h>
259.27 +
259.28 +#include "semaphore.h"
259.29 +
259.30 +
259.31 +
259.32 +/* Obtain control of a semaphore. */
259.33 +
259.34 +long ipc_semaphore_down(l4_cap_idx_t semaphore)
259.35 +{
259.36 + long err;
259.37 +
259.38 + if (l4_is_valid_cap(semaphore))
259.39 + {
259.40 + do
259.41 + {
259.42 + /* Since l4_irq_trigger is a "send-only" operation, l4_error is not
259.43 + appropriate. */
259.44 +
259.45 + err = l4_ipc_error(l4_semaphore_down(semaphore, L4_IPC_NEVER), l4_utcb());
259.46 +
259.47 + /* Handle EAGAIN ("Resource temporarily unavailable") by just retrying. */
259.48 +
259.49 + if (err)
259.50 + {
259.51 + if (err == -L4_EAGAIN)
259.52 + continue;
259.53 + else
259.54 + return err;
259.55 + }
259.56 + }
259.57 + while (0);
259.58 + }
259.59 +
259.60 + return L4_EOK;
259.61 +}
259.62 +
259.63 +/* Relinquish control of a semaphore. */
259.64 +
259.65 +long ipc_semaphore_up(l4_cap_idx_t semaphore)
259.66 +{
259.67 + long err;
259.68 +
259.69 + if (l4_is_valid_cap(semaphore))
259.70 + {
259.71 + do
259.72 + {
259.73 + /* Since l4_irq_trigger is a "send-only" operation, l4_error is not
259.74 + appropriate. */
259.75 +
259.76 + err = l4_ipc_error(l4_semaphore_up(semaphore), l4_utcb());
259.77 +
259.78 + /* Handle EAGAIN ("Resource temporarily unavailable") by just retrying. */
259.79 +
259.80 + if (err)
259.81 + {
259.82 + if (err == -L4_EAGAIN)
259.83 + continue;
259.84 + else
259.85 + return err;
259.86 + }
259.87 + }
259.88 + while (0);
259.89 + }
259.90 +
259.91 + return L4_EOK;
259.92 +}
259.93 +
259.94 +// vim: tabstop=2 expandtab shiftwidth=2
260.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
260.2 +++ b/libipc/lib/src/server.c Wed Aug 25 01:28:08 2021 +0200
260.3 @@ -0,0 +1,343 @@
260.4 +/*
260.5 + * Server binding/registration.
260.6 + *
260.7 + * Copyright (C) 2018, 2019, 2020, 2021 Paul Boddie <paul@boddie.org.uk>
260.8 + *
260.9 + * This program is free software; you can redistribute it and/or
260.10 + * modify it under the terms of the GNU General Public License as
260.11 + * published by the Free Software Foundation; either version 2 of
260.12 + * the License, or (at your option) any later version.
260.13 + *
260.14 + * This program is distributed in the hope that it will be useful,
260.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
260.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
260.17 + * GNU General Public License for more details.
260.18 + *
260.19 + * You should have received a copy of the GNU General Public License
260.20 + * along with this program; if not, write to the Free Software
260.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
260.22 + * Boston, MA 02110-1301, USA
260.23 + */
260.24 +
260.25 +#include <l4/re/env.h>
260.26 +#include <l4/sys/factory.h>
260.27 +#include <l4/sys/kernel_object.h>
260.28 +#include <l4/sys/rcv_endpoint.h>
260.29 +#include <l4/sys/thread.h>
260.30 +#include <l4/util/util.h>
260.31 +
260.32 +#include <stdlib.h>
260.33 +
260.34 +#include "cap_alloc.h"
260.35 +#include "irq.h"
260.36 +#include "server.h"
260.37 +
260.38 +
260.39 +
260.40 +/* Associate an IRQ with the IPC gate in the main thread to handle gate deletion
260.41 + notifications. */
260.42 +
260.43 +long ipc_server_apply_irq(l4_cap_idx_t cap, l4_cap_idx_t *irq)
260.44 +{
260.45 + return ipc_server_apply_irq_for_thread(cap, irq, l4re_env()->main_thread);
260.46 +}
260.47 +
260.48 +/* Associate an IRQ with the IPC gate in the given thread to handle gate deletion
260.49 + notifications. */
260.50 +
260.51 +long ipc_server_apply_irq_for_thread(l4_cap_idx_t cap, l4_cap_idx_t *irq, l4_cap_idx_t thread)
260.52 +{
260.53 + /* Create an IRQ for the gate. */
260.54 +
260.55 + long err = ipc_create_irq(irq);
260.56 +
260.57 + if (err)
260.58 + return err;
260.59 +
260.60 + /* Bind the IRQ to the thread, presenting the label if it provides the
260.61 + incoming message. */
260.62 +
260.63 + err = l4_error(l4_rcv_ep_bind_thread(*irq, thread, (l4_umword_t) *irq));
260.64 +
260.65 + if (err)
260.66 + {
260.67 + ipc_cap_free_um(*irq);
260.68 + return err;
260.69 + }
260.70 +
260.71 + /* Register for notifications. The thread associated with the gate seems to be
260.72 + needed. */
260.73 +
260.74 + err = l4_error(l4_thread_register_del_irq(thread, *irq));
260.75 +
260.76 + if (err)
260.77 + {
260.78 + ipc_cap_free_um(*irq);
260.79 + return err;
260.80 + }
260.81 +
260.82 + /* Decrease the reference count on the server capability (IPC gate). */
260.83 +
260.84 + return l4_error(l4_kobject_dec_refcnt(cap, 1));
260.85 +}
260.86 +
260.87 +
260.88 +
260.89 +/* Bind the main thread to the named capability, employing an identifier for
260.90 + the IPC gate and returning the capability index. */
260.91 +
260.92 +long ipc_server_bind(const char *name, l4_umword_t id, l4_cap_idx_t *server)
260.93 +{
260.94 + /* Obtain a reference to the device. */
260.95 +
260.96 + *server = l4re_env_get_cap(name);
260.97 +
260.98 + if (l4_is_invalid_cap(*server))
260.99 + return -L4_ENOENT;
260.100 +
260.101 + /* Bind to an IPC gate with the label identifying the server as message
260.102 + destination. */
260.103 +
260.104 + return l4_error(l4_rcv_ep_bind_thread(*server, l4re_env()->main_thread, id));
260.105 +}
260.106 +
260.107 +/* Initialise a new server capability, binding it to the main thread. */
260.108 +
260.109 +long ipc_server_new(l4_cap_idx_t *cap, void *obj)
260.110 +{
260.111 + return ipc_server_new_for_thread(cap, obj, l4re_env()->main_thread);
260.112 +}
260.113 +
260.114 +/* Initialise a new server capability, binding it to the given thread. */
260.115 +
260.116 +long ipc_server_new_for_thread(l4_cap_idx_t *cap, void *obj, l4_cap_idx_t thread)
260.117 +{
260.118 + l4_umword_t label = (l4_umword_t) obj;
260.119 +
260.120 + /* Create an IPC gate, presenting the resource's label if this gate provides
260.121 + the message. */
260.122 +
260.123 + return ipc_server_new_gate_for_thread(cap, thread, label);
260.124 +}
260.125 +
260.126 +/* Create an IPC gate, exporting via a new capability an object with the given
260.127 + identifier. */
260.128 +
260.129 +long ipc_server_new_gate(l4_cap_idx_t *ref, l4_umword_t id)
260.130 +{
260.131 + return ipc_server_new_gate_for_thread(ref, l4re_env()->main_thread, id);
260.132 +}
260.133 +
260.134 +/* Create an IPC gate associated with a specific thread. */
260.135 +
260.136 +long ipc_server_new_gate_for_thread(l4_cap_idx_t *ref, l4_cap_idx_t thread, l4_umword_t id)
260.137 +{
260.138 + long err;
260.139 +
260.140 + *ref = ipc_cap_alloc();
260.141 +
260.142 + if (l4_is_invalid_cap(*ref))
260.143 + return -L4_ENOENT;
260.144 +
260.145 + /* Associate the object with an IPC gate. */
260.146 +
260.147 + err = l4_error(l4_factory_create_gate(l4re_env()->factory, *ref, thread, id));
260.148 +
260.149 + if (err)
260.150 + ipc_cap_free_um(*ref);
260.151 +
260.152 + return err;
260.153 +}
260.154 +
260.155 +
260.156 +
260.157 +/* A server main loop with no endpoint deletion detection. */
260.158 +
260.159 +long ipc_server_loop(int expected_items, void *obj,
260.160 + ipc_server_handler_type handler)
260.161 +{
260.162 + return ipc_server_managed_loop(expected_items, obj, L4_INVALID_CAP, handler);
260.163 +}
260.164 +
260.165 +/* A server main loop handling endpoint deletion for an IPC gate dedicated to
260.166 + a particular object within its own thread. */
260.167 +
260.168 +long ipc_server_managed_loop(int expected_items, void *obj, l4_cap_idx_t irq,
260.169 + ipc_server_handler_type handler)
260.170 +{
260.171 + ipc_message_t msg;
260.172 + l4_umword_t label, irq_label = (l4_umword_t) irq;
260.173 +
260.174 + /* Declare the extent to which capabilities are expected in messages. */
260.175 +
260.176 + long err = ipc_message_expect(&msg, expected_items);
260.177 +
260.178 + if (err)
260.179 + return err;
260.180 +
260.181 + /* Unmask the interrupt. */
260.182 +
260.183 + if (l4_is_valid_cap(irq))
260.184 + ipc_init_irq(irq);
260.185 +
260.186 + /* Wait for an incoming message. */
260.187 +
260.188 + while (1)
260.189 + {
260.190 + ipc_message_wait(&msg, &label);
260.191 +
260.192 + /* Clear lower label bits. */
260.193 +
260.194 + label = label & ~3UL;
260.195 +
260.196 + /* Ignore erroneous messages. */
260.197 +
260.198 + if (l4_ipc_error(msg.tag, l4_utcb()))
260.199 + continue;
260.200 +
260.201 + /* Message involves the IPC gate itself. */
260.202 +
260.203 + if (label != irq_label)
260.204 + handler(&msg, obj);
260.205 +
260.206 + /* Message involves the IRQ or a termination condition occurred. */
260.207 +
260.208 + if ((label == irq_label) || msg.terminating)
260.209 + break;
260.210 + }
260.211 +
260.212 + /* Free expected capabilities. */
260.213 +
260.214 + ipc_message_free(&msg);
260.215 +
260.216 + return L4_EOK;
260.217 +}
260.218 +
260.219 +/* A pthread-compatible mainloop initiation function. */
260.220 +
260.221 +void *ipc_server_start_mainloop(void *data)
260.222 +{
260.223 + ipc_server_config_type *config = (ipc_server_config_type *) data;
260.224 +
260.225 + long err = ipc_server_managed_loop(config->expected_items, config->handler_obj,
260.226 + config->irq, config->handler);
260.227 +
260.228 + if (config->finaliser != NULL)
260.229 + config->finaliser(config);
260.230 +
260.231 + return (void *) err;
260.232 +}
260.233 +
260.234 +/* Wait for an incoming message via an IPC gate dedicated to a particular
260.235 + object within its own thread. */
260.236 +
260.237 +l4_msgtag_t ipc_server_wait(l4_umword_t id)
260.238 +{
260.239 + l4_umword_t label;
260.240 + l4_msgtag_t tag;
260.241 +
260.242 + /* Ignore errors and messages not intended for the identified gate. */
260.243 +
260.244 + do tag = l4_ipc_wait(l4_utcb(), &label, L4_IPC_NEVER);
260.245 + while (l4_ipc_error(tag, l4_utcb()) || (label & ~3UL) != id);
260.246 +
260.247 + return tag;
260.248 +}
260.249 +
260.250 +
260.251 +
260.252 +/* Finalise a server configuration. */
260.253 +
260.254 +void ipc_server_finalise_config(ipc_server_config_type *config)
260.255 +{
260.256 + if (l4_is_valid_cap(config->server))
260.257 + {
260.258 + ipc_cap_free_um(config->server);
260.259 + config->server = L4_INVALID_CAP;
260.260 + }
260.261 +
260.262 + if (l4_is_valid_cap(config->irq))
260.263 + {
260.264 + ipc_cap_free_um(config->irq);
260.265 + config->irq = L4_INVALID_CAP;
260.266 + }
260.267 +}
260.268 +
260.269 +/* Discard any thread created but not initiated. */
260.270 +
260.271 +void ipc_server_discard_thread(ipc_server_config_type *config)
260.272 +{
260.273 + if (config->new_thread && l4_is_valid_cap(config->thread))
260.274 + {
260.275 + ipc_cap_free_um(config->thread);
260.276 + config->thread = L4_INVALID_CAP;
260.277 + }
260.278 +}
260.279 +
260.280 +/* Initialise a server configuration. */
260.281 +
260.282 +void ipc_server_init_config(ipc_server_config_type *config)
260.283 +{
260.284 + /* No object references defined. */
260.285 +
260.286 + config->handler_obj = NULL;
260.287 + config->finaliser_obj = NULL;
260.288 +
260.289 + /* Expect no capability items by default. */
260.290 +
260.291 + config->expected_items = 0;
260.292 +
260.293 + /* No handler or finaliser defined. */
260.294 +
260.295 + config->handler = NULL;
260.296 + config->finaliser = NULL;
260.297 +
260.298 + /* No new thread for the mainloop. */
260.299 +
260.300 + config->new_thread = 0;
260.301 +
260.302 + /* Main thread by default with IPC gate to be allocated. */
260.303 +
260.304 + config->thread = l4re_env()->main_thread;
260.305 + config->server = L4_INVALID_CAP;
260.306 +
260.307 + /* No notifications and with IRQ to be potentially allocated. */
260.308 +
260.309 + config->notifications = 0;
260.310 + config->irq = L4_INVALID_CAP;
260.311 +}
260.312 +
260.313 +/* Initialise and start a server using the given configuration. */
260.314 +
260.315 +long ipc_server_start_config(ipc_server_config_type *config)
260.316 +{
260.317 + long err;
260.318 +
260.319 + /* Allocate a new IPC gate if one is not already defined. */
260.320 +
260.321 + if (l4_is_invalid_cap(config->server))
260.322 + {
260.323 + err = ipc_server_new_for_thread(&config->server, config->handler_obj, config->thread);
260.324 +
260.325 + if (err)
260.326 + return err;
260.327 + }
260.328 +
260.329 + /* Allocate an IRQ for notifications if requested. */
260.330 +
260.331 + if (config->notifications)
260.332 + {
260.333 + err = ipc_server_apply_irq_for_thread(config->server, &config->irq, config->thread);
260.334 +
260.335 + if (err)
260.336 + return err;
260.337 + }
260.338 +
260.339 + /* With a new thread, return the last status value. Otherwise, invoke the main
260.340 + loop. */
260.341 +
260.342 + if (config->new_thread)
260.343 + return L4_EOK;
260.344 + else
260.345 + return (long) ipc_server_start_mainloop(config);
260.346 +}
261.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
261.2 +++ b/libipc/lib/src/thread.c Wed Aug 25 01:28:08 2021 +0200
261.3 @@ -0,0 +1,87 @@
261.4 +/*
261.5 + * Thread-related initialisation activities.
261.6 + *
261.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk>
261.8 + *
261.9 + * This program is free software; you can redistribute it and/or
261.10 + * modify it under the terms of the GNU General Public License as
261.11 + * published by the Free Software Foundation; either version 2 of
261.12 + * the License, or (at your option) any later version.
261.13 + *
261.14 + * This program is distributed in the hope that it will be useful,
261.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
261.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
261.17 + * GNU General Public License for more details.
261.18 + *
261.19 + * You should have received a copy of the GNU General Public License
261.20 + * along with this program; if not, write to the Free Software
261.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
261.22 + * Boston, MA 02110-1301, USA
261.23 + */
261.24 +
261.25 +#include <l4/re/c/util/cap_alloc.h>
261.26 +#include <l4/re/env.h>
261.27 +#include <l4/sys/factory.h>
261.28 +#include <l4/sys/semaphore.h>
261.29 +
261.30 +#include "cap_alloc.h"
261.31 +#include "semaphore.h"
261.32 +#include "thread.h"
261.33 +
261.34 +
261.35 +
261.36 +/* Bootstrap the semaphore support needed by the allocation function. */
261.37 +
261.38 +static long ipc_semaphore_init(l4_cap_idx_t *semaphore)
261.39 +{
261.40 + if (l4_is_invalid_cap(*semaphore))
261.41 + {
261.42 + *semaphore = l4re_util_cap_alloc();
261.43 +
261.44 + if (l4_is_invalid_cap(*semaphore))
261.45 + return -L4_ENOENT;
261.46 +
261.47 + if (l4_error(l4_factory_create(l4re_env()->factory, L4_PROTO_SEMAPHORE, *semaphore)))
261.48 + {
261.49 + ipc_cap_free_um(*semaphore);
261.50 + return -L4_ENOENT;
261.51 + }
261.52 +
261.53 + return ipc_semaphore_up(*semaphore);
261.54 + }
261.55 + else
261.56 + return L4_EOK;
261.57 +}
261.58 +
261.59 +/* Bootstrap the semaphore support needed by the allocation functions. */
261.60 +
261.61 +extern l4_cap_idx_t ipc_cap_alloc_semaphore;
261.62 +
261.63 +long ipc_cap_alloc_init()
261.64 +{
261.65 + return ipc_semaphore_init(&ipc_cap_alloc_semaphore);
261.66 +}
261.67 +
261.68 +/* Bootstrap the semaphore support needed by the memory functions. */
261.69 +
261.70 +extern l4_cap_idx_t ipc_mem_semaphore;
261.71 +
261.72 +long ipc_mem_init()
261.73 +{
261.74 + return ipc_semaphore_init(&ipc_mem_semaphore);
261.75 +}
261.76 +
261.77 +/* General semaphore initialisation. */
261.78 +
261.79 +long ipc_thread_init()
261.80 +{
261.81 + long err;
261.82 +
261.83 + err = ipc_cap_alloc_init();
261.84 + if (err)
261.85 + return err;
261.86 +
261.87 + return ipc_mem_init();
261.88 +}
261.89 +
261.90 +// vim: tabstop=2 expandtab shiftwidth=2
262.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
262.2 +++ b/libipc/lib/src/util_ipc.c Wed Aug 25 01:28:08 2021 +0200
262.3 @@ -0,0 +1,224 @@
262.4 +/*
262.5 + * Interprocess communication abstractions.
262.6 + *
262.7 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
262.8 + *
262.9 + * This program is free software; you can redistribute it and/or
262.10 + * modify it under the terms of the GNU General Public License as
262.11 + * published by the Free Software Foundation; either version 2 of
262.12 + * the License, or (at your option) any later version.
262.13 + *
262.14 + * This program is distributed in the hope that it will be useful,
262.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
262.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
262.17 + * GNU General Public License for more details.
262.18 + *
262.19 + * You should have received a copy of the GNU General Public License
262.20 + * along with this program; if not, write to the Free Software
262.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
262.22 + * Boston, MA 02110-1301, USA
262.23 + */
262.24 +
262.25 +#include <l4/re/env.h>
262.26 +#include <l4/util/util.h>
262.27 +#include <l4/sys/factory.h>
262.28 +#include <l4/sys/irq.h>
262.29 +
262.30 +#include "cap_alloc.h"
262.31 +#include "mem_ipc.h"
262.32 +#include "util_ipc.h"
262.33 +
262.34 +
262.35 +
262.36 +/* Declare expected capabilities. */
262.37 +
262.38 +long _expect_capabilities(l4_buf_regs_t *bregs, int number)
262.39 +{
262.40 + int i;
262.41 + long err;
262.42 +
262.43 + for (i = 0; i < number; i++)
262.44 + {
262.45 + err = _expect_capability(bregs, i);
262.46 + if (err)
262.47 + return err;
262.48 + }
262.49 +
262.50 + return L4_EOK;
262.51 +}
262.52 +
262.53 +/* Indicate that a capability is expected at the given position. */
262.54 +
262.55 +long _expect_capability(l4_buf_regs_t *bregs, int item)
262.56 +{
262.57 + l4_cap_idx_t future = ipc_cap_alloc();
262.58 +
262.59 + if (l4_is_invalid_cap(future))
262.60 + return -L4_ENOENT;
262.61 +
262.62 + /* Indicate the expectation of a capability in return. */
262.63 +
262.64 + bregs->bdr = 0;
262.65 + bregs->br[item] = L4_RCV_ITEM_SINGLE_CAP | future;
262.66 +
262.67 + return L4_EOK;
262.68 +}
262.69 +
262.70 +/* Export in the message at the given position the given capability. */
262.71 +
262.72 +void _export_capability(l4_msgtag_t tag, l4_msg_regs_t *mregs, int item, l4_cap_idx_t ref)
262.73 +{
262.74 + int words = l4_msgtag_words(tag);
262.75 +
262.76 + mregs->mr[words + item * 2] = 0 | L4_ITEM_MAP;
262.77 + mregs->mr[words + item * 2 + 1] = l4_obj_fpage(ref, 0, L4_FPAGE_RWX).raw;
262.78 +}
262.79 +
262.80 +/* Export a flexpage at the given position in the message. Here, the snd_base
262.81 + member of the flexpage structure is used to hold the "hot spot" value. */
262.82 +
262.83 +void _export_fpage(l4_msgtag_t tag, l4_msg_regs_t *mregs, int item, l4_snd_fpage_t fpage)
262.84 +{
262.85 + int words = l4_msgtag_words(tag);
262.86 +
262.87 + mregs->mr[words + item * 2] = l4_map_control(fpage.snd_base, L4_FPAGE_CACHEABLE, 0);
262.88 + mregs->mr[words + item * 2 + 1] = fpage.fpage.raw;
262.89 +}
262.90 +
262.91 +/* Export a flexpage at the given position in the message. */
262.92 +
262.93 +void _export_page(l4_msgtag_t tag, l4_msg_regs_t *mregs, int item, l4_umword_t hot_spot, l4_fpage_t fpage)
262.94 +{
262.95 + int words = l4_msgtag_words(tag);
262.96 +
262.97 + mregs->mr[words + item * 2] = l4_map_control(hot_spot, L4_FPAGE_CACHEABLE, 0);
262.98 + mregs->mr[words + item * 2 + 1] = fpage.raw;
262.99 +}
262.100 +
262.101 +/* Free expected capabilities held by the buffer registers. */
262.102 +
262.103 +void _free_expected_capabilities(l4_buf_regs_t *bregs, int number)
262.104 +{
262.105 + int i;
262.106 + l4_cap_idx_t cap;
262.107 +
262.108 + for (i = 0; i < number; i++)
262.109 + {
262.110 + cap = bregs->br[i] & L4_CAP_MASK;
262.111 + if (l4_is_valid_cap(cap))
262.112 + ipc_cap_free_um(cap);
262.113 + }
262.114 +}
262.115 +
262.116 +/* Import from the message the capability at the given item position. */
262.117 +
262.118 +long _import_capability(l4_msgtag_t tag, l4_buf_regs_t *bregs,
262.119 + l4_msg_regs_t *mregs, int item, l4_cap_idx_t *ref)
262.120 +{
262.121 + l4_snd_fpage_t fpage;
262.122 + long err = _import_fpage(tag, bregs, mregs, item, &fpage);
262.123 +
262.124 + if (err)
262.125 + return err;
262.126 +
262.127 + /* Check for a received capability. */
262.128 +
262.129 + if ((fpage.snd_base & 0x3e) != 0x38)
262.130 + return -L4_EIO;
262.131 +
262.132 + /* Update the supplied capability index. */
262.133 +
262.134 + *ref = bregs->br[item] & L4_CAP_MASK;
262.135 +
262.136 + return L4_EOK;
262.137 +}
262.138 +
262.139 +/* Import from the message a dataspace, mapping it to an address. */
262.140 +
262.141 +long _import_dataspace(l4_msgtag_t tag, l4_buf_regs_t *bregs,
262.142 + l4_msg_regs_t *mregs, int item, l4re_ds_t *mem,
262.143 + l4_addr_t *addr)
262.144 +{
262.145 + long err;
262.146 + unsigned long size;
262.147 +
262.148 + *mem = ipc_cap_alloc();
262.149 +
262.150 + err = _import_capability(tag, bregs, mregs, item, mem);
262.151 +
262.152 + if (err)
262.153 + {
262.154 + ipc_cap_free_um(*mem);
262.155 + return err;
262.156 + }
262.157 +
262.158 + /* Attach the dataspace to a region. */
262.159 +
262.160 + err = ipc_dataspace_size(*mem, &size);
262.161 + if (err)
262.162 + {
262.163 + ipc_cap_free_um(*mem);
262.164 + return err;
262.165 + }
262.166 +
262.167 + err = ipc_attach_dataspace(*mem, size, (void **) addr);
262.168 + if (err)
262.169 + {
262.170 + ipc_cap_free_um(*mem);
262.171 + return err;
262.172 + }
262.173 +
262.174 + return L4_EOK;
262.175 +}
262.176 +
262.177 +/* Import from the message the flexpage at the given item position. */
262.178 +
262.179 +long _import_fpage(l4_msgtag_t tag, l4_buf_regs_t *bregs,
262.180 + l4_msg_regs_t *mregs, int item, l4_snd_fpage_t *fpage)
262.181 +{
262.182 + int words = l4_msgtag_words(tag);
262.183 +
262.184 + /* NOTE: Currently, this function does not interact with the received items,
262.185 + but instead just returns the flexpage details from the message
262.186 + words. */
262.187 +
262.188 + (void) bregs;
262.189 +
262.190 + /* Obtain the item details for the capability. */
262.191 +
262.192 + if (item >= (int) l4_msgtag_items(tag))
262.193 + return -L4_EIO;
262.194 +
262.195 + /* Received items should start at zero. */
262.196 +
262.197 + fpage->snd_base = mregs->mr[words + item * 2];
262.198 + fpage->fpage.raw = mregs->mr[words + item * 2 + 1];
262.199 +
262.200 + return L4_EOK;
262.201 +}
262.202 +
262.203 +
262.204 +
262.205 +/* Convenience operations. */
262.206 +
262.207 +/* Send a reply to a call using the given message tag. */
262.208 +
262.209 +l4_msgtag_t util_ipc_reply(l4_msgtag_t tag)
262.210 +{
262.211 + return l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, l4_utcb(), tag, L4_IPC_NEVER);
262.212 +}
262.213 +
262.214 +/* Send a request using a call with the given message tag to the indicated
262.215 + endpoint. */
262.216 +
262.217 +l4_msgtag_t util_ipc_request(l4_msgtag_t tag, l4_cap_idx_t endpoint)
262.218 +{
262.219 + return l4_ipc_call(endpoint, l4_utcb(), tag, L4_IPC_NEVER);
262.220 +}
262.221 +
262.222 +/* Send data with the given message tag to the indicated endpoint. */
262.223 +
262.224 +l4_msgtag_t util_ipc_send(l4_msgtag_t tag, l4_cap_idx_t endpoint)
262.225 +{
262.226 + return l4_ipc_send(endpoint, l4_utcb(), tag, L4_IPC_NEVER);
262.227 +}
263.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
263.2 +++ b/libsystypes/Control Wed Aug 25 01:28:08 2021 +0200
263.3 @@ -0,0 +1,2 @@
263.4 +provides: libsystypes
263.5 +maintainer: paul@boddie.org.uk
264.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
264.2 +++ b/libsystypes/Makefile Wed Aug 25 01:28:08 2021 +0200
264.3 @@ -0,0 +1,4 @@
264.4 +PKGDIR ?= .
264.5 +L4DIR ?= $(PKGDIR)/../../..
264.6 +
264.7 +include $(L4DIR)/mk/subdir.mk
265.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
265.2 +++ b/libsystypes/docs/COPYING-GPL-2 Wed Aug 25 01:28:08 2021 +0200
265.3 @@ -0,0 +1,1 @@
265.4 +LICENCE.txt
265.5 \ No newline at end of file
266.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
266.2 +++ b/libsystypes/docs/COPYING.txt Wed Aug 25 01:28:08 2021 +0200
266.3 @@ -0,0 +1,22 @@
266.4 +Licence Agreement
266.5 +-----------------
266.6 +
266.7 +All original work in this distribution is covered by the following copyright
266.8 +and licensing information:
266.9 +
266.10 +Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
266.11 +
266.12 +This software is free software; you can redistribute it and/or
266.13 +modify it under the terms of the GNU General Public License as
266.14 +published by the Free Software Foundation; either version 2 of
266.15 +the License, or (at your option) any later version.
266.16 +
266.17 +This software is distributed in the hope that it will be useful,
266.18 +but WITHOUT ANY WARRANTY; without even the implied warranty of
266.19 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
266.20 +GNU General Public License for more details.
266.21 +
266.22 +You should have received a copy of the GNU General Public
266.23 +License along with this library; see the file LICENCE.txt
266.24 +If not, write to the Free Software Foundation, Inc.,
266.25 +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
267.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
267.2 +++ b/libsystypes/docs/LICENCE.txt Wed Aug 25 01:28:08 2021 +0200
267.3 @@ -0,0 +1,339 @@
267.4 + GNU GENERAL PUBLIC LICENSE
267.5 + Version 2, June 1991
267.6 +
267.7 + Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
267.8 + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
267.9 + Everyone is permitted to copy and distribute verbatim copies
267.10 + of this license document, but changing it is not allowed.
267.11 +
267.12 + Preamble
267.13 +
267.14 + The licenses for most software are designed to take away your
267.15 +freedom to share and change it. By contrast, the GNU General Public
267.16 +License is intended to guarantee your freedom to share and change free
267.17 +software--to make sure the software is free for all its users. This
267.18 +General Public License applies to most of the Free Software
267.19 +Foundation's software and to any other program whose authors commit to
267.20 +using it. (Some other Free Software Foundation software is covered by
267.21 +the GNU Lesser General Public License instead.) You can apply it to
267.22 +your programs, too.
267.23 +
267.24 + When we speak of free software, we are referring to freedom, not
267.25 +price. Our General Public Licenses are designed to make sure that you
267.26 +have the freedom to distribute copies of free software (and charge for
267.27 +this service if you wish), that you receive source code or can get it
267.28 +if you want it, that you can change the software or use pieces of it
267.29 +in new free programs; and that you know you can do these things.
267.30 +
267.31 + To protect your rights, we need to make restrictions that forbid
267.32 +anyone to deny you these rights or to ask you to surrender the rights.
267.33 +These restrictions translate to certain responsibilities for you if you
267.34 +distribute copies of the software, or if you modify it.
267.35 +
267.36 + For example, if you distribute copies of such a program, whether
267.37 +gratis or for a fee, you must give the recipients all the rights that
267.38 +you have. You must make sure that they, too, receive or can get the
267.39 +source code. And you must show them these terms so they know their
267.40 +rights.
267.41 +
267.42 + We protect your rights with two steps: (1) copyright the software, and
267.43 +(2) offer you this license which gives you legal permission to copy,
267.44 +distribute and/or modify the software.
267.45 +
267.46 + Also, for each author's protection and ours, we want to make certain
267.47 +that everyone understands that there is no warranty for this free
267.48 +software. If the software is modified by someone else and passed on, we
267.49 +want its recipients to know that what they have is not the original, so
267.50 +that any problems introduced by others will not reflect on the original
267.51 +authors' reputations.
267.52 +
267.53 + Finally, any free program is threatened constantly by software
267.54 +patents. We wish to avoid the danger that redistributors of a free
267.55 +program will individually obtain patent licenses, in effect making the
267.56 +program proprietary. To prevent this, we have made it clear that any
267.57 +patent must be licensed for everyone's free use or not licensed at all.
267.58 +
267.59 + The precise terms and conditions for copying, distribution and
267.60 +modification follow.
267.61 +
267.62 + GNU GENERAL PUBLIC LICENSE
267.63 + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
267.64 +
267.65 + 0. This License applies to any program or other work which contains
267.66 +a notice placed by the copyright holder saying it may be distributed
267.67 +under the terms of this General Public License. The "Program", below,
267.68 +refers to any such program or work, and a "work based on the Program"
267.69 +means either the Program or any derivative work under copyright law:
267.70 +that is to say, a work containing the Program or a portion of it,
267.71 +either verbatim or with modifications and/or translated into another
267.72 +language. (Hereinafter, translation is included without limitation in
267.73 +the term "modification".) Each licensee is addressed as "you".
267.74 +
267.75 +Activities other than copying, distribution and modification are not
267.76 +covered by this License; they are outside its scope. The act of
267.77 +running the Program is not restricted, and the output from the Program
267.78 +is covered only if its contents constitute a work based on the
267.79 +Program (independent of having been made by running the Program).
267.80 +Whether that is true depends on what the Program does.
267.81 +
267.82 + 1. You may copy and distribute verbatim copies of the Program's
267.83 +source code as you receive it, in any medium, provided that you
267.84 +conspicuously and appropriately publish on each copy an appropriate
267.85 +copyright notice and disclaimer of warranty; keep intact all the
267.86 +notices that refer to this License and to the absence of any warranty;
267.87 +and give any other recipients of the Program a copy of this License
267.88 +along with the Program.
267.89 +
267.90 +You may charge a fee for the physical act of transferring a copy, and
267.91 +you may at your option offer warranty protection in exchange for a fee.
267.92 +
267.93 + 2. You may modify your copy or copies of the Program or any portion
267.94 +of it, thus forming a work based on the Program, and copy and
267.95 +distribute such modifications or work under the terms of Section 1
267.96 +above, provided that you also meet all of these conditions:
267.97 +
267.98 + a) You must cause the modified files to carry prominent notices
267.99 + stating that you changed the files and the date of any change.
267.100 +
267.101 + b) You must cause any work that you distribute or publish, that in
267.102 + whole or in part contains or is derived from the Program or any
267.103 + part thereof, to be licensed as a whole at no charge to all third
267.104 + parties under the terms of this License.
267.105 +
267.106 + c) If the modified program normally reads commands interactively
267.107 + when run, you must cause it, when started running for such
267.108 + interactive use in the most ordinary way, to print or display an
267.109 + announcement including an appropriate copyright notice and a
267.110 + notice that there is no warranty (or else, saying that you provide
267.111 + a warranty) and that users may redistribute the program under
267.112 + these conditions, and telling the user how to view a copy of this
267.113 + License. (Exception: if the Program itself is interactive but
267.114 + does not normally print such an announcement, your work based on
267.115 + the Program is not required to print an announcement.)
267.116 +
267.117 +These requirements apply to the modified work as a whole. If
267.118 +identifiable sections of that work are not derived from the Program,
267.119 +and can be reasonably considered independent and separate works in
267.120 +themselves, then this License, and its terms, do not apply to those
267.121 +sections when you distribute them as separate works. But when you
267.122 +distribute the same sections as part of a whole which is a work based
267.123 +on the Program, the distribution of the whole must be on the terms of
267.124 +this License, whose permissions for other licensees extend to the
267.125 +entire whole, and thus to each and every part regardless of who wrote it.
267.126 +
267.127 +Thus, it is not the intent of this section to claim rights or contest
267.128 +your rights to work written entirely by you; rather, the intent is to
267.129 +exercise the right to control the distribution of derivative or
267.130 +collective works based on the Program.
267.131 +
267.132 +In addition, mere aggregation of another work not based on the Program
267.133 +with the Program (or with a work based on the Program) on a volume of
267.134 +a storage or distribution medium does not bring the other work under
267.135 +the scope of this License.
267.136 +
267.137 + 3. You may copy and distribute the Program (or a work based on it,
267.138 +under Section 2) in object code or executable form under the terms of
267.139 +Sections 1 and 2 above provided that you also do one of the following:
267.140 +
267.141 + a) Accompany it with the complete corresponding machine-readable
267.142 + source code, which must be distributed under the terms of Sections
267.143 + 1 and 2 above on a medium customarily used for software interchange; or,
267.144 +
267.145 + b) Accompany it with a written offer, valid for at least three
267.146 + years, to give any third party, for a charge no more than your
267.147 + cost of physically performing source distribution, a complete
267.148 + machine-readable copy of the corresponding source code, to be
267.149 + distributed under the terms of Sections 1 and 2 above on a medium
267.150 + customarily used for software interchange; or,
267.151 +
267.152 + c) Accompany it with the information you received as to the offer
267.153 + to distribute corresponding source code. (This alternative is
267.154 + allowed only for noncommercial distribution and only if you
267.155 + received the program in object code or executable form with such
267.156 + an offer, in accord with Subsection b above.)
267.157 +
267.158 +The source code for a work means the preferred form of the work for
267.159 +making modifications to it. For an executable work, complete source
267.160 +code means all the source code for all modules it contains, plus any
267.161 +associated interface definition files, plus the scripts used to
267.162 +control compilation and installation of the executable. However, as a
267.163 +special exception, the source code distributed need not include
267.164 +anything that is normally distributed (in either source or binary
267.165 +form) with the major components (compiler, kernel, and so on) of the
267.166 +operating system on which the executable runs, unless that component
267.167 +itself accompanies the executable.
267.168 +
267.169 +If distribution of executable or object code is made by offering
267.170 +access to copy from a designated place, then offering equivalent
267.171 +access to copy the source code from the same place counts as
267.172 +distribution of the source code, even though third parties are not
267.173 +compelled to copy the source along with the object code.
267.174 +
267.175 + 4. You may not copy, modify, sublicense, or distribute the Program
267.176 +except as expressly provided under this License. Any attempt
267.177 +otherwise to copy, modify, sublicense or distribute the Program is
267.178 +void, and will automatically terminate your rights under this License.
267.179 +However, parties who have received copies, or rights, from you under
267.180 +this License will not have their licenses terminated so long as such
267.181 +parties remain in full compliance.
267.182 +
267.183 + 5. You are not required to accept this License, since you have not
267.184 +signed it. However, nothing else grants you permission to modify or
267.185 +distribute the Program or its derivative works. These actions are
267.186 +prohibited by law if you do not accept this License. Therefore, by
267.187 +modifying or distributing the Program (or any work based on the
267.188 +Program), you indicate your acceptance of this License to do so, and
267.189 +all its terms and conditions for copying, distributing or modifying
267.190 +the Program or works based on it.
267.191 +
267.192 + 6. Each time you redistribute the Program (or any work based on the
267.193 +Program), the recipient automatically receives a license from the
267.194 +original licensor to copy, distribute or modify the Program subject to
267.195 +these terms and conditions. You may not impose any further
267.196 +restrictions on the recipients' exercise of the rights granted herein.
267.197 +You are not responsible for enforcing compliance by third parties to
267.198 +this License.
267.199 +
267.200 + 7. If, as a consequence of a court judgment or allegation of patent
267.201 +infringement or for any other reason (not limited to patent issues),
267.202 +conditions are imposed on you (whether by court order, agreement or
267.203 +otherwise) that contradict the conditions of this License, they do not
267.204 +excuse you from the conditions of this License. If you cannot
267.205 +distribute so as to satisfy simultaneously your obligations under this
267.206 +License and any other pertinent obligations, then as a consequence you
267.207 +may not distribute the Program at all. For example, if a patent
267.208 +license would not permit royalty-free redistribution of the Program by
267.209 +all those who receive copies directly or indirectly through you, then
267.210 +the only way you could satisfy both it and this License would be to
267.211 +refrain entirely from distribution of the Program.
267.212 +
267.213 +If any portion of this section is held invalid or unenforceable under
267.214 +any particular circumstance, the balance of the section is intended to
267.215 +apply and the section as a whole is intended to apply in other
267.216 +circumstances.
267.217 +
267.218 +It is not the purpose of this section to induce you to infringe any
267.219 +patents or other property right claims or to contest validity of any
267.220 +such claims; this section has the sole purpose of protecting the
267.221 +integrity of the free software distribution system, which is
267.222 +implemented by public license practices. Many people have made
267.223 +generous contributions to the wide range of software distributed
267.224 +through that system in reliance on consistent application of that
267.225 +system; it is up to the author/donor to decide if he or she is willing
267.226 +to distribute software through any other system and a licensee cannot
267.227 +impose that choice.
267.228 +
267.229 +This section is intended to make thoroughly clear what is believed to
267.230 +be a consequence of the rest of this License.
267.231 +
267.232 + 8. If the distribution and/or use of the Program is restricted in
267.233 +certain countries either by patents or by copyrighted interfaces, the
267.234 +original copyright holder who places the Program under this License
267.235 +may add an explicit geographical distribution limitation excluding
267.236 +those countries, so that distribution is permitted only in or among
267.237 +countries not thus excluded. In such case, this License incorporates
267.238 +the limitation as if written in the body of this License.
267.239 +
267.240 + 9. The Free Software Foundation may publish revised and/or new versions
267.241 +of the General Public License from time to time. Such new versions will
267.242 +be similar in spirit to the present version, but may differ in detail to
267.243 +address new problems or concerns.
267.244 +
267.245 +Each version is given a distinguishing version number. If the Program
267.246 +specifies a version number of this License which applies to it and "any
267.247 +later version", you have the option of following the terms and conditions
267.248 +either of that version or of any later version published by the Free
267.249 +Software Foundation. If the Program does not specify a version number of
267.250 +this License, you may choose any version ever published by the Free Software
267.251 +Foundation.
267.252 +
267.253 + 10. If you wish to incorporate parts of the Program into other free
267.254 +programs whose distribution conditions are different, write to the author
267.255 +to ask for permission. For software which is copyrighted by the Free
267.256 +Software Foundation, write to the Free Software Foundation; we sometimes
267.257 +make exceptions for this. Our decision will be guided by the two goals
267.258 +of preserving the free status of all derivatives of our free software and
267.259 +of promoting the sharing and reuse of software generally.
267.260 +
267.261 + NO WARRANTY
267.262 +
267.263 + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
267.264 +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
267.265 +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
267.266 +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
267.267 +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
267.268 +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
267.269 +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267.270 +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
267.271 +REPAIR OR CORRECTION.
267.272 +
267.273 + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
267.274 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
267.275 +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
267.276 +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
267.277 +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
267.278 +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
267.279 +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
267.280 +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
267.281 +POSSIBILITY OF SUCH DAMAGES.
267.282 +
267.283 + END OF TERMS AND CONDITIONS
267.284 +
267.285 + How to Apply These Terms to Your New Programs
267.286 +
267.287 + If you develop a new program, and you want it to be of the greatest
267.288 +possible use to the public, the best way to achieve this is to make it
267.289 +free software which everyone can redistribute and change under these terms.
267.290 +
267.291 + To do so, attach the following notices to the program. It is safest
267.292 +to attach them to the start of each source file to most effectively
267.293 +convey the exclusion of warranty; and each file should have at least
267.294 +the "copyright" line and a pointer to where the full notice is found.
267.295 +
267.296 + <one line to give the program's name and a brief idea of what it does.>
267.297 + Copyright (C) <year> <name of author>
267.298 +
267.299 + This program is free software; you can redistribute it and/or modify
267.300 + it under the terms of the GNU General Public License as published by
267.301 + the Free Software Foundation; either version 2 of the License, or
267.302 + (at your option) any later version.
267.303 +
267.304 + This program is distributed in the hope that it will be useful,
267.305 + but WITHOUT ANY WARRANTY; without even the implied warranty of
267.306 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
267.307 + GNU General Public License for more details.
267.308 +
267.309 + You should have received a copy of the GNU General Public License along
267.310 + with this program; if not, write to the Free Software Foundation, Inc.,
267.311 + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
267.312 +
267.313 +Also add information on how to contact you by electronic and paper mail.
267.314 +
267.315 +If the program is interactive, make it output a short notice like this
267.316 +when it starts in an interactive mode:
267.317 +
267.318 + Gnomovision version 69, Copyright (C) year name of author
267.319 + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
267.320 + This is free software, and you are welcome to redistribute it
267.321 + under certain conditions; type `show c' for details.
267.322 +
267.323 +The hypothetical commands `show w' and `show c' should show the appropriate
267.324 +parts of the General Public License. Of course, the commands you use may
267.325 +be called something other than `show w' and `show c'; they could even be
267.326 +mouse-clicks or menu items--whatever suits your program.
267.327 +
267.328 +You should also get your employer (if you work as a programmer) or your
267.329 +school, if any, to sign a "copyright disclaimer" for the program, if
267.330 +necessary. Here is a sample; alter the names:
267.331 +
267.332 + Yoyodyne, Inc., hereby disclaims all copyright interest in the program
267.333 + `Gnomovision' (which makes passes at compilers) written by James Hacker.
267.334 +
267.335 + <signature of Ty Coon>, 1 April 1989
267.336 + Ty Coon, President of Vice
267.337 +
267.338 +This General Public License does not permit incorporating your program into
267.339 +proprietary programs. If your program is a subroutine library, you may
267.340 +consider it more useful to permit linking proprietary applications with the
267.341 +library. If this is what you want to do, use the GNU Lesser General
267.342 +Public License instead of this License.
268.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
268.2 +++ b/libsystypes/idl/dataspace.idl Wed Aug 25 01:28:08 2021 +0200
268.3 @@ -0,0 +1,44 @@
268.4 +#include <l4/re/protocols.h> /* L4RE_PROTO_DATASPACE */
268.5 +#include <systypes/base.h> /* address_t, offset_t */
268.6 +
268.7 +/* A dataspace interface. */
268.8 +
268.9 +[protocol(L4RE_PROTO_DATASPACE)]
268.10 +interface Dataspace
268.11 +{
268.12 + /* Map memory within a dataspace. */
268.13 +
268.14 + [opcode(0)] void map(in offset_t offset, in address_t hot_spot,
268.15 + in map_flags_t flags, out fpage region);
268.16 +
268.17 + /* Clear a dataspace. */
268.18 +
268.19 + [opcode(1)] void clear(in address_t offset, in offset_t size);
268.20 +
268.21 + /* Obtain statistics about a dataspace. */
268.22 +
268.23 + [opcode(2)] void info(out offset_t size, out map_flags_t flags);
268.24 +
268.25 + /* Copy data between dataspaces. */
268.26 +
268.27 + [opcode(3)] void copy_in(in address_t dest_offset, in cap source,
268.28 + in address_t source_offset, in offset_t size);
268.29 +
268.30 + /* Deprecated: take a reference to a dataspace. */
268.31 +
268.32 + [opcode(4)] void take();
268.33 +
268.34 + /* Deprecated: release a reference to a dataspace. */
268.35 +
268.36 + [opcode(5)] void release();
268.37 +
268.38 + /* Obtain the physical address of the given offset in a dataspace, along with
268.39 + the largest physically contiguous region at or after the address in the
268.40 + dataspace. */
268.41 +
268.42 + [opcode(6)] void phys(in address_t offset, out address_t address, out l4_size_t size);
268.43 +
268.44 + /* Allocate at least the given size at the given address in a dataspace. */
268.45 +
268.46 + [opcode(7)] void allocate(in address_t offset, in l4_size_t size);
268.47 +};
269.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
269.2 +++ b/libsystypes/idl/dataspace_factory.idl Wed Aug 25 01:28:08 2021 +0200
269.3 @@ -0,0 +1,15 @@
269.4 +#include <ipc/factory.h>
269.5 +#include <l4/re/protocols.h> /* L4RE_PROTO_DATASPACE */
269.6 +
269.7 +/* Dataspace operations exposed via the factory interface. This appears to
269.8 + involve extra tag values which are incorporated into the provided values.*/
269.9 +
269.10 +[protocol(L4_PROTO_FACTORY)]
269.11 +interface DataspaceFactory
269.12 +{
269.13 + /* Create a new dataspace. */
269.14 +
269.15 + [opcode(L4RE_PROTO_DATASPACE)]
269.16 + void alloc(in ipc_varg_long_t size, in ipc_varg_unsigned_long_t flags,
269.17 + in ipc_varg_unsigned_long_t align, out cap ds);
269.18 +};
270.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
270.2 +++ b/libsystypes/idl/file.idl Wed Aug 25 01:28:08 2021 +0200
270.3 @@ -0,0 +1,15 @@
270.4 +#include <systypes/base.h> /* offset_t */
270.5 +
270.6 +/* An interface providing operations common to both unmapped and mapped files.
270.7 + Other interfaces are used to specialise different kinds of files. */
270.8 +
270.9 +interface File
270.10 +{
270.11 + /* Obtain a file metadata object. */
270.12 +
270.13 + [opcode(11)] void fstat(out offset_t size, out cap statcap);
270.14 +
270.15 + /* Resize the file. */
270.16 +
270.17 + [opcode(21)] void resize(inout offset_t size);
270.18 +};
271.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
271.2 +++ b/libsystypes/idl/filesystem.idl Wed Aug 25 01:28:08 2021 +0200
271.3 @@ -0,0 +1,10 @@
271.4 +#include <systypes/user.h> /* user_t */
271.5 +
271.6 +/* An interface providing filesystem operations. */
271.7 +
271.8 +interface Filesystem
271.9 +{
271.10 + /* Obtain filesystem access for the given user details. */
271.11 +
271.12 + [opcode(6)] void open_for_user(in user_t user, out cap opener);
271.13 +};
272.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
272.2 +++ b/libsystypes/idl/filesystem_factory.idl Wed Aug 25 01:28:08 2021 +0200
272.3 @@ -0,0 +1,15 @@
272.4 +#include <systypes/base.h> /* sys_uid_t, sys_gid_t, sys_mode_t */
272.5 +
272.6 +/* Filesystem operations exposed via the factory interface. This appears to
272.7 + involve extra tag values which are incorporated into the provided values. */
272.8 +
272.9 +[protocol(L4_PROTO_FACTORY)]
272.10 +interface FilesystemFactory
272.11 +{
272.12 + /* Obtain filesystem access for the given user details. */
272.13 +
272.14 + [opcode(6)] void open_for_user(in ipc_varg_sys_uid_t uid,
272.15 + in ipc_varg_sys_gid_t gid,
272.16 + in ipc_varg_sys_mode_t umask,
272.17 + out cap opener);
272.18 +};
273.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
273.2 +++ b/libsystypes/idl/flush.idl Wed Aug 25 01:28:08 2021 +0200
273.3 @@ -0,0 +1,10 @@
273.4 +#include <systypes/base.h> /* offset_t */
273.5 +
273.6 +/* An interface providing a flush operation for files and pipes. */
273.7 +
273.8 +interface Flush
273.9 +{
273.10 + /* Flush data and update the size, if appropriate. */
273.11 +
273.12 + [opcode(5)] void flush(in offset_t populated_size, out offset_t size);
273.13 +};
274.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
274.2 +++ b/libsystypes/idl/mapped_file.idl Wed Aug 25 01:28:08 2021 +0200
274.3 @@ -0,0 +1,13 @@
274.4 +#include <systypes/base.h> /* offset_t */
274.5 +
274.6 +/* An interface providing operations specific to mapped files. */
274.7 +
274.8 +interface MappedFile
274.9 +{
274.10 + /* Memory-map a file for the given file position and length, obtaining the
274.11 + limits of the mapped region and the size of the file. */
274.12 +
274.13 + [opcode(7)] void mmap(in offset_t position, in offset_t length,
274.14 + out offset_t start_pos, out offset_t end_pos,
274.15 + out offset_t size);
274.16 +};
275.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
275.2 +++ b/libsystypes/idl/notification.idl Wed Aug 25 01:28:08 2021 +0200
275.3 @@ -0,0 +1,12 @@
275.4 +#include <systypes/base.h> /* notify_flags_t */
275.5 +
275.6 +interface Notification
275.7 +{
275.8 + /* Subscribe to events. */
275.9 +
275.10 + [opcode(23)] void subscribe(in cap notifier, in notify_flags_t flags);
275.11 +
275.12 + /* Unsubscribe from events. */
275.13 +
275.14 + [opcode(24)] void unsubscribe(in cap notifier);
275.15 +};
276.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
276.2 +++ b/libsystypes/idl/notifier.idl Wed Aug 25 01:28:08 2021 +0200
276.3 @@ -0,0 +1,8 @@
276.4 +#include <systypes/base.h> /* notify_flags_t */
276.5 +
276.6 +interface Notifier
276.7 +{
276.8 + /* Send notification events. */
276.9 +
276.10 + [opcode(25)] void notify(in notify_flags_t flags);
276.11 +};
277.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
277.2 +++ b/libsystypes/idl/opener.idl Wed Aug 25 01:28:08 2021 +0200
277.3 @@ -0,0 +1,10 @@
277.4 +#include <sys/types.h> /* size_t */
277.5 +
277.6 +/* An interface providing a way of opening filesystem objects. */
277.7 +
277.8 +interface Opener
277.9 +{
277.10 + /* Obtain an opener context for subsequent open operations. */
277.11 +
277.12 + [opcode(13)] void context(out cap context);
277.13 +};
278.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
278.2 +++ b/libsystypes/idl/opener_context.idl Wed Aug 25 01:28:08 2021 +0200
278.3 @@ -0,0 +1,24 @@
278.4 +#include <systypes/base.h> /* flags_t, object_flags_t, offset_t */
278.5 +
278.6 +/* An interface providing a way of opening filesystem objects relying on a
278.7 + dataspace to transfer filesystem paths. */
278.8 +
278.9 +interface OpenerContext
278.10 +{
278.11 + /* Mount the filesystem reference given a mountpoint path written to the
278.12 + dataspace. */
278.13 +
278.14 + [opcode(0)] void mount(in cap fs);
278.15 +
278.16 + /* Obtain a filesystem reference. */
278.17 +
278.18 + [opcode(1)] void getfs(out cap fs);
278.19 +
278.20 + /* Obtain a file reference given a path written to the context's dataspace. */
278.21 +
278.22 + [opcode(12)] void open(in flags_t flags, out offset_t size, out cap file,
278.23 + out object_flags_t object_flags);
278.24 +};
278.25 +
278.26 +/* vim: tabstop=2 expandtab shiftwidth=2
278.27 +*/
279.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
279.2 +++ b/libsystypes/idl/pipe.idl Wed Aug 25 01:28:08 2021 +0200
279.3 @@ -0,0 +1,19 @@
279.4 +#include <systypes/base.h> /* offset_t */
279.5 +
279.6 +/* A pipe interface providing access to shared memory. */
279.7 +
279.8 +interface Pipe
279.9 +{
279.10 + /* Obtain details of the current region of shared memory. */
279.11 +
279.12 + [opcode(16)] void current_region(out offset_t populated_size, out offset_t size);
279.13 +
279.14 + /* Advance to the next region of shared memory, indicating and obtaining the
279.15 + populated limit of the region and obtaining the region size. */
279.16 +
279.17 + [opcode(17)] void next_region(inout offset_t populated_size, out offset_t size);
279.18 +
279.19 + /* Return whether the pipe is closed or partly closed. */
279.20 +
279.21 + [opcode(22)] void closed(out int closed);
279.22 +};
280.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
280.2 +++ b/libsystypes/idl/pipe_opener.idl Wed Aug 25 01:28:08 2021 +0200
280.3 @@ -0,0 +1,11 @@
280.4 +#include <systypes/base.h> /* offset_t */
280.5 +
280.6 +/* An interface providing pipe-opening support. */
280.7 +
280.8 +interface PipeOpener
280.9 +{
280.10 + /* Obtain a pipe for communication between two endpoints, indicating a region
280.11 + size for each section of a pipe. */
280.12 +
280.13 + [opcode(20)] void pipe(in offset_t size, out cap reader, out cap writer);
280.14 +};
281.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
281.2 +++ b/libsystypes/idl/region_mapper.idl Wed Aug 25 01:28:08 2021 +0200
281.3 @@ -0,0 +1,46 @@
281.4 +#include <l4/re/protocols.h> /* L4RE_PROTO_RM */
281.5 +#include <systypes/base.h> /* address_t, offset_t */
281.6 +
281.7 +/* A region mapper/manager interface. */
281.8 +
281.9 +[protocol(L4RE_PROTO_RM)]
281.10 +interface RegionMapper
281.11 +{
281.12 + /* Attach the memory associated with a dataspace, employing the given start
281.13 + address to search for a suitable address for the region. */
281.14 +
281.15 + [opcode(0)] void attach(inout address_t start, in offset_t size,
281.16 + in map_flags_t flags, in cap ds,
281.17 + in address_t offset, in unsigned char align);
281.18 +
281.19 + /* Detach memory from the task, searching from the given address for a region
281.20 + of the given size. Return the start address, region size and dataspace. */
281.21 +
281.22 + [opcode(1)] void detach(in address_t addr, in offset_t size,
281.23 + in map_flags_t flags, out address_t start,
281.24 + out offset_t rsize, out cap ds);
281.25 +
281.26 + /* Find a region starting from the given address and having the given size.
281.27 + Return the start address, region size and dataspace. */
281.28 +
281.29 + [opcode(2)] void find(inout address_t addr, inout offset_t size,
281.30 + out map_flags_t flags, out address_t offset,
281.31 + out cap ds);
281.32 +
281.33 + /* Reserve an area in the region map. */
281.34 +
281.35 + [opcode(3)] void reserve_area(inout address_t start, in offset_t size,
281.36 + in map_flags_t flags, in unsigned char align);
281.37 +
281.38 + /* Free (or unreserve) an area in the region map. */
281.39 +
281.40 + [opcode(4)] void free_area(in address_t addr);
281.41 +
281.42 + /* Currently not fully supported by the interface generator...
281.43 +
281.44 + [opcode(5)] void get_regions(in address_t start, out Region[] regions);
281.45 +
281.46 + [opcode(6)] void get_areas(in address_t start, out Area[] areas);
281.47 +
281.48 + See pkg/l4re-core/l4re/include/rm for the Region and Area structures. */
281.49 +};
282.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
282.2 +++ b/libsystypes/include/Makefile Wed Aug 25 01:28:08 2021 +0200
282.3 @@ -0,0 +1,10 @@
282.4 +PKGDIR ?= ..
282.5 +L4DIR ?= $(PKGDIR)/../../..
282.6 +
282.7 +PC_FILENAME = libsystypes
282.8 +CONTRIB_INCDIR = libsystypes
282.9 +
282.10 +PKGNAME = libsystypes
282.11 +CONTRIB_HEADERS = 1
282.12 +
282.13 +include $(L4DIR)/mk/include.mk
283.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
283.2 +++ b/libsystypes/include/systypes/base.h Wed Aug 25 01:28:08 2021 +0200
283.3 @@ -0,0 +1,96 @@
283.4 +/*
283.5 + * Base types used by various other types.
283.6 + *
283.7 + * Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk>
283.8 + *
283.9 + * This program is free software; you can redistribute it and/or
283.10 + * modify it under the terms of the GNU General Public License as
283.11 + * published by the Free Software Foundation; either version 2 of
283.12 + * the License, or (at your option) any later version.
283.13 + *
283.14 + * This program is distributed in the hope that it will be useful,
283.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
283.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
283.17 + * GNU General Public License for more details.
283.18 + *
283.19 + * You should have received a copy of the GNU General Public License
283.20 + * along with this program; if not, write to the Free Software
283.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
283.22 + * Boston, MA 02110-1301, USA
283.23 + */
283.24 +
283.25 +#pragma once
283.26 +
283.27 +#include <l4/sys/compiler.h>
283.28 +
283.29 +#include <systypes/factory.h>
283.30 +
283.31 +EXTERN_C_BEGIN
283.32 +
283.33 +/* unsigned long is a 64-bit type.
283.34 + See: pkg/l4re-core/l4sys/include/l4int.h */
283.35 +
283.36 +/* Types for file access (access flags, offsets) and IPC operations. */
283.37 +
283.38 +typedef unsigned long flags_t;
283.39 +typedef unsigned long offset_t;
283.40 +typedef l4_addr_t address_t; /* unsigned long */
283.41 +
283.42 +/* Dataspace mapping flags.
283.43 + See: pkg/l4re-core/l4re_c/include/dataspace.h */
283.44 +
283.45 +typedef unsigned long map_flags_t; /* 64-bit */
283.46 +
283.47 +/* Types and values for notification. */
283.48 +
283.49 +typedef unsigned long notify_flags_t;
283.50 +
283.51 +enum notify_flags
283.52 +{
283.53 + NOTIFY_CONTENT_AVAILABLE = 1,
283.54 + NOTIFY_SPACE_AVAILABLE = 2,
283.55 + NOTIFY_PEER_CLOSED = 4
283.56 +};
283.57 +
283.58 +/* Filesystem object properties. */
283.59 +
283.60 +typedef unsigned long object_flags_t;
283.61 +
283.62 +enum object_flags
283.63 +{
283.64 + OBJECT_SUPPORTS_MMAP = 1,
283.65 + OBJECT_HAS_SIZE = 2
283.66 +};
283.67 +
283.68 +/* Equivalent types are defined in sys/types.h typically. In newlib, they are
283.69 + defined in sys/_types.h if not defined elsewhere (such as in
283.70 + machine/_types.h). */
283.71 +
283.72 +typedef unsigned long long sys_dev_t; /* device number */
283.73 +typedef unsigned long sys_ino_t; /* inode number */
283.74 +typedef unsigned int sys_mode_t; /* file permissions */
283.75 +typedef unsigned int sys_nlink_t; /* link count */
283.76 +typedef unsigned int sys_uid_t; /* user identifier */
283.77 +typedef unsigned int sys_gid_t; /* group identifier */
283.78 +typedef long sys_off_t; /* file offset/position */
283.79 +typedef long sys_blksize_t; /* input/output block size */
283.80 +typedef long sys_blkcnt_t; /* number of 512-byte blocks */
283.81 +
283.82 +/* Factory types for L4 factory interface invocations. */
283.83 +
283.84 +ipc_varg_typedef(sys_mode_t, ipc_varg_sys_mode_t)
283.85 +ipc_varg_typedef(sys_uid_t, ipc_varg_sys_uid_t)
283.86 +ipc_varg_typedef(sys_gid_t, ipc_varg_sys_gid_t)
283.87 +
283.88 +#define ipc_varg_sys_mode(value) \
283.89 +ipc_varg_umword(ipc_varg_sys_mode_t, value)
283.90 +
283.91 +#define ipc_varg_sys_uid(value) \
283.92 +ipc_varg_umword(ipc_varg_sys_uid_t, value)
283.93 +
283.94 +#define ipc_varg_sys_gid(value) \
283.95 +ipc_varg_umword(ipc_varg_sys_gid_t, value)
283.96 +
283.97 +EXTERN_C_END
283.98 +
283.99 +// vim: tabstop=2 expandtab shiftwidth=2
284.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
284.2 +++ b/libsystypes/include/systypes/factory.h Wed Aug 25 01:28:08 2021 +0200
284.3 @@ -0,0 +1,56 @@
284.4 +/*
284.5 + * Factory-related data type macros.
284.6 + *
284.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
284.8 + *
284.9 + * This program is free software; you can redistribute it and/or
284.10 + * modify it under the terms of the GNU General Public License as
284.11 + * published by the Free Software Foundation; either version 2 of
284.12 + * the License, or (at your option) any later version.
284.13 + *
284.14 + * This program is distributed in the hope that it will be useful,
284.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
284.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
284.17 + * GNU General Public License for more details.
284.18 + *
284.19 + * You should have received a copy of the GNU General Public License
284.20 + * along with this program; if not, write to the Free Software
284.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
284.22 + * Boston, MA 02110-1301, USA
284.23 + */
284.24 +
284.25 +#pragma once
284.26 +
284.27 +#include <l4/sys/types.h>
284.28 +
284.29 +
284.30 +
284.31 +EXTERN_C_BEGIN
284.32 +
284.33 +/* Type and value constructor macros. */
284.34 +
284.35 +#define ipc_varg_typedef(value_type, type) \
284.36 +typedef struct { l4_umword_t tag; value_type value; } type;
284.37 +
284.38 +#define ipc_varg_mword(type, value) \
284.39 +((type) {L4_VARG_TYPE_MWORD | (sizeof(l4_mword_t) << 16), value})
284.40 +
284.41 +#define ipc_varg_umword(type, value) \
284.42 +((type) {L4_VARG_TYPE_UMWORD | (sizeof(l4_umword_t) << 16), value})
284.43 +
284.44 +/* Tag inspection macros. */
284.45 +
284.46 +#define ipc_varg_size(tag) (tag >> 16)
284.47 +
284.48 +#define ipc_varg_type(tag) (tag & 0xff)
284.49 +
284.50 +#define ipc_varg_word(tag) \
284.51 +((ipc_varg_type(tag) == L4_VARG_TYPE_MWORD) || \
284.52 + (ipc_varg_type(tag) == L4_VARG_TYPE_UMWORD))
284.53 +
284.54 +/* Convenience macro for creating a type name, not necessarily employed by all
284.55 + types. */
284.56 +
284.57 +#define ipc_varg(type) ipc_varg_##type##_t
284.58 +
284.59 +EXTERN_C_END
285.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
285.2 +++ b/libsystypes/include/systypes/fcntl.h Wed Aug 25 01:28:08 2021 +0200
285.3 @@ -0,0 +1,49 @@
285.4 +/*
285.5 + * File control definitions.
285.6 + *
285.7 + * Copyright (C) 2019, 2020 Paul Boddie <paul@boddie.org.uk>
285.8 + *
285.9 + * This program is free software; you can redistribute it and/or
285.10 + * modify it under the terms of the GNU General Public License as
285.11 + * published by the Free Software Foundation; either version 2 of
285.12 + * the License, or (at your option) any later version.
285.13 + *
285.14 + * This program is distributed in the hope that it will be useful,
285.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
285.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
285.17 + * GNU General Public License for more details.
285.18 + *
285.19 + * You should have received a copy of the GNU General Public License
285.20 + * along with this program; if not, write to the Free Software
285.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
285.22 + * Boston, MA 02110-1301, USA
285.23 + */
285.24 +
285.25 +#pragma once
285.26 +
285.27 +#include <l4/sys/compiler.h>
285.28 +
285.29 +EXTERN_C_BEGIN
285.30 +
285.31 +/* Employ definitions compatible with fcntl-linux.h which can be different from
285.32 + fcntl.h on MIPS and from Newlib. */
285.33 +
285.34 +#define O_RDONLY 0
285.35 +#define O_WRONLY 1
285.36 +#define O_RDWR 2
285.37 +#define O_APPEND 0x0008
285.38 +#define O_CREAT 0x0200
285.39 +#define O_TRUNC 0x0400
285.40 +#define O_EXCL 0x0800
285.41 +#define O_NBIO 0x1000
285.42 +#define O_SYNC 0x2000
285.43 +#define O_NONBLOCK 0x4000
285.44 +#define O_NDELAY O_NONBLOCK
285.45 +#define O_NOCTTY 0x8000
285.46 +#define O_DIRECTORY 0x200000
285.47 +
285.48 +/* System-level functions. */
285.49 +
285.50 +int open(const char *pathname, int flags, ... /* mode_t mode */);
285.51 +
285.52 +EXTERN_C_END
286.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
286.2 +++ b/libsystypes/include/systypes/stat.h Wed Aug 25 01:28:08 2021 +0200
286.3 @@ -0,0 +1,49 @@
286.4 +/*
286.5 + * File metadata abstractions.
286.6 + *
286.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
286.8 + *
286.9 + * This program is free software; you can redistribute it and/or
286.10 + * modify it under the terms of the GNU General Public License as
286.11 + * published by the Free Software Foundation; either version 2 of
286.12 + * the License, or (at your option) any later version.
286.13 + *
286.14 + * This program is distributed in the hope that it will be useful,
286.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
286.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
286.17 + * GNU General Public License for more details.
286.18 + *
286.19 + * You should have received a copy of the GNU General Public License
286.20 + * along with this program; if not, write to the Free Software
286.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
286.22 + * Boston, MA 02110-1301, USA
286.23 + */
286.24 +
286.25 +#pragma once
286.26 +
286.27 +#include <systypes/base.h>
286.28 +#include <systypes/timespec.h>
286.29 +
286.30 +EXTERN_C_BEGIN
286.31 +
286.32 +/* File metadata abstraction. */
286.33 +
286.34 +typedef struct
286.35 +{
286.36 + sys_dev_t st_dev;
286.37 + sys_ino_t st_ino;
286.38 + sys_mode_t st_mode;
286.39 + sys_nlink_t st_nlink;
286.40 + sys_uid_t st_uid;
286.41 + sys_gid_t st_gid;
286.42 + sys_dev_t st_rdev;
286.43 + sys_off_t st_size;
286.44 + struct sys_timespec st_atim;
286.45 + struct sys_timespec st_mtim;
286.46 + struct sys_timespec st_ctim;
286.47 + sys_blksize_t st_blksize;
286.48 + sys_blkcnt_t st_blocks;
286.49 +
286.50 +} sys_stat_t;
286.51 +
286.52 +EXTERN_C_END
287.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
287.2 +++ b/libsystypes/include/systypes/timespec.h Wed Aug 25 01:28:08 2021 +0200
287.3 @@ -0,0 +1,39 @@
287.4 +/*
287.5 + * Time-related types.
287.6 + *
287.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
287.8 + *
287.9 + * This program is free software; you can redistribute it and/or
287.10 + * modify it under the terms of the GNU General Public License as
287.11 + * published by the Free Software Foundation; either version 2 of
287.12 + * the License, or (at your option) any later version.
287.13 + *
287.14 + * This program is distributed in the hope that it will be useful,
287.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
287.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
287.17 + * GNU General Public License for more details.
287.18 + *
287.19 + * You should have received a copy of the GNU General Public License
287.20 + * along with this program; if not, write to the Free Software
287.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
287.22 + * Boston, MA 02110-1301, USA
287.23 + */
287.24 +
287.25 +#pragma once
287.26 +
287.27 +#include <l4/sys/compiler.h>
287.28 +
287.29 +EXTERN_C_BEGIN
287.30 +
287.31 +/* Equivalent types are defined in sys/timespec.h typically. In newlib, they are
287.32 + defined in sys/_timespec.h. */
287.33 +
287.34 +typedef __INT64_TYPE__ sys_time_t;
287.35 +
287.36 +struct sys_timespec
287.37 +{
287.38 + sys_time_t tv_sec; /* seconds */
287.39 + long tv_nsec; /* nanoseconds */
287.40 +};
287.41 +
287.42 +EXTERN_C_END
288.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
288.2 +++ b/libsystypes/include/systypes/user.h Wed Aug 25 01:28:08 2021 +0200
288.3 @@ -0,0 +1,39 @@
288.4 +/*
288.5 + * User abstractions.
288.6 + *
288.7 + * Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk>
288.8 + *
288.9 + * This program is free software; you can redistribute it and/or
288.10 + * modify it under the terms of the GNU General Public License as
288.11 + * published by the Free Software Foundation; either version 2 of
288.12 + * the License, or (at your option) any later version.
288.13 + *
288.14 + * This program is distributed in the hope that it will be useful,
288.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
288.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
288.17 + * GNU General Public License for more details.
288.18 + *
288.19 + * You should have received a copy of the GNU General Public License
288.20 + * along with this program; if not, write to the Free Software
288.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
288.22 + * Boston, MA 02110-1301, USA
288.23 + */
288.24 +
288.25 +#pragma once
288.26 +
288.27 +#include <l4/sys/compiler.h>
288.28 +#include <systypes/base.h>
288.29 +
288.30 +EXTERN_C_BEGIN
288.31 +
288.32 +/* User abstraction. */
288.33 +
288.34 +typedef struct
288.35 +{
288.36 + sys_uid_t uid;
288.37 + sys_gid_t gid;
288.38 + sys_mode_t umask;
288.39 +
288.40 +} user_t;
288.41 +
288.42 +EXTERN_C_END