Compare commits

...

17 Commits

Author SHA1 Message Date
Cyan 910f6f5f22 Update libfat to 1.1.1 + Ustealth support (Greywolf, Cyan) 2017-12-14 15:19:34 +01:00
Cyan 1fed6e83f2 branches: Updating LibFAT to 1.0.13 2015-03-08 16:40:59 +00:00
Cyan 0cd2573062 Push r1235 in internal update menu and window's installer.
Added used libraries to /branches/libs/
You need to "make" and "make install" both libsicksaxis and libupc to compile USBLoaderGX r1235+
2015-01-04 21:00:24 +00:00
Cyan da71bf99dc Reverted more MEM2 Allocation to prevent black screen when launching a game. (Thanks Dimok) 2013-04-13 14:53:23 +00:00
Cyan f145fb1e91 Updated LibNTFS to 2013-01-13 version
https://code.google.com/p/libntfs-wii/

Added MEM2_alloc for Wii.
2013-03-17 12:52:40 +00:00
strtoul d90a6f0429 branches:
*updated libntfs-wii to version 2012.1.15
*updated libext2fs to e2fsprogs 1.42
*updated libfat to R4883
2012-02-13 20:26:22 +00:00
strtoul afb3b68349 *Update and fixed a few thins in libext2fs-wii. For changelog see http://code.google.com/p/libext2fs-wii/source/list 2011-11-05 18:50:49 +00:00
dimok321 3994181361 *fix for loading games of NTFS partitions with sector size > 512 (thx oggzee for pointing it out) 2011-06-24 19:37:01 +00:00
dimok321 f6c9003574 *Added support for starting .wbfs game files from fat32/ntfs partitions on a sector size > 512 (tested with 4096)
*modified libcustomfat and ntfs fragment fetch function to support >512 bytes per sector
*Added new ehcmodule (thanks rodries)
*Added real support of using both ports simultaniously without shutting down the other (thanks rodries for the ehcmodule works on this). There is no longer the limitation that the settings have to be on SD card for this. (ONLY HERMES CIOS)
*Moved a few settings to Feature Settings and added a new Hard Drive Settings
*Changed Wiinnertag path to only point to the path and not to the file. You must correct the path manually in custom path settings or reset you configs for this change or Winnertag won't work!!
*Removed a few compile warnings for devkitPPC R23
2011-06-22 17:57:37 +00:00
dimok321 d657e03e5f *Added a global block IOS reload option which is set default to "Auto" (Auto = on d2x cIOS >= V6 enabled, every other cIOS disabled)
*Fix for some IOS Reload games
*Updated libext2fs
*Updated libntfs
*Updated language files
2011-06-10 12:22:19 +00:00
dimok321 718245adcd *Updated libntfs to version 2011.1.15:
http://code.google.com/p/libntfs-wii/
*Deleted wiki pages because they are really outdated
*Updated some language files
2011-01-26 18:53:27 +00:00
dimok321 9d46977121 *Fixed display of partition size on WBFS partitions with a different wbfs sector size than 512bytes.
*Made the ProgressWindow for game installation more accurate
*Added displaying newly installed games (marked as new) on favorite list, so you don't have to change to full list when installing new games. (Thanks Cyan for the patch)
*Lot's a small fixes
*Added WDM Menu on game start. You can set it in the alternative DOL option (one new option there). The menu lists all DOLs on the disc and if a wdm file is provided in the WDM path (configurable in the settings) than the dol parameter and dol replacement name will be taken from the wdm. The DOLs that are not listed in the WDM but exist on the DISC will be listed at the end of the list.
*Added avoid of multiple app cleanup when game fails to boot

*Changed libfat to use FS info sector on FAT32 partitions. This speeds up the free space information getting to instant. For that the FS info sector has to have correct values. The values of all partitions where homebrews were writing to are currently incorrect because the official libfat does not support FS info sector (i submited a patch) (Windows does write it correct though). That is why there needs to be a synchronization of the FS info sector for partitions used with homebrews. For this purpose a new setting was added in the Loader Settings. You can synchronize all your FAT32 partitions on the USB with it once and you are done (if you don't write to that partition with current homebrews). After that you can enable free space display and it will be instant like on WBFS/NTFS/EXT partitions.
2011-01-16 13:12:07 +00:00
dimok321 85eb0a7ed2 *Moved every allocation of libntfs now to MEM2 (in mem1 it gets overwritten and so the games didn't work in last rev)
Forwarder change:
*Ignore MBR partition type and read partition type from boot record sector
(Channel will follow later)
2011-01-08 14:26:13 +00:00
dimok321 9bcb476262 *fixed settings paths creation bug
*fixed crash when installing on ntfs
*fixed a few bugs with language setting for games
2010-12-29 10:22:11 +00:00
dimok321 89fc757642 *Fixed no cover image loading for themes
*Fixed Font loading. The font.ttf is loaded from the path with .thems if it exists there.
When a Theme is loaded and a font.ttf file exists in the defined "Image-Folder:" than this font.ttf will override all others. This ensures support for themes with special fonts.
*Fixed double count on playcount bug
*Updated libext2fs to git snapshot 2010-12-24
*Added proper close of all file systems where the games are loaded from (FAT32/NTFS/EXT)
*Fixed hang bug when reloading into the IOS set in the individual game settings with that (reload to 223, 224, 245, ...)
2010-12-28 17:02:10 +00:00
dimok321 93ac37f27c *Fixed crash on NTFS (wrong memory free functions were used)
*Added proper deinitialize of usb before starting game / exiting app. This is supposed to fix Blackops multiplayer mode (Did not test it. I don't have that game.)
*Added Wii message board update (Playlog) (thanks to dkosmari for a starting point). This feature can be enabled/disabled in the global settings. Default is ON.
*Removed unused sources.
2010-12-27 09:44:27 +00:00
dimok321 0f17471b27 *Removed ntfs/fat source and added them as custom libs (makes them easier to update later)
*Added sources of the custom libs to the branches
*Fixed crash when switching from list layout to grid/carousel layout
*Removed 1:1 copy option because its meaningless and almost the same as installing all partitions
*Fixed install partition selection. This option needs a reset. Go to settings and reselect your option for this.
*Fixed schinese and tchinese language modes (filename bugs. has to be schinese.lang and tchinese.lang like on SVN)
*Fixed bug in sound buffer circle
*Fixed incorrect behaviour of x-flip when selecting system like (thx Cyan for the patch)
*Accept ios revision 65535 for Waninkokos IOSes (thx to PPSainity for pointing it out)
*Merged the new theming style branch into trunk. Just as a reminder: ALL old themes will not work until the themers did port it to the new style!
*Removed old theme style completely

Theme example:
The example file of the theme is the Default.them file. It can be found in the SVN trunk.

Change in loading of themes:
When selecting a theme now a list of all .them files in a folder is displayed. The image folder of that theme has to be in the same folder as the .them file. The image path is defined in the head of the .them file in the line with "Image-Folder: Example\n".
2010-12-26 17:02:14 +00:00
813 changed files with 99535 additions and 97228 deletions

View File

@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<app version="1">
<name> USB Loader GX</name>
<coder>USB Loader GX Team</coder>
<version>1.0 r1018</version>
<release_date>201012212002</release_date>
<short_description>Loads games from USB-devices</short_description>
<long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times.
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.
Features are automatic widescreen detection, coverdownload, parental control, theme support and many more.
Credits:
Coding: Dimok, nIxx, giantpune, ardi, Hungyip84, DrayX7, Lustar, r-win, WiiShizzza
Artworks: cyrex, NeoRame
WiiTDB / Hosting covers: Lustar
Hosting updates files: CorneliousJD
USBLoader sources: Waninkoko, Kwiirk, Hermes
Languages files updates: Kinyo and translaters
Hosting themes: Deak Phreak
Libwiigui: Tantric
Libogc/Devkit: Shagkur and Wintermute
FreeTypeGX: Armin Tamzarian.
Links:
USB Loader GX Project Page and Support Site:
http://code.google.com/p/usbloader-gui/
Help Website:
http://usbloadergx.koureio.net/
WiiTDB Site:
http://wiitdb.com
Themes Site:
http://wii.spiffy360.com
Languages Translaters Page:
http://gbatemp.net/index.php?showtopic=155252
Libwiigui Website:
http://wiibrew.org/wiki/Libwiigui/
FreeTypeGX Project Page:
http://code.google.com/p/freetypegx/
Gettext Official Page:
http://www.gnu.org/software/gettext/gettext.html
</long_description>
</app>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
#
# to use this file rename Make.config.default to Make.config
# or create a new Make.config
#
# you can here add defines
#
# in example i have included a switch to diseble
# the gecko-debug stuff. so also in source gecko.c+gecko.h
#
# NOTE when add, remove or change a define here then a "make clean" is needed
#
CFLAGS += -DNO_DEBUG DDEBUG_WBFS

279
Makefile
View File

@ -1,279 +0,0 @@
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
include $(DEVKITPPC)/wii_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := boot
BUILD := build
SOURCES := source \
source/libwiigui \
source/images \
source/fonts \
source/sounds \
source/system \
source/libs/libwbfs \
source/language \
source/mload \
source/mload/modules \
source/patches \
source/usbloader \
source/xml \
source/network \
source/settings \
source/settings/menus \
source/prompts \
source/wad \
source/banner \
source/cheats \
source/homebrewboot \
source/themes \
source/menu \
source/memory \
source/FileOperations \
source/ImageOperations \
source/SoundOperations \
source/utils \
source/utils/minizip \
source/usbloader/wbfs
DATA := data
INCLUDES := source
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -g -O3 -Wall -Wno-multichar $(MACHDEP) $(INCLUDE) -DHAVE_CONFIG_H
CXXFLAGS = -Xassembler -aln=$@.lst $(CFLAGS)
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map,--section-start,.init=0x80B00000,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size
-include $(PROJECTDIR)/Make.config
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lpngu -lpng -lgd -lm -lz -lwiiuse -lbte -lasnd -logc -lfreetype -lvorbisidec \
-lmad -lmxml -ljpeg -lzip -lcustomfat -lcustomntfs -lcustomext2fs
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(DEVKITPPC)/lib $(CURDIR)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export PROJECTDIR := $(CURDIR)
export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
SVNREV := $(shell bash ./svnrev.sh)
export CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
export CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
ELFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.elf)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.bin)))
TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg)))
PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm)))
WAVFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.wav)))
DOLFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.dol)))
MP3FILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.mp3)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
export LD := $(CC)
else
export LD := $(CXX)
endif
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
$(sFILES:.s=.o) $(SFILES:.S=.o) \
$(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) $(addsuffix .o,$(DOLFILES))\
$(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) $(MP3FILES:.mp3=.mp3.o) \
$(WAVFILES:.wav=.wav.o) $(addsuffix .o,$(ELFFILES)) $(CURDIR)/data/magic_patcher.o
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC)
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) -L$(CURDIR)/source/libs/libfat/ \
-L$(CURDIR)/source/libs/libntfs/ -L$(CURDIR)/source/libs/libext2fs/ \
-L$(LIBOGC_LIB)
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) lang all clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@/bin/bash ./buildtype.sh
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
# @echo debug...
# start geckoreader.exe
channel:
@[ -d build ] || mkdir -p build
@/bin/bash ./buildtype.sh FULLCHANNEL
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
lang:
@[ -d build ] || mkdir -p build
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile language
#---------------------------------------------------------------------------------
theme:
@[ -d build ] || mkdir -p build
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile language
#---------------------------------------------------------------------------------
all:
@[ -d build ] || mkdir -p build
@./buildtype.sh
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile language
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
#---------------------------------------------------------------------------------
run:
$(MAKE)
@echo Done building ...
@echo Now Run That Shit ...
wiiload $(OUTPUT).dol
#---------------------------------------------------------------------------------
reload:
wiiload -r $(OUTPUT).dol
#---------------------------------------------------------------------------------
release:
$(MAKE)
cp boot.dol ./hbc/boot.dol
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
$(OUTPUT).elf: $(OFILES)
language: $(wildcard $(PROJECTDIR)/Languages/*.lang) $(wildcard $(PROJECTDIR)/Themes/*.them)
#---------------------------------------------------------------------------------
# This rule links in binary data with .ttf, .png, and .mp3 extensions
#---------------------------------------------------------------------------------
%.elf.o : %.elf
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.dol.o : %.dol
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.ttf.o : %.ttf
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.png.o : %.png
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.ogg.o : %.ogg
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.pcm.o : %.pcm
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.wav.o : %.wav
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.mp3.o : %.mp3
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.certs.o : %.certs
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.dat.o : %.dat
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.bin.o : %.bin
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.tik.o : %.tik
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.tmd.o : %.tmd
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
export PATH := $(PROJECTDIR)/gettext-bin:$(PATH)
%.pot: $(CFILES) $(CPPFILES)
@echo Updating Languagefiles ...
@touch $(PROJECTDIR)/Languages/$(TARGET).pot
@xgettext -C -cTRANSLATORS --from-code=utf-8 --sort-output --no-wrap --no-location -ktr -o$(PROJECTDIR)/Languages/$(TARGET).pot -p $@ $^
@echo Updating Themefiles ...
@touch $(PROJECTDIR)/Themes/$(TARGET).pot
@xgettext -C -cTRANSLATORS --from-code=utf-8 -F --no-wrap --add-location -kthInt -kthColor -kthAlign -o$(PROJECTDIR)/Themes/$(TARGET).pot -p $@ $^
%.lang: $(PROJECTDIR)/Languages/$(TARGET).pot
@msgmerge -U -N --no-wrap --no-location --backup=none -q $@ $<
@touch $@
%.them: $(PROJECTDIR)/Themes/$(TARGET).pot
@msgmerge -U -N --no-wrap --no-location --backup=none -q $@ $<
@touch $@
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

View File

@ -1,405 +0,0 @@
# USB Loader GX theme source file.
# don't delete/change this line (é).
# ONLY the value before the '-' char needs to be entered in msgstr ""
# not the complete text.
# It is important that the image folder is defined for the images to load.
# The image folder should be in the same folder as the .them file and include the theme images.
msgid ""
msgstr ""
"Project-Id-Version: USB Loader GX\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-12-26 16:16+0100\n"
"PO-Revision-Date: 2009-10-01 01:00+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Image-Folder: Example\n"
"Last-Themer: Example\n"
"Theme-Team: Example\n"
msgid "r=0 g=0 b=0 a=255 - prompt windows text color"
msgstr ""
msgid "r=0 g=0 b=0 a=255 - settings text color"
msgstr ""
msgid "9 - game list browser page size"
msgstr ""
msgid "r=0 g=0 b=0 a=255 - game browser list text color"
msgstr ""
msgid "r=0 g=0 b=0 a=255 - game browser list text color over"
msgstr ""
msgid "r=55 g=190 b=237 a=255 - carousel game name text color"
msgstr ""
msgid "0 - game grid layout pos x"
msgstr ""
msgid "20 - game grid layout pos y"
msgstr ""
msgid "255 - tooltip alpha"
msgstr ""
msgid "r=55 g=190 b=237 a=255 - hdd info color"
msgstr ""
msgid "center - hdd info align ver"
msgstr ""
msgid "top - hdd info align hor"
msgstr ""
msgid "0 - hdd info pos x"
msgstr ""
msgid "400 - hdd info pos y"
msgstr ""
msgid "r=55 g=190 b=237 a=255 - game count color"
msgstr ""
msgid "center - game count align ver"
msgstr ""
msgid "top - game count align hor"
msgstr ""
msgid "0 - game count pos x"
msgstr ""
msgid "420 - game count pos y"
msgstr ""
msgid "16 - install btn pos x"
msgstr ""
msgid "355 - install btn pos y"
msgstr ""
msgid "371 - settings btn pos y"
msgstr ""
msgid "64 - settings btn pos x"
msgstr ""
msgid "371 - home menu btn pos x"
msgstr ""
msgid "489 - home menu btn pos x"
msgstr ""
msgid "355 - power off btn pos y"
msgstr ""
msgid "576 - power off btn pos x"
msgstr ""
msgid "160 - sd card btn pos x"
msgstr ""
msgid "395 - sd card btn pos y"
msgstr ""
msgid "405 - HBC btn pos y"
msgstr ""
msgid "410 - HBC btn pos x"
msgstr ""
msgid "26 - cover/download btn pos x"
msgstr ""
msgid "58 - cover/download btn pos y"
msgstr ""
msgid "305 - gameID btn pos y"
msgstr ""
msgid "68 - gameID btn pos x"
msgstr ""
msgid "r=138 g=138 b=138 a=240 - clock color"
msgstr ""
msgid "left - clock align ver"
msgstr ""
msgid "top - clock align hor"
msgstr ""
msgid "275 - clock pos x"
msgstr ""
msgid "275 - clock pos y"
msgstr ""
msgid "260 - list layout favorite btn pos x"
msgstr ""
msgid "288 - list layout favorite btn pos x widescreen"
msgstr ""
msgid "13 - list layout favorite btn pos y"
msgstr ""
msgid "300 - list layout search btn pos x"
msgstr ""
msgid "320 - list layout search btn pos x widescreen"
msgstr ""
msgid "13 - list layout search btn pos x"
msgstr ""
msgid "340 - list layout abc/sort btn pos x"
msgstr ""
msgid "352 - list layout abc/sort btn pos x widescreen"
msgstr ""
msgid "13 - list layout abc/sort btn pos y"
msgstr ""
msgid "380 - list layout list btn pos x"
msgstr ""
msgid "384 - list layout list btn pos x widescreen"
msgstr ""
msgid "13 - list layout list btn pos y"
msgstr ""
msgid "416 - list layout grid btn pos x widescreen"
msgstr ""
msgid "420 - list layout grid btn pos x"
msgstr ""
msgid "13 - list layout grid btn pos y"
msgstr ""
msgid "448 - list layout carousel btn pos x widescreen"
msgstr ""
msgid "460 - list layout carousel btn pos x"
msgstr ""
msgid "13 - list layout carousel btn pos y"
msgstr ""
msgid "480 - list layout lock btn pos x widescreen"
msgstr ""
msgid "500 - list layout lock btn pos x"
msgstr ""
msgid "13 - list layout lock btn pos y"
msgstr ""
msgid "512 - list layout dvd btn pos x widescreen"
msgstr ""
msgid "540 - list layout dvd btn pos x"
msgstr ""
msgid "13 - list layout dvd btn pos y"
msgstr ""
msgid "280 - game list layout height"
msgstr ""
msgid "396 - game list layout width"
msgstr ""
msgid "200 - game list layout pos x"
msgstr ""
msgid "49 - game list layout pos y"
msgstr ""
msgid "200 - grid layout favorite btn pos x"
msgstr ""
msgid "224 - grid layout favorite btn pos x widescreen"
msgstr ""
msgid "13 - grid layout favorite btn pos y"
msgstr ""
msgid "240 - grid layout search btn pos x"
msgstr ""
msgid "256 - grid layout search btn pos x widescreen"
msgstr ""
msgid "13 - grid layout search btn pos x"
msgstr ""
msgid "280 - grid layout abc/sort btn pos x"
msgstr ""
msgid "288 - grid layout abc/sort btn pos x widescreen"
msgstr ""
msgid "13 - grid layout abc/sort btn pos y"
msgstr ""
msgid "320 - grid layout list btn pos x"
msgstr ""
msgid "320 - grid layout list btn pos x widescreen"
msgstr ""
msgid "13 - grid layout list btn pos y"
msgstr ""
msgid "352 - grid layout grid btn pos x widescreen"
msgstr ""
msgid "360 - grid layout grid btn pos x"
msgstr ""
msgid "13 - grid layout grid btn pos y"
msgstr ""
msgid "384 - grid layout carousel btn pos x widescreen"
msgstr ""
msgid "400 - grid layout carousel btn pos x"
msgstr ""
msgid "13 - grid layout carousel btn pos y"
msgstr ""
msgid "416 - grid layout lock btn pos x widescreen"
msgstr ""
msgid "440 - grid layout lock btn pos x"
msgstr ""
msgid "13 - grid layout lock btn pos y"
msgstr ""
msgid "448 - grid layout dvd btn pos x widescreen"
msgstr ""
msgid "480 - grid layout dvd btn pos x"
msgstr ""
msgid "13 - grid layout dvd btn pos y"
msgstr ""
msgid "400 - game grid layout height"
msgstr ""
msgid "640 - game grid layout width"
msgstr ""
msgid "200 - carousel layout favorite btn pos x"
msgstr ""
msgid "224 - carousel layout favorite btn pos x widescreen"
msgstr ""
msgid "13 - carousel layout favorite btn pos y"
msgstr ""
msgid "240 - carousel layout search btn pos x"
msgstr ""
msgid "256 - carousel layout search btn pos x widescreen"
msgstr ""
msgid "13 - carousel layout search btn pos x"
msgstr ""
msgid "280 - carousel layout abc/sort btn pos x"
msgstr ""
msgid "288 - carousel layout abc/sort btn pos x widescreen"
msgstr ""
msgid "13 - carousel layout abc/sort btn pos y"
msgstr ""
msgid "320 - carousel layout list btn pos x"
msgstr ""
msgid "320 - carousel layout list btn pos x widescreen"
msgstr ""
msgid "13 - carousel layout list btn pos y"
msgstr ""
msgid "352 - carousel layout grid btn pos x widescreen"
msgstr ""
msgid "360 - carousel layout grid btn pos x"
msgstr ""
msgid "13 - carousel layout grid btn pos y"
msgstr ""
msgid "384 - carousel layout carousel btn pos x widescreen"
msgstr ""
msgid "400 - carousel layout carousel btn pos x"
msgstr ""
msgid "13 - carousel layout carousel btn pos y"
msgstr ""
msgid "416 - carousel layout lock btn pos x widescreen"
msgstr ""
msgid "440 - carousel layout lock btn pos x"
msgstr ""
msgid "13 - carousel layout lock btn pos y"
msgstr ""
msgid "448 - carousel layout dvd btn pos x widescreen"
msgstr ""
msgid "480 - carousel layout dvd btn pos x"
msgstr ""
msgid "13 - carousel layout dvd btn pos y"
msgstr ""
msgid "400 - game carousel layout height"
msgstr ""
msgid "640 - game carousel layout width"
msgstr ""
msgid "-20 - game carousel layout pos y"
msgstr ""
msgid "0 - game carousel layout pos x"
msgstr ""
msgid "1 - show hdd info: 1 for on and 0 for off"
msgstr ""
msgid "1 - show game count: 1 for on and 0 for off"
msgstr ""
msgid "r=55 g=190 b=237 a=255 - game id text color"
msgstr ""
msgid "r=55 g=190 b=237 a=255 - region info text color"
msgstr ""
msgid "30 - region info text pos x"
msgstr ""
msgid "68 - region info text pos x"
msgstr ""
msgid "1 - Enable tooltips: 0 for off and 1 for on"
msgstr ""

View File

@ -1,14 +0,0 @@
#!/bin/bash
if [ ! -z "$1" ];
then
if [ ! -s source/buildtype.h ];
then
echo "#define $1" > source/buildtype.h
fi
else
if [[ ! -f source/buildtype.h || -s source/buildtype.h ]];
then
cp /dev/null source/buildtype.h
fi
fi

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
<pd><ViewState><e p="gui\source\mload" x="false"></e><e p="gui\source\settings" x="false"></e><e p="gui\source\utils" x="false"></e><e p="gui\source\SoundOperations" x="false"></e><e p="gui\source\images" x="false"></e><e p="gui\source\prompts" x="false"></e><e p="gui\source\banner" x="false"></e><e p="gui\source\cheats" x="false"></e><e p="gui\source\network" x="true"></e><e p="gui\source\fonts" x="false"></e><e p="gui\source\libs" x="false"></e><e p="gui\source\menu" x="false"></e><e p="gui\source\sounds" x="false"></e><e p="gui\source\system" x="false"></e><e p="gui\source\wad" x="false"></e><e p="gui" x="true"></e><e p="gui\source\FileOperations" x="false"></e><e p="gui\source\homebrewboot" x="false"></e><e p="gui\source\language" x="false"></e><e p="gui\source" x="true"></e><e p="gui\source\libwiigui" x="false"></e><e p="gui\source\patches" x="false"></e><e p="gui\source\themes" x="false"></e><e p="gui\source\ImageOperations" x="false"></e><e p="gui\source\memory" x="false"></e><e p="gui\source\usbloader" x="false"></e><e p="gui\source\xml" x="false"></e></ViewState></pd>

11
libcustomext2fs/AUTHORS Normal file
View File

@ -0,0 +1,11 @@
Present author and main programmer of ext2fs in alphabetical order:
Theodore Ts'o
Many more are contributing to this project. Read it all up at http://e2fsprogs.sourceforge.net/ext2.html
Nintendo GameCube/Wii port author:
Dimok

10
libcustomext2fs/CREDITS Normal file
View File

@ -0,0 +1,10 @@
First of all thanks goes to everyone who contributed to ext2fs directly or indirectly.
Visit the site to inform yourself who was involved in it http://e2fsprogs.sourceforge.net/ext2.html
The following people have contributed directly or indirectly
to the Nintendo GameCube/Wii port of ext2fs.
Michael "Chishm" Chisholm
rodries
Rhys "Shareese" Koedijk
Dimok

340
libcustomext2fs/LICENSE Normal file
View File

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

27
libcustomext2fs/Makefile Normal file
View File

@ -0,0 +1,27 @@
default: cube-release wii-release
all: debug release
debug: cube-debug wii-debug
release: cube-release wii-release
cube-debug:
$(MAKE) -C source PLATFORM=cube BUILD=cube_debug
wii-debug:
$(MAKE) -C source PLATFORM=wii BUILD=wii_debug
cube-release:
$(MAKE) -C source PLATFORM=cube BUILD=cube_release
wii-release:
$(MAKE) -C source PLATFORM=wii BUILD=wii_release
clean:
$(MAKE) -C source clean
install: cube-release wii-release
$(MAKE) -C source install

View File

@ -0,0 +1,106 @@
/********************************************************************************
* ext2.h - devoptab file routines for EXT2/3/4-based devices. *
* *
* Copyright (c) 2010 Dimok *
* *
* This program/include file is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as published *
* by the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program/include file is distributed in the hope that it will be *
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty *
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation, *
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
********************************************************************************/
#ifndef __EXT2_H_
#define __EXT2_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <gctypes.h>
#include <gccore.h>
#include <ogc/disc_io.h>
/**
* EXT2 cache options
*
* It is recommended to use more pages instead of large page sizes for cache due to the sporadic write behaviour of ext file system.
* It will significantly increase the speed. A page size of 32 is mostly suffiecient. The larger the page count the faster the
* read/write between smaller files will be. Larger page sizes result in faster read/write of single big files.
*/
#define EXT2_CACHE_DEFAULT_PAGE_COUNT 64 /* The default number of pages in the cache */
#define EXT2_CACHE_DEFAULT_PAGE_SIZE 32 /* The default number of sectors per cache page */
/* EXT2 mount flags */
#define EXT2_FLAG_RW 0x00001 /* Open the filesystem for reading and writing. Without this flag, the filesystem is opened for reading only. */
#define EXT2_FLAG_FORCE 0x00400 /* Open the filesystem regardless of the feature sets listed in the superblock */
#define EXT2_FLAG_JOURNAL_DEV_OK 0x01000 /* Only open external journal devices if this flag is set (e.g. ext3/ext4) */
#define EXT2_FLAG_64BITS 0x20000 /* Use the new style 64-Bit bitmaps. For more information see gen_bitmap64.c */
#define EXT2_FLAG_PRINT_PROGRESS 0x40000 /* If this flag is set the progress of file operations will be printed to stdout */
#define EXT2_FLAG_SKIP_MMP 0x100000 /* Open without multi-mount protection check. */
#define EXT2_FLAG_DEFAULT (EXT2_FLAG_RW | EXT2_FLAG_64BITS | EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_SKIP_MMP)
/**
* Find all EXT2/3/4 partitions on a block device.
*
* @param INTERFACE The block device to search
* @param PARTITIONS (out) A pointer to receive the array of partition start sectors
*
* @return The number of entries in PARTITIONS or -1 if an error occurred (see errno)
* @note The caller is responsible for freeing PARTITIONS when finished with it
*/
int ext2FindPartitions(const DISC_INTERFACE *interface, sec_t **partitions);
/**
* Mount a EXT2/3/4 partition from a specific sector on a block device.
*
* @param NAME The name to mount the device under (can then be accessed as "NAME:/")
* @param INTERFACE The block device to mount
* @param STARTSECTOR The sector the partition begins at
* @param CACHEPAGECOUNT The total number of pages in the device cache
* @param CACHEPAGESIZE The number of sectors per cache page
* @param FLAGS Additional mounting flags (see above)
*
* @return True if mount was successful, false if no partition was found or an error occurred (see errno)
*/
bool ext2Mount(const char *name, const DISC_INTERFACE *interface, sec_t startSector, u32 cachePageCount, u32 cachePageSize, u32 flags);
/**
* Unmount a EXT2/3/4 partition.
*
* @param NAME The name of mount used in ext2Mount()
*/
void ext2Unmount(const char *name);
/**
* Get the volume name of a mounted EXT2/3/4 partition.
*
* @param NAME The name of mount
*
* @return The volumes name if successful or NULL if an error occurred (see errno)
*/
const char *ext2GetVolumeName (const char *name);
/**
* Set the volume name of a mounted EXT2/3/4 partition.
*
* @param NAME The name of mount
* @param VOLUMENAME The new volume name
*
* @return True if mount was successful, false if an error occurred (see errno)
* @note The mount must be write-enabled else this will fail
*/
bool ext2SetVolumeName (const char *name, const char *volumeName);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,130 @@
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
ifeq ($(PLATFORM),wii)
include $(DEVKITPPC)/wii_rules
endif
ifeq ($(PLATFORM),cube)
include $(DEVKITPPC)/gamecube_rules
endif
#---------------------------------------------------------------------------------
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
BUILD ?= wii_release
SOURCES := .
INCLUDES := ../include
LIBDIR := ../lib
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -O2 -Wall -Wno-unused $(MACHDEP) $(INCLUDE) -DGEKKO -DWORDS_BIGENDIAN
CXXFLAGS = $(CFLAGS)
ASFLAGS := -g
export EXT2BIN := $(LIBDIR)/$(PLATFORM)/libext2fs.a
ifeq ($(BUILD),cube_debug)
CFLAGS += -DDEBUG_GEKKO
CXXFLAGS += -DDEBUG_GEKKO
endif
ifeq ($(BUILD),wii_debug)
CFLAGS += -DDEBUG_GEKKO
CXXFLAGS += -DDEBUG_GEKKO
endif
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
-L$(LIBOGC_LIB)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr wii_debug wii_release cube_debug cube_release $(LIBDIR)
all: $(EXT2BIN)
install:
cp ../include/ext2.h $(DEVKITPRO)/libogc/include
cp ../lib/wii/libext2fs.a $(DEVKITPRO)/libogc/lib/wii
cp ../lib/cube/libext2fs.a $(DEVKITPRO)/libogc/lib/cube
wii-install:
cp ../include/ext2.h $(DEVKITPRO)/libogc/include
cp ../lib/wii/libext2fs.a $(DEVKITPRO)/libogc/lib/wii
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(EXT2BIN): $(OFILES) $(LIBDIR)/$(PLATFORM)
@rm -f "../$(EXT2BIN)"
@$(AR) rcs "../$(EXT2BIN)" $(OFILES)
@echo built ... $(notdir $@)
$(LIBDIR)/$(PLATFORM):
mkdir -p ../$(LIBDIR)/$(PLATFORM)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,320 @@
/*
* alloc.c --- allocate new inodes, blocks for ext2fs
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <time.h>
#include <string.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
/*
* Check for uninit block bitmaps and deal with them appropriately
*/
static void check_block_uninit(ext2_filsys fs, ext2fs_block_bitmap map,
dgrp_t group)
{
blk_t i;
blk64_t blk, super_blk, old_desc_blk, new_desc_blk;
int old_desc_blocks;
if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) ||
!(ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
return;
blk = (group * fs->super->s_blocks_per_group) +
fs->super->s_first_data_block;
ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
&old_desc_blk, &new_desc_blk, 0);
if (fs->super->s_feature_incompat &
EXT2_FEATURE_INCOMPAT_META_BG)
old_desc_blocks = fs->super->s_first_meta_bg;
else
old_desc_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
for (i=0; i < fs->super->s_blocks_per_group; i++, blk++)
ext2fs_fast_unmark_block_bitmap2(map, blk);
blk = (group * fs->super->s_blocks_per_group) +
fs->super->s_first_data_block;
for (i=0; i < fs->super->s_blocks_per_group; i++, blk++) {
if ((blk == super_blk) ||
(old_desc_blk && old_desc_blocks &&
(blk >= old_desc_blk) &&
(blk < old_desc_blk + old_desc_blocks)) ||
(new_desc_blk && (blk == new_desc_blk)) ||
(blk == ext2fs_block_bitmap_loc(fs, group)) ||
(blk == ext2fs_inode_bitmap_loc(fs, group)) ||
(blk >= ext2fs_inode_table_loc(fs, group) &&
(blk < ext2fs_inode_table_loc(fs, group)
+ fs->inode_blocks_per_group)))
ext2fs_fast_mark_block_bitmap2(map, blk);
}
ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, group);
}
/*
* Check for uninit inode bitmaps and deal with them appropriately
*/
static void check_inode_uninit(ext2_filsys fs, ext2fs_inode_bitmap map,
dgrp_t group)
{
ext2_ino_t i, ino;
if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) ||
!(ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)))
return;
ino = (group * fs->super->s_inodes_per_group) + 1;
for (i=0; i < fs->super->s_inodes_per_group; i++, ino++)
ext2fs_fast_unmark_inode_bitmap2(map, ino);
ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
check_block_uninit(fs, fs->block_map, group);
}
/*
* Right now, just search forward from the parent directory's block
* group to find the next free inode.
*
* Should have a special policy for directories.
*/
errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
int mode EXT2FS_ATTR((unused)),
ext2fs_inode_bitmap map, ext2_ino_t *ret)
{
ext2_ino_t dir_group = 0;
ext2_ino_t i;
ext2_ino_t start_inode;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!map)
map = fs->inode_map;
if (!map)
return EXT2_ET_NO_INODE_BITMAP;
if (dir > 0)
dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super);
start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1;
if (start_inode < EXT2_FIRST_INODE(fs->super))
start_inode = EXT2_FIRST_INODE(fs->super);
if (start_inode > fs->super->s_inodes_count)
return EXT2_ET_INODE_ALLOC_FAIL;
i = start_inode;
do {
if (((i - 1) % EXT2_INODES_PER_GROUP(fs->super)) == 0)
check_inode_uninit(fs, map, (i - 1) /
EXT2_INODES_PER_GROUP(fs->super));
if (!ext2fs_fast_test_inode_bitmap2(map, i))
break;
i++;
if (i > fs->super->s_inodes_count)
i = EXT2_FIRST_INODE(fs->super);
} while (i != start_inode);
if (ext2fs_test_inode_bitmap2(map, i))
return EXT2_ET_INODE_ALLOC_FAIL;
*ret = i;
return 0;
}
/*
* Stupid algorithm --- we now just search forward starting from the
* goal. Should put in a smarter one someday....
*/
errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal,
ext2fs_block_bitmap map, blk64_t *ret)
{
blk64_t i;
int c_ratio;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!map)
map = fs->block_map;
if (!map)
return EXT2_ET_NO_BLOCK_BITMAP;
if (!goal || (goal >= ext2fs_blocks_count(fs->super)))
goal = fs->super->s_first_data_block;
i = goal;
c_ratio = 1 << ext2fs_get_bitmap_granularity(map);
if (c_ratio > 1)
goal &= ~EXT2FS_CLUSTER_MASK(fs);
check_block_uninit(fs, map,
(i - fs->super->s_first_data_block) /
EXT2_BLOCKS_PER_GROUP(fs->super));
do {
if (((i - fs->super->s_first_data_block) %
EXT2_BLOCKS_PER_GROUP(fs->super)) == 0)
check_block_uninit(fs, map,
(i - fs->super->s_first_data_block) /
EXT2_BLOCKS_PER_GROUP(fs->super));
if (!ext2fs_fast_test_block_bitmap2(map, i)) {
*ret = i;
return 0;
}
i = (i + c_ratio) & ~(c_ratio - 1);
if (i >= ext2fs_blocks_count(fs->super))
i = fs->super->s_first_data_block;
} while (i != goal);
return EXT2_ET_BLOCK_ALLOC_FAIL;
}
errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
ext2fs_block_bitmap map, blk_t *ret)
{
errcode_t retval;
blk64_t val;
retval = ext2fs_new_block2(fs, goal, map, &val);
if (!retval)
*ret = (blk_t) val;
return retval;
}
/*
* This function zeros out the allocated block, and updates all of the
* appropriate filesystem records.
*/
errcode_t ext2fs_alloc_block2(ext2_filsys fs, blk64_t goal,
char *block_buf, blk64_t *ret)
{
errcode_t retval;
blk64_t block;
char *buf = 0;
if (!block_buf) {
retval = ext2fs_get_mem(fs->blocksize, &buf);
if (retval)
return retval;
block_buf = buf;
}
memset(block_buf, 0, fs->blocksize);
if (fs->get_alloc_block) {
retval = (fs->get_alloc_block)(fs, goal, &block);
if (retval)
goto fail;
} else {
if (!fs->block_map) {
retval = ext2fs_read_block_bitmap(fs);
if (retval)
goto fail;
}
retval = ext2fs_new_block2(fs, goal, 0, &block);
if (retval)
goto fail;
}
retval = io_channel_write_blk64(fs->io, block, 1, block_buf);
if (retval)
goto fail;
ext2fs_block_alloc_stats2(fs, block, +1);
*ret = block;
fail:
if (buf)
ext2fs_free_mem(&buf);
return retval;
}
errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
char *block_buf, blk_t *ret)
{
errcode_t retval;
blk64_t val;
retval = ext2fs_alloc_block2(fs, goal, block_buf, &val);
if (!retval)
*ret = (blk_t) val;
return retval;
}
errcode_t ext2fs_get_free_blocks2(ext2_filsys fs, blk64_t start, blk64_t finish,
int num, ext2fs_block_bitmap map, blk64_t *ret)
{
blk64_t b = start;
int c_ratio;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!map)
map = fs->block_map;
if (!map)
return EXT2_ET_NO_BLOCK_BITMAP;
if (!b)
b = fs->super->s_first_data_block;
if (!finish)
finish = start;
if (!num)
num = 1;
c_ratio = 1 << ext2fs_get_bitmap_granularity(map);
b &= ~(c_ratio - 1);
finish &= ~(c_ratio -1);
do {
if (b+num-1 > ext2fs_blocks_count(fs->super))
b = fs->super->s_first_data_block;
if (ext2fs_fast_test_block_bitmap_range2(map, b, num)) {
*ret = b;
return 0;
}
b += c_ratio;
} while (b != finish);
return EXT2_ET_BLOCK_ALLOC_FAIL;
}
errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
int num, ext2fs_block_bitmap map, blk_t *ret)
{
errcode_t retval;
blk64_t val;
retval = ext2fs_get_free_blocks2(fs, start, finish, num, map, &val);
if(!retval)
*ret = (blk_t) val;
return retval;
}
void ext2fs_set_alloc_block_callback(ext2_filsys fs,
errcode_t (*func)(ext2_filsys fs,
blk64_t goal,
blk64_t *ret),
errcode_t (**old)(ext2_filsys fs,
blk64_t goal,
blk64_t *ret))
{
if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
return;
if (old)
*old = fs->get_alloc_block;
fs->get_alloc_block = func;
}

View File

@ -0,0 +1,82 @@
/*
* alloc_sb.c --- Allocate the superblock and block group descriptors for a
* newly initialized filesystem. Used by mke2fs when initializing a filesystem
*
* Copyright (C) 1994, 1995, 1996, 2003 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
/*
* This function reserves the superblock and block group descriptors
* for a given block group. It currently returns the number of free
* blocks assuming that inode table and allocation bitmaps will be in
* the group. This is not necessarily the case when the flex_bg
* feature is enabled, so callers should take care! It was only
* really intended for use by mke2fs, and even there it's not that
* useful. In the future, when we redo this function for 64-bit block
* numbers, we should probably return the number of blocks used by the
* super block and group descriptors instead.
*
* See also the comment for ext2fs_super_and_bgd_loc()
*/
int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
dgrp_t group,
ext2fs_block_bitmap bmap)
{
blk64_t super_blk, old_desc_blk, new_desc_blk;
blk_t used_blks;
int j, old_desc_blocks, num_blocks;
ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
&old_desc_blk, &new_desc_blk, &used_blks);
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
old_desc_blocks = fs->super->s_first_meta_bg;
else
old_desc_blocks =
fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
if (super_blk || (group == 0))
ext2fs_mark_block_bitmap2(bmap, super_blk);
if ((group == 0) && (fs->blocksize == 1024) &&
EXT2FS_CLUSTER_RATIO(fs) > 1)
ext2fs_mark_block_bitmap2(bmap, 0);
if (old_desc_blk) {
if (fs->super->s_reserved_gdt_blocks && fs->block_map == bmap)
ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
for (j=0; j < old_desc_blocks; j++)
if (old_desc_blk + j < ext2fs_blocks_count(fs->super))
ext2fs_mark_block_bitmap2(bmap,
old_desc_blk + j);
}
if (new_desc_blk)
ext2fs_mark_block_bitmap2(bmap, new_desc_blk);
num_blocks = ext2fs_group_blocks_count(fs, group);
num_blocks -= 2 + fs->inode_blocks_per_group + used_blks;
return num_blocks ;
}

View File

@ -0,0 +1,108 @@
/*
* alloc_stats.c --- Update allocation statistics for ext2fs
*
* Copyright (C) 2001 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include "ext2_fs.h"
#include "ext2fs.h"
void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
int inuse, int isdir)
{
int group = ext2fs_group_of_ino(fs, ino);
#ifndef OMIT_COM_ERR
if (ino > fs->super->s_inodes_count) {
com_err("ext2fs_inode_alloc_stats2", 0,
"Illegal inode number: %lu", (unsigned long) ino);
return;
}
#endif
if (inuse > 0)
ext2fs_mark_inode_bitmap2(fs->inode_map, ino);
else
ext2fs_unmark_inode_bitmap2(fs->inode_map, ino);
ext2fs_bg_free_inodes_count_set(fs, group, ext2fs_bg_free_inodes_count(fs, group) - inuse);
if (isdir)
ext2fs_bg_used_dirs_count_set(fs, group, ext2fs_bg_used_dirs_count(fs, group) + inuse);
/* We don't strictly need to be clearing the uninit flag if inuse < 0
* (i.e. freeing inodes) but it also means something is bad. */
ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
ext2_ino_t first_unused_inode = fs->super->s_inodes_per_group -
ext2fs_bg_itable_unused(fs, group) +
group * fs->super->s_inodes_per_group + 1;
if (ino >= first_unused_inode)
ext2fs_bg_itable_unused_set(fs, group, group * fs->super->s_inodes_per_group + fs->super->s_inodes_per_group - ino);
ext2fs_group_desc_csum_set(fs, group);
}
fs->super->s_free_inodes_count -= inuse;
ext2fs_mark_super_dirty(fs);
ext2fs_mark_ib_dirty(fs);
}
void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse)
{
ext2fs_inode_alloc_stats2(fs, ino, inuse, 0);
}
void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse)
{
int group = ext2fs_group_of_blk2(fs, blk);
#ifndef OMIT_COM_ERR
if (blk >= ext2fs_blocks_count(fs->super)) {
com_err("ext2fs_block_alloc_stats", 0,
"Illegal block number: %lu", (unsigned long) blk);
return;
}
#endif
if (inuse > 0)
ext2fs_mark_block_bitmap2(fs->block_map, blk);
else
ext2fs_unmark_block_bitmap2(fs->block_map, blk);
ext2fs_bg_free_blocks_count_set(fs, group, ext2fs_bg_free_blocks_count(fs, group) - inuse);
ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, group);
ext2fs_free_blocks_count_add(fs->super,
-inuse * EXT2FS_CLUSTER_RATIO(fs));
ext2fs_mark_super_dirty(fs);
ext2fs_mark_bb_dirty(fs);
if (fs->block_alloc_stats)
(fs->block_alloc_stats)(fs, (blk64_t) blk, inuse);
}
void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse)
{
ext2fs_block_alloc_stats2(fs, blk, inuse);
}
void ext2fs_set_block_alloc_stats_callback(ext2_filsys fs,
void (*func)(ext2_filsys fs,
blk64_t blk,
int inuse),
void (**old)(ext2_filsys fs,
blk64_t blk,
int inuse))
{
if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
return;
if (old)
*old = fs->block_alloc_stats;
fs->block_alloc_stats = func;
}

View File

@ -0,0 +1,245 @@
/*
* alloc_tables.c --- Allocate tables for a newly initialized
* filesystem. Used by mke2fs when initializing a filesystem
*
* Copyright (C) 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#include "ext2fsP.h"
/*
* This routine searches for free blocks that can allocate a full
* group of bitmaps or inode tables for a flexbg group. Returns the
* block number with a correct offset were the bitmaps and inode
* tables can be allocated continously and in order.
*/
static blk64_t flexbg_offset(ext2_filsys fs, dgrp_t group, blk64_t start_blk,
ext2fs_block_bitmap bmap, int rem_grp,
int elem_size)
{
int flexbg, flexbg_size, size;
blk64_t last_blk, first_free = 0;
dgrp_t last_grp;
flexbg_size = 1 << fs->super->s_log_groups_per_flex;
flexbg = group / flexbg_size;
size = rem_grp * elem_size;
if (size > (int) (fs->super->s_blocks_per_group / 8))
size = (int) fs->super->s_blocks_per_group / 8;
/*
* Don't do a long search if the previous block
* search is still valid.
*/
if (start_blk && ext2fs_test_block_bitmap_range2(bmap, start_blk,
elem_size))
return start_blk;
start_blk = ext2fs_group_first_block2(fs, flexbg_size * flexbg);
last_grp = group | (flexbg_size - 1);
if (last_grp > fs->group_desc_count-1)
last_grp = fs->group_desc_count-1;
last_blk = ext2fs_group_last_block2(fs, last_grp);
/* Find the first available block */
if (ext2fs_get_free_blocks2(fs, start_blk, last_blk, size,
bmap, &first_free) == 0)
return first_free;
if (ext2fs_get_free_blocks2(fs, start_blk, last_blk, elem_size,
bmap, &first_free) == 0)
return first_free;
if (ext2fs_get_free_blocks2(fs, 0, last_blk, elem_size, bmap,
&first_free) == 0)
return first_free;
return first_free;
}
errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
ext2fs_block_bitmap bmap)
{
unsigned int j;
errcode_t retval;
blk64_t group_blk, start_blk, last_blk, new_blk, blk;
dgrp_t last_grp = 0;
int rem_grps = 0, flexbg_size = 0;
group_blk = ext2fs_group_first_block2(fs, group);
last_blk = ext2fs_group_last_block2(fs, group);
if (!bmap)
bmap = fs->block_map;
if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
EXT4_FEATURE_INCOMPAT_FLEX_BG) &&
fs->super->s_log_groups_per_flex) {
flexbg_size = 1 << fs->super->s_log_groups_per_flex;
last_grp = group | (flexbg_size - 1);
if (last_grp > fs->group_desc_count-1)
last_grp = fs->group_desc_count-1;
rem_grps = last_grp - group + 1;
}
/*
* Allocate the block and inode bitmaps, if necessary
*/
if (fs->stride) {
retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk,
1, bmap, &start_blk);
if (retval)
return retval;
start_blk += fs->inode_blocks_per_group;
start_blk += ((fs->stride * group) %
(last_blk - start_blk + 1));
if (start_blk >= last_blk)
start_blk = group_blk;
} else
start_blk = group_blk;
if (flexbg_size) {
blk64_t prev_block = 0;
if (group % flexbg_size)
prev_block = ext2fs_block_bitmap_loc(fs, group - 1) + 1;
start_blk = flexbg_offset(fs, group, prev_block, bmap,
rem_grps, 1);
last_blk = ext2fs_group_last_block2(fs, last_grp);
}
if (!ext2fs_block_bitmap_loc(fs, group)) {
retval = ext2fs_get_free_blocks2(fs, start_blk, last_blk,
1, bmap, &new_blk);
if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
retval = ext2fs_get_free_blocks2(fs, group_blk,
last_blk, 1, bmap, &new_blk);
if (retval)
return retval;
ext2fs_mark_block_bitmap2(bmap, new_blk);
ext2fs_block_bitmap_loc_set(fs, group, new_blk);
if (flexbg_size) {
dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk);
ext2fs_bg_free_blocks_count_set(fs, gr, ext2fs_bg_free_blocks_count(fs, gr) - 1);
ext2fs_free_blocks_count_add(fs->super, -1);
ext2fs_bg_flags_clear(fs, gr, EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, gr);
}
}
if (flexbg_size) {
blk64_t prev_block = 0;
if (group % flexbg_size)
prev_block = ext2fs_inode_bitmap_loc(fs, group - 1) + 1;
else
prev_block = ext2fs_block_bitmap_loc(fs, group) +
flexbg_size;
start_blk = flexbg_offset(fs, group, prev_block, bmap,
rem_grps, 1);
last_blk = ext2fs_group_last_block2(fs, last_grp);
}
if (!ext2fs_inode_bitmap_loc(fs, group)) {
retval = ext2fs_get_free_blocks2(fs, start_blk, last_blk,
1, bmap, &new_blk);
if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
retval = ext2fs_get_free_blocks2(fs, group_blk,
last_blk, 1, bmap, &new_blk);
if (retval)
return retval;
ext2fs_mark_block_bitmap2(bmap, new_blk);
ext2fs_inode_bitmap_loc_set(fs, group, new_blk);
if (flexbg_size) {
dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk);
ext2fs_bg_free_blocks_count_set(fs, gr, ext2fs_bg_free_blocks_count(fs, gr) - 1);
ext2fs_free_blocks_count_add(fs->super, -1);
ext2fs_bg_flags_clear(fs, gr, EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, gr);
}
}
/*
* Allocate the inode table
*/
if (flexbg_size) {
blk64_t prev_block = 0;
if (group % flexbg_size)
prev_block = ext2fs_inode_table_loc(fs, group - 1) +
fs->inode_blocks_per_group;
else
prev_block = ext2fs_inode_bitmap_loc(fs, group) +
flexbg_size;
group_blk = flexbg_offset(fs, group, prev_block, bmap,
rem_grps, fs->inode_blocks_per_group);
last_blk = ext2fs_group_last_block2(fs, last_grp);
}
if (!ext2fs_inode_table_loc(fs, group)) {
retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk,
fs->inode_blocks_per_group,
bmap, &new_blk);
if (retval)
return retval;
for (j=0, blk = new_blk;
j < fs->inode_blocks_per_group;
j++, blk++) {
ext2fs_mark_block_bitmap2(bmap, blk);
if (flexbg_size) {
dgrp_t gr = ext2fs_group_of_blk2(fs, blk);
ext2fs_bg_free_blocks_count_set(fs, gr, ext2fs_bg_free_blocks_count(fs, gr) - 1);
ext2fs_free_blocks_count_add(fs->super, -1);
ext2fs_bg_flags_clear(fs, gr,
EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, gr);
}
}
ext2fs_inode_table_loc_set(fs, group, new_blk);
}
ext2fs_group_desc_csum_set(fs, group);
return 0;
}
errcode_t ext2fs_allocate_tables(ext2_filsys fs)
{
errcode_t retval;
dgrp_t i;
struct ext2fs_numeric_progress_struct progress;
ext2fs_numeric_progress_init(fs, &progress, NULL,
fs->group_desc_count);
for (i = 0; i < fs->group_desc_count; i++) {
ext2fs_numeric_progress_update(fs, &progress, i);
retval = ext2fs_allocate_group_table(fs, i, fs->block_map);
if (retval)
return retval;
}
ext2fs_numeric_progress_close(fs, &progress, NULL);
return 0;
}

View File

@ -0,0 +1,328 @@
/*
* badblocks.c --- routines to manipulate the bad block structure
*
* Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fsP.h"
/*
* Helper function for making a badblocks list
*/
static errcode_t make_u32_list(int size, int num, __u32 *list,
ext2_u32_list *ret)
{
ext2_u32_list bb;
errcode_t retval;
retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb);
if (retval)
return retval;
memset(bb, 0, sizeof(struct ext2_struct_u32_list));
bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
bb->size = size ? size : 10;
bb->num = num;
retval = ext2fs_get_array(bb->size, sizeof(blk_t), &bb->list);
if (retval) {
ext2fs_free_mem(&bb);
return retval;
}
if (list)
memcpy(bb->list, list, bb->size * sizeof(blk_t));
else
memset(bb->list, 0, bb->size * sizeof(blk_t));
*ret = bb;
return 0;
}
/*
* This procedure creates an empty u32 list.
*/
errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size)
{
return make_u32_list(size, 0, 0, ret);
}
/*
* This procedure creates an empty badblocks list.
*/
errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
{
return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret);
}
/*
* This procedure copies a badblocks list
*/
errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest)
{
errcode_t retval;
retval = make_u32_list(src->size, src->num, src->list, dest);
if (retval)
return retval;
(*dest)->badblocks_flags = src->badblocks_flags;
return 0;
}
errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
ext2_badblocks_list *dest)
{
return ext2fs_u32_copy((ext2_u32_list) src,
(ext2_u32_list *) dest);
}
/*
* This procedure frees a badblocks list.
*
* (note: moved to closefs.c)
*/
/*
* This procedure adds a block to a badblocks list.
*/
errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk)
{
errcode_t retval;
int i, j;
unsigned long old_size;
EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
if (bb->num >= bb->size) {
old_size = bb->size * sizeof(__u32);
bb->size += 100;
retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32),
&bb->list);
if (retval) {
bb->size -= 100;
return retval;
}
}
/*
* Add special case code for appending to the end of the list
*/
i = bb->num-1;
if ((bb->num != 0) && (bb->list[i] == blk))
return 0;
if ((bb->num == 0) || (bb->list[i] < blk)) {
bb->list[bb->num++] = blk;
return 0;
}
j = bb->num;
for (i=0; i < bb->num; i++) {
if (bb->list[i] == blk)
return 0;
if (bb->list[i] > blk) {
j = i;
break;
}
}
for (i=bb->num; i > j; i--)
bb->list[i] = bb->list[i-1];
bb->list[j] = blk;
bb->num++;
return 0;
}
errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
{
return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk);
}
/*
* This procedure finds a particular block is on a badblocks
* list.
*/
int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk)
{
int low, high, mid;
if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
return -1;
if (bb->num == 0)
return -1;
low = 0;
high = bb->num-1;
if (blk == bb->list[low])
return low;
if (blk == bb->list[high])
return high;
while (low < high) {
mid = ((unsigned)low + (unsigned)high)/2;
if (mid == low || mid == high)
break;
if (blk == bb->list[mid])
return mid;
if (blk < bb->list[mid])
high = mid;
else
low = mid;
}
return -1;
}
/*
* This procedure tests to see if a particular block is on a badblocks
* list.
*/
int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk)
{
if (ext2fs_u32_list_find(bb, blk) < 0)
return 0;
else
return 1;
}
int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
{
return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk);
}
/*
* Remove a block from the badblock list
*/
int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk)
{
int remloc, i;
if (bb->num == 0)
return -1;
remloc = ext2fs_u32_list_find(bb, blk);
if (remloc < 0)
return -1;
for (i = remloc ; i < bb->num-1; i++)
bb->list[i] = bb->list[i+1];
bb->num--;
return 0;
}
void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk)
{
ext2fs_u32_list_del(bb, blk);
}
errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
ext2_u32_iterate *ret)
{
ext2_u32_iterate iter;
errcode_t retval;
EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter);
if (retval)
return retval;
iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
iter->bb = bb;
iter->ptr = 0;
*ret = iter;
return 0;
}
errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
ext2_badblocks_iterate *ret)
{
return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb,
(ext2_u32_iterate *) ret);
}
int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk)
{
ext2_u32_list bb;
if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
return 0;
bb = iter->bb;
if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
return 0;
if (iter->ptr < bb->num) {
*blk = bb->list[iter->ptr++];
return 1;
}
*blk = 0;
return 0;
}
int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
{
return ext2fs_u32_list_iterate((ext2_u32_iterate) iter,
(__u32 *) blk);
}
void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter)
{
if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
return;
iter->bb = 0;
ext2fs_free_mem(&iter);
}
void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
{
ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter);
}
int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2)
{
EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST);
EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST);
if (bb1->num != bb2->num)
return 0;
if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0)
return 0;
return 1;
}
int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2)
{
return ext2fs_u32_list_equal((ext2_u32_list) bb1,
(ext2_u32_list) bb2);
}
int ext2fs_u32_list_count(ext2_u32_list bb)
{
return bb->num;
}

View File

@ -0,0 +1,64 @@
/*
* bb_compat.c --- compatibility badblocks routines
*
* Copyright (C) 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fsP.h"
errcode_t badblocks_list_create(badblocks_list *ret, int size)
{
return ext2fs_badblocks_list_create(ret, size);
}
void badblocks_list_free(badblocks_list bb)
{
ext2fs_badblocks_list_free(bb);
}
errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
{
return ext2fs_badblocks_list_add(bb, blk);
}
int badblocks_list_test(badblocks_list bb, blk_t blk)
{
return ext2fs_badblocks_list_test(bb, blk);
}
errcode_t badblocks_list_iterate_begin(badblocks_list bb,
badblocks_iterate *ret)
{
return ext2fs_badblocks_list_iterate_begin(bb, ret);
}
int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
{
return ext2fs_badblocks_list_iterate(iter, blk);
}
void badblocks_list_iterate_end(badblocks_iterate iter)
{
ext2fs_badblocks_list_iterate_end(iter);
}

View File

@ -0,0 +1,267 @@
/*
* bb_inode.c --- routines to update the bad block inode.
*
* WARNING: This routine modifies a lot of state in the filesystem; if
* this routine returns an error, the bad block inode may be in an
* inconsistent state.
*
* Copyright (C) 1994, 1995 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
struct set_badblock_record {
ext2_badblocks_iterate bb_iter;
int bad_block_count;
blk_t *ind_blocks;
int max_ind_blocks;
int ind_blocks_size;
int ind_blocks_ptr;
char *block_buf;
errcode_t err;
};
static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
e2_blkcnt_t blockcnt,
blk_t ref_block, int ref_offset,
void *priv_data);
static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
e2_blkcnt_t blockcnt,
blk_t ref_block, int ref_offset,
void *priv_data);
/*
* Given a bad blocks bitmap, update the bad blocks inode to reflect
* the map.
*/
errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
{
errcode_t retval;
struct set_badblock_record rec;
struct ext2_inode inode;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!fs->block_map)
return EXT2_ET_NO_BLOCK_BITMAP;
memset(&rec, 0, sizeof(rec));
rec.max_ind_blocks = 10;
retval = ext2fs_get_array(rec.max_ind_blocks, sizeof(blk_t),
&rec.ind_blocks);
if (retval)
return retval;
memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf);
if (retval)
goto cleanup;
memset(rec.block_buf, 0, fs->blocksize);
rec.err = 0;
/*
* First clear the old bad blocks (while saving the indirect blocks)
*/
retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
BLOCK_FLAG_DEPTH_TRAVERSE, 0,
clear_bad_block_proc, &rec);
if (retval)
goto cleanup;
if (rec.err) {
retval = rec.err;
goto cleanup;
}
/*
* Now set the bad blocks!
*
* First, mark the bad blocks as used. This prevents a bad
* block from being used as an indirecto block for the bad
* block inode (!).
*/
if (bb_list) {
retval = ext2fs_badblocks_list_iterate_begin(bb_list,
&rec.bb_iter);
if (retval)
goto cleanup;
retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
BLOCK_FLAG_APPEND, 0,
set_bad_block_proc, &rec);
ext2fs_badblocks_list_iterate_end(rec.bb_iter);
if (retval)
goto cleanup;
if (rec.err) {
retval = rec.err;
goto cleanup;
}
}
/*
* Update the bad block inode's mod time and block count
* field.
*/
retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
if (retval)
goto cleanup;
inode.i_atime = inode.i_mtime = fs->now ? fs->now : time(0);
if (!inode.i_ctime)
inode.i_ctime = fs->now ? fs->now : time(0);
ext2fs_iblk_set(fs, &inode, rec.bad_block_count);
inode.i_size = rec.bad_block_count * fs->blocksize;
retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode);
if (retval)
goto cleanup;
cleanup:
ext2fs_free_mem(&rec.ind_blocks);
ext2fs_free_mem(&rec.block_buf);
return retval;
}
/*
* Helper function for update_bb_inode()
*
* Clear the bad blocks in the bad block inode, while saving the
* indirect blocks.
*/
#ifdef __TURBOC__
#pragma argsused
#endif
static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
e2_blkcnt_t blockcnt,
blk_t ref_block EXT2FS_ATTR((unused)),
int ref_offset EXT2FS_ATTR((unused)),
void *priv_data)
{
struct set_badblock_record *rec = (struct set_badblock_record *)
priv_data;
errcode_t retval;
unsigned long old_size;
if (!*block_nr)
return 0;
/*
* If the block number is outrageous, clear it and ignore it.
*/
if (*block_nr >= ext2fs_blocks_count(fs->super) ||
*block_nr < fs->super->s_first_data_block) {
*block_nr = 0;
return BLOCK_CHANGED;
}
if (blockcnt < 0) {
if (rec->ind_blocks_size >= rec->max_ind_blocks) {
old_size = rec->max_ind_blocks * sizeof(blk_t);
rec->max_ind_blocks += 10;
retval = ext2fs_resize_mem(old_size,
rec->max_ind_blocks * sizeof(blk_t),
&rec->ind_blocks);
if (retval) {
rec->max_ind_blocks -= 10;
rec->err = retval;
return BLOCK_ABORT;
}
}
rec->ind_blocks[rec->ind_blocks_size++] = *block_nr;
}
/*
* Mark the block as unused, and update accounting information
*/
ext2fs_block_alloc_stats2(fs, *block_nr, -1);
*block_nr = 0;
return BLOCK_CHANGED;
}
/*
* Helper function for update_bb_inode()
*
* Set the block list in the bad block inode, using the supplied bitmap.
*/
#ifdef __TURBOC__
#pragma argsused
#endif
static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
e2_blkcnt_t blockcnt,
blk_t ref_block EXT2FS_ATTR((unused)),
int ref_offset EXT2FS_ATTR((unused)),
void *priv_data)
{
struct set_badblock_record *rec = (struct set_badblock_record *)
priv_data;
errcode_t retval;
blk_t blk;
if (blockcnt >= 0) {
/*
* Get the next bad block.
*/
if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
return BLOCK_ABORT;
rec->bad_block_count++;
} else {
/*
* An indirect block; fetch a block from the
* previously used indirect block list. The block
* most be not marked as used; if so, get another one.
* If we run out of reserved indirect blocks, allocate
* a new one.
*/
retry:
if (rec->ind_blocks_ptr < rec->ind_blocks_size) {
blk = rec->ind_blocks[rec->ind_blocks_ptr++];
if (ext2fs_test_block_bitmap2(fs->block_map, blk))
goto retry;
} else {
retval = ext2fs_new_block(fs, 0, 0, &blk);
if (retval) {
rec->err = retval;
return BLOCK_ABORT;
}
}
retval = io_channel_write_blk64(fs->io, blk, 1, rec->block_buf);
if (retval) {
rec->err = retval;
return BLOCK_ABORT;
}
}
/*
* Update block counts
*/
ext2fs_block_alloc_stats2(fs, blk, +1);
*block_nr = blk;
return BLOCK_CHANGED;
}

View File

@ -0,0 +1,57 @@
/*
bit_ops.h
Functions for dealing with conversion of data between types
Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _BIT_OPS_H
#define _BIT_OPS_H
#include <stdint.h>
/*-----------------------------------------------------------------
Functions to deal with little endian values stored in uint8_t arrays
-----------------------------------------------------------------*/
static inline uint16_t u8array_to_u16 (const uint8_t* item, int offset) {
return ( item[offset] | (item[offset + 1] << 8));
}
static inline uint32_t u8array_to_u32 (const uint8_t* item, int offset) {
return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24));
}
static inline void u16_to_u8array (uint8_t* item, int offset, uint16_t value) {
item[offset] = (uint8_t) value;
item[offset + 1] = (uint8_t)(value >> 8);
}
static inline void u32_to_u8array (uint8_t* item, int offset, uint32_t value) {
item[offset] = (uint8_t) value;
item[offset + 1] = (uint8_t)(value >> 8);
item[offset + 2] = (uint8_t)(value >> 16);
item[offset + 3] = (uint8_t)(value >> 24);
}
#endif // _BIT_OPS_H

View File

@ -0,0 +1,308 @@
/*
* bitmaps.c --- routines to read, write, and manipulate the inode and
* block bitmaps.
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#include "ext2fsP.h"
#include "bmap64.h"
void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap)
{
ext2fs_free_generic_bmap(bitmap);
}
void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap)
{
ext2fs_free_generic_bmap(bitmap);
}
errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
ext2fs_generic_bitmap *dest)
{
return (ext2fs_copy_generic_bmap(src, dest));
}
void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map)
{
ext2fs_set_generic_bmap_padding(map);
}
errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
const char *descr,
ext2fs_inode_bitmap *ret)
{
__u64 start, end, real_end;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
fs->write_bitmaps = ext2fs_write_bitmaps;
start = 1;
end = fs->super->s_inodes_count;
real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count);
/* Are we permitted to use new-style bitmaps? */
if (fs->flags & EXT2_FLAG_64BITS)
return (ext2fs_alloc_generic_bmap(fs,
EXT2_ET_MAGIC_INODE_BITMAP64,
EXT2FS_BMAP64_BITARRAY,
start, end, real_end, descr, ret));
/* Otherwise, check to see if the file system is small enough
* to use old-style 32-bit bitmaps */
if ((end > ~0U) || (real_end > ~0U))
return EXT2_ET_CANT_USE_LEGACY_BITMAPS;
return (ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_INODE_BITMAP, fs,
start, end, real_end,
descr, 0,
(ext2fs_generic_bitmap *) ret));
}
errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
const char *descr,
ext2fs_block_bitmap *ret)
{
__u64 start, end, real_end;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
fs->write_bitmaps = ext2fs_write_bitmaps;
start = EXT2FS_B2C(fs, fs->super->s_first_data_block);
end = EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1);
real_end = ((__u64) EXT2_CLUSTERS_PER_GROUP(fs->super)
* (__u64) fs->group_desc_count)-1 + start;
if (fs->flags & EXT2_FLAG_64BITS)
return (ext2fs_alloc_generic_bmap(fs,
EXT2_ET_MAGIC_BLOCK_BITMAP64,
EXT2FS_BMAP64_BITARRAY,
start, end, real_end, descr, ret));
if ((end > ~0U) || (real_end > ~0U))
return EXT2_ET_CANT_USE_LEGACY_BITMAPS;
return (ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, fs,
start, end, real_end,
descr, 0,
(ext2fs_generic_bitmap *) ret));
}
/*
* ext2fs_allocate_block_bitmap() really allocates a per-cluster
* bitmap for backwards compatibility. This function allocates a
* block bitmap which is truly per-block, even if clusters/bigalloc
* are enabled. mke2fs and e2fsck need this for tracking the
* allocation of the file system metadata blocks.
*/
errcode_t ext2fs_allocate_subcluster_bitmap(ext2_filsys fs,
const char *descr,
ext2fs_block_bitmap *ret)
{
__u64 start, end, real_end;
ext2fs_generic_bitmap bmap;
errcode_t retval;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
fs->write_bitmaps = ext2fs_write_bitmaps;
if (!fs->cluster_ratio_bits)
return ext2fs_allocate_block_bitmap(fs, descr, ret);
if ((fs->flags & EXT2_FLAG_64BITS) == 0)
return EXT2_ET_CANT_USE_LEGACY_BITMAPS;
start = fs->super->s_first_data_block;
end = ext2fs_blocks_count(fs->super)-1;
real_end = ((__u64) EXT2_BLOCKS_PER_GROUP(fs->super)
* (__u64) fs->group_desc_count)-1 + start;
retval = ext2fs_alloc_generic_bmap(fs, EXT2_ET_MAGIC_BLOCK_BITMAP64,
EXT2FS_BMAP64_BITARRAY, start,
end, real_end, descr, &bmap);
if (retval)
return retval;
bmap->cluster_bits = 0;
*ret = bmap;
return 0;
}
int ext2fs_get_bitmap_granularity(ext2fs_block_bitmap bitmap)
{
ext2fs_generic_bitmap bmap = bitmap;
if (!EXT2FS_IS_64_BITMAP(bmap))
return 0;
return bmap->cluster_bits;
}
errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
ext2_ino_t end, ext2_ino_t *oend)
{
__u64 tmp_oend;
int retval;
retval = ext2fs_fudge_generic_bmap_end((ext2fs_generic_bitmap) bitmap,
EXT2_ET_FUDGE_INODE_BITMAP_END,
end, &tmp_oend);
if (oend)
*oend = tmp_oend;
return retval;
}
errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
blk_t end, blk_t *oend)
{
return (ext2fs_fudge_generic_bitmap_end(bitmap,
EXT2_ET_MAGIC_BLOCK_BITMAP,
EXT2_ET_FUDGE_BLOCK_BITMAP_END,
end, oend));
}
errcode_t ext2fs_fudge_block_bitmap_end2(ext2fs_block_bitmap bitmap,
blk64_t end, blk64_t *oend)
{
return (ext2fs_fudge_generic_bmap_end(bitmap,
EXT2_ET_FUDGE_BLOCK_BITMAP_END,
end, oend));
}
void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap)
{
ext2fs_clear_generic_bmap(bitmap);
}
void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
{
ext2fs_clear_generic_bmap(bitmap);
}
errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
ext2fs_inode_bitmap bmap)
{
return (ext2fs_resize_generic_bitmap(EXT2_ET_MAGIC_INODE_BITMAP,
new_end, new_real_end, bmap));
}
errcode_t ext2fs_resize_inode_bitmap2(__u64 new_end, __u64 new_real_end,
ext2fs_inode_bitmap bmap)
{
return (ext2fs_resize_generic_bmap(bmap, new_end, new_real_end));
}
errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
ext2fs_block_bitmap bmap)
{
return (ext2fs_resize_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP,
new_end, new_real_end, bmap));
}
errcode_t ext2fs_resize_block_bitmap2(__u64 new_end, __u64 new_real_end,
ext2fs_block_bitmap bmap)
{
return (ext2fs_resize_generic_bmap(bmap, new_end, new_real_end));
}
errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
ext2fs_block_bitmap bm2)
{
return (ext2fs_compare_generic_bmap(EXT2_ET_NEQ_BLOCK_BITMAP,
bm1, bm2));
}
errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
ext2fs_inode_bitmap bm2)
{
return (ext2fs_compare_generic_bmap(EXT2_ET_NEQ_INODE_BITMAP,
bm1, bm2));
}
errcode_t ext2fs_set_inode_bitmap_range(ext2fs_inode_bitmap bmap,
ext2_ino_t start, unsigned int num,
void *in)
{
return (ext2fs_set_generic_bitmap_range(bmap,
EXT2_ET_MAGIC_INODE_BITMAP,
start, num, in));
}
errcode_t ext2fs_set_inode_bitmap_range2(ext2fs_inode_bitmap bmap,
__u64 start, size_t num,
void *in)
{
return (ext2fs_set_generic_bmap_range(bmap, start, num, in));
}
errcode_t ext2fs_get_inode_bitmap_range(ext2fs_inode_bitmap bmap,
ext2_ino_t start, unsigned int num,
void *out)
{
return (ext2fs_get_generic_bitmap_range(bmap,
EXT2_ET_MAGIC_INODE_BITMAP,
start, num, out));
}
errcode_t ext2fs_get_inode_bitmap_range2(ext2fs_inode_bitmap bmap,
__u64 start, size_t num,
void *out)
{
return (ext2fs_get_generic_bmap_range(bmap, start, num, out));
}
errcode_t ext2fs_set_block_bitmap_range(ext2fs_block_bitmap bmap,
blk_t start, unsigned int num,
void *in)
{
return (ext2fs_set_generic_bitmap_range(bmap,
EXT2_ET_MAGIC_BLOCK_BITMAP,
start, num, in));
}
errcode_t ext2fs_set_block_bitmap_range2(ext2fs_block_bitmap bmap,
blk64_t start, size_t num,
void *in)
{
return (ext2fs_set_generic_bmap_range(bmap, start, num, in));
}
errcode_t ext2fs_get_block_bitmap_range(ext2fs_block_bitmap bmap,
blk_t start, unsigned int num,
void *out)
{
return (ext2fs_get_generic_bitmap_range(bmap,
EXT2_ET_MAGIC_BLOCK_BITMAP,
start, num, out));
}
errcode_t ext2fs_get_block_bitmap_range2(ext2fs_block_bitmap bmap,
blk64_t start, size_t num,
void *out)
{
return (ext2fs_get_generic_bmap_range(bmap, start, num, out));
}

View File

@ -0,0 +1,118 @@
/*
* bitops.c --- Bitmap frobbing code. See bitops.h for the inlined
* routines.
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#ifndef _EXT2_HAVE_ASM_BITOPS_
/*
* For the benefit of those who are trying to port Linux to another
* architecture, here are some C-language equivalents. You should
* recode these in the native assmebly language, if at all possible.
*
* C language equivalents written by Theodore Ts'o, 9/26/92.
* Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian
* systems, as well as non-32 bit systems.
*/
int ext2fs_set_bit(unsigned int nr,void * addr)
{
int mask, retval;
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
mask = 1 << (nr & 0x07);
retval = mask & *ADDR;
*ADDR |= mask;
return retval;
}
int ext2fs_clear_bit(unsigned int nr, void * addr)
{
int mask, retval;
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
mask = 1 << (nr & 0x07);
retval = mask & *ADDR;
*ADDR &= ~mask;
return retval;
}
int ext2fs_test_bit(unsigned int nr, const void * addr)
{
int mask;
const unsigned char *ADDR = (const unsigned char *) addr;
ADDR += nr >> 3;
mask = 1 << (nr & 0x07);
return (mask & *ADDR);
}
#endif /* !_EXT2_HAVE_ASM_BITOPS_ */
void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
const char *description)
{
#ifndef OMIT_COM_ERR
if (description)
com_err(0, errcode, "#%lu for %s", arg, description);
else
com_err(0, errcode, "#%lu", arg);
#endif
}
/*
* C-only 64 bit ops.
*/
int ext2fs_set_bit64(__u64 nr, void * addr)
{
int mask, retval;
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
mask = 1 << (nr & 0x07);
retval = mask & *ADDR;
*ADDR |= mask;
return retval;
}
int ext2fs_clear_bit64(__u64 nr, void * addr)
{
int mask, retval;
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
mask = 1 << (nr & 0x07);
retval = mask & *ADDR;
*ADDR &= ~mask;
return retval;
}
int ext2fs_test_bit64(__u64 nr, const void * addr)
{
int mask;
const unsigned char *ADDR = (const unsigned char *) addr;
ADDR += nr >> 3;
mask = 1 << (nr & 0x07);
return (mask & *ADDR);
}

View File

@ -0,0 +1,643 @@
/*
* bitops.h --- Bitmap frobbing code. The byte swapping routines are
* also included here.
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#ifndef _BITOPS_H_
#define _BITOPS_H_
#include "config.h"
extern int ext2fs_set_bit(unsigned int nr,void * addr);
extern int ext2fs_clear_bit(unsigned int nr, void * addr);
extern int ext2fs_test_bit(unsigned int nr, const void * addr);
extern void ext2fs_fast_set_bit(unsigned int nr,void * addr);
extern void ext2fs_fast_clear_bit(unsigned int nr, void * addr);
extern int ext2fs_set_bit64(__u64 nr,void * addr);
extern int ext2fs_clear_bit64(__u64 nr, void * addr);
extern int ext2fs_test_bit64(__u64 nr, const void * addr);
extern void ext2fs_fast_set_bit64(__u64 nr,void * addr);
extern void ext2fs_fast_clear_bit64(__u64 nr, void * addr);
extern __u16 ext2fs_swab16(__u16 val);
extern __u32 ext2fs_swab32(__u32 val);
extern __u64 ext2fs_swab64(__u64 val);
#ifdef WORDS_BIGENDIAN
#define ext2fs_cpu_to_le64(x) ext2fs_swab64((x))
#define ext2fs_le64_to_cpu(x) ext2fs_swab64((x))
#define ext2fs_cpu_to_le32(x) ext2fs_swab32((x))
#define ext2fs_le32_to_cpu(x) ext2fs_swab32((x))
#define ext2fs_cpu_to_le16(x) ext2fs_swab16((x))
#define ext2fs_le16_to_cpu(x) ext2fs_swab16((x))
#define ext2fs_cpu_to_be64(x) ((__u64)(x))
#define ext2fs_be64_to_cpu(x) ((__u64)(x))
#define ext2fs_cpu_to_be32(x) ((__u32)(x))
#define ext2fs_be32_to_cpu(x) ((__u32)(x))
#define ext2fs_cpu_to_be16(x) ((__u16)(x))
#define ext2fs_be16_to_cpu(x) ((__u16)(x))
#else
#define ext2fs_cpu_to_le64(x) ((__u64)(x))
#define ext2fs_le64_to_cpu(x) ((__u64)(x))
#define ext2fs_cpu_to_le32(x) ((__u32)(x))
#define ext2fs_le32_to_cpu(x) ((__u32)(x))
#define ext2fs_cpu_to_le16(x) ((__u16)(x))
#define ext2fs_le16_to_cpu(x) ((__u16)(x))
#define ext2fs_cpu_to_be64(x) ext2fs_swab64((x))
#define ext2fs_be64_to_cpu(x) ext2fs_swab64((x))
#define ext2fs_cpu_to_be32(x) ext2fs_swab32((x))
#define ext2fs_be32_to_cpu(x) ext2fs_swab32((x))
#define ext2fs_cpu_to_be16(x) ext2fs_swab16((x))
#define ext2fs_be16_to_cpu(x) ext2fs_swab16((x))
#endif
/*
* EXT2FS bitmap manipulation routines.
*/
/* Support for sending warning messages from the inline subroutines */
extern const char *ext2fs_block_string;
extern const char *ext2fs_inode_string;
extern const char *ext2fs_mark_string;
extern const char *ext2fs_unmark_string;
extern const char *ext2fs_test_string;
extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
const char *description);
extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
int code, unsigned long arg);
extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block);
extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block);
extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block);
extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block);
extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap,
ino_t inode, int num);
extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
/* These routines moved to gen_bitmap.c (actually, some of the above, too) */
extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
__u32 bitno);
extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
blk_t bitno);
extern int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
blk_t bitno);
extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern __u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap);
extern __u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap);
/* 64-bit versions */
extern int ext2fs_mark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block);
extern int ext2fs_unmark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block);
extern int ext2fs_test_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block);
extern int ext2fs_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern int ext2fs_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern int ext2fs_test_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern void ext2fs_fast_mark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block);
extern void ext2fs_fast_unmark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block);
extern int ext2fs_fast_test_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block);
extern void ext2fs_fast_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern void ext2fs_fast_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern int ext2fs_fast_test_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern blk64_t ext2fs_get_block_bitmap_start2(ext2fs_block_bitmap bitmap);
extern ext2_ino_t ext2fs_get_inode_bitmap_start2(ext2fs_inode_bitmap bitmap);
extern blk64_t ext2fs_get_block_bitmap_end2(ext2fs_block_bitmap bitmap);
extern ext2_ino_t ext2fs_get_inode_bitmap_end2(ext2fs_inode_bitmap bitmap);
extern int ext2fs_fast_test_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block,
unsigned int num);
extern void ext2fs_fast_mark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block,
unsigned int num);
extern void ext2fs_fast_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block,
unsigned int num);
/* These routines moved to gen_bitmap64.c */
extern void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap);
extern errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
ext2fs_generic_bitmap bm1,
ext2fs_generic_bitmap bm2);
extern void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap);
extern int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap,
blk64_t bitno);
extern int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap,
blk64_t bitno);
extern int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap,
blk64_t bitno);
extern int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block, unsigned int num);
extern __u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap);
extern __u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap);
extern int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block, unsigned int num);
extern void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block, unsigned int num);
extern void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block, unsigned int num);
/*
* The inline routines themselves...
*
* If NO_INLINE_FUNCS is defined, then we won't try to do inline
* functions at all; they will be included as normal functions in
* inline.c
*/
#ifdef NO_INLINE_FUNCS
#if (defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || \
defined(__i586__) || defined(__mc68000__)))
/* This prevents bitops.c from trying to include the C */
/* function version of these functions */
#define _EXT2_HAVE_ASM_BITOPS_
#endif
#endif /* NO_INLINE_FUNCS */
#if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
#ifdef INCLUDE_INLINE_FUNCS
#define _INLINE_ extern
#else
#ifdef __GNUC__
#define _INLINE_ extern __inline__
#else /* For Watcom C */
#define _INLINE_ extern inline
#endif
#endif
/*
* Fast bit set/clear functions that doesn't need to return the
* previous bit value.
*/
_INLINE_ void ext2fs_fast_set_bit(unsigned int nr,void * addr)
{
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
*ADDR |= (1 << (nr & 0x07));
}
_INLINE_ void ext2fs_fast_clear_bit(unsigned int nr, void * addr)
{
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
*ADDR &= ~(1 << (nr & 0x07));
}
_INLINE_ void ext2fs_fast_set_bit64(__u64 nr, void * addr)
{
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
*ADDR |= (1 << (nr & 0x07));
}
_INLINE_ void ext2fs_fast_clear_bit64(__u64 nr, void * addr)
{
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
*ADDR &= ~(1 << (nr & 0x07));
}
#if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
(defined(__i386__) || defined(__i486__) || defined(__i586__)))
#define _EXT2_HAVE_ASM_BITOPS_
#define _EXT2_HAVE_ASM_SWAB_
/*
* These are done by inline assembly for speed reasons.....
*
* All bitoperations return 0 if the bit was cleared before the
* operation and != 0 if it was not. Bit 0 is the LSB of addr; bit 32
* is the LSB of (addr+1).
*/
/*
* Some hacks to defeat gcc over-optimizations..
*/
struct __dummy_h { unsigned long a[100]; };
#define EXT2FS_ADDR (*(struct __dummy_h *) addr)
#define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr)
_INLINE_ int ext2fs_set_bit(unsigned int nr, void * addr)
{
int oldbit;
addr = (void *) (((unsigned char *) addr) + (nr >> 3));
__asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"+m" (EXT2FS_ADDR)
:"r" (nr & 7));
return oldbit;
}
_INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr)
{
int oldbit;
addr = (void *) (((unsigned char *) addr) + (nr >> 3));
__asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"+m" (EXT2FS_ADDR)
:"r" (nr & 7));
return oldbit;
}
_INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr)
{
int oldbit;
addr = (const void *) (((const unsigned char *) addr) + (nr >> 3));
__asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit)
:"m" (EXT2FS_CONST_ADDR),"r" (nr & 7));
return oldbit;
}
_INLINE_ __u32 ext2fs_swab32(__u32 val)
{
#ifdef EXT2FS_REQUIRE_486
__asm__("bswap %0" : "=r" (val) : "0" (val));
#else
__asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
"rorl $16,%0\n\t" /* swap words */
"xchgb %b0,%h0" /* swap higher bytes */
:"=q" (val)
: "0" (val));
#endif
return val;
}
_INLINE_ __u16 ext2fs_swab16(__u16 val)
{
__asm__("xchgb %b0,%h0" /* swap bytes */ \
: "=q" (val) \
: "0" (val)); \
return val;
}
#undef EXT2FS_ADDR
#endif /* i386 */
#if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
(defined(__mc68000__)))
#define _EXT2_HAVE_ASM_BITOPS_
_INLINE_ int ext2fs_set_bit(unsigned int nr,void * addr)
{
char retval;
__asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
: "=d" (retval) : "d" (nr^7), "a" (addr));
return retval;
}
_INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr)
{
char retval;
__asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
: "=d" (retval) : "d" (nr^7), "a" (addr));
return retval;
}
_INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr)
{
char retval;
__asm__ __volatile__ ("bftst %2@{%1:#1}; sne %0"
: "=d" (retval) : "d" (nr^7), "a" (addr));
return retval;
}
#endif /* __mc68000__ */
#if !defined(_EXT2_HAVE_ASM_SWAB_)
_INLINE_ __u16 ext2fs_swab16(__u16 val)
{
return (val >> 8) | (val << 8);
}
_INLINE_ __u32 ext2fs_swab32(__u32 val)
{
return ((val>>24) | ((val>>8)&0xFF00) |
((val<<8)&0xFF0000) | (val<<24));
}
#endif /* !_EXT2_HAVE_ASM_SWAB */
_INLINE_ __u64 ext2fs_swab64(__u64 val)
{
return (ext2fs_swab32(val >> 32) |
(((__u64)ext2fs_swab32(val & 0xFFFFFFFFUL)) << 32));
}
_INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
}
_INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
}
_INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
}
_INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
}
_INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
{
return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
{
return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
{
return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
{
return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
return ext2fs_test_block_bitmap_range(bitmap, block, num);
}
_INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
ext2fs_mark_block_bitmap_range(bitmap, block, num);
}
_INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
ext2fs_unmark_block_bitmap_range(bitmap, block, num);
}
/* 64-bit versions */
_INLINE_ int ext2fs_mark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block)
{
return ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ int ext2fs_unmark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block)
{
return ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap, block);
}
_INLINE_ int ext2fs_test_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block)
{
return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ int ext2fs_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ int ext2fs_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ int ext2fs_test_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ void ext2fs_fast_mark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block)
{
ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap, block);
}
_INLINE_ void ext2fs_fast_unmark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block)
{
ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap, block);
}
_INLINE_ int ext2fs_fast_test_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block)
{
return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ void ext2fs_fast_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap, inode);
}
_INLINE_ void ext2fs_fast_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap, inode);
}
_INLINE_ int ext2fs_fast_test_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ blk64_t ext2fs_get_block_bitmap_start2(ext2fs_block_bitmap bitmap)
{
return ext2fs_get_generic_bmap_start((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start2(ext2fs_inode_bitmap bitmap)
{
return ext2fs_get_generic_bmap_start((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ blk64_t ext2fs_get_block_bitmap_end2(ext2fs_block_bitmap bitmap)
{
return ext2fs_get_generic_bmap_end((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end2(ext2fs_inode_bitmap bitmap)
{
return ext2fs_get_generic_bmap_end((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ int ext2fs_fast_test_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block,
unsigned int num)
{
return ext2fs_test_block_bitmap_range2(bitmap, block, num);
}
_INLINE_ void ext2fs_fast_mark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block,
unsigned int num)
{
ext2fs_mark_block_bitmap_range2(bitmap, block, num);
}
_INLINE_ void ext2fs_fast_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block,
unsigned int num)
{
ext2fs_unmark_block_bitmap_range2(bitmap, block, num);
}
#undef _INLINE_
#endif
#endif

View File

@ -0,0 +1,328 @@
/*
* blkmap64_ba.c --- Simple bitarray implementation for bitmaps
*
* Copyright (C) 2008 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fsP.h"
#include "bmap64.h"
/*
* Private data for bit array implementation of bitmap ops.
* Currently, this is just a pointer to our big flat hunk of memory,
* exactly equivalent to the old-skool char * bitmap member.
*/
struct ext2fs_ba_private_struct {
char *bitarray;
};
typedef struct ext2fs_ba_private_struct *ext2fs_ba_private;
static errcode_t ba_alloc_private_data (ext2fs_generic_bitmap bitmap)
{
ext2fs_ba_private bp;
errcode_t retval;
size_t size;
/*
* Since we only have the one pointer, we could just shove our
* private data in the void *private field itself, but then
* we'd have to do a fair bit of rewriting if we ever added a
* field. I'm agnostic.
*/
retval = ext2fs_get_mem(sizeof (ext2fs_ba_private), &bp);
if (retval)
return retval;
size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
retval = ext2fs_get_mem(size, &bp->bitarray);
if (retval) {
ext2fs_free_mem(&bp);
bp = 0;
return retval;
}
bitmap->private = (void *) bp;
return 0;
}
static errcode_t ba_new_bmap(ext2_filsys fs EXT2FS_ATTR((unused)),
ext2fs_generic_bitmap bitmap)
{
ext2fs_ba_private bp;
errcode_t retval;
size_t size;
retval = ba_alloc_private_data (bitmap);
if (retval)
return retval;
bp = (ext2fs_ba_private) bitmap->private;
size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
memset(bp->bitarray, 0, size);
return 0;
}
static void ba_free_bmap(ext2fs_generic_bitmap bitmap)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
if (!bp)
return;
if (bp->bitarray) {
ext2fs_free_mem (&bp->bitarray);
bp->bitarray = 0;
}
ext2fs_free_mem (&bp);
bp = 0;
}
static errcode_t ba_copy_bmap(ext2fs_generic_bitmap src,
ext2fs_generic_bitmap dest)
{
ext2fs_ba_private src_bp = (ext2fs_ba_private) src->private;
ext2fs_ba_private dest_bp;
errcode_t retval;
size_t size;
retval = ba_alloc_private_data (dest);
if (retval)
return retval;
dest_bp = (ext2fs_ba_private) dest->private;
size = (size_t) (((src->real_end - src->start) / 8) + 1);
memcpy (dest_bp->bitarray, src_bp->bitarray, size);
return 0;
}
static errcode_t ba_resize_bmap(ext2fs_generic_bitmap bmap,
__u64 new_end, __u64 new_real_end)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bmap->private;
errcode_t retval;
size_t size, new_size;
__u64 bitno;
/*
* If we're expanding the bitmap, make sure all of the new
* parts of the bitmap are zero.
*/
if (new_end > bmap->end) {
bitno = bmap->real_end;
if (bitno > new_end)
bitno = new_end;
for (; bitno > bmap->end; bitno--)
ext2fs_clear_bit64(bitno - bmap->start, bp->bitarray);
}
if (new_real_end == bmap->real_end) {
bmap->end = new_end;
return 0;
}
size = ((bmap->real_end - bmap->start) / 8) + 1;
new_size = ((new_real_end - bmap->start) / 8) + 1;
if (size != new_size) {
retval = ext2fs_resize_mem(size, new_size, &bp->bitarray);
if (retval)
return retval;
}
if (new_size > size)
memset(bp->bitarray + size, 0, new_size - size);
bmap->end = new_end;
bmap->real_end = new_real_end;
return 0;
}
static int ba_mark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
blk64_t bitno = (blk64_t) arg;
return ext2fs_set_bit64(bitno - bitmap->start, bp->bitarray);
}
static int ba_unmark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
blk64_t bitno = (blk64_t) arg;
return ext2fs_clear_bit64(bitno - bitmap->start, bp->bitarray);
}
static int ba_test_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
blk64_t bitno = (blk64_t) arg;
return ext2fs_test_bit64(bitno - bitmap->start, bp->bitarray);
}
static void ba_mark_bmap_extent(ext2fs_generic_bitmap bitmap, __u64 arg,
unsigned int num)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
blk64_t bitno = (blk64_t) arg;
unsigned int i;
for (i = 0; i < num; i++)
ext2fs_fast_set_bit64(bitno + i - bitmap->start, bp->bitarray);
}
static void ba_unmark_bmap_extent(ext2fs_generic_bitmap bitmap, __u64 arg,
unsigned int num)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
blk64_t bitno = (blk64_t) arg;
unsigned int i;
for (i = 0; i < num; i++)
ext2fs_fast_clear_bit64(bitno + i - bitmap->start, bp->bitarray);
}
static int ba_test_clear_bmap_extent(ext2fs_generic_bitmap bitmap,
__u64 start, unsigned int len)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
__u64 start_byte, len_byte = len >> 3;
unsigned int start_bit, len_bit = len % 8;
unsigned int first_bit = 0;
unsigned int last_bit = 0;
int mark_count = 0;
int mark_bit = 0;
int i;
const char *ADDR;
ADDR = bp->bitarray;
start -= bitmap->start;
start_byte = start >> 3;
start_bit = start % 8;
if (start_bit != 0) {
/*
* The compared start block number or start inode number
* is not the first bit in a byte.
*/
mark_count = 8 - start_bit;
if (len < 8 - start_bit) {
mark_count = (int)len;
mark_bit = len + start_bit - 1;
} else
mark_bit = 7;
for (i = mark_count; i > 0; i--, mark_bit--)
first_bit |= 1 << mark_bit;
/*
* Compare blocks or inodes in the first byte.
* If there is any marked bit, this function returns 0.
*/
if (first_bit & ADDR[start_byte])
return 0;
else if (len <= 8 - start_bit)
return 1;
start_byte++;
len_bit = (len - mark_count) % 8;
len_byte = (len - mark_count) >> 3;
}
/*
* The compared start block number or start inode number is
* the first bit in a byte.
*/
if (len_bit != 0) {
/*
* The compared end block number or end inode number is
* not the last bit in a byte.
*/
for (mark_bit = len_bit - 1; mark_bit >= 0; mark_bit--)
last_bit |= 1 << mark_bit;
/*
* Compare blocks or inodes in the last byte.
* If there is any marked bit, this function returns 0.
*/
if (last_bit & ADDR[start_byte + len_byte])
return 0;
else if (len_byte == 0)
return 1;
}
/* Check whether all bytes are 0 */
return ext2fs_mem_is_zero(ADDR + start_byte, len_byte);
}
static errcode_t ba_set_bmap_range(ext2fs_generic_bitmap bitmap,
__u64 start, size_t num, void *in)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
memcpy (bp->bitarray + (start >> 3), in, (num + 7) >> 3);
return 0;
}
static errcode_t ba_get_bmap_range(ext2fs_generic_bitmap bitmap,
__u64 start, size_t num, void *out)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
memcpy (out, bp->bitarray + (start >> 3), (num + 7) >> 3);
return 0;
}
static void ba_clear_bmap(ext2fs_generic_bitmap bitmap)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
memset(bp->bitarray, 0,
(size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
}
struct ext2_bitmap_ops ext2fs_blkmap64_bitarray = {
.type = EXT2FS_BMAP64_BITARRAY,
.new_bmap = ba_new_bmap,
.free_bmap = ba_free_bmap,
.copy_bmap = ba_copy_bmap,
.resize_bmap = ba_resize_bmap,
.mark_bmap = ba_mark_bmap,
.unmark_bmap = ba_unmark_bmap,
.test_bmap = ba_test_bmap,
.test_clear_bmap_extent = ba_test_clear_bmap_extent,
.mark_bmap_extent = ba_mark_bmap_extent,
.unmark_bmap_extent = ba_unmark_bmap_extent,
.set_bmap_range = ba_set_bmap_range,
.get_bmap_range = ba_get_bmap_range,
.clear_bmap = ba_clear_bmap,
};

View File

@ -0,0 +1,498 @@
/*
* blknum.c --- Functions to handle blk64_t and high/low 64-bit block
* number.
*
* Copyright IBM Corporation, 2007
* Author Jose R. Santos <jrs@us.ibm.com>
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include "config.h"
#include "ext2fs.h"
/*
* Return the group # of a block
*/
dgrp_t ext2fs_group_of_blk2(ext2_filsys fs, blk64_t blk)
{
return (blk - fs->super->s_first_data_block) /
fs->super->s_blocks_per_group;
}
/*
* Return the first block (inclusive) in a group
*/
blk64_t ext2fs_group_first_block2(ext2_filsys fs, dgrp_t group)
{
return fs->super->s_first_data_block +
((blk64_t)group * fs->super->s_blocks_per_group);
}
/*
* Return the last block (inclusive) in a group
*/
blk64_t ext2fs_group_last_block2(ext2_filsys fs, dgrp_t group)
{
return (group == fs->group_desc_count - 1 ?
ext2fs_blocks_count(fs->super) - 1 :
ext2fs_group_first_block2(fs, group) +
(fs->super->s_blocks_per_group - 1));
}
/*
* Return the number of blocks in a group
*/
int ext2fs_group_blocks_count(ext2_filsys fs, dgrp_t group)
{
int num_blocks;
if (group == fs->group_desc_count - 1) {
num_blocks = (ext2fs_blocks_count(fs->super) -
fs->super->s_first_data_block) %
fs->super->s_blocks_per_group;
if (!num_blocks)
num_blocks = fs->super->s_blocks_per_group;
} else
num_blocks = fs->super->s_blocks_per_group;
return num_blocks;
}
/*
* Return the inode data block count
*/
blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs,
struct ext2_inode *inode)
{
return (inode->i_blocks |
((fs->super->s_feature_ro_compat &
EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ?
(__u64) inode->osd2.linux2.l_i_blocks_hi << 32 : 0)) -
(inode->i_file_acl ? fs->blocksize >> 9 : 0);
}
/*
* Return the inode i_blocks count
*/
blk64_t ext2fs_inode_i_blocks(ext2_filsys fs,
struct ext2_inode *inode)
{
return (inode->i_blocks |
((fs->super->s_feature_ro_compat &
EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ?
(__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0));
}
/*
* Return the fs block count
*/
blk64_t ext2fs_blocks_count(struct ext2_super_block *super)
{
return super->s_blocks_count |
(super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
(__u64) super->s_blocks_count_hi << 32 : 0);
}
/*
* Set the fs block count
*/
void ext2fs_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
{
super->s_blocks_count = blk;
if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
super->s_blocks_count_hi = (__u64) blk >> 32;
}
/*
* Add to the current fs block count
*/
void ext2fs_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
{
blk64_t tmp;
tmp = ext2fs_blocks_count(super) + blk;
ext2fs_blocks_count_set(super, tmp);
}
/*
* Return the fs reserved block count
*/
blk64_t ext2fs_r_blocks_count(struct ext2_super_block *super)
{
return super->s_r_blocks_count |
(super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
(__u64) super->s_r_blocks_count_hi << 32 : 0);
}
/*
* Set the fs reserved block count
*/
void ext2fs_r_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
{
super->s_r_blocks_count = blk;
if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
super->s_r_blocks_count_hi = (__u64) blk >> 32;
}
/*
* Add to the current reserved fs block count
*/
void ext2fs_r_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
{
blk64_t tmp;
tmp = ext2fs_r_blocks_count(super) + blk;
ext2fs_r_blocks_count_set(super, tmp);
}
/*
* Return the fs free block count
*/
blk64_t ext2fs_free_blocks_count(struct ext2_super_block *super)
{
return super->s_free_blocks_count |
(super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
(__u64) super->s_free_blocks_hi << 32 : 0);
}
/*
* Set the fs free block count
*/
void ext2fs_free_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
{
super->s_free_blocks_count = blk;
if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
super->s_free_blocks_hi = (__u64) blk >> 32;
}
/*
* Add to the current free fs block count
*/
void ext2fs_free_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
{
blk64_t tmp;
tmp = ext2fs_free_blocks_count(super) + blk;
ext2fs_free_blocks_count_set(super, tmp);
}
/*
* Get a pointer to a block group descriptor. We need the explicit
* pointer to the group desc for code that swaps block group
* descriptors before writing them out, as it wants to make a copy and
* do the swap there.
*/
struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs,
struct opaque_ext2_group_desc *gdp,
dgrp_t group)
{
if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT)
return (struct ext2_group_desc *)
((struct ext4_group_desc *) gdp + group);
else
return (struct ext2_group_desc *) gdp + group;
}
/* Do the same but as an ext4 group desc for internal use here */
static struct ext4_group_desc *ext4fs_group_desc(ext2_filsys fs,
struct opaque_ext2_group_desc *gdp,
dgrp_t group)
{
return (struct ext4_group_desc *)ext2fs_group_desc(fs, gdp, group);
}
/*
* Return the block bitmap block of a group
*/
blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_block_bitmap |
(fs->super->s_feature_incompat
& EXT4_FEATURE_INCOMPAT_64BIT ?
(__u64)gdp->bg_block_bitmap_hi << 32 : 0);
}
/*
* Set the block bitmap block of a group
*/
void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_block_bitmap = blk;
if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
gdp->bg_block_bitmap_hi = (__u64) blk >> 32;
}
/*
* Return the inode bitmap block of a group
*/
blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_inode_bitmap |
(fs->super->s_feature_incompat
& EXT4_FEATURE_INCOMPAT_64BIT ?
(__u64) gdp->bg_inode_bitmap_hi << 32 : 0);
}
/*
* Set the inode bitmap block of a group
*/
void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_inode_bitmap = blk;
if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
gdp->bg_inode_bitmap_hi = (__u64) blk >> 32;
}
/*
* Return the inode table block of a group
*/
blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_inode_table |
(fs->super->s_feature_incompat
& EXT4_FEATURE_INCOMPAT_64BIT ?
(__u64) gdp->bg_inode_table_hi << 32 : 0);
}
/*
* Set the inode table block of a group
*/
void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_inode_table = blk;
if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
gdp->bg_inode_table_hi = (__u64) blk >> 32;
}
/*
* Return the free blocks count of a group
*/
__u32 ext2fs_bg_free_blocks_count(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_free_blocks_count |
(fs->super->s_feature_incompat
& EXT4_FEATURE_INCOMPAT_64BIT ?
(__u32) gdp->bg_free_blocks_count_hi << 16 : 0);
}
/*
* Set the free blocks count of a group
*/
void ext2fs_bg_free_blocks_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_free_blocks_count = n;
if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
gdp->bg_free_blocks_count_hi = (__u32) n >> 16;
}
/*
* Return the free inodes count of a group
*/
__u32 ext2fs_bg_free_inodes_count(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_free_inodes_count |
(fs->super->s_feature_incompat
& EXT4_FEATURE_INCOMPAT_64BIT ?
(__u32) gdp->bg_free_inodes_count_hi << 16 : 0);
}
/*
* Set the free inodes count of a group
*/
void ext2fs_bg_free_inodes_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_free_inodes_count = n;
if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
gdp->bg_free_inodes_count_hi = (__u32) n >> 16;
}
/*
* Return the used dirs count of a group
*/
__u32 ext2fs_bg_used_dirs_count(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_used_dirs_count |
(fs->super->s_feature_incompat
& EXT4_FEATURE_INCOMPAT_64BIT ?
(__u32) gdp->bg_used_dirs_count_hi << 16 : 0);
}
/*
* Set the used dirs count of a group
*/
void ext2fs_bg_used_dirs_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_used_dirs_count = n;
if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
gdp->bg_used_dirs_count_hi = (__u32) n >> 16;
}
/*
* Return the unused inodes count of a group
*/
__u32 ext2fs_bg_itable_unused(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_itable_unused |
(fs->super->s_feature_incompat
& EXT4_FEATURE_INCOMPAT_64BIT ?
(__u32) gdp->bg_itable_unused_hi << 16 : 0);
}
/*
* Set the unused inodes count of a group
*/
void ext2fs_bg_itable_unused_set(ext2_filsys fs, dgrp_t group, __u32 n)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_itable_unused = n;
if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
gdp->bg_itable_unused_hi = (__u32) n >> 16;
}
/*
* Get the flags for this block group
*/
__u16 ext2fs_bg_flags(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_flags;
}
/*
* Zero out the flags for this block group
*/
void ext2fs_bg_flags_zap(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_flags = 0;
return;
}
/*
* Get the value of a particular flag for this block group
*/
int ext2fs_bg_flags_test(ext2_filsys fs, dgrp_t group, __u16 bg_flag)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_flags & bg_flag;
}
/*
* Set a flag or set of flags for this block group
*/
void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_flags |= bg_flags;
return;
}
/*
* Clear a flag or set of flags for this block group
*/
void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_flags &= ~bg_flags;
return;
}
/*
* Get the checksum for this block group
*/
__u16 ext2fs_bg_checksum(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_checksum;
}
/*
* Set the checksum for this block group to a previously calculated value
*/
void ext2fs_bg_checksum_set(ext2_filsys fs, dgrp_t group, __u16 checksum)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_checksum = checksum;
return;
}
/*
* Get the acl block of a file
*/
blk64_t ext2fs_file_acl_block(ext2_filsys fs, const struct ext2_inode *inode)
{
blk64_t blk = inode->i_file_acl;
if (fs && fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
blk |= ((__u64) inode->osd2.linux2.l_i_file_acl_high) << 32;
return blk;
}
/*
* Set the acl block of a file
*/
void ext2fs_file_acl_block_set(ext2_filsys fs, struct ext2_inode *inode,
blk64_t blk)
{
inode->i_file_acl = blk;
if (fs && fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32;
}

View File

@ -0,0 +1,635 @@
/*
* block.c --- iterate over all blocks in an inode
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
struct block_context {
ext2_filsys fs;
int (*func)(ext2_filsys fs,
blk64_t *blocknr,
e2_blkcnt_t bcount,
blk64_t ref_blk,
int ref_offset,
void *priv_data);
e2_blkcnt_t bcount;
int bsize;
int flags;
errcode_t errcode;
char *ind_buf;
char *dind_buf;
char *tind_buf;
void *priv_data;
};
#define check_for_ro_violation_return(ctx, ret) \
do { \
if (((ctx)->flags & BLOCK_FLAG_READ_ONLY) && \
((ret) & BLOCK_CHANGED)) { \
(ctx)->errcode = EXT2_ET_RO_BLOCK_ITERATE; \
ret |= BLOCK_ABORT | BLOCK_ERROR; \
return ret; \
} \
} while (0)
#define check_for_ro_violation_goto(ctx, ret, label) \
do { \
if (((ctx)->flags & BLOCK_FLAG_READ_ONLY) && \
((ret) & BLOCK_CHANGED)) { \
(ctx)->errcode = EXT2_ET_RO_BLOCK_ITERATE; \
ret |= BLOCK_ABORT | BLOCK_ERROR; \
goto label; \
} \
} while (0)
static int block_iterate_ind(blk_t *ind_block, blk_t ref_block,
int ref_offset, struct block_context *ctx)
{
int ret = 0, changed = 0;
int i, flags, limit, offset;
blk_t *block_nr;
blk64_t blk64;
limit = ctx->fs->blocksize >> 2;
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ctx->flags & BLOCK_FLAG_DATA_ONLY)) {
blk64 = *ind_block;
ret = (*ctx->func)(ctx->fs, &blk64,
BLOCK_COUNT_IND, ref_block,
ref_offset, ctx->priv_data);
*ind_block = blk64;
}
check_for_ro_violation_return(ctx, ret);
if (!*ind_block || (ret & BLOCK_ABORT)) {
ctx->bcount += limit;
return ret;
}
if (*ind_block >= ext2fs_blocks_count(ctx->fs->super) ||
*ind_block < ctx->fs->super->s_first_data_block) {
ctx->errcode = EXT2_ET_BAD_IND_BLOCK;
ret |= BLOCK_ERROR;
return ret;
}
ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block,
ctx->ind_buf);
if (ctx->errcode) {
ret |= BLOCK_ERROR;
return ret;
}
block_nr = (blk_t *) ctx->ind_buf;
offset = 0;
if (ctx->flags & BLOCK_FLAG_APPEND) {
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
blk64 = *block_nr;
flags = (*ctx->func)(ctx->fs, &blk64, ctx->bcount,
*ind_block, offset,
ctx->priv_data);
*block_nr = blk64;
changed |= flags;
if (flags & BLOCK_ABORT) {
ret |= BLOCK_ABORT;
break;
}
offset += sizeof(blk_t);
}
} else {
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
if (*block_nr == 0)
goto skip_sparse;
blk64 = *block_nr;
flags = (*ctx->func)(ctx->fs, &blk64, ctx->bcount,
*ind_block, offset,
ctx->priv_data);
*block_nr = blk64;
changed |= flags;
if (flags & BLOCK_ABORT) {
ret |= BLOCK_ABORT;
break;
}
skip_sparse:
offset += sizeof(blk_t);
}
}
check_for_ro_violation_return(ctx, changed);
if (changed & BLOCK_CHANGED) {
ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block,
ctx->ind_buf);
if (ctx->errcode)
ret |= BLOCK_ERROR | BLOCK_ABORT;
}
if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
!(ret & BLOCK_ABORT)) {
blk64 = *ind_block;
ret |= (*ctx->func)(ctx->fs, &blk64,
BLOCK_COUNT_IND, ref_block,
ref_offset, ctx->priv_data);
*ind_block = blk64;
}
check_for_ro_violation_return(ctx, ret);
return ret;
}
static int block_iterate_dind(blk_t *dind_block, blk_t ref_block,
int ref_offset, struct block_context *ctx)
{
int ret = 0, changed = 0;
int i, flags, limit, offset;
blk_t *block_nr;
blk64_t blk64;
limit = ctx->fs->blocksize >> 2;
if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
BLOCK_FLAG_DATA_ONLY))) {
blk64 = *dind_block;
ret = (*ctx->func)(ctx->fs, &blk64,
BLOCK_COUNT_DIND, ref_block,
ref_offset, ctx->priv_data);
*dind_block = blk64;
}
check_for_ro_violation_return(ctx, ret);
if (!*dind_block || (ret & BLOCK_ABORT)) {
ctx->bcount += limit*limit;
return ret;
}
if (*dind_block >= ext2fs_blocks_count(ctx->fs->super) ||
*dind_block < ctx->fs->super->s_first_data_block) {
ctx->errcode = EXT2_ET_BAD_DIND_BLOCK;
ret |= BLOCK_ERROR;
return ret;
}
ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block,
ctx->dind_buf);
if (ctx->errcode) {
ret |= BLOCK_ERROR;
return ret;
}
block_nr = (blk_t *) ctx->dind_buf;
offset = 0;
if (ctx->flags & BLOCK_FLAG_APPEND) {
for (i = 0; i < limit; i++, block_nr++) {
flags = block_iterate_ind(block_nr,
*dind_block, offset,
ctx);
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
offset += sizeof(blk_t);
}
} else {
for (i = 0; i < limit; i++, block_nr++) {
if (*block_nr == 0) {
ctx->bcount += limit;
continue;
}
flags = block_iterate_ind(block_nr,
*dind_block, offset,
ctx);
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
offset += sizeof(blk_t);
}
}
check_for_ro_violation_return(ctx, changed);
if (changed & BLOCK_CHANGED) {
ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block,
ctx->dind_buf);
if (ctx->errcode)
ret |= BLOCK_ERROR | BLOCK_ABORT;
}
if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
!(ret & BLOCK_ABORT)) {
blk64 = *dind_block;
ret |= (*ctx->func)(ctx->fs, &blk64,
BLOCK_COUNT_DIND, ref_block,
ref_offset, ctx->priv_data);
*dind_block = blk64;
}
check_for_ro_violation_return(ctx, ret);
return ret;
}
static int block_iterate_tind(blk_t *tind_block, blk_t ref_block,
int ref_offset, struct block_context *ctx)
{
int ret = 0, changed = 0;
int i, flags, limit, offset;
blk_t *block_nr;
blk64_t blk64;
limit = ctx->fs->blocksize >> 2;
if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
BLOCK_FLAG_DATA_ONLY))) {
blk64 = *tind_block;
ret = (*ctx->func)(ctx->fs, &blk64,
BLOCK_COUNT_TIND, ref_block,
ref_offset, ctx->priv_data);
*tind_block = blk64;
}
check_for_ro_violation_return(ctx, ret);
if (!*tind_block || (ret & BLOCK_ABORT)) {
ctx->bcount += limit*limit*limit;
return ret;
}
if (*tind_block >= ext2fs_blocks_count(ctx->fs->super) ||
*tind_block < ctx->fs->super->s_first_data_block) {
ctx->errcode = EXT2_ET_BAD_TIND_BLOCK;
ret |= BLOCK_ERROR;
return ret;
}
ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block,
ctx->tind_buf);
if (ctx->errcode) {
ret |= BLOCK_ERROR;
return ret;
}
block_nr = (blk_t *) ctx->tind_buf;
offset = 0;
if (ctx->flags & BLOCK_FLAG_APPEND) {
for (i = 0; i < limit; i++, block_nr++) {
flags = block_iterate_dind(block_nr,
*tind_block,
offset, ctx);
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
offset += sizeof(blk_t);
}
} else {
for (i = 0; i < limit; i++, block_nr++) {
if (*block_nr == 0) {
ctx->bcount += limit*limit;
continue;
}
flags = block_iterate_dind(block_nr,
*tind_block,
offset, ctx);
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
offset += sizeof(blk_t);
}
}
check_for_ro_violation_return(ctx, changed);
if (changed & BLOCK_CHANGED) {
ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block,
ctx->tind_buf);
if (ctx->errcode)
ret |= BLOCK_ERROR | BLOCK_ABORT;
}
if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
!(ret & BLOCK_ABORT)) {
blk64 = *tind_block;
ret |= (*ctx->func)(ctx->fs, &blk64,
BLOCK_COUNT_TIND, ref_block,
ref_offset, ctx->priv_data);
*tind_block = blk64;
}
check_for_ro_violation_return(ctx, ret);
return ret;
}
errcode_t ext2fs_block_iterate3(ext2_filsys fs,
ext2_ino_t ino,
int flags,
char *block_buf,
int (*func)(ext2_filsys fs,
blk64_t *blocknr,
e2_blkcnt_t blockcnt,
blk64_t ref_blk,
int ref_offset,
void *priv_data),
void *priv_data)
{
int i;
int r, ret = 0;
struct ext2_inode inode;
errcode_t retval;
struct block_context ctx;
int limit;
blk64_t blk64;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
if (ctx.errcode)
return ctx.errcode;
/*
* Check to see if we need to limit large files
*/
if (flags & BLOCK_FLAG_NO_LARGE) {
if (!LINUX_S_ISDIR(inode.i_mode) &&
(inode.i_size_high != 0))
return EXT2_ET_FILE_TOO_BIG;
}
limit = fs->blocksize >> 2;
ctx.fs = fs;
ctx.func = func;
ctx.priv_data = priv_data;
ctx.flags = flags;
ctx.bcount = 0;
if (block_buf) {
ctx.ind_buf = block_buf;
} else {
retval = ext2fs_get_array(3, fs->blocksize, &ctx.ind_buf);
if (retval)
return retval;
}
ctx.dind_buf = ctx.ind_buf + fs->blocksize;
ctx.tind_buf = ctx.dind_buf + fs->blocksize;
/*
* Iterate over the HURD translator block (if present)
*/
if ((fs->super->s_creator_os == EXT2_OS_HURD) &&
!(flags & BLOCK_FLAG_DATA_ONLY)) {
if (inode.osd1.hurd1.h_i_translator) {
blk64 = inode.osd1.hurd1.h_i_translator;
ret |= (*ctx.func)(fs, &blk64,
BLOCK_COUNT_TRANSLATOR,
0, 0, priv_data);
inode.osd1.hurd1.h_i_translator = (blk_t) blk64;
if (ret & BLOCK_ABORT)
goto abort_exit;
check_for_ro_violation_goto(&ctx, ret, abort_exit);
}
}
if (inode.i_flags & EXT4_EXTENTS_FL) {
ext2_extent_handle_t handle;
struct ext2fs_extent extent;
e2_blkcnt_t blockcnt = 0;
blk64_t blk, new_blk;
int op = EXT2_EXTENT_ROOT;
int uninit;
unsigned int j;
ctx.errcode = ext2fs_extent_open2(fs, ino, &inode, &handle);
if (ctx.errcode)
goto abort_exit;
while (1) {
ctx.errcode = ext2fs_extent_get(handle, op, &extent);
if (ctx.errcode) {
if (ctx.errcode != EXT2_ET_EXTENT_NO_NEXT)
break;
ctx.errcode = 0;
if (!(flags & BLOCK_FLAG_APPEND))
break;
next_block_set:
blk = 0;
r = (*ctx.func)(fs, &blk, blockcnt,
0, 0, priv_data);
ret |= r;
check_for_ro_violation_goto(&ctx, ret,
extent_errout);
if (r & BLOCK_CHANGED) {
ctx.errcode =
ext2fs_extent_set_bmap(handle,
(blk64_t) blockcnt++,
(blk64_t) blk, 0);
if (ctx.errcode || (ret & BLOCK_ABORT))
break;
if (blk)
goto next_block_set;
}
break;
}
op = EXT2_EXTENT_NEXT;
blk = extent.e_pblk;
if (!(extent.e_flags & EXT2_EXTENT_FLAGS_LEAF)) {
if (ctx.flags & BLOCK_FLAG_DATA_ONLY)
continue;
if ((!(extent.e_flags &
EXT2_EXTENT_FLAGS_SECOND_VISIT) &&
!(ctx.flags & BLOCK_FLAG_DEPTH_TRAVERSE)) ||
((extent.e_flags &
EXT2_EXTENT_FLAGS_SECOND_VISIT) &&
(ctx.flags & BLOCK_FLAG_DEPTH_TRAVERSE))) {
ret |= (*ctx.func)(fs, &blk,
-1, 0, 0, priv_data);
if (ret & BLOCK_CHANGED) {
extent.e_pblk = blk;
ctx.errcode =
ext2fs_extent_replace(handle, 0, &extent);
if (ctx.errcode)
break;
}
}
continue;
}
uninit = 0;
if (extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
uninit = EXT2_EXTENT_SET_BMAP_UNINIT;
#if 0
printf("lblk %llu pblk %llu len %d blockcnt %llu\n",
extent.e_lblk, extent.e_pblk,
extent.e_len, blockcnt);
#endif
if (extent.e_lblk + extent.e_len <= blockcnt)
continue;
if (extent.e_lblk > blockcnt)
blockcnt = extent.e_lblk;
j = blockcnt - extent.e_lblk;
blk += j;
for (blockcnt = extent.e_lblk, j = 0;
j < extent.e_len;
blk++, blockcnt++, j++) {
new_blk = blk;
r = (*ctx.func)(fs, &new_blk, blockcnt,
0, 0, priv_data);
ret |= r;
check_for_ro_violation_goto(&ctx, ret,
extent_errout);
if (r & BLOCK_CHANGED) {
ctx.errcode =
ext2fs_extent_set_bmap(handle,
(blk64_t) blockcnt,
new_blk, uninit);
if (ctx.errcode)
goto extent_errout;
}
if (ret & BLOCK_ABORT)
break;
}
}
extent_errout:
ext2fs_extent_free(handle);
ret |= BLOCK_ERROR | BLOCK_ABORT;
goto errout;
}
/*
* Iterate over normal data blocks
*/
for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) {
if (inode.i_block[i] || (flags & BLOCK_FLAG_APPEND)) {
blk64 = inode.i_block[i];
ret |= (*ctx.func)(fs, &blk64, ctx.bcount, 0, i,
priv_data);
inode.i_block[i] = (blk_t) blk64;
if (ret & BLOCK_ABORT)
goto abort_exit;
}
}
check_for_ro_violation_goto(&ctx, ret, abort_exit);
if (inode.i_block[EXT2_IND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) {
ret |= block_iterate_ind(&inode.i_block[EXT2_IND_BLOCK],
0, EXT2_IND_BLOCK, &ctx);
if (ret & BLOCK_ABORT)
goto abort_exit;
} else
ctx.bcount += limit;
if (inode.i_block[EXT2_DIND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) {
ret |= block_iterate_dind(&inode.i_block[EXT2_DIND_BLOCK],
0, EXT2_DIND_BLOCK, &ctx);
if (ret & BLOCK_ABORT)
goto abort_exit;
} else
ctx.bcount += limit * limit;
if (inode.i_block[EXT2_TIND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) {
ret |= block_iterate_tind(&inode.i_block[EXT2_TIND_BLOCK],
0, EXT2_TIND_BLOCK, &ctx);
if (ret & BLOCK_ABORT)
goto abort_exit;
}
abort_exit:
if (ret & BLOCK_CHANGED) {
retval = ext2fs_write_inode(fs, ino, &inode);
if (retval) {
ret |= BLOCK_ERROR;
ctx.errcode = retval;
}
}
errout:
if (!block_buf)
ext2fs_free_mem(&ctx.ind_buf);
return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
}
/*
* Emulate the old ext2fs_block_iterate function!
*/
struct xlate64 {
int (*func)(ext2_filsys fs,
blk_t *blocknr,
e2_blkcnt_t blockcnt,
blk_t ref_blk,
int ref_offset,
void *priv_data);
void *real_private;
};
static int xlate64_func(ext2_filsys fs, blk64_t *blocknr,
e2_blkcnt_t blockcnt, blk64_t ref_blk,
int ref_offset, void *priv_data)
{
struct xlate64 *xl = (struct xlate64 *) priv_data;
int ret;
blk_t block32 = *blocknr;
ret = (*xl->func)(fs, &block32, blockcnt, (blk_t) ref_blk, ref_offset,
xl->real_private);
*blocknr = block32;
return ret;
}
errcode_t ext2fs_block_iterate2(ext2_filsys fs,
ext2_ino_t ino,
int flags,
char *block_buf,
int (*func)(ext2_filsys fs,
blk_t *blocknr,
e2_blkcnt_t blockcnt,
blk_t ref_blk,
int ref_offset,
void *priv_data),
void *priv_data)
{
struct xlate64 xl;
xl.real_private = priv_data;
xl.func = func;
return ext2fs_block_iterate3(fs, ino, flags, block_buf,
xlate64_func, &xl);
}
struct xlate {
int (*func)(ext2_filsys fs,
blk_t *blocknr,
int bcount,
void *priv_data);
void *real_private;
};
#ifdef __TURBOC__
#pragma argsused
#endif
static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt,
blk_t ref_block EXT2FS_ATTR((unused)),
int ref_offset EXT2FS_ATTR((unused)),
void *priv_data)
{
struct xlate *xl = (struct xlate *) priv_data;
return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private);
}
errcode_t ext2fs_block_iterate(ext2_filsys fs,
ext2_ino_t ino,
int flags,
char *block_buf,
int (*func)(ext2_filsys fs,
blk_t *blocknr,
int blockcnt,
void *priv_data),
void *priv_data)
{
struct xlate xl;
xl.real_private = priv_data;
xl.func = func;
return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags,
block_buf, xlate_func, &xl);
}

View File

@ -0,0 +1,398 @@
/*
* bmap.c --- logical to physical block mapping
*
* Copyright (C) 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <errno.h>
#include "ext2_fs.h"
#include "ext2fs.h"
#if defined(__GNUC__) && !defined(NO_INLINE_FUNCS)
#define _BMAP_INLINE_ __inline__
#else
#define _BMAP_INLINE_
#endif
extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
char *block_buf, int bmap_flags,
blk_t block, blk_t *phys_blk);
#define inode_bmap(inode, nr) ((inode)->i_block[(nr)])
static _BMAP_INLINE_ errcode_t block_ind_bmap(ext2_filsys fs, int flags,
blk_t ind, char *block_buf,
int *blocks_alloc,
blk_t nr, blk_t *ret_blk)
{
errcode_t retval;
blk_t b;
if (!ind) {
if (flags & BMAP_SET)
return EXT2_ET_SET_BMAP_NO_IND;
*ret_blk = 0;
return 0;
}
retval = io_channel_read_blk(fs->io, ind, 1, block_buf);
if (retval)
return retval;
if (flags & BMAP_SET) {
b = *ret_blk;
#ifdef WORDS_BIGENDIAN
b = ext2fs_swab32(b);
#endif
((blk_t *) block_buf)[nr] = b;
return io_channel_write_blk(fs->io, ind, 1, block_buf);
}
b = ((blk_t *) block_buf)[nr];
#ifdef WORDS_BIGENDIAN
b = ext2fs_swab32(b);
#endif
if (!b && (flags & BMAP_ALLOC)) {
b = nr ? ((blk_t *) block_buf)[nr-1] : 0;
retval = ext2fs_alloc_block(fs, b,
block_buf + fs->blocksize, &b);
if (retval)
return retval;
#ifdef WORDS_BIGENDIAN
((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
#else
((blk_t *) block_buf)[nr] = b;
#endif
retval = io_channel_write_blk(fs->io, ind, 1, block_buf);
if (retval)
return retval;
(*blocks_alloc)++;
}
*ret_blk = b;
return 0;
}
static _BMAP_INLINE_ errcode_t block_dind_bmap(ext2_filsys fs, int flags,
blk_t dind, char *block_buf,
int *blocks_alloc,
blk_t nr, blk_t *ret_blk)
{
blk_t b;
errcode_t retval;
blk_t addr_per_block;
addr_per_block = (blk_t) fs->blocksize >> 2;
retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf,
blocks_alloc, nr / addr_per_block, &b);
if (retval)
return retval;
retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
nr % addr_per_block, ret_blk);
return retval;
}
static _BMAP_INLINE_ errcode_t block_tind_bmap(ext2_filsys fs, int flags,
blk_t tind, char *block_buf,
int *blocks_alloc,
blk_t nr, blk_t *ret_blk)
{
blk_t b;
errcode_t retval;
blk_t addr_per_block;
addr_per_block = (blk_t) fs->blocksize >> 2;
retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf,
blocks_alloc, nr / addr_per_block, &b);
if (retval)
return retval;
retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
nr % addr_per_block, ret_blk);
return retval;
}
static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
ext2_extent_handle_t handle,
char *block_buf, int bmap_flags, blk64_t block,
int *ret_flags, int *blocks_alloc,
blk64_t *phys_blk);
static errcode_t implied_cluster_alloc(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
ext2_extent_handle_t handle,
blk64_t block, blk64_t *phys_blk)
{
blk64_t base_block, pblock = 0;
int i;
if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_BIGALLOC))
return 0;
base_block = block & ~EXT2FS_CLUSTER_MASK(fs);
for (i = 0; i < EXT2FS_CLUSTER_RATIO(fs); i++) {
if (block == base_block)
return 0;
extent_bmap(fs, ino, inode, handle, 0, 0,
base_block + i, 0, 0, &pblock);
if (pblock)
break;
}
if (pblock == 0)
return 0;
*phys_blk = pblock - i + (block - base_block);
return 0;
}
static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
ext2_extent_handle_t handle,
char *block_buf, int bmap_flags, blk64_t block,
int *ret_flags, int *blocks_alloc,
blk64_t *phys_blk)
{
struct ext2fs_extent extent;
unsigned int offset;
errcode_t retval = 0;
blk64_t blk64 = 0;
int alloc = 0;
if (bmap_flags & BMAP_SET) {
retval = ext2fs_extent_set_bmap(handle, block,
*phys_blk, 0);
return retval;
}
retval = ext2fs_extent_goto(handle, block);
if (retval) {
/* If the extent is not found, return phys_blk = 0 */
if (retval == EXT2_ET_EXTENT_NOT_FOUND)
goto got_block;
return retval;
}
retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
if (retval)
return retval;
offset = block - extent.e_lblk;
if (block >= extent.e_lblk && (offset <= extent.e_len)) {
*phys_blk = extent.e_pblk + offset;
if (ret_flags && extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
*ret_flags |= BMAP_RET_UNINIT;
}
got_block:
if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
implied_cluster_alloc(fs, ino, inode, handle, block, &blk64);
if (blk64)
goto set_extent;
retval = extent_bmap(fs, ino, inode, handle, block_buf,
0, block-1, 0, blocks_alloc, &blk64);
if (retval)
blk64 = 0;
retval = ext2fs_alloc_block2(fs, blk64, block_buf,
&blk64);
if (retval)
return retval;
blk64 &= ~EXT2FS_CLUSTER_MASK(fs);
blk64 += EXT2FS_CLUSTER_MASK(fs) & block;
alloc++;
set_extent:
retval = ext2fs_extent_set_bmap(handle, block,
blk64, 0);
if (retval)
return retval;
/* Update inode after setting extent */
retval = ext2fs_read_inode(fs, ino, inode);
if (retval)
return retval;
*blocks_alloc += alloc;
*phys_blk = blk64;
}
return 0;
}
errcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
char *block_buf, int bmap_flags, blk64_t block,
int *ret_flags, blk64_t *phys_blk)
{
struct ext2_inode inode_buf;
ext2_extent_handle_t handle = 0;
blk_t addr_per_block;
blk_t b, blk32;
char *buf = 0;
errcode_t retval = 0;
int blocks_alloc = 0, inode_dirty = 0;
if (!(bmap_flags & BMAP_SET))
*phys_blk = 0;
if (ret_flags)
*ret_flags = 0;
/* Read inode structure if necessary */
if (!inode) {
retval = ext2fs_read_inode(fs, ino, &inode_buf);
if (retval)
return retval;
inode = &inode_buf;
}
addr_per_block = (blk_t) fs->blocksize >> 2;
if (!block_buf) {
retval = ext2fs_get_array(2, fs->blocksize, &buf);
if (retval)
return retval;
block_buf = buf;
}
if (inode->i_flags & EXT4_EXTENTS_FL) {
retval = ext2fs_extent_open2(fs, ino, inode, &handle);
if (retval)
goto done;
retval = extent_bmap(fs, ino, inode, handle, block_buf,
bmap_flags, block, ret_flags,
&blocks_alloc, phys_blk);
goto done;
}
if (block < EXT2_NDIR_BLOCKS) {
if (bmap_flags & BMAP_SET) {
b = *phys_blk;
inode_bmap(inode, block) = b;
inode_dirty++;
goto done;
}
*phys_blk = inode_bmap(inode, block);
b = block ? inode_bmap(inode, block-1) : 0;
if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
retval = ext2fs_alloc_block(fs, b, block_buf, &b);
if (retval)
goto done;
inode_bmap(inode, block) = b;
blocks_alloc++;
*phys_blk = b;
}
goto done;
}
/* Indirect block */
block -= EXT2_NDIR_BLOCKS;
blk32 = *phys_blk;
if (block < addr_per_block) {
b = inode_bmap(inode, EXT2_IND_BLOCK);
if (!b) {
if (!(bmap_flags & BMAP_ALLOC)) {
if (bmap_flags & BMAP_SET)
retval = EXT2_ET_SET_BMAP_NO_IND;
goto done;
}
b = inode_bmap(inode, EXT2_IND_BLOCK-1);
retval = ext2fs_alloc_block(fs, b, block_buf, &b);
if (retval)
goto done;
inode_bmap(inode, EXT2_IND_BLOCK) = b;
blocks_alloc++;
}
retval = block_ind_bmap(fs, bmap_flags, b, block_buf,
&blocks_alloc, block, &blk32);
if (retval == 0)
*phys_blk = blk32;
goto done;
}
/* Doubly indirect block */
block -= addr_per_block;
if (block < addr_per_block * addr_per_block) {
b = inode_bmap(inode, EXT2_DIND_BLOCK);
if (!b) {
if (!(bmap_flags & BMAP_ALLOC)) {
if (bmap_flags & BMAP_SET)
retval = EXT2_ET_SET_BMAP_NO_IND;
goto done;
}
b = inode_bmap(inode, EXT2_IND_BLOCK);
retval = ext2fs_alloc_block(fs, b, block_buf, &b);
if (retval)
goto done;
inode_bmap(inode, EXT2_DIND_BLOCK) = b;
blocks_alloc++;
}
retval = block_dind_bmap(fs, bmap_flags, b, block_buf,
&blocks_alloc, block, &blk32);
if (retval == 0)
*phys_blk = blk32;
goto done;
}
/* Triply indirect block */
block -= addr_per_block * addr_per_block;
b = inode_bmap(inode, EXT2_TIND_BLOCK);
if (!b) {
if (!(bmap_flags & BMAP_ALLOC)) {
if (bmap_flags & BMAP_SET)
retval = EXT2_ET_SET_BMAP_NO_IND;
goto done;
}
b = inode_bmap(inode, EXT2_DIND_BLOCK);
retval = ext2fs_alloc_block(fs, b, block_buf, &b);
if (retval)
goto done;
inode_bmap(inode, EXT2_TIND_BLOCK) = b;
blocks_alloc++;
}
retval = block_tind_bmap(fs, bmap_flags, b, block_buf,
&blocks_alloc, block, &blk32);
if (retval == 0)
*phys_blk = blk32;
done:
if (buf)
ext2fs_free_mem(&buf);
if (handle)
ext2fs_extent_free(handle);
if ((retval == 0) && (blocks_alloc || inode_dirty)) {
ext2fs_iblk_add_blocks(fs, inode, blocks_alloc);
retval = ext2fs_write_inode(fs, ino, inode);
}
return retval;
}
errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
char *block_buf, int bmap_flags, blk_t block,
blk_t *phys_blk)
{
errcode_t ret;
blk64_t ret_blk = *phys_blk;
ret = ext2fs_bmap2(fs, ino, inode, block_buf, bmap_flags, block,
0, &ret_blk);
if (ret)
return ret;
if (ret_blk >= ((long long) 1 << 32))
return EOVERFLOW;
*phys_blk = ret_blk;
return 0;
}

View File

@ -0,0 +1,62 @@
/*
* bmap64.h --- 64-bit bitmap structure
*
* Copyright (C) 2007, 2008 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
struct ext2fs_struct_generic_bitmap {
errcode_t magic;
ext2_filsys fs;
struct ext2_bitmap_ops *bitmap_ops;
int flags;
__u64 start, end;
__u64 real_end;
int cluster_bits;
char *description;
void *private;
errcode_t base_error_code;
};
#define EXT2FS_IS_32_BITMAP(bmap) \
(((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) || \
((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP) || \
((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP))
#define EXT2FS_IS_64_BITMAP(bmap) \
(((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP64) || \
((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP64) || \
((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP64))
struct ext2_bitmap_ops {
int type;
/* Generic bmap operators */
errcode_t (*new_bmap)(ext2_filsys fs, ext2fs_generic_bitmap bmap);
void (*free_bmap)(ext2fs_generic_bitmap bitmap);
errcode_t (*copy_bmap)(ext2fs_generic_bitmap src,
ext2fs_generic_bitmap dest);
errcode_t (*resize_bmap)(ext2fs_generic_bitmap bitmap,
__u64 new_end,
__u64 new_real_end);
/* bit set/test operators */
int (*mark_bmap)(ext2fs_generic_bitmap bitmap, __u64 arg);
int (*unmark_bmap)(ext2fs_generic_bitmap bitmap, __u64 arg);
int (*test_bmap)(ext2fs_generic_bitmap bitmap, __u64 arg);
void (*mark_bmap_extent)(ext2fs_generic_bitmap bitmap, __u64 arg,
unsigned int num);
void (*unmark_bmap_extent)(ext2fs_generic_bitmap bitmap, __u64 arg,
unsigned int num);
int (*test_clear_bmap_extent)(ext2fs_generic_bitmap bitmap,
__u64 arg, unsigned int num);
errcode_t (*set_bmap_range)(ext2fs_generic_bitmap bitmap,
__u64 start, size_t num, void *in);
errcode_t (*get_bmap_range)(ext2fs_generic_bitmap bitmap,
__u64 start, size_t num, void *out);
void (*clear_bmap)(ext2fs_generic_bitmap bitmap);
};
extern struct ext2_bitmap_ops ext2fs_blkmap64_bitarray;

View File

@ -0,0 +1,167 @@
/*
* bmove.c --- Move blocks around to make way for a particular
* filesystem structure.
*
* Copyright (C) 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include "ext2_fs.h"
#include "ext2fsP.h"
struct process_block_struct {
ext2_ino_t ino;
struct ext2_inode * inode;
ext2fs_block_bitmap reserve;
ext2fs_block_bitmap alloc_map;
errcode_t error;
char *buf;
int add_dir;
int flags;
};
static int process_block(ext2_filsys fs, blk64_t *block_nr,
e2_blkcnt_t blockcnt, blk64_t ref_block,
int ref_offset, void *priv_data)
{
struct process_block_struct *pb;
errcode_t retval;
int ret;
blk64_t block, orig;
pb = (struct process_block_struct *) priv_data;
block = orig = *block_nr;
ret = 0;
/*
* Let's see if this is one which we need to relocate
*/
if (ext2fs_test_block_bitmap2(pb->reserve, block)) {
do {
if (++block >= ext2fs_blocks_count(fs->super))
block = fs->super->s_first_data_block;
if (block == orig) {
pb->error = EXT2_ET_BLOCK_ALLOC_FAIL;
return BLOCK_ABORT;
}
} while (ext2fs_test_block_bitmap2(pb->reserve, block) ||
ext2fs_test_block_bitmap2(pb->alloc_map, block));
retval = io_channel_read_blk64(fs->io, orig, 1, pb->buf);
if (retval) {
pb->error = retval;
return BLOCK_ABORT;
}
retval = io_channel_write_blk64(fs->io, block, 1, pb->buf);
if (retval) {
pb->error = retval;
return BLOCK_ABORT;
}
*block_nr = block;
ext2fs_mark_block_bitmap2(pb->alloc_map, block);
ret = BLOCK_CHANGED;
if (pb->flags & EXT2_BMOVE_DEBUG)
printf("ino=%u, blockcnt=%lld, %llu->%llu\n",
(unsigned) pb->ino, blockcnt,
(unsigned long long) orig,
(unsigned long long) block);
}
if (pb->add_dir) {
retval = ext2fs_add_dir_block2(fs->dblist, pb->ino,
block, blockcnt);
if (retval) {
pb->error = retval;
ret |= BLOCK_ABORT;
}
}
return ret;
}
errcode_t ext2fs_move_blocks(ext2_filsys fs,
ext2fs_block_bitmap reserve,
ext2fs_block_bitmap alloc_map,
int flags)
{
ext2_ino_t ino;
struct ext2_inode inode;
errcode_t retval;
struct process_block_struct pb;
ext2_inode_scan scan;
char *block_buf;
retval = ext2fs_open_inode_scan(fs, 0, &scan);
if (retval)
return retval;
pb.reserve = reserve;
pb.error = 0;
pb.alloc_map = alloc_map ? alloc_map : fs->block_map;
pb.flags = flags;
retval = ext2fs_get_array(4, fs->blocksize, &block_buf);
if (retval)
return retval;
pb.buf = block_buf + fs->blocksize * 3;
/*
* If GET_DBLIST is set in the flags field, then we should
* gather directory block information while we're doing the
* block move.
*/
if (flags & EXT2_BMOVE_GET_DBLIST) {
if (fs->dblist) {
ext2fs_free_dblist(fs->dblist);
fs->dblist = NULL;
}
retval = ext2fs_init_dblist(fs, 0);
if (retval)
return retval;
}
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval)
return retval;
while (ino) {
if ((inode.i_links_count == 0) ||
!ext2fs_inode_has_valid_blocks2(fs, &inode))
goto next;
pb.ino = ino;
pb.inode = &inode;
pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) &&
flags & EXT2_BMOVE_GET_DBLIST);
retval = ext2fs_block_iterate3(fs, ino, 0, block_buf,
process_block, &pb);
if (retval)
return retval;
if (pb.error)
return pb.error;
next:
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
goto next;
}
return 0;
}

View File

@ -0,0 +1,86 @@
/*
* brel.h
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
struct ext2_block_relocate_entry {
blk_t new;
__s16 offset;
__u16 flags;
union {
blk_t block_ref;
ext2_ino_t inode_ref;
} owner;
};
#define RELOCATE_TYPE_REF 0x0007
#define RELOCATE_BLOCK_REF 0x0001
#define RELOCATE_INODE_REF 0x0002
typedef struct ext2_block_relocation_table *ext2_brel;
struct ext2_block_relocation_table {
__u32 magic;
char *name;
blk_t current;
void *priv_data;
/*
* Add a block relocation entry.
*/
errcode_t (*put)(ext2_brel brel, blk_t old,
struct ext2_block_relocate_entry *ent);
/*
* Get a block relocation entry.
*/
errcode_t (*get)(ext2_brel brel, blk_t old,
struct ext2_block_relocate_entry *ent);
/*
* Initialize for iterating over the block relocation entries.
*/
errcode_t (*start_iter)(ext2_brel brel);
/*
* The iterator function for the inode relocation entries.
* Returns an inode number of 0 when out of entries.
*/
errcode_t (*next)(ext2_brel brel, blk_t *old,
struct ext2_block_relocate_entry *ent);
/*
* Move the inode relocation table from one block number to
* another.
*/
errcode_t (*move)(ext2_brel brel, blk_t old, blk_t new);
/*
* Remove a block relocation entry.
*/
errcode_t (*delete)(ext2_brel brel, blk_t old);
/*
* Free the block relocation table.
*/
errcode_t (*free)(ext2_brel brel);
};
errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
ext2_brel *brel);
#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent))
#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent))
#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel)))
#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent))
#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new))
#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old))
#define ext2fs_brel_free(brel) ((brel)->free((brel)))

View File

@ -0,0 +1,199 @@
/*
* brel_ma.c
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* TODO: rewrite to not use a direct array!!! (Fortunately this
* module isn't really used yet.)
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#include "brel.h"
static errcode_t bma_put(ext2_brel brel, blk_t old,
struct ext2_block_relocate_entry *ent);
static errcode_t bma_get(ext2_brel brel, blk_t old,
struct ext2_block_relocate_entry *ent);
static errcode_t bma_start_iter(ext2_brel brel);
static errcode_t bma_next(ext2_brel brel, blk_t *old,
struct ext2_block_relocate_entry *ent);
static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new);
static errcode_t bma_delete(ext2_brel brel, blk_t old);
static errcode_t bma_free(ext2_brel brel);
struct brel_ma {
__u32 magic;
blk_t max_block;
struct ext2_block_relocate_entry *entries;
};
errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
ext2_brel *new_brel)
{
ext2_brel brel = 0;
errcode_t retval;
struct brel_ma *ma = 0;
size_t size;
*new_brel = 0;
/*
* Allocate memory structures
*/
retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table),
&brel);
if (retval)
goto errout;
memset(brel, 0, sizeof(struct ext2_block_relocation_table));
retval = ext2fs_get_mem(strlen(name)+1, &brel->name);
if (retval)
goto errout;
strcpy(brel->name, name);
retval = ext2fs_get_mem(sizeof(struct brel_ma), &ma);
if (retval)
goto errout;
memset(ma, 0, sizeof(struct brel_ma));
brel->priv_data = ma;
size = (size_t) (sizeof(struct ext2_block_relocate_entry) *
(max_block+1));
retval = ext2fs_get_array(max_block+1,
sizeof(struct ext2_block_relocate_entry), &ma->entries);
if (retval)
goto errout;
memset(ma->entries, 0, size);
ma->max_block = max_block;
/*
* Fill in the brel data structure
*/
brel->put = bma_put;
brel->get = bma_get;
brel->start_iter = bma_start_iter;
brel->next = bma_next;
brel->move = bma_move;
brel->delete = bma_delete;
brel->free = bma_free;
*new_brel = brel;
return 0;
errout:
bma_free(brel);
return retval;
}
static errcode_t bma_put(ext2_brel brel, blk_t old,
struct ext2_block_relocate_entry *ent)
{
struct brel_ma *ma;
ma = brel->priv_data;
if (old > ma->max_block)
return EXT2_ET_INVALID_ARGUMENT;
ma->entries[(unsigned)old] = *ent;
return 0;
}
static errcode_t bma_get(ext2_brel brel, blk_t old,
struct ext2_block_relocate_entry *ent)
{
struct brel_ma *ma;
ma = brel->priv_data;
if (old > ma->max_block)
return EXT2_ET_INVALID_ARGUMENT;
if (ma->entries[(unsigned)old].new == 0)
return ENOENT;
*ent = ma->entries[old];
return 0;
}
static errcode_t bma_start_iter(ext2_brel brel)
{
brel->current = 0;
return 0;
}
static errcode_t bma_next(ext2_brel brel, blk_t *old,
struct ext2_block_relocate_entry *ent)
{
struct brel_ma *ma;
ma = brel->priv_data;
while (++brel->current < ma->max_block) {
if (ma->entries[(unsigned)brel->current].new == 0)
continue;
*old = brel->current;
*ent = ma->entries[(unsigned)brel->current];
return 0;
}
*old = 0;
return 0;
}
static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new)
{
struct brel_ma *ma;
ma = brel->priv_data;
if ((old > ma->max_block) || (new > ma->max_block))
return EXT2_ET_INVALID_ARGUMENT;
if (ma->entries[(unsigned)old].new == 0)
return ENOENT;
ma->entries[(unsigned)new] = ma->entries[old];
ma->entries[(unsigned)old].new = 0;
return 0;
}
static errcode_t bma_delete(ext2_brel brel, blk_t old)
{
struct brel_ma *ma;
ma = brel->priv_data;
if (old > ma->max_block)
return EXT2_ET_INVALID_ARGUMENT;
if (ma->entries[(unsigned)old].new == 0)
return ENOENT;
ma->entries[(unsigned)old].new = 0;
return 0;
}
static errcode_t bma_free(ext2_brel brel)
{
struct brel_ma *ma;
if (!brel)
return 0;
ma = brel->priv_data;
if (ma) {
if (ma->entries)
ext2fs_free_mem(&ma->entries);
ext2fs_free_mem(&ma);
}
if (brel->name)
ext2fs_free_mem(&brel->name);
ext2fs_free_mem(&brel);
return 0;
}

View File

@ -0,0 +1,102 @@
/*
* check_desc.c --- Check the group descriptors of an ext2 filesystem
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
/*
* This routine sanity checks the group descriptors
*/
errcode_t ext2fs_check_desc(ext2_filsys fs)
{
ext2fs_block_bitmap bmap;
errcode_t retval;
dgrp_t i;
blk64_t first_block = fs->super->s_first_data_block;
blk64_t last_block = ext2fs_blocks_count(fs->super)-1;
blk64_t blk, b;
unsigned int j;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
retval = ext2fs_allocate_subcluster_bitmap(fs, "check_desc map", &bmap);
if (retval)
return retval;
for (i = 0; i < fs->group_desc_count; i++)
ext2fs_reserve_super_and_bgd(fs, i, bmap);
for (i = 0; i < fs->group_desc_count; i++) {
if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
first_block = ext2fs_group_first_block2(fs, i);
last_block = ext2fs_group_last_block2(fs, i);
}
/*
* Check to make sure the block bitmap for group is sane
*/
blk = ext2fs_block_bitmap_loc(fs, i);
if (blk < first_block || blk > last_block ||
ext2fs_test_block_bitmap2(bmap, blk)) {
retval = EXT2_ET_GDESC_BAD_BLOCK_MAP;
goto errout;
}
ext2fs_mark_block_bitmap2(bmap, blk);
/*
* Check to make sure the inode bitmap for group is sane
*/
blk = ext2fs_inode_bitmap_loc(fs, i);
if (blk < first_block || blk > last_block ||
ext2fs_test_block_bitmap2(bmap, blk)) {
retval = EXT2_ET_GDESC_BAD_INODE_MAP;
goto errout;
}
ext2fs_mark_block_bitmap2(bmap, blk);
/*
* Check to make sure the inode table for group is sane
*/
blk = ext2fs_inode_table_loc(fs, i);
if (blk < first_block ||
((blk + fs->inode_blocks_per_group - 1) > last_block)) {
retval = EXT2_ET_GDESC_BAD_INODE_TABLE;
goto errout;
}
for (j = 0, b = blk; j < fs->inode_blocks_per_group;
j++, b++) {
if (ext2fs_test_block_bitmap2(bmap, b)) {
retval = EXT2_ET_GDESC_BAD_INODE_TABLE;
goto errout;
}
ext2fs_mark_block_bitmap2(bmap, b);
}
}
errout:
ext2fs_free_block_bitmap(bmap);
return retval;
}

View File

@ -0,0 +1,474 @@
/*
* closefs.c --- close an ext2 filesystem
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <time.h>
#include <string.h>
#include "ext2_fs.h"
#include "ext2fsP.h"
static int test_root(int a, int b)
{
if (a == 0)
return 1;
while (1) {
if (a == 1)
return 1;
if (a % b)
return 0;
a = a / b;
}
}
int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
{
if (!(fs->super->s_feature_ro_compat &
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
return 1;
if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
test_root(group_block, 7))
return 1;
return 0;
}
/*
* ext2fs_super_and_bgd_loc2()
* @fs: ext2 fs pointer
* @group given block group
* @ret_super_blk: if !NULL, returns super block location
* @ret_old_desc_blk: if !NULL, returns location of the old block
* group descriptor
* @ret_new_desc_blk: if !NULL, returns location of meta_bg block
* group descriptor
* @ret_used_blks: if !NULL, returns number of blocks used by
* super block and group_descriptors.
*
* Returns errcode_t of 0
*/
errcode_t ext2fs_super_and_bgd_loc2(ext2_filsys fs,
dgrp_t group,
blk64_t *ret_super_blk,
blk64_t *ret_old_desc_blk,
blk64_t *ret_new_desc_blk,
blk_t *ret_used_blks)
{
blk64_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0;
unsigned int meta_bg, meta_bg_size;
blk_t numblocks = 0;
blk64_t old_desc_blocks;
int has_super;
group_block = ext2fs_group_first_block2(fs, group);
if (group_block == 0 && fs->blocksize == 1024)
group_block = 1; /* Deal with 1024 blocksize && bigalloc */
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
old_desc_blocks = fs->super->s_first_meta_bg;
else
old_desc_blocks =
fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
has_super = ext2fs_bg_has_super(fs, group);
if (has_super) {
super_blk = group_block;
numblocks++;
}
meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
meta_bg = group / meta_bg_size;
if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
(meta_bg < fs->super->s_first_meta_bg)) {
if (has_super) {
old_desc_blk = group_block + 1;
numblocks += old_desc_blocks;
}
} else {
if (((group % meta_bg_size) == 0) ||
((group % meta_bg_size) == 1) ||
((group % meta_bg_size) == (meta_bg_size-1))) {
if (has_super)
has_super = 1;
new_desc_blk = group_block + has_super;
numblocks++;
}
}
if (ret_super_blk)
*ret_super_blk = super_blk;
if (ret_old_desc_blk)
*ret_old_desc_blk = old_desc_blk;
if (ret_new_desc_blk)
*ret_new_desc_blk = new_desc_blk;
if (ret_used_blks)
*ret_used_blks = numblocks;
return 0;
}
/*
* This function returns the location of the superblock, block group
* descriptors for a given block group. It currently returns the
* number of free blocks assuming that inode table and allocation
* bitmaps will be in the group. This is not necessarily the case
* when the flex_bg feature is enabled, so callers should take care!
* It was only really intended for use by mke2fs, and even there it's
* not that useful.
*
* The ext2fs_super_and_bgd_loc2() function is 64-bit block number
* capable and returns the number of blocks used by super block and
* group descriptors.
*/
int ext2fs_super_and_bgd_loc(ext2_filsys fs,
dgrp_t group,
blk_t *ret_super_blk,
blk_t *ret_old_desc_blk,
blk_t *ret_new_desc_blk,
int *ret_meta_bg)
{
blk64_t ret_super_blk2;
blk64_t ret_old_desc_blk2;
blk64_t ret_new_desc_blk2;
blk_t ret_used_blks;
blk_t numblocks;
unsigned int meta_bg_size;
ext2fs_super_and_bgd_loc2(fs, group, &ret_super_blk2,
&ret_old_desc_blk2,
&ret_new_desc_blk2,
&ret_used_blks);
numblocks = ext2fs_group_blocks_count(fs, group);
if (ret_super_blk)
*ret_super_blk = (blk_t)ret_super_blk2;
if (ret_old_desc_blk)
*ret_old_desc_blk = (blk_t)ret_old_desc_blk2;
if (ret_new_desc_blk)
*ret_new_desc_blk = (blk_t)ret_new_desc_blk2;
if (ret_meta_bg) {
meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
*ret_meta_bg = group / meta_bg_size;
}
numblocks -= 2 + fs->inode_blocks_per_group + ret_used_blks;
return numblocks;
}
/*
* This function forces out the primary superblock. We need to only
* write out those fields which we have changed, since if the
* filesystem is mounted, it may have changed some of the other
* fields.
*
* It takes as input a superblock which has already been byte swapped
* (if necessary).
*
*/
static errcode_t write_primary_superblock(ext2_filsys fs,
struct ext2_super_block *super)
{
__u16 *old_super, *new_super;
int check_idx, write_idx, size;
errcode_t retval;
if (!fs->io->manager->write_byte || !fs->orig_super) {
fallback:
io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
retval = io_channel_write_blk64(fs->io, 1, -SUPERBLOCK_SIZE,
super);
io_channel_set_blksize(fs->io, fs->blocksize);
return retval;
}
old_super = (__u16 *) fs->orig_super;
new_super = (__u16 *) super;
for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) {
if (old_super[check_idx] == new_super[check_idx])
continue;
write_idx = check_idx;
for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++)
if (old_super[check_idx] == new_super[check_idx])
break;
size = 2 * (check_idx - write_idx);
#if 0
printf("Writing %d bytes starting at %d\n",
size, write_idx*2);
#endif
retval = io_channel_write_byte(fs->io,
SUPERBLOCK_OFFSET + (2 * write_idx), size,
new_super + write_idx);
if (retval == EXT2_ET_UNIMPLEMENTED)
goto fallback;
if (retval)
return retval;
}
memcpy(fs->orig_super, super, SUPERBLOCK_SIZE);
return 0;
}
/*
* Updates the revision to EXT2_DYNAMIC_REV
*/
void ext2fs_update_dynamic_rev(ext2_filsys fs)
{
struct ext2_super_block *sb = fs->super;
if (sb->s_rev_level > EXT2_GOOD_OLD_REV)
return;
sb->s_rev_level = EXT2_DYNAMIC_REV;
sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
/* s_uuid is handled by e2fsck already */
/* other fields should be left alone */
}
static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group,
blk_t group_block,
struct ext2_super_block *super_shadow)
{
dgrp_t sgrp = group;
if (sgrp > ((1 << 16) - 1))
sgrp = (1 << 16) - 1;
#ifdef WORDS_BIGENDIAN
super_shadow->s_block_group_nr = ext2fs_swab16(sgrp);
#else
fs->super->s_block_group_nr = sgrp;
#endif
return io_channel_write_blk64(fs->io, group_block, -SUPERBLOCK_SIZE,
super_shadow);
}
errcode_t ext2fs_flush(ext2_filsys fs)
{
return ext2fs_flush2(fs, 0);
}
errcode_t ext2fs_flush2(ext2_filsys fs, int flags)
{
dgrp_t i;
errcode_t retval;
unsigned long fs_state;
__u32 feature_incompat;
struct ext2_super_block *super_shadow = 0;
struct ext2_group_desc *group_shadow = 0;
#ifdef WORDS_BIGENDIAN
struct ext2_group_desc *gdp;
dgrp_t j;
#endif
char *group_ptr;
int old_desc_blocks;
struct ext2fs_numeric_progress_struct progress;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
fs_state = fs->super->s_state;
feature_incompat = fs->super->s_feature_incompat;
fs->super->s_wtime = fs->now ? fs->now : time(NULL);
fs->super->s_block_group_nr = 0;
#ifdef WORDS_BIGENDIAN
retval = EXT2_ET_NO_MEMORY;
retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
if (retval)
goto errout;
retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
&group_shadow);
if (retval)
goto errout;
memcpy(group_shadow, fs->group_desc, (size_t) fs->blocksize *
fs->desc_blocks);
/* swap the group descriptors */
for (j=0; j < fs->group_desc_count; j++) {
gdp = ext2fs_group_desc(fs, (struct opaque_ext2_group_desc *) group_shadow, j);
ext2fs_swap_group_desc2(fs, gdp);
}
#else
super_shadow = fs->super;
group_shadow = ext2fs_group_desc(fs, fs->group_desc, 0);
#endif
/*
* Set the state of the FS to be non-valid. (The state has
* already been backed up earlier, and will be restored after
* we write out the backup superblocks.)
*/
fs->super->s_state &= ~EXT2_VALID_FS;
fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
#ifdef WORDS_BIGENDIAN
*super_shadow = *fs->super;
ext2fs_swap_super(super_shadow);
#endif
/*
* If this is an external journal device, don't write out the
* block group descriptors or any of the backup superblocks
*/
if (fs->super->s_feature_incompat &
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
goto write_primary_superblock_only;
/*
* Write out the master group descriptors, and the backup
* superblocks and group descriptors.
*/
group_ptr = (char *) group_shadow;
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
old_desc_blocks = fs->super->s_first_meta_bg;
else
old_desc_blocks = fs->desc_blocks;
ext2fs_numeric_progress_init(fs, &progress, NULL,
fs->group_desc_count);
for (i = 0; i < fs->group_desc_count; i++) {
blk64_t super_blk, old_desc_blk, new_desc_blk;
ext2fs_numeric_progress_update(fs, &progress, i);
ext2fs_super_and_bgd_loc2(fs, i, &super_blk, &old_desc_blk,
&new_desc_blk, 0);
if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) {
retval = write_backup_super(fs, i, super_blk,
super_shadow);
if (retval)
goto errout;
}
if (fs->flags & EXT2_FLAG_SUPER_ONLY)
continue;
if ((old_desc_blk) &&
(!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) {
retval = io_channel_write_blk64(fs->io,
old_desc_blk, old_desc_blocks, group_ptr);
if (retval)
goto errout;
}
if (new_desc_blk) {
int meta_bg = i / EXT2_DESC_PER_BLOCK(fs->super);
retval = io_channel_write_blk64(fs->io, new_desc_blk,
1, group_ptr + (meta_bg*fs->blocksize));
if (retval)
goto errout;
}
}
ext2fs_numeric_progress_close(fs, &progress, NULL);
/*
* If the write_bitmaps() function is present, call it to
* flush the bitmaps. This is done this way so that a simple
* program that doesn't mess with the bitmaps doesn't need to
* drag in the bitmaps.c code.
*/
if (fs->write_bitmaps) {
retval = fs->write_bitmaps(fs);
if (retval)
goto errout;
}
write_primary_superblock_only:
/*
* Write out master superblock. This has to be done
* separately, since it is located at a fixed location
* (SUPERBLOCK_OFFSET). We flush all other pending changes
* out to disk first, just to avoid a race condition with an
* insy-tinsy window....
*/
fs->super->s_block_group_nr = 0;
fs->super->s_state = fs_state;
fs->super->s_feature_incompat = feature_incompat;
#ifdef WORDS_BIGENDIAN
*super_shadow = *fs->super;
ext2fs_swap_super(super_shadow);
#endif
if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC))
retval = io_channel_flush(fs->io);
retval = write_primary_superblock(fs, super_shadow);
if (retval)
goto errout;
fs->flags &= ~EXT2_FLAG_DIRTY;
if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC))
retval = io_channel_flush(fs->io);
errout:
fs->super->s_state = fs_state;
#ifdef WORDS_BIGENDIAN
if (super_shadow)
ext2fs_free_mem(&super_shadow);
if (group_shadow)
ext2fs_free_mem(&group_shadow);
#endif
return retval;
}
errcode_t ext2fs_close(ext2_filsys fs)
{
return ext2fs_close2(fs, 0);
}
errcode_t ext2fs_close2(ext2_filsys fs, int flags)
{
errcode_t retval;
int meta_blks;
io_stats stats = 0;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (fs->write_bitmaps) {
retval = fs->write_bitmaps(fs);
if (retval)
return retval;
}
if (fs->super->s_kbytes_written &&
fs->io->manager->get_stats)
fs->io->manager->get_stats(fs->io, &stats);
if (stats && stats->bytes_written && (fs->flags & EXT2_FLAG_RW)) {
fs->super->s_kbytes_written += stats->bytes_written >> 10;
meta_blks = fs->desc_blocks + 1;
if (!(fs->flags & EXT2_FLAG_SUPER_ONLY))
fs->super->s_kbytes_written += meta_blks /
(fs->blocksize / 1024);
if ((fs->flags & EXT2_FLAG_DIRTY) == 0)
fs->flags |= EXT2_FLAG_SUPER_ONLY | EXT2_FLAG_DIRTY;
}
if (fs->flags & EXT2_FLAG_DIRTY) {
retval = ext2fs_flush2(fs, flags);
if (retval)
return retval;
}
retval = ext2fs_mmp_stop(fs);
if (retval)
return retval;
ext2fs_free(fs);
return 0;
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 1987, 1988 by MIT Student Information Processing Board.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose is hereby granted, provided that
* the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. M.I.T. and the
* M.I.T. S.I.P.B. make no representations about the suitability of
* this software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#include "ext2_internal.h"
void com_err (const char *whoami,
errcode_t code,
const char *fmt, ...)
{
if(whoami)
ext2_log_trace("%s: ", whoami);
ext2_log_trace("error code: %i ", (int) code);
if(fmt)
ext2_log_trace(fmt);
ext2_log_trace("\n");
}

View File

@ -0,0 +1,70 @@
/*
* Header file for common error description library.
*
* Copyright 1988, Student Information Processing Board of the
* Massachusetts Institute of Technology.
*
* For copyright and distribution info, see the documentation supplied
* with this package.
*/
#if !defined(__COM_ERR_H) && !defined(__COM_ERR_H__)
#ifdef __GNUC__
#define COM_ERR_ATTR(x) __attribute__(x)
#else
#define COM_ERR_ATTR(x)
#endif
#ifndef DEBUG_GEKKO
#define OMIT_COM_ERR
#endif
#include <stddef.h>
#include <stdarg.h>
typedef long errcode_t;
struct error_table {
char const * const * msgs;
long base;
int n_msgs;
};
struct et_list;
extern void com_err (const char *, long, const char *, ...)
COM_ERR_ATTR((format(printf, 3, 4)));
extern void com_err_va (const char *whoami, errcode_t code, const char *fmt,
va_list args)
COM_ERR_ATTR((format(printf, 3, 0)));
extern char const *error_message (long);
extern void (*com_err_hook) (const char *, long, const char *, va_list);
extern void (*set_com_err_hook (void (*) (const char *, long,
const char *, va_list)))
(const char *, long, const char *, va_list);
extern void (*reset_com_err_hook (void)) (const char *, long,
const char *, va_list);
extern int init_error_table(const char * const *msgs, long base, int count);
extern errcode_t add_error_table(const struct error_table * et);
extern errcode_t remove_error_table(const struct error_table * et);
extern void add_to_error_table(struct et_list *new_table);
/* Provided for Heimdall compatibility */
extern const char *com_right(struct et_list *list, long code);
extern const char *com_right_r(struct et_list *list, long code, char *str, size_t len);
extern void initialize_error_table_r(struct et_list **list,
const char **messages,
int num_errors,
long base);
extern void free_error_table(struct et_list *et);
/* Provided for compatibility with other com_err libraries */
extern int et_list_lock(void);
extern int et_list_unlock(void);
#define __COM_ERR_H
#define __COM_ERR_H__
#endif /* !defined(__COM_ERR_H) && !defined(__COM_ERR_H__)*/

View File

@ -0,0 +1,603 @@
/* lib/config.h. Generated from config.h.in by configure. */
/* lib/config.h.in. Generated from configure.in by autoheader. */
#ifndef __CONFIG_H_
#define __CONFIG_H_
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Define to 1 if debugging the blkid library */
/* #undef CONFIG_BLKID_DEBUG */
/* Define to 1 to compile findfs */
/* #undef CONFIG_BUILD_FINDFS 1 */
/* Define to 1 if debugging ext3/4 journal code */
/* #undef CONFIG_JBD_DEBUG */
/* Define to 1 if the testio I/O manager should be enabled */
/* #undef CONFIG_TESTIO_DEBUG 1 */
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
/* #undef CRAY_STACKSEG_END */
/* Define to 1 if using `alloca.c'. */
/* #undef C_ALLOCA */
/* Define to 1 if ext2 compression enabled */
/* #undef ENABLE_COMPRESSION */
/* Define to 1 if ext3/4 htree support enabled */
#define ENABLE_HTREE 1
/* Define to 1 if translation of program messages to the user's native
language is requested. */
#define ENABLE_NLS 1
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
#define HAVE_ALLOCA_H 1
/* Define to 1 if you have the <argz.h> header file. */
#define HAVE_ARGZ_H 1
/* Define to 1 if you have the `asprintf' function. */
#define HAVE_ASPRINTF 1
/* Define to 1 if you have the `backtrace' function. */
/* #undef HAVE_BACKTRACE 1 */
/* Define to 1 if you have the `blkid_probe_get_topology' function. */
/* #undef HAVE_BLKID_PROBE_GET_TOPOLOGY */
/* Define to 1 if you have the `chflags' function. */
/* #undef HAVE_CHFLAGS */
/* Define if the GNU dcgettext() function is already present or preinstalled.
*/
/* #undef HAVE_DCGETTEXT 1 */
/* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you
don't. */
/* #undef HAVE_DECL_FEOF_UNLOCKED 1 */
/* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if
you don't. */
/* #undef HAVE_DECL_FGETS_UNLOCKED 0 */
/* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you
don't. */
/* #undef HAVE_DECL_GETC_UNLOCKED 1 */
/* Define to 1 if you have the declaration of `_snprintf', and to 0 if you
don't. */
/* #undef HAVE_DECL__SNPRINTF 0 */
/* Define to 1 if you have the declaration of `_snwprintf', and to 0 if you
don't. */
/* #undef HAVE_DECL__SNWPRINTF 0 */
/* Define to 1 if you have the <dirent.h> header file. */
#define HAVE_DIRENT_H 1
/* Define to 1 if dlopen/libdl exists */
/* #undef HAVE_DLOPEN 1 */
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
/* #undef HAVE_DOPRNT */
/* Define to 1 if you have the <errno.h> header file. */
#define HAVE_ERRNO_H 1
/* Define to 1 if you have the <execinfo.h> header file. */
/* #undef HAVE_EXECINFO_H 1 */
/* Define to 1 if Ext2 ioctls present */
/* #undef HAVE_EXT2_IOCTLS 1 */
/* Define to 1 if you have the `fallocate' function. */
/* #undef HAVE_FALLOCATE 1 */
/* Define to 1 if you have the `fallocate64' function. */
/* #undef HAVE_FALLOCATE64 1 */
/* Define to 1 if you have the `fchown' function. */
/* #undef HAVE_FCHOWN 1 */
/* Define to 1 if you have the `fdatasync' function. */
/* #undef HAVE_FDATASYNC 1 */
/* Define to 1 if you have the `fstat64' function. */
/* #undef HAVE_FSTAT64 1 */
/* Define to 1 if you have the `ftruncate64' function. */
/* #undef HAVE_FTRUNCATE64 1 */
/* Define to 1 if you have the `fwprintf' function. */
/* #undef HAVE_FWPRINTF 1 */
/* Define to 1 if you have the `getcwd' function. */
/* #undef HAVE_GETCWD 1 */
/* Define to 1 if you have the `getdtablesize' function. */
/* #undef HAVE_GETDTABLESIZE 1 */
/* Define to 1 if you have the `getegid' function. */
/* #undef HAVE_GETEGID 1 */
/* Define to 1 if you have the `geteuid' function. */
/* #undef HAVE_GETEUID 1 */
/* Define to 1 if you have the `getgid' function. */
/* #undef HAVE_GETGID 1 */
/* Define to 1 if you have the `getmntinfo' function. */
/* #undef HAVE_GETMNTINFO */
/* Define to 1 if you have the <getopt.h> header file. */
/* #undef HAVE_GETOPT_H 1 */
/* Define to 1 if you have the `getpagesize' function. */
/* #undef HAVE_GETPAGESIZE 1 */
/* Define to 1 if you have the `getrlimit' function. */
/* #undef HAVE_GETRLIMIT 1 */
/* Define to 1 if you have the `getrusage' function. */
/* #undef HAVE_GETRUSAGE 1 */
/* Define if the GNU gettext() function is already present or preinstalled. */
/* #undef HAVE_GETTEXT 1 */
/* Define to 1 if you have the `getuid' function. */
/* #undef HAVE_GETUID 1 */
/* Define if you have the iconv() function. */
/* #undef HAVE_ICONV 1 */
/* Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>. */
#define HAVE_INTMAX_T 1
/* Define to 1 if the system has the type `intptr_t'. */
#define HAVE_INTPTR_T 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, and
declares uintmax_t. */
#define HAVE_INTTYPES_H_WITH_UINTMAX 1
/* Define to 1 if you have the `jrand48' function. */
/* #undef HAVE_JRAND48 1 */
/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
/* #undef HAVE_LANGINFO_CODESET 1 */
/* Define if your <locale.h> file defines LC_MESSAGES. */
#define HAVE_LC_MESSAGES 1
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if you have the <linux/falloc.h> header file. */
/* #undef HAVE_LINUX_FALLOC_H 1 */
/* Define to 1 if you have the <linux/fd.h> header file. */
/* #undef HAVE_LINUX_FD_H 1 */
/* Define to 1 if you have the <linux/major.h> header file. */
/* #undef HAVE_LINUX_MAJOR_H 1 */
/* Define to 1 if you have the `llseek' function. */
/* #undef HAVE_LLSEEK 1 */
/* Define to 1 if llseek declared in unistd.h */
/* #undef HAVE_LLSEEK_PROTOTYPE */
/* Define to 1 if you have the <locale.h> header file. */
#define HAVE_LOCALE_H 1
/* Define if you have the 'long double' type. */
#define HAVE_LONG_DOUBLE 1
/* Define if you have the 'long long' type. */
#define HAVE_LONG_LONG 1
/* Define to 1 if you have the `lseek64' function. */
/* #undef HAVE_LSEEK64 1 */
/* Define to 1 if lseek64 declared in unistd.h */
#define HAVE_LSEEK64_PROTOTYPE 1
/* Define to 1 if you have the `mallinfo' function. */
/* #undef HAVE_MALLINFO 1 */
/* Define to 1 if you have the <malloc.h> header file. */
#define HAVE_MALLOC_H 1
/* Define to 1 if you have the `mbstowcs' function. */
#define HAVE_MBSTOWCS 1
/* Define to 1 if you have the `memalign' function. */
#define HAVE_MEMALIGN 1
/* Define to 1 if you have the <memory.h> header file. */
/* #undef HAVE_MEMORY_H 1 */
/* Define to 1 if you have the `mempcpy' function. */
/* #undef HAVE_MEMPCPY 1 */
/* Define to 1 if you have the `mmap' function. */
/* #undef HAVE_MMAP 1 */
/* Define to 1 if you have the <mntent.h> header file. */
/* #undef HAVE_MNTENT_H 1 */
/* Define to 1 if you have the `munmap' function. */
/* #undef HAVE_MUNMAP 1 */
/* Define to 1 if you have the `nanosleep' function. */
#define HAVE_NANOSLEEP 1
/* Define to 1 if you have the <netinet/in.h> header file. */
/* #undef HAVE_NETINET_IN_H 1 */
/* Define to 1 if you have the <net/if_dl.h> header file. */
/* #undef HAVE_NET_IF_DL_H */
/* Define to 1 if you have the <net/if.h> header file. */
/* #undef HAVE_NET_IF_H 1 */
/* Define to 1 if you have the <nl_types.h> header file. */
/* #undef HAVE_NL_TYPES_H 1 */
/* Define to 1 if you have the `open64' function. */
/* #undef HAVE_OPEN64 1 */
/* Define to 1 if optreset for getopt is present */
/* #undef HAVE_OPTRESET */
/* Define to 1 if you have the `pathconf' function. */
/* #undef HAVE_PATHCONF 1 */
/* Define to 1 if you have the <paths.h> header file. */
/* #undef HAVE_PATHS_H 1 */
/* Define to 1 if you have the `posix_fadvise' function. */
/* #undef HAVE_POSIX_FADVISE 1 */
/* Define to 1 if you have the `posix_memalign' function. */
/* #undef HAVE_POSIX_MEMALIGN 1 */
/* Define if your printf() function supports format strings with positions. */
#define HAVE_POSIX_PRINTF 1
/* Define to 1 if you have the `prctl' function. */
/* #undef HAVE_PRCTL 1 */
/* Define to 1 if you have the `putenv' function. */
/* #undef HAVE_PUTENV 1 */
/* Define to 1 if you have the `quotactl' function. */
/* #undef HAVE_QUOTACTL 1 */
/* Define to 1 if dirent has d_reclen */
/* #undef HAVE_RECLEN_DIRENT 1 */
/* Define to 1 if if struct sockaddr contains sa_len */
/* #undef HAVE_SA_LEN */
/* Define to 1 if you have the <semaphore.h> header file. */
/* #undef HAVE_SEMAPHORE_H 1 */
/* Define to 1 if sem_init() exists */
/* #undef HAVE_SEM_INIT 1 */
/* Define to 1 if you have the `setenv' function. */
/* #undef HAVE_SETENV 1 */
/* Define to 1 if you have the <setjmp.h> header file. */
/* #undef HAVE_SETJMP_H 1 */
/* Define to 1 if you have the `setlocale' function. */
#define HAVE_SETLOCALE 1
/* Define to 1 if you have the `setresgid' function. */
/* #undef HAVE_SETRESGID 1 */
/* Define to 1 if you have the `setresuid' function. */
/* #undef HAVE_SETRESUID 1*/
/* Define to 1 if you have the <signal.h> header file. */
#define HAVE_SIGNAL_H 1
/* Define to 1 if you have the `snprintf' function. */
#define HAVE_SNPRINTF 1
/* Define to 1 if you have the `srandom' function. */
/* #undef HAVE_SRANDOM 1 */
/* Define to 1 if struct stat has st_flags */
/* #undef HAVE_STAT_FLAGS */
/* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1
/* Define to 1 if you have the <stddef.h> header file. */
#define HAVE_STDDEF_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define if <stdint.h> exists, doesn't clash with <sys/types.h>, and declares
uintmax_t. */
#define HAVE_STDINT_H_WITH_UINTMAX 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `stpcpy' function. */
#define HAVE_STPCPY 1
/* Define to 1 if you have the `strcasecmp' function. */
#define HAVE_STRCASECMP 1
/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 1
/* Define to 1 if you have the <strings.h> header file. */
/* #undef HAVE_STRINGS_H 1 */
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strnlen' function. */
#define HAVE_STRNLEN 1
/* Define to 1 if you have the `strptime' function. */
#define HAVE_STRPTIME 1
/* Define to 1 if you have the `strtoul' function. */
#define HAVE_STRTOUL 1
/* Define to 1 if you have the `strtoull' function. */
#define HAVE_STRTOULL 1
/* Define to 1 if you have the `sync_file_range' function. */
/* #undef HAVE_SYNC_FILE_RANGE 1 */
/* Define to 1 if you have the `sysconf' function. */
/* #undef HAVE_SYSCONF 1 */
/* Define to 1 if you have the <sys/disklabel.h> header file. */
/* #undef HAVE_SYS_DISKLABEL_H */
/* Define to 1 if you have the <sys/disk.h> header file. */
/* #undef HAVE_SYS_DISK_H */
/* Define to 1 if you have the <sys/file.h> header file. */
#define HAVE_SYS_FILE_H 1
/* Define to 1 if you have the <sys/ioctl.h> header file. */
/* #undef HAVE_SYS_IOCTL_H 1 */
/* Define to 1 if you have the <sys/mkdev.h> header file. */
/* #undef HAVE_SYS_MKDEV_H */
/* Define to 1 if you have the <sys/mman.h> header file. */
/* #undef HAVE_SYS_MMAN_H 1 */
/* Define to 1 if you have the <sys/mount.h> header file. */
/* #undef HAVE_SYS_MOUNT_H 1 */
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/prctl.h> header file. */
/* #undef HAVE_SYS_PRCTL_H 1 */
/* Define to 1 if you have the <sys/queue.h> header file. */
#define HAVE_SYS_QUEUE_H 1
/* Define to 1 if you have the <sys/quota.h> header file. */
/* #undef HAVE_SYS_QUOTA_H 1 */
/* Define to 1 if you have the <sys/resource.h> header file. */
#define HAVE_SYS_RESOURCE_H 1
/* Define to 1 if you have the <sys/select.h> header file. */
/* #undef HAVE_SYS_SELECT_H 1 */
/* Define to 1 if you have the <sys/socket.h> header file. */
/* #undef HAVE_SYS_SOCKET_H 1 */
/* Define to 1 if you have the <sys/sockio.h> header file. */
/* #undef HAVE_SYS_SOCKIO_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/syscall.h> header file. */
/* #undef HAVE_SYS_SYSCALL_H 1 */
/* Define to 1 if you have the <sys/sysmacros.h> header file. */
/* #undef HAVE_SYS_SYSMACROS_H 1 */
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/un.h> header file. */
/* #undef HAVE_SYS_UN_H 1 */
/* Define to 1 if you have the <sys/wait.h> header file. */
#define HAVE_SYS_WAIT_H 1
/* Define to 1 if you have the <termios.h> header file. */
#define HAVE_TERMIOS_H 1
/* Define to 1 if you have the <termio.h> header file. */
/* #undef HAVE_TERMIO_H 1 */
/* Define to 1 if you have the `tsearch' function. */
/* #undef HAVE_TSEARCH 1 */
/* Define to 1 if ssize_t declared */
#define HAVE_TYPE_SSIZE_T 1
/* Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>. */
#define HAVE_UINTMAX_T 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define if you have the 'unsigned long long' type. */
#define HAVE_UNSIGNED_LONG_LONG 1
/* Define to 1 if you have the `usleep' function. */
#define HAVE_USLEEP 1
/* Define to 1 if you have the `utime' function. */
/* #undef HAVE_UTIME 1 */
/* Define to 1 if you have the <utime.h> header file. */
#define HAVE_UTIME_H 1
/* Define to 1 if you have the `valloc' function. */
/* #undef HAVE_VALLOC 1 */
/* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1
/* Define if you have the 'wchar_t' type. */
#define HAVE_WCHAR_T 1
/* Define to 1 if you have the `wcslen' function. */
#define HAVE_WCSLEN 1
/* Define if you have the 'wint_t' type. */
#define HAVE_WINT_T 1
/* Define to 1 if you have the `__argz_count' function. */
/* #undef HAVE___ARGZ_COUNT 1 */
/* Define to 1 if you have the `__argz_next' function. */
/* #undef HAVE___ARGZ_NEXT 1 */
/* Define to 1 if you have the `__argz_stringify' function. */
/* #undef HAVE___ARGZ_STRINGIFY 1 */
/* Define to 1 if you have the `__fsetlocking' function. */
/* #undef HAVE___FSETLOCKING 1 */
/* Define to 1 if you have the `__secure_getenv' function. */
/* #undef HAVE___SECURE_GETENV 1 */
/* Define as const if the declaration of iconv() needs const. */
/* #undef ICONV_CONST */
/* Define if integer division by zero raises signal SIGFPE. */
/* #undef INTDIV0_RAISES_SIGFPE 1 */
/* package name for gettext */
#define PACKAGE "e2fsprogs"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
/* Define to the full name of this package. */
#define PACKAGE_NAME ""
/* Define to the full name and version of this package. */
#define PACKAGE_STRING ""
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME ""
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION ""
/* Define if <inttypes.h> exists and defines unusable PRI* macros. */
/* #undef PRI_MACROS_BROKEN */
/* The size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
/* The size of `long', as computed by sizeof. */
#define SIZEOF_LONG 4
/* The size of `long long', as computed by sizeof. */
#define SIZEOF_LONG_LONG 8
/* The size of `short', as computed by sizeof. */
#define SIZEOF_SHORT 2
/* Define as the maximum value of type 'size_t', if the system doesn't define
it. */
/* #undef SIZE_MAX */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at runtime.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
/* #undef STACK_DIRECTION */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* If the compiler supports a TLS storage class define it to that here */
/* #undef TLS __thread */
/* Define to 1 to build uuidd */
/* #undef USE_UUIDD 1 */
/* version for gettext */
#define VERSION "0.14.1"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#define WORDS_BIGENDIAN 1
/* Define to 1 if Apple Darwin libintl workaround is needed */
/* #undef _INTL_REDIRECT_MACROS */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif
/* Define to `long int' if <sys/types.h> does not define. */
/* #undef off_t */
/* Define as the type of the result of subtracting two pointers, if the system
doesn't define it. */
/* #undef ptrdiff_t */
/* Define to empty if the C compiler doesn't support this keyword. */
/* #undef signed */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
/* Define to unsigned long or unsigned long long if <stdint.h> and
<inttypes.h> don't define. */
/* #undef uintmax_t */
#endif

View File

@ -0,0 +1,74 @@
/*
* crc16.c
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*/
#include "config.h"
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_types.h"
#include "crc16.h"
/** CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1) */
static __u16 const crc16_table[256] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
/**
* Compute the CRC-16 for the data buffer
*
* @param crc previous CRC value
* @param buffer data pointer
* @param len number of bytes in the buffer
* @return the updated CRC value
*/
crc16_t ext2fs_crc16(crc16_t crc, const void *buffer, unsigned int len)
{
const unsigned char *cp = buffer;
while (len--)
/*
* for an unknown reason, PPC treats __u16 as signed
* and keeps doing sign extension on the value.
* Instead, use only the low 16 bits of an unsigned
* int for holding the CRC value to avoid this.
*/
crc = (((crc >> 8) & 0xffU) ^
crc16_table[(crc ^ *cp++) & 0xffU]) & 0x0000ffffU;
return crc;
}

View File

@ -0,0 +1,26 @@
/*
* crc16.h - CRC-16 routine
*
* Implements the standard CRC-16:
* Width 16
* Poly 0x8005 (x16 + x15 + x2 + 1)
* Init 0
*
* Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*/
#ifndef __CRC16_H
#define __CRC16_H
/* for an unknown reason, PPC treats __u16 as signed and keeps doing sign
* extension on the value. Instead, use only the low 16 bits of an
* unsigned int for holding the CRC value to avoid this.
*/
typedef unsigned int crc16_t;
extern crc16_t ext2fs_crc16(crc16_t crc, const void *buffer, unsigned int len);
#endif /* __CRC16_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
/*
* This is the CRC32c polynomial, as outlined by Castagnoli.
* 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+
* x^8+x^6+x^0
*/
#define CRCPOLY_LE 0x82F63B78
#define CRCPOLY_BE 0x1EDC6F41
/* How many bits at a time to use. Valid values are 1, 2, 4, 8, 32 and 64. */
/* For less performance-sensitive, use 4 */
#ifndef CRC_LE_BITS
# define CRC_LE_BITS 64
#endif
#ifndef CRC_BE_BITS
# define CRC_BE_BITS 64
#endif
/*
* Little-endian CRC computation. Used with serial bit streams sent
* lsbit-first. Be sure to use cpu_to_le32() to append the computed CRC.
*/
#if CRC_LE_BITS > 64 || CRC_LE_BITS < 1 || CRC_LE_BITS == 16 || \
CRC_LE_BITS & CRC_LE_BITS-1
# error "CRC_LE_BITS must be one of {1, 2, 4, 8, 32, 64}"
#endif
/*
* Big-endian CRC computation. Used with serial bit streams sent
* msbit-first. Be sure to use cpu_to_be32() to append the computed CRC.
*/
#if CRC_BE_BITS > 64 || CRC_BE_BITS < 1 || CRC_BE_BITS == 16 || \
CRC_BE_BITS & CRC_BE_BITS-1
# error "CRC_BE_BITS must be one of {1, 2, 4, 8, 32, 64}"
#endif
#define ___constant_swab32(x) \
((uint32_t)( \
(((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
#if (__GNUC__ >= 3)
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely(x) (x)
#define unlikely(x) (x)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,289 @@
/*
* csum.c --- checksumming of ext3 structures
*
* Copyright (C) 2006 Cluster File Systems, Inc.
* Copyright (C) 2006, 2007 by Andreas Dilger <adilger@clusterfs.com>
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#include "crc16.h"
#include <assert.h>
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#ifdef DEBUG
#define STATIC
#else
#define STATIC static
#endif
STATIC __u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group)
{
__u16 crc = 0;
struct ext2_group_desc *desc;
size_t size;
size = fs->super->s_desc_size;
if (size < EXT2_MIN_DESC_SIZE)
size = EXT2_MIN_DESC_SIZE;
if (size > sizeof(struct ext4_group_desc)) {
printf("%s: illegal s_desc_size(%zd)\n", __func__, size);
size = sizeof(struct ext4_group_desc);
}
desc = ext2fs_group_desc(fs, fs->group_desc, group);
if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
size_t offset = offsetof(struct ext2_group_desc, bg_checksum);
#ifdef WORDS_BIGENDIAN
struct ext4_group_desc swabdesc;
/* Have to swab back to little-endian to do the checksum */
memcpy(&swabdesc, desc, size);
ext2fs_swap_group_desc2(fs,
(struct ext2_group_desc *) &swabdesc);
desc = (struct ext2_group_desc *) &swabdesc;
group = ext2fs_swab32(group);
#endif
crc = ext2fs_crc16(~0, fs->super->s_uuid,
sizeof(fs->super->s_uuid));
crc = ext2fs_crc16(crc, &group, sizeof(group));
crc = ext2fs_crc16(crc, desc, offset);
offset += sizeof(desc->bg_checksum); /* skip checksum */
/* for checksum of struct ext4_group_desc do the rest...*/
if (offset < size) {
crc = ext2fs_crc16(crc, (char *)desc + offset,
size - offset);
}
}
return crc;
}
int ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group)
{
if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_GDT_CSUM) &&
(ext2fs_bg_checksum(fs, group) !=
ext2fs_group_desc_csum(fs, group)))
return 0;
return 1;
}
void ext2fs_group_desc_csum_set(ext2_filsys fs, dgrp_t group)
{
if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
return;
/* ext2fs_bg_checksum_set() sets the actual checksum field but
* does not calculate the checksum itself. */
ext2fs_bg_checksum_set(fs, group, ext2fs_group_desc_csum(fs, group));
}
static __u32 find_last_inode_ingrp(ext2fs_inode_bitmap bitmap,
__u32 inodes_per_grp, dgrp_t grp_no)
{
ext2_ino_t i, start_ino, end_ino;
start_ino = grp_no * inodes_per_grp + 1;
end_ino = start_ino + inodes_per_grp - 1;
for (i = end_ino; i >= start_ino; i--) {
if (ext2fs_fast_test_inode_bitmap2(bitmap, i))
return i - start_ino + 1;
}
return inodes_per_grp;
}
/* update the bitmap flags, set the itable high watermark, and calculate
* checksums for the group descriptors */
errcode_t ext2fs_set_gdt_csum(ext2_filsys fs)
{
struct ext2_super_block *sb = fs->super;
int dirty = 0;
dgrp_t i;
if (!fs->inode_map)
return EXT2_ET_NO_INODE_BITMAP;
if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
return 0;
for (i = 0; i < fs->group_desc_count; i++) {
__u32 old_csum = ext2fs_bg_checksum(fs, i);
__u32 old_unused = ext2fs_bg_itable_unused(fs, i);
__u32 old_flags = ext2fs_bg_flags(fs, i);
__u32 old_free_inodes_count = ext2fs_bg_free_inodes_count(fs, i);
if (old_free_inodes_count == sb->s_inodes_per_group) {
ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
ext2fs_bg_itable_unused_set(fs, i, sb->s_inodes_per_group);
} else {
int unused =
sb->s_inodes_per_group -
find_last_inode_ingrp(fs->inode_map,
sb->s_inodes_per_group, i);
ext2fs_bg_flags_clear(fs, i, EXT2_BG_INODE_UNINIT);
ext2fs_bg_itable_unused_set(fs, i, unused);
}
ext2fs_group_desc_csum_set(fs, i);
if (old_flags != ext2fs_bg_flags(fs, i))
dirty = 1;
if (old_unused != ext2fs_bg_itable_unused(fs, i))
dirty = 1;
if (old_csum != ext2fs_bg_checksum(fs, i))
dirty = 1;
}
if (dirty)
ext2fs_mark_super_dirty(fs);
return 0;
}
#ifdef DEBUG
#include "e2p/e2p.h"
void print_csum(const char *msg, ext2_filsys fs, dgrp_t group)
{
__u16 crc1, crc2, crc3;
dgrp_t swabgroup;
struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc, group);
size_t size;
struct ext2_super_block *sb = fs->super;
int offset = offsetof(struct ext2_group_desc, bg_checksum);
#ifdef WORDS_BIGENDIAN
struct ext4_group_desc swabdesc;
#endif
size = fs->super->s_desc_size;
if (size < EXT2_MIN_DESC_SIZE)
size = EXT2_MIN_DESC_SIZE;
if (size > sizeof(struct ext4_group_desc))
size = sizeof(struct ext4_group_desc);
#ifdef WORDS_BIGENDIAN
/* Have to swab back to little-endian to do the checksum */
memcpy(&swabdesc, desc, size);
ext2fs_swap_group_desc2(fs, (struct ext2_group_desc *) &swabdesc);
desc = (struct ext2_group_desc *) &swabdesc;
swabgroup = ext2fs_swab32(group);
#else
swabgroup = group;
#endif
crc1 = ext2fs_crc16(~0, sb->s_uuid, sizeof(fs->super->s_uuid));
crc2 = ext2fs_crc16(crc1, &swabgroup, sizeof(swabgroup));
crc3 = ext2fs_crc16(crc2, desc, offset);
offset += sizeof(desc->bg_checksum); /* skip checksum */
/* for checksum of struct ext4_group_desc do the rest...*/
if (offset < size)
crc3 = ext2fs_crc16(crc3, (char *)desc + offset, size - offset);
printf("%s: UUID %s(%04x), grp %u(%04x): %04x=%04x\n",
msg, e2p_uuid2str(sb->s_uuid), crc1, group, crc2, crc3,
ext2fs_group_desc_csum(fs, group));
}
unsigned char sb_uuid[16] = { 0x4f, 0x25, 0xe8, 0xcf, 0xe7, 0x97, 0x48, 0x23,
0xbe, 0xfa, 0xa7, 0x88, 0x4b, 0xae, 0xec, 0xdb };
int main(int argc, char **argv)
{
struct ext2_super_block param;
errcode_t retval;
ext2_filsys fs;
int i;
__u16 csum1, csum2, csum_known = 0xd3a4;
memset(&param, 0, sizeof(param));
ext2fs_blocks_count_set(&param, 32768);
retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, &param,
test_io_manager, &fs);
if (retval) {
com_err("setup", retval,
"While initializing filesystem");
exit(1);
}
memcpy(fs->super->s_uuid, sb_uuid, 16);
fs->super->s_feature_ro_compat = EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
for (i=0; i < fs->group_desc_count; i++) {
ext2fs_block_bitmap_loc_set(fs, i, 124);
ext2fs_inode_bitmap_loc_set(fs, i, 125);
ext2fs_inode_table_loc_set(fs, i, 126);
ext2fs_bg_free_blocks_count_set(fs, i, 31119);
ext2fs_bg_free_inodes_count_set(fs, i, 15701);
ext2fs_bg_used_dirs_count_set(fs, i, 2);
ext2fs_bg_flags_zap(fs, i);
};
csum1 = ext2fs_group_desc_csum(fs, 0);
print_csum("csum0000", fs, 0);
if (csum1 != csum_known) {
printf("checksum for group 0 should be %04x\n", csum_known);
exit(1);
}
csum2 = ext2fs_group_desc_csum(fs, 1);
print_csum("csum0001", fs, 1);
if (csum1 == csum2) {
printf("checksums for different groups shouldn't match\n");
exit(1);
}
csum2 = ext2fs_group_desc_csum(fs, 2);
print_csum("csumffff", fs, 2);
if (csum1 == csum2) {
printf("checksums for different groups shouldn't match\n");
exit(1);
}
ext2fs_bg_checksum_set(fs, 0, csum1);
csum2 = ext2fs_group_desc_csum(fs, 0);
print_csum("csum_set", fs, 0);
if (csum1 != csum2) {
printf("checksums should not depend on checksum field\n");
exit(1);
}
if (!ext2fs_group_desc_csum_verify(fs, 0)) {
printf("checksums should verify against gd_checksum\n");
exit(1);
}
memset(fs->super->s_uuid, 0x30, sizeof(fs->super->s_uuid));
print_csum("new_uuid", fs, 0);
if (ext2fs_group_desc_csum_verify(fs, 0) != 0) {
printf("checksums for different filesystems shouldn't match\n");
exit(1);
}
csum1 = ext2fs_group_desc_csum(fs, 0);
ext2fs_bg_checksum_set(fs, 0, csum1);
print_csum("csum_new", fs, 0);
ext2fs_bg_free_blocks_count_set(fs, 0, 1);
csum2 = ext2fs_group_desc_csum(fs, 0);
print_csum("csum_blk", fs, 0);
if (csum1 == csum2) {
printf("checksums for different data shouldn't match\n");
exit(1);
}
return 0;
}
#endif

View File

@ -0,0 +1,415 @@
/*
* dblist.c -- directory block list functions
*
* Copyright 1997 by Theodore Ts'o
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <time.h>
#include "ext2_fs.h"
#include "ext2fsP.h"
static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b);
static EXT2_QSORT_TYPE dir_block_cmp2(const void *a, const void *b);
static EXT2_QSORT_TYPE (*sortfunc32)(const void *a, const void *b);
/*
* Returns the number of directories in the filesystem as reported by
* the group descriptors. Of course, the group descriptors could be
* wrong!
*/
errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs)
{
dgrp_t i;
ext2_ino_t num_dirs, max_dirs;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
num_dirs = 0;
max_dirs = fs->super->s_inodes_per_group;
for (i = 0; i < fs->group_desc_count; i++) {
if (ext2fs_bg_used_dirs_count(fs, i) > max_dirs)
num_dirs += max_dirs / 8;
else
num_dirs += ext2fs_bg_used_dirs_count(fs, i);
}
if (num_dirs > fs->super->s_inodes_count)
num_dirs = fs->super->s_inodes_count;
*ret_num_dirs = num_dirs;
return 0;
}
/*
* helper function for making a new directory block list (for
* initialize and copy).
*/
static errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size,
ext2_ino_t count,
struct ext2_db_entry2 *list,
ext2_dblist *ret_dblist)
{
ext2_dblist dblist = 0;
errcode_t retval;
ext2_ino_t num_dirs;
size_t len;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if ((ret_dblist == 0) && fs->dblist &&
(fs->dblist->magic == EXT2_ET_MAGIC_DBLIST))
return 0;
retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist);
if (retval)
goto cleanup;
memset(dblist, 0, sizeof(struct ext2_struct_dblist));
dblist->magic = EXT2_ET_MAGIC_DBLIST;
dblist->fs = fs;
if (size)
dblist->size = size;
else {
retval = ext2fs_get_num_dirs(fs, &num_dirs);
if (retval)
goto cleanup;
dblist->size = (num_dirs * 2) + 12;
}
len = (size_t) sizeof(struct ext2_db_entry2) * dblist->size;
dblist->count = count;
retval = ext2fs_get_array(dblist->size, sizeof(struct ext2_db_entry2),
&dblist->list);
if (retval)
goto cleanup;
if (list)
memcpy(dblist->list, list, len);
else
memset(dblist->list, 0, len);
if (ret_dblist)
*ret_dblist = dblist;
else
fs->dblist = dblist;
return 0;
cleanup:
if (dblist)
ext2fs_free_mem(&dblist);
return retval;
}
/*
* Initialize a directory block list
*/
errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist)
{
ext2_dblist dblist;
errcode_t retval;
retval = make_dblist(fs, 0, 0, 0, &dblist);
if (retval)
return retval;
dblist->sorted = 1;
if (ret_dblist)
*ret_dblist = dblist;
else
fs->dblist = dblist;
return 0;
}
/*
* Copy a directory block list
*/
errcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest)
{
ext2_dblist dblist;
errcode_t retval;
retval = make_dblist(src->fs, src->size, src->count, src->list,
&dblist);
if (retval)
return retval;
dblist->sorted = src->sorted;
*dest = dblist;
return 0;
}
/*
* Close a directory block list
*
* (moved to closefs.c)
*/
/*
* Add a directory block to the directory block list
*/
errcode_t ext2fs_add_dir_block2(ext2_dblist dblist, ext2_ino_t ino,
blk64_t blk, e2_blkcnt_t blockcnt)
{
struct ext2_db_entry2 *new_entry;
errcode_t retval;
unsigned long old_size;
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
if (dblist->count >= dblist->size) {
old_size = dblist->size * sizeof(struct ext2_db_entry2);
dblist->size += dblist->size > 200 ? dblist->size / 2 : 100;
retval = ext2fs_resize_mem(old_size, (size_t) dblist->size *
sizeof(struct ext2_db_entry2),
&dblist->list);
if (retval) {
dblist->size = old_size / sizeof(struct ext2_db_entry2);
return retval;
}
}
new_entry = dblist->list + ( dblist->count++);
new_entry->blk = blk;
new_entry->ino = ino;
new_entry->blockcnt = blockcnt;
dblist->sorted = 0;
return 0;
}
/*
* Change the directory block to the directory block list
*/
errcode_t ext2fs_set_dir_block2(ext2_dblist dblist, ext2_ino_t ino,
blk64_t blk, e2_blkcnt_t blockcnt)
{
dgrp_t i;
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
for (i=0; i < dblist->count; i++) {
if ((dblist->list[i].ino != ino) ||
(dblist->list[i].blockcnt != blockcnt))
continue;
dblist->list[i].blk = blk;
dblist->sorted = 0;
return 0;
}
return EXT2_ET_DB_NOT_FOUND;
}
void ext2fs_dblist_sort2(ext2_dblist dblist,
EXT2_QSORT_TYPE (*sortfunc)(const void *,
const void *))
{
if (!sortfunc)
sortfunc = dir_block_cmp2;
qsort(dblist->list, (size_t) dblist->count,
sizeof(struct ext2_db_entry2), sortfunc);
dblist->sorted = 1;
}
/*
* This function iterates over the directory block list
*/
errcode_t ext2fs_dblist_iterate2(ext2_dblist dblist,
int (*func)(ext2_filsys fs,
struct ext2_db_entry2 *db_info,
void *priv_data),
void *priv_data)
{
unsigned long long i;
int ret;
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
if (!dblist->sorted)
ext2fs_dblist_sort2(dblist, 0);
for (i=0; i < dblist->count; i++) {
ret = (*func)(dblist->fs, &dblist->list[i], priv_data);
if (ret & DBLIST_ABORT)
return 0;
}
return 0;
}
static EXT2_QSORT_TYPE dir_block_cmp2(const void *a, const void *b)
{
const struct ext2_db_entry2 *db_a =
(const struct ext2_db_entry2 *) a;
const struct ext2_db_entry2 *db_b =
(const struct ext2_db_entry2 *) b;
if (db_a->blk != db_b->blk)
return (int) (db_a->blk - db_b->blk);
if (db_a->ino != db_b->ino)
return (int) (db_a->ino - db_b->ino);
return (db_a->blockcnt - db_b->blockcnt);
}
blk64_t ext2fs_dblist_count2(ext2_dblist dblist)
{
return dblist->count;
}
errcode_t ext2fs_dblist_get_last2(ext2_dblist dblist,
struct ext2_db_entry2 **entry)
{
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
if (dblist->count == 0)
return EXT2_ET_DBLIST_EMPTY;
if (entry)
*entry = dblist->list + ( dblist->count-1);
return 0;
}
errcode_t ext2fs_dblist_drop_last(ext2_dblist dblist)
{
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
if (dblist->count == 0)
return EXT2_ET_DBLIST_EMPTY;
dblist->count--;
return 0;
}
/*
* Legacy 32-bit versions
*/
/*
* Add a directory block to the directory block list
*/
errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
int blockcnt)
{
return ext2fs_add_dir_block2(dblist, ino, blk, blockcnt);
}
/*
* Change the directory block to the directory block list
*/
errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
int blockcnt)
{
return ext2fs_set_dir_block2(dblist, ino, blk, blockcnt);
}
void ext2fs_dblist_sort(ext2_dblist dblist,
EXT2_QSORT_TYPE (*sortfunc)(const void *,
const void *))
{
if (sortfunc) {
sortfunc32 = sortfunc;
sortfunc = dir_block_cmp;
} else
sortfunc = dir_block_cmp2;
qsort(dblist->list, (size_t) dblist->count,
sizeof(struct ext2_db_entry2), sortfunc);
dblist->sorted = 1;
}
/*
* This function iterates over the directory block list
*/
struct iterate_passthrough {
int (*func)(ext2_filsys fs,
struct ext2_db_entry *db_info,
void *priv_data);
void *priv_data;
};
static int passthrough_func(ext2_filsys fs,
struct ext2_db_entry2 *db_info,
void *priv_data)
{
struct iterate_passthrough *p = priv_data;
struct ext2_db_entry db;
int ret;
db.ino = db_info->ino;
db.blk = (blk_t) db_info->blk;
db.blockcnt = (int) db_info->blockcnt;
ret = (p->func)(fs, &db, p->priv_data);
db_info->ino = db.ino;
db_info->blk = db.blk;
db_info->blockcnt = db.blockcnt;
return ret;
}
errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
int (*func)(ext2_filsys fs,
struct ext2_db_entry *db_info,
void *priv_data),
void *priv_data)
{
struct iterate_passthrough pass;
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
pass.func = func;
pass.priv_data = priv_data;
return ext2fs_dblist_iterate2(dblist, passthrough_func, &pass);
}
static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b)
{
const struct ext2_db_entry2 *db_a =
(const struct ext2_db_entry2 *) a;
const struct ext2_db_entry2 *db_b =
(const struct ext2_db_entry2 *) b;
struct ext2_db_entry a32, b32;
a32.ino = db_a->ino; a32.blk = db_a->blk;
a32.blockcnt = db_a->blockcnt;
b32.ino = db_b->ino; b32.blk = db_b->blk;
b32.blockcnt = db_b->blockcnt;
return sortfunc32(&a32, &b32);
}
int ext2fs_dblist_count(ext2_dblist dblist)
{
return dblist->count;
}
errcode_t ext2fs_dblist_get_last(ext2_dblist dblist,
struct ext2_db_entry **entry)
{
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
static struct ext2_db_entry ret_entry;
struct ext2_db_entry2 *last;
if (dblist->count == 0)
return EXT2_ET_DBLIST_EMPTY;
if (!entry)
return 0;
last = dblist->list + dblist->count -1;
ret_entry.ino = last->ino;
ret_entry.blk = last->blk;
ret_entry.blockcnt = last->blockcnt;
*entry = &ret_entry;
return 0;
}

View File

@ -0,0 +1,80 @@
/*
* dblist_dir.c --- iterate by directory entry
*
* Copyright 1997 by Theodore Ts'o
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <time.h>
#include "ext2_fs.h"
#include "ext2fsP.h"
static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry2 *db_info,
void *priv_data);
errcode_t ext2fs_dblist_dir_iterate(ext2_dblist dblist,
int flags,
char *block_buf,
int (*func)(ext2_ino_t dir,
int entry,
struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *priv_data),
void *priv_data)
{
errcode_t retval;
struct dir_context ctx;
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
ctx.dir = 0;
ctx.flags = flags;
if (block_buf)
ctx.buf = block_buf;
else {
retval = ext2fs_get_mem(dblist->fs->blocksize, &ctx.buf);
if (retval)
return retval;
}
ctx.func = func;
ctx.priv_data = priv_data;
ctx.errcode = 0;
retval = ext2fs_dblist_iterate2(dblist, db_dir_proc, &ctx);
if (!block_buf)
ext2fs_free_mem(&ctx.buf);
if (retval)
return retval;
return ctx.errcode;
}
static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry2 *db_info,
void *priv_data)
{
struct dir_context *ctx;
int ret;
ctx = (struct dir_context *) priv_data;
ctx->dir = db_info->ino;
ctx->errcode = 0;
ret = ext2fs_process_dir_block(fs, &db_info->blk,
db_info->blockcnt, 0, 0, priv_data);
if ((ret & BLOCK_ABORT) && !ctx->errcode)
return DBLIST_ABORT;
return 0;
}

View File

@ -0,0 +1,271 @@
/*
* dir_iterate.c --- ext2fs directory iteration operations
*
* Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#include "ext2_fs.h"
#include "ext2fsP.h"
#define EXT4_MAX_REC_LEN ((1<<16)-1)
errcode_t ext2fs_get_rec_len(ext2_filsys fs,
struct ext2_dir_entry *dirent,
unsigned int *rec_len)
{
unsigned int len = dirent->rec_len;
if (fs->blocksize < 65536)
*rec_len = len;
else if (len == EXT4_MAX_REC_LEN || len == 0)
*rec_len = fs->blocksize;
else
*rec_len = (len & 65532) | ((len & 3) << 16);
return 0;
}
errcode_t ext2fs_set_rec_len(ext2_filsys fs,
unsigned int len,
struct ext2_dir_entry *dirent)
{
if ((len > fs->blocksize) || (fs->blocksize > (1 << 18)) || (len & 3))
return EINVAL;
if (len < 65536) {
dirent->rec_len = len;
return 0;
}
if (len == fs->blocksize) {
if (fs->blocksize == 65536)
dirent->rec_len = EXT4_MAX_REC_LEN;
else
dirent->rec_len = 0;
} else
dirent->rec_len = (len & 65532) | ((len >> 16) & 3);
return 0;
}
/*
* This function checks to see whether or not a potential deleted
* directory entry looks valid. What we do is check the deleted entry
* and each successive entry to make sure that they all look valid and
* that the last deleted entry ends at the beginning of the next
* undeleted entry. Returns 1 if the deleted entry looks valid, zero
* if not valid.
*/
static int ext2fs_validate_entry(ext2_filsys fs, char *buf,
unsigned int offset,
unsigned int final_offset)
{
struct ext2_dir_entry *dirent;
unsigned int rec_len;
#define DIRENT_MIN_LENGTH 12
while ((offset < final_offset) &&
(offset <= fs->blocksize - DIRENT_MIN_LENGTH)) {
dirent = (struct ext2_dir_entry *)(buf + offset);
if (ext2fs_get_rec_len(fs, dirent, &rec_len))
return 0;
offset += rec_len;
if ((rec_len < 8) ||
((rec_len % 4) != 0) ||
((((unsigned) dirent->name_len & 0xFF)+8) > rec_len))
return 0;
}
return (offset == final_offset);
}
errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
ext2_ino_t dir,
int flags,
char *block_buf,
int (*func)(ext2_ino_t dir,
int entry,
struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *priv_data),
void *priv_data)
{
struct dir_context ctx;
errcode_t retval;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
retval = ext2fs_check_directory(fs, dir);
if (retval)
return retval;
ctx.dir = dir;
ctx.flags = flags;
if (block_buf)
ctx.buf = block_buf;
else {
retval = ext2fs_get_mem(fs->blocksize, &ctx.buf);
if (retval)
return retval;
}
ctx.func = func;
ctx.priv_data = priv_data;
ctx.errcode = 0;
retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_READ_ONLY, 0,
ext2fs_process_dir_block, &ctx);
if (!block_buf)
ext2fs_free_mem(&ctx.buf);
if (retval)
return retval;
return ctx.errcode;
}
struct xlate {
int (*func)(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *priv_data);
void *real_private;
};
static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)),
int entry EXT2FS_ATTR((unused)),
struct ext2_dir_entry *dirent, int offset,
int blocksize, char *buf, void *priv_data)
{
struct xlate *xl = (struct xlate *) priv_data;
return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private);
}
extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
ext2_ino_t dir,
int flags,
char *block_buf,
int (*func)(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *priv_data),
void *priv_data)
{
struct xlate xl;
xl.real_private = priv_data;
xl.func = func;
return ext2fs_dir_iterate2(fs, dir, flags, block_buf,
xlate_func, &xl);
}
/*
* Helper function which is private to this module. Used by
* ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
*/
int ext2fs_process_dir_block(ext2_filsys fs,
blk64_t *blocknr,
e2_blkcnt_t blockcnt,
blk64_t ref_block EXT2FS_ATTR((unused)),
int ref_offset EXT2FS_ATTR((unused)),
void *priv_data)
{
struct dir_context *ctx = (struct dir_context *) priv_data;
unsigned int offset = 0;
unsigned int next_real_entry = 0;
int ret = 0;
int changed = 0;
int do_abort = 0;
unsigned int rec_len, size;
int entry;
struct ext2_dir_entry *dirent;
if (blockcnt < 0)
return 0;
entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
ctx->errcode = ext2fs_read_dir_block3(fs, *blocknr, ctx->buf, 0);
if (ctx->errcode)
return BLOCK_ABORT;
while (offset < fs->blocksize) {
dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
if (ext2fs_get_rec_len(fs, dirent, &rec_len))
return BLOCK_ABORT;
if (((offset + rec_len) > fs->blocksize) ||
(rec_len < 8) ||
((rec_len % 4) != 0) ||
((((unsigned) dirent->name_len & 0xFF)+8) > rec_len)) {
ctx->errcode = EXT2_ET_DIR_CORRUPTED;
return BLOCK_ABORT;
}
if (!dirent->inode &&
!(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
goto next;
ret = (ctx->func)(ctx->dir,
(next_real_entry > offset) ?
DIRENT_DELETED_FILE : entry,
dirent, offset,
fs->blocksize, ctx->buf,
ctx->priv_data);
if (entry < DIRENT_OTHER_FILE)
entry++;
if (ret & DIRENT_CHANGED) {
if (ext2fs_get_rec_len(fs, dirent, &rec_len))
return BLOCK_ABORT;
changed++;
}
if (ret & DIRENT_ABORT) {
do_abort++;
break;
}
next:
if (next_real_entry == offset)
next_real_entry += rec_len;
if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) {
size = ((dirent->name_len & 0xFF) + 11) & ~3;
if (rec_len != size) {
unsigned int final_offset;
final_offset = offset + rec_len;
offset += size;
while (offset < final_offset &&
!ext2fs_validate_entry(fs, ctx->buf,
offset,
final_offset))
offset += 4;
continue;
}
}
offset += rec_len;
}
if (changed) {
ctx->errcode = ext2fs_write_dir_block3(fs, *blocknr, ctx->buf,
0);
if (ctx->errcode)
return BLOCK_ABORT;
}
if (do_abort)
return BLOCK_ABORT;
return 0;
}

View File

@ -0,0 +1,127 @@
/*
* dirblock.c --- directory block routines.
*
* Copyright (C) 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <time.h>
#include "ext2_fs.h"
#include "ext2fs.h"
errcode_t ext2fs_read_dir_block3(ext2_filsys fs, blk64_t block,
void *buf, int flags EXT2FS_ATTR((unused)))
{
errcode_t retval;
char *p, *end;
struct ext2_dir_entry *dirent;
unsigned int name_len, rec_len;
retval = io_channel_read_blk64(fs->io, block, 1, buf);
if (retval)
return retval;
p = (char *) buf;
end = (char *) buf + fs->blocksize;
while (p < end-8) {
dirent = (struct ext2_dir_entry *) p;
#ifdef WORDS_BIGENDIAN
dirent->inode = ext2fs_swab32(dirent->inode);
dirent->rec_len = ext2fs_swab16(dirent->rec_len);
dirent->name_len = ext2fs_swab16(dirent->name_len);
#endif
name_len = dirent->name_len;
#ifdef WORDS_BIGENDIAN
if (flags & EXT2_DIRBLOCK_V2_STRUCT)
dirent->name_len = ext2fs_swab16(dirent->name_len);
#endif
if ((retval = ext2fs_get_rec_len(fs, dirent, &rec_len)) != 0)
return retval;
if ((rec_len < 8) || (rec_len % 4)) {
rec_len = 8;
retval = EXT2_ET_DIR_CORRUPTED;
} else if (((name_len & 0xFF) + 8) > rec_len)
retval = EXT2_ET_DIR_CORRUPTED;
p += rec_len;
}
return retval;
}
errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
void *buf, int flags EXT2FS_ATTR((unused)))
{
return ext2fs_read_dir_block3(fs, block, buf, flags);
}
errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
void *buf)
{
return ext2fs_read_dir_block3(fs, block, buf, 0);
}
errcode_t ext2fs_write_dir_block3(ext2_filsys fs, blk64_t block,
void *inbuf, int flags EXT2FS_ATTR((unused)))
{
#ifdef WORDS_BIGENDIAN
errcode_t retval;
char *p, *end;
char *buf = 0;
unsigned int rec_len;
struct ext2_dir_entry *dirent;
retval = ext2fs_get_mem(fs->blocksize, &buf);
if (retval)
return retval;
memcpy(buf, inbuf, fs->blocksize);
p = buf;
end = buf + fs->blocksize;
while (p < end) {
dirent = (struct ext2_dir_entry *) p;
if ((retval = ext2fs_get_rec_len(fs, dirent, &rec_len)) != 0)
return retval;
if ((rec_len < 8) ||
(rec_len % 4)) {
ext2fs_free_mem(&buf);
return (EXT2_ET_DIR_CORRUPTED);
}
p += rec_len;
dirent->inode = ext2fs_swab32(dirent->inode);
dirent->rec_len = ext2fs_swab16(dirent->rec_len);
dirent->name_len = ext2fs_swab16(dirent->name_len);
if (flags & EXT2_DIRBLOCK_V2_STRUCT)
dirent->name_len = ext2fs_swab16(dirent->name_len);
}
retval = io_channel_write_blk64(fs->io, block, 1, buf);
ext2fs_free_mem(&buf);
return retval;
#else
return io_channel_write_blk64(fs->io, block, 1, (char *) inbuf);
#endif
}
errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
void *inbuf, int flags EXT2FS_ATTR((unused)))
{
return ext2fs_write_dir_block3(fs, block, inbuf, flags);
}
errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
void *inbuf)
{
return ext2fs_write_dir_block3(fs, block, inbuf, 0);
}

View File

@ -0,0 +1,261 @@
/*
* dirhash.c -- Calculate the hash of a directory entry
*
* Copyright (c) 2001 Daniel Phillips
*
* Copyright (c) 2002 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include "ext2_fs.h"
#include "ext2fs.h"
/*
* Keyed 32-bit hash function using TEA in a Davis-Meyer function
* H0 = Key
* Hi = E Mi(Hi-1) + Hi-1
*
* (see Applied Cryptography, 2nd edition, p448).
*
* Jeremy Fitzhardinge <jeremy@zip.com.au> 1998
*
* This code is made available under the terms of the GPL
*/
#define DELTA 0x9E3779B9
static void TEA_transform(__u32 buf[4], __u32 const in[])
{
__u32 sum = 0;
__u32 b0 = buf[0], b1 = buf[1];
__u32 a = in[0], b = in[1], c = in[2], d = in[3];
int n = 16;
do {
sum += DELTA;
b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
} while(--n);
buf[0] += b0;
buf[1] += b1;
}
/* F, G and H are basic MD4 functions: selection, majority, parity */
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
/*
* The generic round function. The application is so specific that
* we don't bother protecting all the arguments with parens, as is generally
* good macro practice, in favor of extra legibility.
* Rotation is separate from addition to prevent recomputation
*/
#define ROUND(f, a, b, c, d, x, s) \
(a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
#define K1 0
#define K2 013240474631UL
#define K3 015666365641UL
/*
* Basic cut-down MD4 transform. Returns only 32 bits of result.
*/
static void halfMD4Transform (__u32 buf[4], __u32 const in[])
{
__u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
/* Round 1 */
ROUND(F, a, b, c, d, in[0] + K1, 3);
ROUND(F, d, a, b, c, in[1] + K1, 7);
ROUND(F, c, d, a, b, in[2] + K1, 11);
ROUND(F, b, c, d, a, in[3] + K1, 19);
ROUND(F, a, b, c, d, in[4] + K1, 3);
ROUND(F, d, a, b, c, in[5] + K1, 7);
ROUND(F, c, d, a, b, in[6] + K1, 11);
ROUND(F, b, c, d, a, in[7] + K1, 19);
/* Round 2 */
ROUND(G, a, b, c, d, in[1] + K2, 3);
ROUND(G, d, a, b, c, in[3] + K2, 5);
ROUND(G, c, d, a, b, in[5] + K2, 9);
ROUND(G, b, c, d, a, in[7] + K2, 13);
ROUND(G, a, b, c, d, in[0] + K2, 3);
ROUND(G, d, a, b, c, in[2] + K2, 5);
ROUND(G, c, d, a, b, in[4] + K2, 9);
ROUND(G, b, c, d, a, in[6] + K2, 13);
/* Round 3 */
ROUND(H, a, b, c, d, in[3] + K3, 3);
ROUND(H, d, a, b, c, in[7] + K3, 9);
ROUND(H, c, d, a, b, in[2] + K3, 11);
ROUND(H, b, c, d, a, in[6] + K3, 15);
ROUND(H, a, b, c, d, in[1] + K3, 3);
ROUND(H, d, a, b, c, in[5] + K3, 9);
ROUND(H, c, d, a, b, in[0] + K3, 11);
ROUND(H, b, c, d, a, in[4] + K3, 15);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
#undef ROUND
#undef F
#undef G
#undef H
#undef K1
#undef K2
#undef K3
/* The old legacy hash */
static ext2_dirhash_t dx_hack_hash (const char *name, int len,
int unsigned_flag)
{
__u32 hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
const unsigned char *ucp = (const unsigned char *) name;
const signed char *scp = (const signed char *) name;
int c;
while (len--) {
if (unsigned_flag)
c = (int) *ucp++;
else
c = (int) *scp++;
hash = hash1 + (hash0 ^ (c * 7152373));
if (hash & 0x80000000) hash -= 0x7fffffff;
hash1 = hash0;
hash0 = hash;
}
return (hash0 << 1);
}
static void str2hashbuf(const char *msg, int len, __u32 *buf, int num,
int unsigned_flag)
{
__u32 pad, val;
int i, c;
const unsigned char *ucp = (const unsigned char *) msg;
const signed char *scp = (const signed char *) msg;
pad = (__u32)len | ((__u32)len << 8);
pad |= pad << 16;
val = pad;
if (len > num*4)
len = num * 4;
for (i=0; i < len; i++) {
if ((i % 4) == 0)
val = pad;
if (unsigned_flag)
c = (int) ucp[i];
else
c = (int) scp[i];
val = c + (val << 8);
if ((i % 4) == 3) {
*buf++ = val;
val = pad;
num--;
}
}
if (--num >= 0)
*buf++ = val;
while (--num >= 0)
*buf++ = pad;
}
/*
* Returns the hash of a filename. If len is 0 and name is NULL, then
* this function can be used to test whether or not a hash version is
* supported.
*
* The seed is an 4 longword (32 bits) "secret" which can be used to
* uniquify a hash. If the seed is all zero's, then some default seed
* may be used.
*
* A particular hash version specifies whether or not the seed is
* represented, and whether or not the returned hash is 32 bits or 64
* bits. 32 bit hashes will return 0 for the minor hash.
*/
errcode_t ext2fs_dirhash(int version, const char *name, int len,
const __u32 *seed,
ext2_dirhash_t *ret_hash,
ext2_dirhash_t *ret_minor_hash)
{
__u32 hash;
__u32 minor_hash = 0;
const char *p;
int i;
__u32 in[8], buf[4];
int unsigned_flag = 0;
/* Initialize the default seed for the hash checksum functions */
buf[0] = 0x67452301;
buf[1] = 0xefcdab89;
buf[2] = 0x98badcfe;
buf[3] = 0x10325476;
/* Check to see if the seed is all zero's */
if (seed) {
for (i=0; i < 4; i++) {
if (seed[i])
break;
}
if (i < 4)
memcpy(buf, seed, sizeof(buf));
}
switch (version) {
case EXT2_HASH_LEGACY_UNSIGNED:
unsigned_flag++;
/* fallthrough */
case EXT2_HASH_LEGACY:
hash = dx_hack_hash(name, len, unsigned_flag);
break;
case EXT2_HASH_HALF_MD4_UNSIGNED:
unsigned_flag++;
/* fallthrough */
case EXT2_HASH_HALF_MD4:
p = name;
while (len > 0) {
str2hashbuf(p, len, in, 8, unsigned_flag);
halfMD4Transform(buf, in);
len -= 32;
p += 32;
}
minor_hash = buf[2];
hash = buf[1];
break;
case EXT2_HASH_TEA_UNSIGNED:
unsigned_flag++;
/* fallthrough */
case EXT2_HASH_TEA:
p = name;
while (len > 0) {
str2hashbuf(p, len, in, 4, unsigned_flag);
TEA_transform(buf, in);
len -= 16;
p += 16;
}
hash = buf[0];
minor_hash = buf[1];
break;
default:
*ret_hash = 0;
return EXT2_ET_DIRHASH_UNSUPP;
}
*ret_hash = hash & ~1;
if (ret_minor_hash)
*ret_minor_hash = minor_hash;
return 0;
}

View File

@ -0,0 +1,374 @@
/*
cache.c
The cache is not visible to the user. It should be flushed
when any file is closed or changes are made to the filesystem.
This cache implements a least-used-page replacement policy. This will
distribute sectors evenly over the pages, so if less than the maximum
pages are used at once, they should all eventually remain in the cache.
This also has the benefit of throwing out old sectors, so as not to keep
too many stale pages around.
Copyright (c) 2006 Michael "Chishm" Chisholm
Copyright (c) 2009 shareese, rodries
Copyright (c) 2010 Dimok
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <ogc/lwp_watchdog.h>
#include <string.h>
#include <limits.h>
#include "disc_cache.h"
#include "bit_ops.h"
#include "mem_allocate.h"
#define CACHE_FREE UINT_MAX
CACHE* cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, sec_t sectorSize) {
CACHE* cache;
unsigned int i;
CACHE_ENTRY* cacheEntries;
if(numberOfPages==0 || sectorsPerPage==0) return NULL;
if (numberOfPages < 32) {
numberOfPages = 32;
}
if (sectorsPerPage < 16) {
sectorsPerPage = 16;
}
cache = (CACHE*) mem_alloc (sizeof(CACHE));
if (cache == NULL) {
return NULL;
}
cache->disc = discInterface;
cache->endOfPartition = endOfPartition;
cache->numberOfPages = numberOfPages;
cache->sectorsPerPage = sectorsPerPage;
cache->sectorSize = sectorSize;
cacheEntries = (CACHE_ENTRY*) mem_alloc ( sizeof(CACHE_ENTRY) * numberOfPages);
if (cacheEntries == NULL) {
mem_free (cache);
return NULL;
}
for (i = 0; i < numberOfPages; i++) {
cacheEntries[i].sector = CACHE_FREE;
cacheEntries[i].count = 0;
cacheEntries[i].last_access = 0;
cacheEntries[i].dirty = false;
cacheEntries[i].cache = (uint8_t*) mem_align (32, sectorsPerPage * cache->sectorSize);
}
cache->cacheEntries = cacheEntries;
return cache;
}
void cache_destructor (CACHE* cache) {
unsigned int i;
if(cache==NULL) return;
// Clear out cache before destroying it
cache_flush(cache);
// Free memory in reverse allocation order
for (i = 0; i < cache->numberOfPages; i++) {
mem_free (cache->cacheEntries[i].cache);
}
mem_free (cache->cacheEntries);
mem_free (cache);
}
static u32 accessCounter = 0;
static u32 accessTime(){
accessCounter++;
return accessCounter;
}
static CACHE_ENTRY* cache_getPage(CACHE *cache,sec_t sector)
{
unsigned int i;
CACHE_ENTRY* cacheEntries = cache->cacheEntries;
unsigned int numberOfPages = cache->numberOfPages;
unsigned int sectorsPerPage = cache->sectorsPerPage;
bool foundFree = false;
unsigned int oldUsed = 0;
unsigned int oldAccess = UINT_MAX;
for(i=0;i<numberOfPages;i++) {
if(sector>=cacheEntries[i].sector && sector<(cacheEntries[i].sector + cacheEntries[i].count)) {
cacheEntries[i].last_access = accessTime();
return &(cacheEntries[i]);
}
if(foundFree==false && (cacheEntries[i].sector==CACHE_FREE || cacheEntries[i].last_access<oldAccess)) {
if(cacheEntries[i].sector==CACHE_FREE) foundFree = true;
oldUsed = i;
oldAccess = cacheEntries[i].last_access;
}
}
if(foundFree==false && cacheEntries[oldUsed].dirty==true) {
if(!cache->disc->writeSectors(cacheEntries[oldUsed].sector,cacheEntries[oldUsed].count,cacheEntries[oldUsed].cache)) return NULL;
cacheEntries[oldUsed].dirty = false;
}
sector = (sector/sectorsPerPage)*sectorsPerPage; // align base sector to page size
sec_t next_page = sector + sectorsPerPage;
if(next_page > cache->endOfPartition) next_page = cache->endOfPartition;
if(!cache->disc->readSectors(sector,next_page-sector,cacheEntries[oldUsed].cache)) return NULL;
cacheEntries[oldUsed].sector = sector;
cacheEntries[oldUsed].count = next_page-sector;
cacheEntries[oldUsed].last_access = accessTime();
return &(cacheEntries[oldUsed]);
}
static CACHE_ENTRY* cache_findPage(CACHE *cache, sec_t sector, sec_t count) {
unsigned int i;
CACHE_ENTRY* cacheEntries = cache->cacheEntries;
unsigned int numberOfPages = cache->numberOfPages;
CACHE_ENTRY *entry = NULL;
sec_t lowest = UINT_MAX;
for(i=0;i<numberOfPages;i++) {
if (cacheEntries[i].sector != CACHE_FREE) {
bool intersect;
if (sector > cacheEntries[i].sector) {
intersect = sector - cacheEntries[i].sector < cacheEntries[i].count;
} else {
intersect = cacheEntries[i].sector - sector < count;
}
if ( intersect && (cacheEntries[i].sector < lowest)) {
lowest = cacheEntries[i].sector;
entry = &cacheEntries[i];
}
}
}
return entry;
}
bool cache_readSectors(CACHE *cache,sec_t sector,sec_t numSectors,void *buffer)
{
sec_t sec;
sec_t secs_to_read;
CACHE_ENTRY *entry;
uint8_t *dest = buffer;
while(numSectors>0) {
entry = cache_getPage(cache,sector);
if(entry==NULL) return false;
sec = sector - entry->sector;
secs_to_read = entry->count - sec;
if(secs_to_read>numSectors) secs_to_read = numSectors;
memcpy(dest,entry->cache + (sec*cache->sectorSize),(secs_to_read*cache->sectorSize));
dest += (secs_to_read*cache->sectorSize);
sector += secs_to_read;
numSectors -= secs_to_read;
}
return true;
}
/*
Reads some data from a cache page, determined by the sector number
*/
bool cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size)
{
sec_t sec;
CACHE_ENTRY *entry;
if (offset + size > cache->sectorSize) return false;
entry = cache_getPage(cache,sector);
if(entry==NULL) return false;
sec = sector - entry->sector;
memcpy(buffer,entry->cache + ((sec*cache->sectorSize) + offset),size);
return true;
}
bool cache_readLittleEndianValue (CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes) {
uint8_t buf[4];
if (!cache_readPartialSector(cache, buf, sector, offset, num_bytes)) return false;
switch(num_bytes) {
case 1: *value = buf[0]; break;
case 2: *value = u8array_to_u16(buf,0); break;
case 4: *value = u8array_to_u32(buf,0); break;
default: return false;
}
return true;
}
/*
Writes some data to a cache page, making sure it is loaded into memory first.
*/
bool cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size)
{
sec_t sec;
CACHE_ENTRY *entry;
if (offset + size > cache->sectorSize) return false;
entry = cache_getPage(cache,sector);
if(entry==NULL) return false;
sec = sector - entry->sector;
memcpy(entry->cache + ((sec*cache->sectorSize) + offset),buffer,size);
entry->dirty = true;
return true;
}
bool cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int size) {
uint8_t buf[4] = {0, 0, 0, 0};
switch(size) {
case 1: buf[0] = value; break;
case 2: u16_to_u8array(buf, 0, value); break;
case 4: u32_to_u8array(buf, 0, value); break;
default: return false;
}
return cache_writePartialSector(cache, buf, sector, offset, size);
}
/*
Writes some data to a cache page, zeroing out the page first
*/
bool cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size)
{
sec_t sec;
CACHE_ENTRY *entry;
if (offset + size > cache->sectorSize) return false;
entry = cache_getPage(cache,sector);
if(entry==NULL) return false;
sec = sector - entry->sector;
memset(entry->cache + (sec*cache->sectorSize),0,cache->sectorSize);
memcpy(entry->cache + ((sec*cache->sectorSize) + offset),buffer,size);
entry->dirty = true;
return true;
}
bool cache_writeSectors (CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer)
{
sec_t sec;
sec_t secs_to_write;
CACHE_ENTRY* entry;
const uint8_t *src = buffer;
while(numSectors>0)
{
entry = cache_findPage(cache,sector,numSectors);
if(entry!=NULL) {
if ( entry->sector > sector) {
secs_to_write = entry->sector - sector;
cache->disc->writeSectors(sector,secs_to_write,src);
src += (secs_to_write*cache->sectorSize);
sector += secs_to_write;
numSectors -= secs_to_write;
}
sec = sector - entry->sector;
secs_to_write = entry->count - sec;
if(secs_to_write>numSectors) secs_to_write = numSectors;
memcpy(entry->cache + (sec*cache->sectorSize),src,(secs_to_write*cache->sectorSize));
src += (secs_to_write*cache->sectorSize);
sector += secs_to_write;
numSectors -= secs_to_write;
entry->dirty = true;
} else {
cache->disc->writeSectors(sector,numSectors,src);
numSectors=0;
}
}
return true;
}
/*
Flushes all dirty pages to disc, clearing the dirty flag.
*/
bool cache_flush (CACHE* cache) {
unsigned int i;
if(cache==NULL) return true;
for (i = 0; i < cache->numberOfPages; i++) {
if (cache->cacheEntries[i].dirty) {
if (!cache->disc->writeSectors (cache->cacheEntries[i].sector, cache->cacheEntries[i].count, cache->cacheEntries[i].cache)) {
return false;
}
}
cache->cacheEntries[i].dirty = false;
}
return true;
}
void cache_invalidate (CACHE* cache) {
unsigned int i;
if(cache==NULL)
return;
cache_flush(cache);
for (i = 0; i < cache->numberOfPages; i++) {
cache->cacheEntries[i].sector = CACHE_FREE;
cache->cacheEntries[i].last_access = 0;
cache->cacheEntries[i].count = 0;
cache->cacheEntries[i].dirty = false;
}
}

View File

@ -0,0 +1,118 @@
/*
CACHE.h
The CACHE is not visible to the user. It should be flushed
when any file is closed or changes are made to the filesystem.
This CACHE implements a least-used-page replacement policy. This will
distribute sectors evenly over the pages, so if less than the maximum
pages are used at once, they should all eventually remain in the CACHE.
This also has the benefit of throwing out old sectors, so as not to keep
too many stale pages around.
Copyright (c) 2006 Michael "Chishm" Chisholm
Copyright (c) 2009 shareese, rodries
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DISC_CACHE_H
#define _DISC_CACHE_H
#include <stddef.h>
#include <stdint.h>
#include <gctypes.h>
#include <ogc/disc_io.h>
#include <gccore.h>
typedef struct
{
sec_t sector;
unsigned int count;
u64 last_access;
bool dirty;
u8* cache;
} CACHE_ENTRY;
typedef struct
{
const DISC_INTERFACE* disc;
sec_t endOfPartition;
unsigned int numberOfPages;
unsigned int sectorsPerPage;
sec_t sectorSize;
CACHE_ENTRY* cacheEntries;
} CACHE;
/*
Read data from a sector in the CACHE
If the sector is not in the CACHE, it will be swapped in
offset is the position to start reading from
size is the amount of data to read
Precondition: offset + size <= BYTES_PER_READ
*/
/*
Write data to a sector in the CACHE
If the sector is not in the CACHE, it will be swapped in.
When the sector is swapped out, the data will be written to the disc
offset is the position to start writing to
size is the amount of data to write
Precondition: offset + size <= BYTES_PER_READ
*/
/*
Write data to a sector in the CACHE, zeroing the sector first
If the sector is not in the CACHE, it will be swapped in.
When the sector is swapped out, the data will be written to the disc
offset is the position to start writing to
size is the amount of data to write
Precondition: offset + size <= BYTES_PER_READ
*/
/*
Read several sectors from the CACHE
*/
bool cache_readSectors (CACHE* DISC_CACHE, sec_t sector, sec_t numSectors, void* buffer);
/*
Read a full sector from the CACHE
*/
/*
Write a full sector to the CACHE
*/
bool cache_writeSectors (CACHE* DISC_CACHE, sec_t sector, sec_t numSectors, const void* buffer);
/*
Write any dirty sectors back to disc and clear out the contents of the CACHE
*/
bool cache_flush (CACHE* DISC_CACHE);
/*
Clear out the contents of the CACHE without writing any dirty sectors first
*/
void cache_invalidate (CACHE* DISC_CACHE);
CACHE* cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, sec_t sectorSize);
void cache_destructor (CACHE* DISC_CACHE);
#endif // _CACHE_H

View File

@ -0,0 +1,97 @@
/*
* dupfs.c --- duplicate a ext2 filesystem handle
*
* Copyright (C) 1997, 1998, 2001, 2003, 2005 by Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <time.h>
#include <string.h>
#include "ext2_fs.h"
#include "ext2fsP.h"
errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest)
{
ext2_filsys fs;
errcode_t retval;
EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS);
retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
if (retval)
return retval;
*fs = *src;
fs->device_name = 0;
fs->super = 0;
fs->orig_super = 0;
fs->group_desc = 0;
fs->inode_map = 0;
fs->block_map = 0;
fs->badblocks = 0;
fs->dblist = 0;
io_channel_bumpcount(fs->io);
if (fs->icache)
fs->icache->refcount++;
retval = ext2fs_get_mem(strlen(src->device_name)+1, &fs->device_name);
if (retval)
goto errout;
strcpy(fs->device_name, src->device_name);
retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super);
if (retval)
goto errout;
memcpy(fs->super, src->super, SUPERBLOCK_SIZE);
retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
if (retval)
goto errout;
memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE);
retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
&fs->group_desc);
if (retval)
goto errout;
memcpy(fs->group_desc, src->group_desc,
(size_t) fs->desc_blocks * fs->blocksize);
if (src->inode_map) {
retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map);
if (retval)
goto errout;
}
if (src->block_map) {
retval = ext2fs_copy_bitmap(src->block_map, &fs->block_map);
if (retval)
goto errout;
}
if (src->badblocks) {
retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks);
if (retval)
goto errout;
}
if (src->dblist) {
retval = ext2fs_copy_dblist(src->dblist, &fs->dblist);
if (retval)
goto errout;
}
*dest = fs;
return 0;
errout:
ext2fs_free(fs);
return retval;
}

View File

@ -0,0 +1,46 @@
/*
* e2image.h --- header file describing the ext2 image format
*
* Copyright (C) 2000 Theodore Ts'o.
*
* Note: this uses the POSIX IO interfaces, unlike most of the other
* functions in this library. So sue me.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
/* Image types */
#define E2IMAGE_RAW 1
#define E2IMAGE_QCOW2 2
/* Image flags */
#define E2IMAGE_INSTALL_FLAG 1
#define E2IMAGE_SCRAMBLE_FLAG 2
#define E2IMAGE_IS_QCOW2_FLAG 3
struct ext2_image_hdr {
__u32 magic_number; /* This must be EXT2_ET_MAGIC_E2IMAGE */
char magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */
char fs_hostname[64];/* Hostname of machine of image */
char fs_netaddr[32]; /* Network address */
__u32 fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */
__u32 fs_device; /* Device number of image */
char fs_device_name[64]; /* Device name */
char fs_uuid[16]; /* UUID of filesystem */
__u32 fs_blocksize; /* Block size of the filesystem */
__u32 fs_reserved[8];
__u32 image_device; /* Device number of image file */
__u32 image_inode; /* Inode number of image file */
__u32 image_time; /* Time of image creation */
__u32 image_reserved[8];
__u32 offset_super; /* Byte offset of the sb and descriptors */
__u32 offset_inode; /* Byte offset of the inode table */
__u32 offset_inodemap; /* Byte offset of the inode bitmaps */
__u32 offset_blockmap; /* Byte offset of the inode bitmaps */
__u32 offset_reserved[8];
};

View File

@ -0,0 +1,137 @@
/*
* expand.c --- expand an ext2fs directory
*
* Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
struct expand_dir_struct {
int done;
int newblocks;
blk64_t goal;
errcode_t err;
};
static int expand_dir_proc(ext2_filsys fs,
blk64_t *blocknr,
e2_blkcnt_t blockcnt,
blk64_t ref_block EXT2FS_ATTR((unused)),
int ref_offset EXT2FS_ATTR((unused)),
void *priv_data)
{
struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
blk64_t new_blk;
char *block;
errcode_t retval;
if (*blocknr) {
if (blockcnt >= 0)
es->goal = *blocknr;
return 0;
}
if (blockcnt &&
(EXT2FS_B2C(fs, es->goal) == EXT2FS_B2C(fs, es->goal+1)))
new_blk = es->goal+1;
else {
es->goal &= ~EXT2FS_CLUSTER_MASK(fs);
retval = ext2fs_new_block2(fs, es->goal, 0, &new_blk);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
}
es->newblocks++;
}
if (blockcnt > 0) {
retval = ext2fs_new_dir_block(fs, 0, 0, &block);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
}
es->done = 1;
retval = ext2fs_write_dir_block(fs, new_blk, block);
} else {
retval = ext2fs_get_mem(fs->blocksize, &block);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
}
memset(block, 0, fs->blocksize);
retval = io_channel_write_blk64(fs->io, new_blk, 1, block);
}
if (blockcnt >= 0)
es->goal = new_blk;
if (retval) {
es->err = retval;
return BLOCK_ABORT;
}
ext2fs_free_mem(&block);
*blocknr = new_blk;
ext2fs_block_alloc_stats2(fs, new_blk, +1);
if (es->done)
return (BLOCK_CHANGED | BLOCK_ABORT);
else
return BLOCK_CHANGED;
}
errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir)
{
errcode_t retval;
struct expand_dir_struct es;
struct ext2_inode inode;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!(fs->flags & EXT2_FLAG_RW))
return EXT2_ET_RO_FILSYS;
if (!fs->block_map)
return EXT2_ET_NO_BLOCK_BITMAP;
retval = ext2fs_check_directory(fs, dir);
if (retval)
return retval;
es.done = 0;
es.err = 0;
es.goal = 0;
es.newblocks = 0;
retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_APPEND,
0, expand_dir_proc, &es);
if (es.err)
return es.err;
if (!es.done)
return EXT2_ET_EXPAND_DIR_ERR;
/*
* Update the size and block count fields in the inode.
*/
retval = ext2fs_read_inode(fs, dir, &inode);
if (retval)
return retval;
inode.i_size += fs->blocksize;
ext2fs_iblk_add_blocks(fs, &inode, es.newblocks);
retval = ext2fs_write_inode(fs, dir, &inode);
if (retval)
return retval;
return 0;
}

View File

@ -0,0 +1,423 @@
/**
* ext2file.c - devoptab file routines for EXT2-based devices.
*
* Copyright (c) 2006 Michael "Chishm" Chisholm
* Copyright (c) 2009 Rhys "Shareese" Koedijk
* Copyright (c) 2010 Dimok
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <errno.h>
#include <string.h>
#include "ext2_fs.h"
#include "ext2fs.h"
#include "ext2_internal.h"
#include "gekko_io.h"
#include "mem_allocate.h"
#include "partitions.h"
bool ext2Mount(const char *name, const DISC_INTERFACE *interface, sec_t startSector, u32 cachePageCount, u32 cachePageSize, u32 flags)
{
errcode_t retval = -1;
ext2_filsys fs = NULL;
io_channel io_chan = NULL;
gekko_fd *fd = NULL;
ext2_vd * vd = NULL;
// Sanity check
if (!name || !interface)
{
errno = EINVAL;
return false;
}
// Allocate the device driver descriptor
fd = (gekko_fd*) mem_alloc(sizeof(gekko_fd));
if (!fd)
goto cleanup;
memset(fd, 0, sizeof(gekko_fd));
// Setup the device driver descriptor
fd->interface = interface;
fd->startSector = startSector;
fd->sectorSize = 0;
fd->sectorCount = 0;
fd->cachePageCount = cachePageCount;
fd->cachePageSize = cachePageSize;
fs = mem_alloc(sizeof(struct struct_ext2_filsys));
if (!fs)
{
ext2_log_trace("no memory for fs\n");
errno = ENOMEM;
goto cleanup;
}
memset(fs, 0, sizeof(struct struct_ext2_filsys));
io_chan = mem_alloc(sizeof(struct struct_io_channel));
if (!io_chan)
{
ext2_log_trace("no memory for io_chan\n");
errno = ENOMEM;
goto cleanup;
}
memset(io_chan, 0, sizeof(struct struct_io_channel));
io_chan->magic = EXT2_ET_MAGIC_IO_CHANNEL;
io_chan->manager = gekko_io_manager;
io_chan->name = strdup(name);
if(!io_chan->name) goto cleanup;
io_chan->block_size = 1024;
io_chan->read_error = 0;
io_chan->write_error = 0;
io_chan->refcount = 1;
io_chan->private_data = fd;
io_chan->flags = flags;
retval = ext2fs_open2(io_chan->name, 0, io_chan->flags, 0, 0, io_chan, &fs);
if(retval)
{
ext2_log_trace("error mounting %i\n", (int) retval);
goto cleanup;
}
vd = mem_alloc(sizeof(ext2_vd));
if(!vd)
{
ext2_log_trace("no memory for vd\n");
goto cleanup;
}
// Initialise the volume descriptor
ext2InitVolume(vd);
vd->fs = fs;
vd->io = io_chan;
vd->root = EXT2_ROOT_INO;
// Add the device to the devoptab table
if (ext2AddDevice(name, vd)) {
ext2DeinitVolume(vd);
goto cleanup;
}
return true;
cleanup:
if(fd)
mem_free(fd);
if(io_chan)
mem_free(io_chan);
if(vd)
mem_free(vd);
if(fs)
{
ext2fs_close(fs);
ext2fs_free(fs);
}
return false;
}
void ext2Unmount(const char *name)
{
ext2_vd *vd = NULL;
// Get the devices volume descriptor
vd = ext2GetVolume(name);
if (!vd)
return;
// Remove the device from the devoptab table
ext2RemoveDevice(name);
// Deinitialise the volume descriptor
ext2DeinitVolume(vd);
// Unmount the volume
ext2fs_close(vd->fs);
ext2fs_free(vd->fs);
//Free the io manager
mem_free(vd->io->private_data);
mem_free(vd->io);
// Free the volume descriptor
mem_free(vd);
return;
}
const char *ext2GetVolumeName (const char *name)
{
if (!name) {
errno = EINVAL;
return NULL;
}
// Get the devices volume descriptor
ext2_vd *vd = ext2GetVolume(name);
if (!vd) {
errno = ENODEV;
return NULL;
}
return vd->fs->super->s_volume_name;
}
bool ext2SetVolumeName (const char *name, const char *volumeName)
{
// Sanity check
if (!name || !volumeName) {
errno = EINVAL;
return false;
}
// Get the devices volume descriptor
ext2_vd *vd = ext2GetVolume(name);
if (!vd) {
errno = ENODEV;
return false;
}
// Lock
ext2Lock(vd);
int i;
for(i = 0; i < 15 && *volumeName != 0; ++i, volumeName++)
vd->fs->super->s_volume_name[i] = *volumeName;
vd->fs->super->s_volume_name[i] = '\0';
ext2fs_mark_super_dirty(vd->fs);
ext2Sync(vd, NULL);
// Unlock
ext2Unlock(vd);
return true;
}
int ext2FindPartitions (const DISC_INTERFACE *interface, sec_t **out_partitions)
{
MASTER_BOOT_RECORD mbr;
PARTITION_RECORD *partition = NULL;
int partition_count = 0, ret = -1;
sec_t part_lba = 0;
sec_t * partitions = NULL;
int i;
union {
u8 buffer[MAX_SECTOR_SIZE];
MASTER_BOOT_RECORD mbr;
EXTENDED_BOOT_RECORD ebr;
} sector;
// Sanity check
if (!interface) {
errno = EINVAL;
return -1;
}
if(!out_partitions) {
errno = EINVAL;
return -1;
}
// Start the device and check that it is inserted
if (!interface->startup()) {
errno = EIO;
return -1;
}
if (!interface->isInserted()) {
errno = EIO;
return 0;
}
// Allocate 4 x max sector size in case of 4096 sector size
u8 *buffer = (u8 *) mem_alloc(4 * MAX_SECTOR_SIZE);
if(!buffer)
{
ext2_log_trace("no memory for superblock");
errno = ENOMEM;
return -1;
}
// Super is always at offset SUPERBLOCK_OFFSET
struct ext2_super_block * super = (struct ext2_super_block *) (buffer + SUPERBLOCK_OFFSET); //1024 bytes
partitions = (sec_t *) malloc(sizeof(sec_t));
if(!partitions)
{
ext2_log_trace("no memory for partitions");
errno = ENOMEM;
mem_free(buffer);
return -1;
}
// Read the first sector on the device
if (!interface->readSectors(0, 1, &sector.buffer)) {
errno = EIO;
mem_free(partitions);
mem_free(buffer);
return -1;
}
// If this is the devices master boot record
if (sector.mbr.signature == MBR_SIGNATURE)
{
memcpy(&mbr, &sector, sizeof(MASTER_BOOT_RECORD));
// Search the partition table for all EXT2/3/4 partitions (max. 4 primary partitions)
for (i = 0; i < 4; i++)
{
partition = &mbr.partitions[i];
part_lba = ext2fs_le32_to_cpu(mbr.partitions[i].lba_start);
// Figure out what type of partition this is
switch (partition->type)
{
// Ignore empty partitions
case PARTITION_TYPE_EMPTY:
continue;
// EXT2/3/4 partition
case PARTITION_TYPE_LINUX:
// Read and validate the EXT partition
if (interface->readSectors(part_lba, 4, buffer))
{
if (ext2fs_le16_to_cpu(super->s_magic) == EXT2_SUPER_MAGIC)
{
partition_count++;
sec_t * tmp = (sec_t *) realloc(partitions, partition_count*sizeof(sec_t));
if(!tmp) goto cleanup;
partitions = tmp;
partitions[partition_count-1] = part_lba;
}
}
break;
// DOS 3.3+ or Windows 95 extended partition
case PARTITION_TYPE_DOS33_EXTENDED:
case PARTITION_TYPE_WIN95_EXTENDED:
{
ext2_log_trace("Partition %i: Claims to be Extended\n", i + 1);
// Walk the extended partition chain, finding all EXT partitions within it
sec_t ebr_lba = part_lba;
sec_t next_erb_lba = 0;
do {
// Read and validate the extended boot record
if (interface->readSectors(ebr_lba + next_erb_lba, 1, &sector))
{
if (sector.ebr.signature == EBR_SIGNATURE)
{
ext2_log_trace("Logical Partition @ %d: %s type 0x%x\n", ebr_lba + next_erb_lba,
sector.ebr.partition.status == PARTITION_STATUS_BOOTABLE ? "bootable (active)" : "non-bootable",
sector.ebr.partition.type);
// Get the start sector of the current partition
// and the next extended boot record in the chain
part_lba = ebr_lba + next_erb_lba + ext2fs_le32_to_cpu(sector.ebr.partition.lba_start);
next_erb_lba = ext2fs_le32_to_cpu(sector.ebr.next_ebr.lba_start);
// Check if this partition has a valid EXT boot record
if (interface->readSectors(part_lba, 4, buffer))
{
if (ext2fs_le16_to_cpu(super->s_magic) == EXT2_SUPER_MAGIC)
{
partition_count++;
sec_t * tmp = (sec_t *) realloc(partitions, partition_count*sizeof(sec_t));
if(!tmp) goto cleanup;
partitions = tmp;
partitions[partition_count-1] = part_lba;
}
}
}
else
next_erb_lba = 0;
}
} while (next_erb_lba);
break;
}
// Unknown or unsupported partition type
default:
{
// Check if this partition has a valid EXT boot record anyway,
// it might be misrepresented due to a lazy partition editor
if (interface->readSectors(part_lba, 4, buffer))
{
if (ext2fs_le16_to_cpu(super->s_magic) == EXT2_SUPER_MAGIC)
{
partition_count++;
sec_t * tmp = (sec_t *) realloc(partitions, partition_count*sizeof(sec_t));
if(!tmp) goto cleanup;
partitions = tmp;
partitions[partition_count-1] = part_lba;
}
}
break;
}
}
}
// Else it is assumed this device has no master boot record
}
else
{
ext2_log_trace("No Master Boot Record was found!\n");
// As a last-ditched effort, search the first 64 sectors of the device for stray EXT partitions
for (i = 1; i < 64; i++)
{
if (interface->readSectors(i, 4, buffer))
{
if (ext2fs_le16_to_cpu(super->s_magic) == EXT2_SUPER_MAGIC)
{
partition_count++;
sec_t * tmp = (sec_t *) realloc(partitions, partition_count*sizeof(sec_t));
if(!tmp) goto cleanup;
partitions = tmp;
partitions[partition_count-1] = i;
}
}
}
}
// Return the found partitions (if any)
if (partition_count > 0)
{
*out_partitions = partitions;
ret = partition_count;
}
cleanup:
if(partitions && partition_count == 0)
mem_free(partitions);
if(buffer)
mem_free(buffer);
return ret;
}

View File

@ -0,0 +1,199 @@
/*
* ext2_err.c:
* This file is automatically generated; please do not edit it.
*/
#include <stdlib.h>
#define N_(a) a
static const char * const text[] = {
N_( "EXT2FS Library version 1.42"),
N_( "Wrong magic number for ext2_filsys structure"),
N_( "Wrong magic number for badblocks_list structure"),
N_( "Wrong magic number for badblocks_iterate structure"),
N_( "Wrong magic number for inode_scan structure"),
N_( "Wrong magic number for io_channel structure"),
N_( "Wrong magic number for unix io_channel structure"),
N_( "Wrong magic number for io_manager structure"),
N_( "Wrong magic number for block_bitmap structure"),
N_( "Wrong magic number for inode_bitmap structure"),
N_( "Wrong magic number for generic_bitmap structure"),
N_( "Wrong magic number for test io_channel structure"),
N_( "Wrong magic number for directory block list structure"),
N_( "Wrong magic number for icount structure"),
N_( "Wrong magic number for Powerquest io_channel structure"),
N_( "Wrong magic number for ext2 file structure"),
N_( "Wrong magic number for Ext2 Image Header"),
N_( "Wrong magic number for inode io_channel structure"),
N_( "Wrong magic number for ext4 extent handle"),
N_( "Bad magic number in super-block"),
N_( "Filesystem revision too high"),
N_( "Attempt to write to filesystem opened read-only"),
N_( "Can't read group descriptors"),
N_( "Can't write group descriptors"),
N_( "Corrupt group descriptor: bad block for block bitmap"),
N_( "Corrupt group descriptor: bad block for inode bitmap"),
N_( "Corrupt group descriptor: bad block for inode table"),
N_( "Can't write an inode bitmap"),
N_( "Can't read an inode bitmap"),
N_( "Can't write an block bitmap"),
N_( "Can't read an block bitmap"),
N_( "Can't write an inode table"),
N_( "Can't read an inode table"),
N_( "Can't read next inode"),
N_( "Filesystem has unexpected block size"),
N_( "EXT2 directory corrupted"),
N_( "Attempt to read block from filesystem resulted in short read"),
N_( "Attempt to write block to filesystem resulted in short write"),
N_( "No free space in the directory"),
N_( "Inode bitmap not loaded"),
N_( "Block bitmap not loaded"),
N_( "Illegal inode number"),
N_( "Illegal block number"),
N_( "Internal error in ext2fs_expand_dir"),
N_( "Not enough space to build proposed filesystem"),
N_( "Illegal block number passed to ext2fs_mark_block_bitmap"),
N_( "Illegal block number passed to ext2fs_unmark_block_bitmap"),
N_( "Illegal block number passed to ext2fs_test_block_bitmap"),
N_( "Illegal inode number passed to ext2fs_mark_inode_bitmap"),
N_( "Illegal inode number passed to ext2fs_unmark_inode_bitmap"),
N_( "Illegal inode number passed to ext2fs_test_inode_bitmap"),
N_( "Attempt to fudge end of block bitmap past the real end"),
N_( "Attempt to fudge end of inode bitmap past the real end"),
N_( "Illegal indirect block found" ),
N_( "Illegal doubly indirect block found" ),
N_( "Illegal triply indirect block found" ),
N_( "Block bitmaps are not the same"),
N_( "Inode bitmaps are not the same"),
N_( "Illegal or malformed device name"),
N_( "A block group is missing an inode table"),
N_( "The ext2 superblock is corrupt"),
N_( "Illegal generic bit number passed to ext2fs_mark_generic_bitmap"),
N_( "Illegal generic bit number passed to ext2fs_unmark_generic_bitmap"),
N_( "Illegal generic bit number passed to ext2fs_test_generic_bitmap"),
N_( "Too many symbolic links encountered."),
N_( "The callback function will not handle this case"),
N_( "The inode is from a bad block in the inode table"),
N_( "Filesystem has unsupported feature(s)"),
N_( "Filesystem has unsupported read-only feature(s)"),
N_( "IO Channel failed to seek on read or write"),
N_( "Memory allocation failed"),
N_( "Invalid argument passed to ext2 library"),
N_( "Could not allocate block in ext2 filesystem"),
N_( "Could not allocate inode in ext2 filesystem"),
N_( "Ext2 inode is not a directory"),
N_( "Too many references in table"),
N_( "File not found by ext2_lookup"),
N_( "File open read-only"),
N_( "Ext2 directory block not found"),
N_( "Ext2 directory already exists"),
N_( "Unimplemented ext2 library function"),
N_( "User cancel requested"),
N_( "Ext2 file too big"),
N_( "Supplied journal device not a block device"),
N_( "Journal superblock not found"),
N_( "Journal must be at least 1024 blocks"),
N_( "Unsupported journal version"),
N_( "Error loading external journal"),
N_( "Journal not found"),
N_( "Directory hash unsupported"),
N_( "Illegal extended attribute block number"),
N_( "Cannot create filesystem with requested number of inodes"),
N_( "E2image snapshot not in use"),
N_( "Too many reserved group descriptor blocks"),
N_( "Resize inode is corrupt"),
N_( "Tried to set block bmap with missing indirect block"),
N_( "TDB: Success"),
N_( "TDB: Corrupt database"),
N_( "TDB: IO Error"),
N_( "TDB: Locking error"),
N_( "TDB: Out of memory"),
N_( "TDB: Record exists"),
N_( "TDB: Lock exists on other keys"),
N_( "TDB: Invalid parameter"),
N_( "TDB: Record does not exist"),
N_( "TDB: Write not permitted"),
N_( "Ext2fs directory block list is empty"),
N_( "Attempt to modify a block mapping via a read-only block iterator"),
N_( "Wrong magic number for ext4 extent saved path"),
N_( "Wrong magic number for 64-bit generic bitmap"),
N_( "Wrong magic number for 64-bit block bitmap"),
N_( "Wrong magic number for 64-bit inode bitmap"),
N_( "Wrong magic number --- RESERVED_13"),
N_( "Wrong magic number --- RESERVED_14"),
N_( "Wrong magic number --- RESERVED_15"),
N_( "Wrong magic number --- RESERVED_16"),
N_( "Wrong magic number --- RESERVED_17"),
N_( "Wrong magic number --- RESERVED_18"),
N_( "Wrong magic number --- RESERVED_19"),
N_( "Corrupt extent header"),
N_( "Corrupt extent index"),
N_( "Corrupt extent"),
N_( "No free space in extent map"),
N_( "Inode does not use extents"),
N_( "No 'next' extent"),
N_( "No 'previous' extent"),
N_( "No 'up' extent"),
N_( "No 'down' extent"),
N_( "No current node"),
N_( "Ext2fs operation not supported"),
N_( "No room to insert extent in node"),
N_( "Splitting would result in empty node"),
N_( "Extent not found"),
N_( "Operation not supported for inodes containing extents"),
N_( "Extent length is invalid"),
N_( "I/O Channel does not support 64-bit block numbers"),
N_( "Can't check if filesystem is mounted due to missing mtab file"),
N_( "Filesystem too large to use legacy bitmaps"),
N_( "MMP: invalid magic number"),
N_( "MMP: device currently active"),
N_( "MMP: fsck being run"),
N_( "MMP: block number beyond filesystem range"),
N_( "MMP: undergoing an unknown operation"),
N_( "MMP: filesystem still in use"),
N_( "MMP: open with O_DIRECT failed"),
0
};
struct error_table {
char const * const * msgs;
long base;
int n_msgs;
};
struct et_list {
struct et_list *next;
const struct error_table * table;
};
extern struct et_list *_et_list;
const struct error_table et_ext2_error_table = { text, 2133571328L, 145 };
static struct et_list link = { 0, 0 };
void initialize_ext2_error_table_r(struct et_list **list);
void initialize_ext2_error_table(void);
void initialize_ext2_error_table(void) {
initialize_ext2_error_table_r(&_et_list);
}
/* For Heimdal compatibility */
void initialize_ext2_error_table_r(struct et_list **list)
{
struct et_list *et, **end;
for (end = list, et = *list; et; end = &et->next, et = et->next)
if (et->table->msgs == text)
return;
et = malloc(sizeof(struct et_list));
if (et == 0) {
if (!link.table)
et = &link;
else
return;
}
et->table = &et_ext2_error_table;
et->next = 0;
*end = et;
}

View File

@ -0,0 +1,169 @@
/*
* ext2_err.h:
* This file is automatically generated; please do not edit it.
*/
#ifndef EXT2_ERR_H_
#define EXT2_ERR_H_
#include "com_err.h"
#define EXT2_ET_OK (0)
#define EXT2_ET_BASE (2133571328L)
#define EXT2_ET_MAGIC_EXT2FS_FILSYS (2133571329L)
#define EXT2_ET_MAGIC_BADBLOCKS_LIST (2133571330L)
#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE (2133571331L)
#define EXT2_ET_MAGIC_INODE_SCAN (2133571332L)
#define EXT2_ET_MAGIC_IO_CHANNEL (2133571333L)
#define EXT2_ET_MAGIC_UNIX_IO_CHANNEL (2133571334L)
#define EXT2_ET_MAGIC_IO_MANAGER (2133571335L)
#define EXT2_ET_MAGIC_BLOCK_BITMAP (2133571336L)
#define EXT2_ET_MAGIC_INODE_BITMAP (2133571337L)
#define EXT2_ET_MAGIC_GENERIC_BITMAP (2133571338L)
#define EXT2_ET_MAGIC_TEST_IO_CHANNEL (2133571339L)
#define EXT2_ET_MAGIC_DBLIST (2133571340L)
#define EXT2_ET_MAGIC_ICOUNT (2133571341L)
#define EXT2_ET_MAGIC_PQ_IO_CHANNEL (2133571342L)
#define EXT2_ET_MAGIC_EXT2_FILE (2133571343L)
#define EXT2_ET_MAGIC_E2IMAGE (2133571344L)
#define EXT2_ET_MAGIC_INODE_IO_CHANNEL (2133571345L)
#define EXT2_ET_MAGIC_EXTENT_HANDLE (2133571346L)
#define EXT2_ET_BAD_MAGIC (2133571347L)
#define EXT2_ET_REV_TOO_HIGH (2133571348L)
#define EXT2_ET_RO_FILSYS (2133571349L)
#define EXT2_ET_GDESC_READ (2133571350L)
#define EXT2_ET_GDESC_WRITE (2133571351L)
#define EXT2_ET_GDESC_BAD_BLOCK_MAP (2133571352L)
#define EXT2_ET_GDESC_BAD_INODE_MAP (2133571353L)
#define EXT2_ET_GDESC_BAD_INODE_TABLE (2133571354L)
#define EXT2_ET_INODE_BITMAP_WRITE (2133571355L)
#define EXT2_ET_INODE_BITMAP_READ (2133571356L)
#define EXT2_ET_BLOCK_BITMAP_WRITE (2133571357L)
#define EXT2_ET_BLOCK_BITMAP_READ (2133571358L)
#define EXT2_ET_INODE_TABLE_WRITE (2133571359L)
#define EXT2_ET_INODE_TABLE_READ (2133571360L)
#define EXT2_ET_NEXT_INODE_READ (2133571361L)
#define EXT2_ET_UNEXPECTED_BLOCK_SIZE (2133571362L)
#define EXT2_ET_DIR_CORRUPTED (2133571363L)
#define EXT2_ET_SHORT_READ (2133571364L)
#define EXT2_ET_SHORT_WRITE (2133571365L)
#define EXT2_ET_DIR_NO_SPACE (2133571366L)
#define EXT2_ET_NO_INODE_BITMAP (2133571367L)
#define EXT2_ET_NO_BLOCK_BITMAP (2133571368L)
#define EXT2_ET_BAD_INODE_NUM (2133571369L)
#define EXT2_ET_BAD_BLOCK_NUM (2133571370L)
#define EXT2_ET_EXPAND_DIR_ERR (2133571371L)
#define EXT2_ET_TOOSMALL (2133571372L)
#define EXT2_ET_BAD_BLOCK_MARK (2133571373L)
#define EXT2_ET_BAD_BLOCK_UNMARK (2133571374L)
#define EXT2_ET_BAD_BLOCK_TEST (2133571375L)
#define EXT2_ET_BAD_INODE_MARK (2133571376L)
#define EXT2_ET_BAD_INODE_UNMARK (2133571377L)
#define EXT2_ET_BAD_INODE_TEST (2133571378L)
#define EXT2_ET_FUDGE_BLOCK_BITMAP_END (2133571379L)
#define EXT2_ET_FUDGE_INODE_BITMAP_END (2133571380L)
#define EXT2_ET_BAD_IND_BLOCK (2133571381L)
#define EXT2_ET_BAD_DIND_BLOCK (2133571382L)
#define EXT2_ET_BAD_TIND_BLOCK (2133571383L)
#define EXT2_ET_NEQ_BLOCK_BITMAP (2133571384L)
#define EXT2_ET_NEQ_INODE_BITMAP (2133571385L)
#define EXT2_ET_BAD_DEVICE_NAME (2133571386L)
#define EXT2_ET_MISSING_INODE_TABLE (2133571387L)
#define EXT2_ET_CORRUPT_SUPERBLOCK (2133571388L)
#define EXT2_ET_BAD_GENERIC_MARK (2133571389L)
#define EXT2_ET_BAD_GENERIC_UNMARK (2133571390L)
#define EXT2_ET_BAD_GENERIC_TEST (2133571391L)
#define EXT2_ET_SYMLINK_LOOP (2133571392L)
#define EXT2_ET_CALLBACK_NOTHANDLED (2133571393L)
#define EXT2_ET_BAD_BLOCK_IN_INODE_TABLE (2133571394L)
#define EXT2_ET_UNSUPP_FEATURE (2133571395L)
#define EXT2_ET_RO_UNSUPP_FEATURE (2133571396L)
#define EXT2_ET_LLSEEK_FAILED (2133571397L)
#define EXT2_ET_NO_MEMORY (2133571398L)
#define EXT2_ET_INVALID_ARGUMENT (2133571399L)
#define EXT2_ET_BLOCK_ALLOC_FAIL (2133571400L)
#define EXT2_ET_INODE_ALLOC_FAIL (2133571401L)
#define EXT2_ET_NO_DIRECTORY (2133571402L)
#define EXT2_ET_TOO_MANY_REFS (2133571403L)
#define EXT2_ET_FILE_NOT_FOUND (2133571404L)
#define EXT2_ET_FILE_RO (2133571405L)
#define EXT2_ET_DB_NOT_FOUND (2133571406L)
#define EXT2_ET_DIR_EXISTS (2133571407L)
#define EXT2_ET_UNIMPLEMENTED (2133571408L)
#define EXT2_ET_CANCEL_REQUESTED (2133571409L)
#define EXT2_ET_FILE_TOO_BIG (2133571410L)
#define EXT2_ET_JOURNAL_NOT_BLOCK (2133571411L)
#define EXT2_ET_NO_JOURNAL_SB (2133571412L)
#define EXT2_ET_JOURNAL_TOO_SMALL (2133571413L)
#define EXT2_ET_JOURNAL_UNSUPP_VERSION (2133571414L)
#define EXT2_ET_LOAD_EXT_JOURNAL (2133571415L)
#define EXT2_ET_NO_JOURNAL (2133571416L)
#define EXT2_ET_DIRHASH_UNSUPP (2133571417L)
#define EXT2_ET_BAD_EA_BLOCK_NUM (2133571418L)
#define EXT2_ET_TOO_MANY_INODES (2133571419L)
#define EXT2_ET_NOT_IMAGE_FILE (2133571420L)
#define EXT2_ET_RES_GDT_BLOCKS (2133571421L)
#define EXT2_ET_RESIZE_INODE_CORRUPT (2133571422L)
#define EXT2_ET_SET_BMAP_NO_IND (2133571423L)
#define EXT2_ET_TDB_SUCCESS (2133571424L)
#define EXT2_ET_TDB_ERR_CORRUPT (2133571425L)
#define EXT2_ET_TDB_ERR_IO (2133571426L)
#define EXT2_ET_TDB_ERR_LOCK (2133571427L)
#define EXT2_ET_TDB_ERR_OOM (2133571428L)
#define EXT2_ET_TDB_ERR_EXISTS (2133571429L)
#define EXT2_ET_TDB_ERR_NOLOCK (2133571430L)
#define EXT2_ET_TDB_ERR_EINVAL (2133571431L)
#define EXT2_ET_TDB_ERR_NOEXIST (2133571432L)
#define EXT2_ET_TDB_ERR_RDONLY (2133571433L)
#define EXT2_ET_DBLIST_EMPTY (2133571434L)
#define EXT2_ET_RO_BLOCK_ITERATE (2133571435L)
#define EXT2_ET_MAGIC_EXTENT_PATH (2133571436L)
#define EXT2_ET_MAGIC_GENERIC_BITMAP64 (2133571437L)
#define EXT2_ET_MAGIC_BLOCK_BITMAP64 (2133571438L)
#define EXT2_ET_MAGIC_INODE_BITMAP64 (2133571439L)
#define EXT2_ET_MAGIC_RESERVED_13 (2133571440L)
#define EXT2_ET_MAGIC_RESERVED_14 (2133571441L)
#define EXT2_ET_MAGIC_RESERVED_15 (2133571442L)
#define EXT2_ET_MAGIC_RESERVED_16 (2133571443L)
#define EXT2_ET_MAGIC_RESERVED_17 (2133571444L)
#define EXT2_ET_MAGIC_RESERVED_18 (2133571445L)
#define EXT2_ET_MAGIC_RESERVED_19 (2133571446L)
#define EXT2_ET_EXTENT_HEADER_BAD (2133571447L)
#define EXT2_ET_EXTENT_INDEX_BAD (2133571448L)
#define EXT2_ET_EXTENT_LEAF_BAD (2133571449L)
#define EXT2_ET_EXTENT_NO_SPACE (2133571450L)
#define EXT2_ET_INODE_NOT_EXTENT (2133571451L)
#define EXT2_ET_EXTENT_NO_NEXT (2133571452L)
#define EXT2_ET_EXTENT_NO_PREV (2133571453L)
#define EXT2_ET_EXTENT_NO_UP (2133571454L)
#define EXT2_ET_EXTENT_NO_DOWN (2133571455L)
#define EXT2_ET_NO_CURRENT_NODE (2133571456L)
#define EXT2_ET_OP_NOT_SUPPORTED (2133571457L)
#define EXT2_ET_CANT_INSERT_EXTENT (2133571458L)
#define EXT2_ET_CANT_SPLIT_EXTENT (2133571459L)
#define EXT2_ET_EXTENT_NOT_FOUND (2133571460L)
#define EXT2_ET_EXTENT_NOT_SUPPORTED (2133571461L)
#define EXT2_ET_EXTENT_INVALID_LENGTH (2133571462L)
#define EXT2_ET_IO_CHANNEL_NO_SUPPORT_64 (2133571463L)
#define EXT2_NO_MTAB_FILE (2133571464L)
#define EXT2_ET_CANT_USE_LEGACY_BITMAPS (2133571465L)
#define EXT2_ET_MMP_MAGIC_INVALID (2133571466L)
#define EXT2_ET_MMP_FAILED (2133571467L)
#define EXT2_ET_MMP_FSCK_ON (2133571468L)
#define EXT2_ET_MMP_BAD_BLOCK (2133571469L)
#define EXT2_ET_MMP_UNKNOWN_SEQ (2133571470L)
#define EXT2_ET_MMP_CHANGE_ABORT (2133571471L)
#define EXT2_ET_MMP_OPEN_DIRECT (2133571472L)
extern const struct error_table et_ext2_error_table;
extern void initialize_ext2_error_table(void);
/* For compatibility with Heimdal */
extern void initialize_ext2_error_table_r(struct et_list **list);
#define ERROR_TABLE_BASE_ext2 (2133571328L)
/* for compatibility with older versions... */
#define init_ext2_err_tbl initialize_ext2_error_table
#define ext2_err_base ERROR_TABLE_BASE_ext2
#endif

View File

@ -0,0 +1,71 @@
/*
File: linux/ext2_ext_attr.h
On-disk format of extended attributes for the ext2 filesystem.
(C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.org>
*/
#ifndef _EXT2_EXT_ATTR_H
#define _EXT2_EXT_ATTR_H
/* Magic value in attribute blocks */
#define EXT2_EXT_ATTR_MAGIC_v1 0xEA010000
#define EXT2_EXT_ATTR_MAGIC 0xEA020000
/* Maximum number of references to one attribute block */
#define EXT2_EXT_ATTR_REFCOUNT_MAX 1024
struct ext2_ext_attr_header {
__u32 h_magic; /* magic number for identification */
__u32 h_refcount; /* reference count */
__u32 h_blocks; /* number of disk blocks used */
__u32 h_hash; /* hash value of all attributes */
__u32 h_reserved[4]; /* zero right now */
};
struct ext2_ext_attr_entry {
__u8 e_name_len; /* length of name */
__u8 e_name_index; /* attribute name index */
__u16 e_value_offs; /* offset in disk block of value */
__u32 e_value_block; /* disk block attribute is stored on (n/i) */
__u32 e_value_size; /* size of attribute value */
__u32 e_hash; /* hash value of name and value */
#if 0
char e_name[0]; /* attribute name */
#endif
};
#define EXT2_EXT_ATTR_PAD_BITS 2
#define EXT2_EXT_ATTR_PAD ((unsigned) 1<<EXT2_EXT_ATTR_PAD_BITS)
#define EXT2_EXT_ATTR_ROUND (EXT2_EXT_ATTR_PAD-1)
#define EXT2_EXT_ATTR_LEN(name_len) \
(((name_len) + EXT2_EXT_ATTR_ROUND + \
sizeof(struct ext2_ext_attr_entry)) & ~EXT2_EXT_ATTR_ROUND)
#define EXT2_EXT_ATTR_NEXT(entry) \
( (struct ext2_ext_attr_entry *)( \
(char *)(entry) + EXT2_EXT_ATTR_LEN((entry)->e_name_len)) )
#define EXT2_EXT_ATTR_SIZE(size) \
(((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
#define EXT2_EXT_IS_LAST_ENTRY(entry) (*((__u32 *)(entry)) == 0UL)
#define EXT2_EXT_ATTR_NAME(entry) \
(((char *) (entry)) + sizeof(struct ext2_ext_attr_entry))
#define EXT2_XATTR_LEN(name_len) \
(((name_len) + EXT2_EXT_ATTR_ROUND + \
sizeof(struct ext2_xattr_entry)) & ~EXT2_EXT_ATTR_ROUND)
#define EXT2_XATTR_SIZE(size) \
(((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
#ifdef __KERNEL__
# ifdef CONFIG_EXT2_FS_EXT_ATTR
extern int ext2_get_ext_attr(struct inode *, const char *, char *, size_t, int);
extern int ext2_set_ext_attr(struct inode *, const char *, char *, size_t, int);
extern void ext2_ext_attr_free_inode(struct inode *inode);
extern void ext2_ext_attr_put_super(struct super_block *sb);
extern int ext2_ext_attr_init(void);
extern void ext2_ext_attr_done(void);
# else
# define ext2_get_ext_attr NULL
# define ext2_set_ext_attr NULL
# endif
#endif /* __KERNEL__ */
#endif /* _EXT2_EXT_ATTR_H */

View File

@ -0,0 +1,60 @@
#include "ext2_internal.h"
#include "ext2_frag.h"
typedef struct _PrivData
{
_ext2_frag_append_t append_fragment;
void * callback_data;
} PrivDataST;
static int block_iter_callback(ext2_filsys fs, blk64_t *blocknr, e2_blkcnt_t blockcnt, blk64_t ref_block, int ref_offset, void *privateData)
{
PrivDataST *priv = (PrivDataST *) privateData;
blk64_t block;
block = *blocknr;
return priv->append_fragment(priv->callback_data, blockcnt*fs->io->block_size/512, block*fs->io->block_size/512, fs->io->block_size/512);
}
int _EXT2_get_fragments(const char *in_path, _ext2_frag_append_t append_fragment, void *callback_data)
{
ext2_inode_t *ni = NULL;
ext2_vd *vd;
vd = ext2GetVolume(in_path);
if(!vd)
{
errno = EXDEV;
return -1;
}
// Get the actual path of the entry
const char * path = ext2RealPath(in_path);
if (!path) {
errno = EINVAL;
return -1;
}
// Find the entry
ni = ext2OpenEntry(vd, path);
if (!ni) {
errno = ENOENT;
return -1;
}
PrivDataST priv;
priv.callback_data = callback_data;
priv.append_fragment = append_fragment;
int ret = ext2fs_block_iterate3(vd->fs, ni->ino, BLOCK_FLAG_DATA_ONLY, NULL, block_iter_callback, &priv);
if(ret == 0)
ret = priv.append_fragment(callback_data, EXT2_I_SIZE(&ni->ni) >> 9, 0, 0);
ext2UpdateTimes(vd, ni, EXT2_UPDATE_ATIME);
ext2CloseEntry(vd, ni);
return ret;
}

View File

@ -0,0 +1,854 @@
/*
* linux/include/linux/ext2_fs.h
*
* Copyright (C) 1992, 1993, 1994, 1995
* Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
* linux/include/linux/minix_fs.h
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
#ifndef _LINUX_EXT2_FS_H
#define _LINUX_EXT2_FS_H
#include "ext2_types.h" /* Changed from linux/types.h */
/*
* The second extended filesystem constants/structures
*/
/*
* Define EXT2FS_DEBUG to produce debug messages
*/
#undef EXT2FS_DEBUG
/*
* Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
*/
#define EXT2_PREALLOCATE
#define EXT2_DEFAULT_PREALLOC_BLOCKS 8
/*
* The second extended file system version
*/
#define EXT2FS_DATE "95/08/09"
#define EXT2FS_VERSION "0.5b"
/*
* Special inode numbers
*/
#define EXT2_BAD_INO 1 /* Bad blocks inode */
#define EXT2_ROOT_INO 2 /* Root inode */
#define EXT4_USR_QUOTA_INO 3 /* User quota inode */
#define EXT4_GRP_QUOTA_INO 4 /* Group quota inode */
#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */
#define EXT2_JOURNAL_INO 8 /* Journal inode */
#define EXT2_EXCLUDE_INO 9 /* The "exclude" inode, for snapshots */
/* First non-reserved inode for old ext2 filesystems */
#define EXT2_GOOD_OLD_FIRST_INO 11
/*
* The second extended file system magic number
*/
#define EXT2_SUPER_MAGIC 0xEF53
#ifdef __KERNEL__
#define EXT2_SB(sb) (&((sb)->u.ext2_sb))
#else
/* Assume that user mode programs are passing in an ext2fs superblock, not
* a kernel struct super_block. This will allow us to call the feature-test
* macros from user land. */
#define EXT2_SB(sb) (sb)
#endif
/*
* Maximal count of links to a file
*/
#define EXT2_LINK_MAX 65000
/*
* Macro-instructions used to manage several block sizes
*/
#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */
#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */
#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE)
#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE)
#ifdef __KERNEL__
#define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
#define EXT2_ADDR_PER_BLOCK_BITS(s) (EXT2_SB(s)->addr_per_block_bits)
#define EXT2_INODE_SIZE(s) (EXT2_SB(s)->s_inode_size)
#define EXT2_FIRST_INO(s) (EXT2_SB(s)->s_first_ino)
#else
#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size)
#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino)
#endif
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(__u32))
/*
* Macro-instructions used to manage allocation clusters
*/
#define EXT2_MIN_CLUSTER_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE
#define EXT2_MAX_CLUSTER_LOG_SIZE 29 /* 512MB */
#define EXT2_MIN_CLUSTER_SIZE EXT2_MIN_BLOCK_SIZE
#define EXT2_MAX_CLUSTER_SIZE (1 << EXT2_MAX_CLUSTER_LOG_SIZE)
#define EXT2_CLUSTER_SIZE(s) (EXT2_MIN_BLOCK_SIZE << \
(s)->s_log_cluster_size)
#define EXT2_CLUSTER_SIZE_BITS(s) ((s)->s_log_cluster_size + 10)
/*
* Macro-instructions used to manage fragments
*
* Note: for backwards compatibility only, for the dump program.
* Ext2/3/4 will never support fragments....
*/
#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE
#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE
#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE
#define EXT2_FRAG_SIZE(s) EXT2_BLOCK_SIZE(s)
#define EXT2_FRAGS_PER_BLOCK(s) 1
/*
* ACL structures
*/
struct ext2_acl_header /* Header of Access Control Lists */
{
__u32 aclh_size;
__u32 aclh_file_count;
__u32 aclh_acle_count;
__u32 aclh_first_acle;
};
struct ext2_acl_entry /* Access Control List Entry */
{
__u32 acle_size;
__u16 acle_perms; /* Access permissions */
__u16 acle_type; /* Type of entry */
__u16 acle_tag; /* User or group identity */
__u16 acle_pad1;
__u32 acle_next; /* Pointer on next entry for the */
/* same inode or on next free entry */
};
/*
* Structure of a blocks group descriptor
*/
struct ext2_group_desc
{
__u32 bg_block_bitmap; /* Blocks bitmap block */
__u32 bg_inode_bitmap; /* Inodes bitmap block */
__u32 bg_inode_table; /* Inodes table block */
__u16 bg_free_blocks_count; /* Free blocks count */
__u16 bg_free_inodes_count; /* Free inodes count */
__u16 bg_used_dirs_count; /* Directories count */
__u16 bg_flags;
__u32 bg_exclude_bitmap_lo; /* Exclude bitmap for snapshots */
__u16 bg_block_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */
__u16 bg_inode_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */
__u16 bg_itable_unused; /* Unused inodes count */
__u16 bg_checksum; /* crc16(s_uuid+grouo_num+group_desc)*/
};
/*
* Structure of a blocks group descriptor
*/
struct ext4_group_desc
{
__u32 bg_block_bitmap; /* Blocks bitmap block */
__u32 bg_inode_bitmap; /* Inodes bitmap block */
__u32 bg_inode_table; /* Inodes table block */
__u16 bg_free_blocks_count; /* Free blocks count */
__u16 bg_free_inodes_count; /* Free inodes count */
__u16 bg_used_dirs_count; /* Directories count */
__u16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
__u32 bg_exclude_bitmap_lo; /* Exclude bitmap for snapshots */
__u16 bg_block_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */
__u16 bg_inode_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */
__u16 bg_itable_unused; /* Unused inodes count */
__u16 bg_checksum; /* crc16(sb_uuid+group+desc) */
__u32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
__u32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */
__u32 bg_inode_table_hi; /* Inodes table block MSB */
__u16 bg_free_blocks_count_hi;/* Free blocks count MSB */
__u16 bg_free_inodes_count_hi;/* Free inodes count MSB */
__u16 bg_used_dirs_count_hi; /* Directories count MSB */
__u16 bg_itable_unused_hi; /* Unused inodes count MSB */
__u32 bg_exclude_bitmap_hi; /* Exclude bitmap block MSB */
__u16 bg_block_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+bitmap) MSB */
__u16 bg_inode_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+bitmap) MSB */
__u32 bg_reserved;
};
#define EXT2_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not initialized */
#define EXT2_BG_BLOCK_UNINIT 0x0002 /* Block bitmap not initialized */
#define EXT2_BG_INODE_ZEROED 0x0004 /* On-disk itable initialized to zero */
/*
* Data structures used by the directory indexing feature
*
* Note: all of the multibyte integer fields are little endian.
*/
/*
* Note: dx_root_info is laid out so that if it should somehow get
* overlaid by a dirent the two low bits of the hash version will be
* zero. Therefore, the hash version mod 4 should never be 0.
* Sincerely, the paranoia department.
*/
struct ext2_dx_root_info {
__u32 reserved_zero;
__u8 hash_version; /* 0 now, 1 at release */
__u8 info_length; /* 8 */
__u8 indirect_levels;
__u8 unused_flags;
};
#define EXT2_HASH_LEGACY 0
#define EXT2_HASH_HALF_MD4 1
#define EXT2_HASH_TEA 2
#define EXT2_HASH_LEGACY_UNSIGNED 3 /* reserved for userspace lib */
#define EXT2_HASH_HALF_MD4_UNSIGNED 4 /* reserved for userspace lib */
#define EXT2_HASH_TEA_UNSIGNED 5 /* reserved for userspace lib */
#define EXT2_HASH_FLAG_INCOMPAT 0x1
struct ext2_dx_entry {
__u32 hash;
__u32 block;
};
struct ext2_dx_countlimit {
__u16 limit;
__u16 count;
};
/*
* Macro-instructions used to manage group descriptors
*/
#define EXT2_MIN_DESC_SIZE 32
#define EXT2_MIN_DESC_SIZE_64BIT 64
#define EXT2_MAX_DESC_SIZE EXT2_MIN_BLOCK_SIZE
#define EXT2_DESC_SIZE(s) \
((EXT2_SB(s)->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) ? \
(s)->s_desc_size : EXT2_MIN_DESC_SIZE)
#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group)
#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group)
#define EXT2_CLUSTERS_PER_GROUP(s) (EXT2_SB(s)->s_clusters_per_group)
#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */
#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((((unsigned) 1 << 16) - 8) * \
(EXT2_CLUSTER_SIZE(s) / \
EXT2_BLOCK_SIZE(s)))
#define EXT2_MAX_CLUSTERS_PER_GROUP(s) (((unsigned) 1 << 16) - 8)
#define EXT2_MAX_INODES_PER_GROUP(s) (((unsigned) 1 << 16) - \
EXT2_INODES_PER_BLOCK(s))
#ifdef __KERNEL__
#define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block)
#define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_desc_per_block_bits)
#else
#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s))
#endif
/*
* Constants relative to the data blocks
*/
#define EXT2_NDIR_BLOCKS 12
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
/*
* Inode flags
*/
#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
#define EXT2_UNRM_FL 0x00000002 /* Undelete */
#define EXT2_COMPR_FL 0x00000004 /* Compress file */
#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
/* Reserved for compression usage... */
#define EXT2_DIRTY_FL 0x00000100
#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */
#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
/* End compression flags --- maybe not all used */
#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */
#define EXT2_IMAGIC_FL 0x00002000
#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */
#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */
#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
#define EXT4_EA_INODE_FL 0x00200000 /* Inode used for large EA */
#define EXT4_EOFBLOCKS_FL 0x00400000 /* Blocks allocated beyond EOF */
#define EXT4_SNAPFILE_FL 0x01000000 /* Inode is a snapshot */
#define EXT4_SNAPFILE_DELETED_FL 0x04000000 /* Snapshot is being deleted */
#define EXT4_SNAPFILE_SHRUNK_FL 0x08000000 /* Snapshot shrink has completed */
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
#define EXT2_FL_USER_VISIBLE 0x004BDFFF /* User visible flags */
#define EXT2_FL_USER_MODIFIABLE 0x004B80FF /* User modifiable flags */
/*
* ioctl commands
*/
/* Used for online resize */
struct ext2_new_group_input {
__u32 group; /* Group number for this data */
__u32 block_bitmap; /* Absolute block number of block bitmap */
__u32 inode_bitmap; /* Absolute block number of inode bitmap */
__u32 inode_table; /* Absolute block number of inode table start */
__u32 blocks_count; /* Total number of blocks in this group */
__u16 reserved_blocks; /* Number of reserved blocks in this group */
__u16 unused; /* Number of reserved GDT blocks in group */
};
struct ext4_new_group_input {
__u32 group; /* Group number for this data */
__u64 block_bitmap; /* Absolute block number of block bitmap */
__u64 inode_bitmap; /* Absolute block number of inode bitmap */
__u64 inode_table; /* Absolute block number of inode table start */
__u32 blocks_count; /* Total number of blocks in this group */
__u16 reserved_blocks; /* Number of reserved blocks in this group */
__u16 unused;
};
#ifdef __GNU__ /* Needed for the Hurd */
#define _IOT_ext2_new_group_input _IOT (_IOTS(__u32), 5, _IOTS(__u16), 2, 0, 0)
#endif
#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
#define EXT2_IOC_GETVERSION_NEW _IOR('f', 3, long)
#define EXT2_IOC_SETVERSION_NEW _IOW('f', 4, long)
#define EXT2_IOC_GROUP_EXTEND _IOW('f', 7, unsigned long)
#define EXT2_IOC_GROUP_ADD _IOW('f', 8,struct ext2_new_group_input)
#define EXT4_IOC_GROUP_ADD _IOW('f', 8,struct ext4_new_group_input)
#define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64)
/*
* Structure of an inode on the disk
*/
struct ext2_inode {
__u16 i_mode; /* File mode */
__u16 i_uid; /* Low 16 bits of Owner Uid */
__u32 i_size; /* Size in bytes */
__u32 i_atime; /* Access time */
__u32 i_ctime; /* Inode change time */
__u32 i_mtime; /* Modification time */
__u32 i_dtime; /* Deletion Time */
__u16 i_gid; /* Low 16 bits of Group Id */
__u16 i_links_count; /* Links count */
__u32 i_blocks; /* Blocks count */
__u32 i_flags; /* File flags */
union {
struct {
__u32 l_i_version; /* was l_i_reserved1 */
} linux1;
struct {
__u32 h_i_translator;
} hurd1;
} osd1; /* OS dependent 1 */
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__u32 i_generation; /* File version (for NFS) */
__u32 i_file_acl; /* File ACL */
__u32 i_size_high; /* Formerly i_dir_acl, directory ACL */
__u32 i_faddr; /* Fragment address */
union {
struct {
__u16 l_i_blocks_hi;
__u16 l_i_file_acl_high;
__u16 l_i_uid_high; /* these 2 fields */
__u16 l_i_gid_high; /* were reserved2[0] */
__u16 l_i_checksum_lo; /* crc32c(uuid+inum+inode) */
__u16 l_i_reserved;
} linux2;
struct {
__u8 h_i_frag; /* Fragment number */
__u8 h_i_fsize; /* Fragment size */
__u16 h_i_mode_high;
__u16 h_i_uid_high;
__u16 h_i_gid_high;
__u32 h_i_author;
} hurd2;
} osd2; /* OS dependent 2 */
};
/*
* Permanent part of an large inode on the disk
*/
struct ext2_inode_large {
__u16 i_mode; /* File mode */
__u16 i_uid; /* Low 16 bits of Owner Uid */
__u32 i_size; /* Size in bytes */
__u32 i_atime; /* Access time */
__u32 i_ctime; /* Inode Change time */
__u32 i_mtime; /* Modification time */
__u32 i_dtime; /* Deletion Time */
__u16 i_gid; /* Low 16 bits of Group Id */
__u16 i_links_count; /* Links count */
__u32 i_blocks; /* Blocks count */
__u32 i_flags; /* File flags */
union {
struct {
__u32 l_i_version; /* was l_i_reserved1 */
} linux1;
struct {
__u32 h_i_translator;
} hurd1;
} osd1; /* OS dependent 1 */
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__u32 i_generation; /* File version (for NFS) */
__u32 i_file_acl; /* File ACL */
__u32 i_size_high; /* Formerly i_dir_acl, directory ACL */
__u32 i_faddr; /* Fragment address */
union {
struct {
__u16 l_i_blocks_hi;
__u16 l_i_file_acl_high;
__u16 l_i_uid_high; /* these 2 fields */
__u16 l_i_gid_high; /* were reserved2[0] */
__u16 l_i_checksum_lo; /* crc32c(uuid+inum+inode) */
__u16 l_i_reserved;
} linux2;
struct {
__u8 h_i_frag; /* Fragment number */
__u8 h_i_fsize; /* Fragment size */
__u16 h_i_mode_high;
__u16 h_i_uid_high;
__u16 h_i_gid_high;
__u32 h_i_author;
} hurd2;
} osd2; /* OS dependent 2 */
__u16 i_extra_isize;
__u16 i_checksum_hi; /* crc32c(uuid+inum+inode) */
__u32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
__u32 i_mtime_extra; /* extra Modification time (nsec << 2 | epoch) */
__u32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
__u32 i_crtime; /* File creation time */
__u32 i_crtime_extra; /* extra File creation time (nsec << 2 | epoch)*/
__u32 i_version_hi; /* high 32 bits for 64-bit version */
};
#define i_dir_acl i_size_high
#if defined(__KERNEL__) || defined(__linux__)
#define i_reserved1 osd1.linux1.l_i_reserved1
#define i_frag osd2.linux2.l_i_frag
#define i_fsize osd2.linux2.l_i_fsize
#define i_uid_low i_uid
#define i_gid_low i_gid
#define i_uid_high osd2.linux2.l_i_uid_high
#define i_gid_high osd2.linux2.l_i_gid_high
#else
#if defined(__GNU__)
#define i_translator osd1.hurd1.h_i_translator
#define i_frag osd2.hurd2.h_i_frag;
#define i_fsize osd2.hurd2.h_i_fsize;
#define i_uid_high osd2.hurd2.h_i_uid_high
#define i_gid_high osd2.hurd2.h_i_gid_high
#define i_author osd2.hurd2.h_i_author
#endif /* __GNU__ */
#endif /* defined(__KERNEL__) || defined(__linux__) */
#define inode_uid(inode) ((inode).i_uid | (inode).osd2.linux2.l_i_uid_high << 16)
#define inode_gid(inode) ((inode).i_gid | (inode).osd2.linux2.l_i_gid_high << 16)
#define ext2fs_set_i_uid_high(inode,x) ((inode).osd2.linux2.l_i_uid_high = (x))
#define ext2fs_set_i_gid_high(inode,x) ((inode).osd2.linux2.l_i_gid_high = (x))
/*
* File system states
*/
#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
#define EXT2_ERROR_FS 0x0002 /* Errors detected */
#define EXT3_ORPHAN_FS 0x0004 /* Orphans being recovered */
/*
* Misc. filesystem flags
*/
#define EXT2_FLAGS_SIGNED_HASH 0x0001 /* Signed dirhash in use */
#define EXT2_FLAGS_UNSIGNED_HASH 0x0002 /* Unsigned dirhash in use */
#define EXT2_FLAGS_TEST_FILESYS 0x0004 /* OK for use on development code */
#define EXT2_FLAGS_IS_SNAPSHOT 0x0010 /* This is a snapshot image */
#define EXT2_FLAGS_FIX_SNAPSHOT 0x0020 /* Snapshot inodes corrupted */
#define EXT2_FLAGS_FIX_EXCLUDE 0x0040 /* Exclude bitmaps corrupted */
/*
* Mount flags
*/
#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \
EXT2_MOUNT_##opt)
/*
* Maximal mount counts between two filesystem checks
*/
#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
/*
* Behaviour when detecting errors
*/
#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
#define EXT2_ERRORS_PANIC 3 /* Panic */
#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
#if (__GNUC__ >= 4)
#define ext4_offsetof(TYPE,MEMBER) __builtin_offsetof(TYPE,MEMBER)
#else
#define ext4_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
/*
* Structure of the super block
*/
struct ext2_super_block {
__u32 s_inodes_count; /* Inodes count */
__u32 s_blocks_count; /* Blocks count */
__u32 s_r_blocks_count; /* Reserved blocks count */
__u32 s_free_blocks_count; /* Free blocks count */
__u32 s_free_inodes_count; /* Free inodes count */
__u32 s_first_data_block; /* First Data Block */
__u32 s_log_block_size; /* Block size */
__u32 s_log_cluster_size; /* Allocation cluster size */
__u32 s_blocks_per_group; /* # Blocks per group */
__u32 s_clusters_per_group; /* # Fragments per group */
__u32 s_inodes_per_group; /* # Inodes per group */
__u32 s_mtime; /* Mount time */
__u32 s_wtime; /* Write time */
__u16 s_mnt_count; /* Mount count */
__s16 s_max_mnt_count; /* Maximal mount count */
__u16 s_magic; /* Magic signature */
__u16 s_state; /* File system state */
__u16 s_errors; /* Behaviour when detecting errors */
__u16 s_minor_rev_level; /* minor revision level */
__u32 s_lastcheck; /* time of last check */
__u32 s_checkinterval; /* max. time between checks */
__u32 s_creator_os; /* OS */
__u32 s_rev_level; /* Revision level */
__u16 s_def_resuid; /* Default uid for reserved blocks */
__u16 s_def_resgid; /* Default gid for reserved blocks */
/*
* These fields are for EXT2_DYNAMIC_REV superblocks only.
*
* Note: the difference between the compatible feature set and
* the incompatible feature set is that if there is a bit set
* in the incompatible feature set that the kernel doesn't
* know about, it should refuse to mount the filesystem.
*
* e2fsck's requirements are more strict; if it doesn't know
* about a feature in either the compatible or incompatible
* feature set, it must abort and not try to meddle with
* things it doesn't understand...
*/
__u32 s_first_ino; /* First non-reserved inode */
__u16 s_inode_size; /* size of inode structure */
__u16 s_block_group_nr; /* block group # of this superblock */
__u32 s_feature_compat; /* compatible feature set */
__u32 s_feature_incompat; /* incompatible feature set */
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
__u8 s_uuid[16]; /* 128-bit uuid for volume */
char s_volume_name[16]; /* volume name */
char s_last_mounted[64]; /* directory where last mounted */
__u32 s_algorithm_usage_bitmap; /* For compression */
/*
* Performance hints. Directory preallocation should only
* happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
*/
__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
__u16 s_reserved_gdt_blocks; /* Per group table for online growth */
/*
* Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
*/
__u8 s_journal_uuid[16]; /* uuid of journal superblock */
__u32 s_journal_inum; /* inode number of journal file */
__u32 s_journal_dev; /* device number of journal file */
__u32 s_last_orphan; /* start of list of inodes to delete */
__u32 s_hash_seed[4]; /* HTREE hash seed */
__u8 s_def_hash_version; /* Default hash version to use */
__u8 s_jnl_backup_type; /* Default type of journal backup */
__u16 s_desc_size; /* Group desc. size: INCOMPAT_64BIT */
__u32 s_default_mount_opts;
__u32 s_first_meta_bg; /* First metablock group */
__u32 s_mkfs_time; /* When the filesystem was created */
__u32 s_jnl_blocks[17]; /* Backup of the journal inode */
__u32 s_blocks_count_hi; /* Blocks count high 32bits */
__u32 s_r_blocks_count_hi; /* Reserved blocks count high 32 bits*/
__u32 s_free_blocks_hi; /* Free blocks count */
__u16 s_min_extra_isize; /* All inodes have at least # bytes */
__u16 s_want_extra_isize; /* New inodes should reserve # bytes */
__u32 s_flags; /* Miscellaneous flags */
__u16 s_raid_stride; /* RAID stride */
__u16 s_mmp_update_interval; /* # seconds to wait in MMP checking */
__u64 s_mmp_block; /* Block for multi-mount protection */
__u32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/
__u8 s_log_groups_per_flex; /* FLEX_BG group size */
__u8 s_reserved_char_pad;
__u16 s_reserved_pad; /* Padding to next 32bits */
__u64 s_kbytes_written; /* nr of lifetime kilobytes written */
__u32 s_snapshot_inum; /* Inode number of active snapshot */
__u32 s_snapshot_id; /* sequential ID of active snapshot */
__u64 s_snapshot_r_blocks_count; /* reserved blocks for active
snapshot's future use */
__u32 s_snapshot_list; /* inode number of the head of the on-disk snapshot list */
#define EXT4_S_ERR_START ext4_offsetof(struct ext2_super_block, s_error_count)
__u32 s_error_count; /* number of fs errors */
__u32 s_first_error_time; /* first time an error happened */
__u32 s_first_error_ino; /* inode involved in first error */
__u64 s_first_error_block; /* block involved of first error */
__u8 s_first_error_func[32]; /* function where the error happened */
__u32 s_first_error_line; /* line number where error happened */
__u32 s_last_error_time; /* most recent time of an error */
__u32 s_last_error_ino; /* inode involved in last error */
__u32 s_last_error_line; /* line number where error happened */
__u64 s_last_error_block; /* block involved of last error */
__u8 s_last_error_func[32]; /* function where the error happened */
#define EXT4_S_ERR_END ext4_offsetof(struct ext2_super_block, s_mount_opts)
__u8 s_mount_opts[64];
__u32 s_usr_quota_inum; /* inode number of user quota file */
__u32 s_grp_quota_inum; /* inode number of group quota file */
__u32 s_overhead_blocks; /* overhead blocks/clusters in fs */
__u32 s_reserved[108]; /* Padding to the end of the block */
__u32 s_checksum; /* crc32c(superblock) */
};
#define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START)
/*
* Codes for operating systems
*/
#define EXT2_OS_LINUX 0
#define EXT2_OS_HURD 1
#define EXT2_OBSO_OS_MASIX 2
#define EXT2_OS_FREEBSD 3
#define EXT2_OS_LITES 4
/*
* Revision levels
*/
#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
#define EXT2_GOOD_OLD_INODE_SIZE 128
/*
* Journal inode backup types
*/
#define EXT3_JNL_BACKUP_BLOCKS 1
/*
* Feature set definitions
*/
#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_feature_compat & (mask) )
#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_feature_incompat & (mask) )
#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010
#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
#define EXT2_FEATURE_COMPAT_LAZY_BG 0x0040
/* #define EXT2_FEATURE_COMPAT_EXCLUDE_INODE 0x0080 not used, legacy */
#define EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP 0x0100
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */
#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008
#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
#define EXT4_FEATURE_RO_COMPAT_HAS_SNAPSHOT 0x0080
#define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100
#define EXT4_FEATURE_RO_COMPAT_BIGALLOC 0x0200
#define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400
#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
#define EXT4_FEATURE_INCOMPAT_EA_INODE 0x0400
#define EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000
#define EXT2_FEATURE_COMPAT_SUPP 0
#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
EXT4_FEATURE_INCOMPAT_MMP)
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
/*
* Default values for user and/or group using reserved blocks
*/
#define EXT2_DEF_RESUID 0
#define EXT2_DEF_RESGID 0
/*
* Default mount options
*/
#define EXT2_DEFM_DEBUG 0x0001
#define EXT2_DEFM_BSDGROUPS 0x0002
#define EXT2_DEFM_XATTR_USER 0x0004
#define EXT2_DEFM_ACL 0x0008
#define EXT2_DEFM_UID16 0x0010
#define EXT3_DEFM_JMODE 0x0060
#define EXT3_DEFM_JMODE_DATA 0x0020
#define EXT3_DEFM_JMODE_ORDERED 0x0040
#define EXT3_DEFM_JMODE_WBACK 0x0060
#define EXT4_DEFM_NOBARRIER 0x0100
#define EXT4_DEFM_BLOCK_VALIDITY 0x0200
#define EXT4_DEFM_DISCARD 0x0400
#define EXT4_DEFM_NODELALLOC 0x0800
/*
* Structure of a directory entry
*/
#define EXT2_NAME_LEN 255
struct ext2_dir_entry {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u16 name_len; /* Name length */
char name[EXT2_NAME_LEN]; /* File name */
};
/*
* The new version of the directory entry. Since EXT2 structures are
* stored in intel byte order, and the name_len field could never be
* bigger than 255 chars, it's safe to reclaim the extra byte for the
* file_type field.
*/
struct ext2_dir_entry_2 {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u8 name_len; /* Name length */
__u8 file_type;
char name[EXT2_NAME_LEN]; /* File name */
};
/*
* Ext2 directory file types. Only the low 3 bits are used. The
* other bits are reserved for now.
*/
#define EXT2_FT_UNKNOWN 0
#define EXT2_FT_REG_FILE 1
#define EXT2_FT_DIR 2
#define EXT2_FT_CHRDEV 3
#define EXT2_FT_BLKDEV 4
#define EXT2_FT_FIFO 5
#define EXT2_FT_SOCK 6
#define EXT2_FT_SYMLINK 7
#define EXT2_FT_MAX 8
/*
* EXT2_DIR_PAD defines the directory entries boundaries
*
* NOTE: It must be a multiple of 4
*/
#define EXT2_DIR_PAD 4
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND)
/*
* This structure is used for multiple mount protection. It is written
* into the block number saved in the s_mmp_block field in the superblock.
* Programs that check MMP should assume that if SEQ_FSCK (or any unknown
* code above SEQ_MAX) is present then it is NOT safe to use the filesystem,
* regardless of how old the timestamp is.
*
* The timestamp in the MMP structure will be updated by e2fsck at some
* arbitary intervals (start of passes, after every few groups of inodes
* in pass1 and pass1b). There is no guarantee that e2fsck is updating
* the MMP block in a timely manner, and the updates it does are purely
* for the convenience of the sysadmin and not for automatic validation.
*
* Note: Only the mmp_seq value is used to determine whether the MMP block
* is being updated. The mmp_time, mmp_nodename, and mmp_bdevname
* fields are only for informational purposes for the administrator,
* due to clock skew between nodes and hostname HA service takeover.
*/
#define EXT4_MMP_MAGIC 0x004D4D50U /* ASCII for MMP */
#define EXT4_MMP_SEQ_CLEAN 0xFF4D4D50U /* mmp_seq value for clean unmount */
#define EXT4_MMP_SEQ_FSCK 0xE24D4D50U /* mmp_seq value when being fscked */
#define EXT4_MMP_SEQ_MAX 0xE24D4D4FU /* maximum valid mmp_seq value */
struct mmp_struct {
__u32 mmp_magic; /* Magic number for MMP */
__u32 mmp_seq; /* Sequence no. updated periodically */
__u64 mmp_time; /* Time last updated */
char mmp_nodename[64]; /* Node which last updated MMP block */
char mmp_bdevname[32]; /* Bdev which last updated MMP block */
__u16 mmp_check_interval; /* Changed mmp_check_interval */
__u16 mmp_pad1;
__u32 mmp_pad2[227];
};
/*
* Default interval for MMP update in seconds.
*/
#define EXT4_MMP_UPDATE_INTERVAL 5
/*
* Maximum interval for MMP update in seconds.
*/
#define EXT4_MMP_MAX_UPDATE_INTERVAL 300
/*
* Minimum interval for MMP checking in seconds.
*/
#define EXT4_MMP_MIN_CHECK_INTERVAL 5
#endif /* _LINUX_EXT2_FS_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,102 @@
/**
* ext2_internal.h
*
* Copyright (c) 2009 Rhys "Shareese" Koedijk
* Copyright (c) 2010 Dimok
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EXT2_INTERNAL_H_
#define EXT2_INTERNAL_H_
#include <gccore.h>
#include <ogc/disc_io.h>
#include <sys/iosupport.h>
#include "ext2fs.h"
#include "ext2_fs.h"
#include "mem_allocate.h"
#ifdef DEBUG_GEKKO
#define ext2_log_trace printf
#else
#define ext2_log_trace(...)
#endif
typedef struct _ext2_inode_t
{
struct ext2_inode ni;
ext2_ino_t ino;
bool dirty;
} ext2_inode_t;
/**
* ext2_vd - EXT2 volume descriptor
*/
typedef struct _ext2_vd
{
io_channel io; /* EXT device handle */
ext2_filsys fs; /* EXT volume handle */
mutex_t lock; /* Volume lock mutex */
ext2_inode_t *cwd_ni; /* Current directory */
struct _ext2_dir_state *firstOpenDir; /* The start of a FILO linked list of currently opened directories */
struct _ext2_file_state *firstOpenFile; /* The start of a FILO linked list of currently opened files */
u16 openDirCount; /* The total number of directories currently open in this volume */
u16 openFileCount; /* The total number of files currently open in this volume */
ext2_ino_t root; /* Root node */
} ext2_vd;
typedef enum {
EXT2_UPDATE_ATIME = 0x01,
EXT2_UPDATE_MTIME = 0x02,
EXT2_UPDATE_CTIME = 0x04,
EXT2_UPDATE_AMTIME = EXT2_UPDATE_ATIME | EXT2_UPDATE_MTIME,
EXT2_UPDATE_ACTIME = EXT2_UPDATE_ATIME | EXT2_UPDATE_CTIME,
EXT2_UPDATE_MCTIME = EXT2_UPDATE_MTIME | EXT2_UPDATE_CTIME,
EXT2_UPDATE_AMCTIME = EXT2_UPDATE_ATIME | EXT2_UPDATE_MTIME | EXT2_UPDATE_CTIME,
} ext2_time_update_flags;
/* Lock volume */
static inline void ext2Lock (ext2_vd *vd)
{
LWP_MutexLock(vd->lock);
}
/* Unlock volume */
static inline void ext2Unlock (ext2_vd *vd)
{
LWP_MutexUnlock(vd->lock);
}
const char *ext2RealPath (const char *path);
int ext2InitVolume (ext2_vd *vd);
void ext2DeinitVolume (ext2_vd *vd);
ext2_vd *ext2GetVolume (const char *path);
int ext2AddDevice (const char *name, void *deviceData);
void ext2RemoveDevice (const char *path);
const devoptab_t *ext2GetDevice (const char *path);
ext2_inode_t *ext2OpenEntry (ext2_vd *vd, const char *path);
void ext2CloseEntry (ext2_vd *vd, ext2_inode_t * ni);
int ext2Stat (ext2_vd *vd, ext2_inode_t * ni, struct stat *st);
int ext2Sync (ext2_vd *vd, ext2_inode_t * ni);
ext2_inode_t *ext2Create (ext2_vd *vd, const char *path, mode_t type, const char *target);
int ext2Link (ext2_vd *vd, const char *old_path, const char *new_path);
int ext2Unlink (ext2_vd *vd, const char *path);
void ext2UpdateTimes(ext2_vd *vd, ext2_inode_t *ni, ext2_time_update_flags mask);
#endif

View File

@ -0,0 +1,145 @@
/*
* io.h --- the I/O manager abstraction
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#ifndef _EXT2FS_EXT2_IO_H
#define _EXT2FS_EXT2_IO_H
#include "ext2fs.h"
/*
* ext2_loff_t is defined here since unix_io.c needs it.
*/
typedef long long ext2_loff_t;
/* llseek.c */
ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int);
typedef struct struct_io_manager *io_manager;
typedef struct struct_io_channel *io_channel;
typedef struct struct_io_stats *io_stats;
#define CHANNEL_FLAGS_WRITETHROUGH 0x01
#define CHANNEL_FLAGS_DISCARD_ZEROES 0x02
#define CHANNEL_FLAGS_BLOCK_DEVICE 0x04
#define io_channel_discard_zeroes_data(i) (i->flags & CHANNEL_FLAGS_DISCARD_ZEROES)
struct struct_io_channel {
errcode_t magic;
io_manager manager;
char *name;
int block_size;
errcode_t (*read_error)(io_channel channel,
unsigned long block,
int count,
void *data,
size_t size,
int actual_bytes_read,
errcode_t error);
errcode_t (*write_error)(io_channel channel,
unsigned long block,
int count,
const void *data,
size_t size,
int actual_bytes_written,
errcode_t error);
int refcount;
int flags;
long reserved[14];
void *private_data;
void *app_data;
};
struct struct_io_stats {
int num_fields;
int reserved;
unsigned long long bytes_read;
unsigned long long bytes_written;
};
struct struct_io_manager {
errcode_t magic;
const char *name;
errcode_t (*open)(const char *name, int flags, io_channel *channel);
errcode_t (*close)(io_channel channel);
errcode_t (*set_blksize)(io_channel channel, int blksize);
errcode_t (*read_blk)(io_channel channel, unsigned long block,
int count, void *data);
errcode_t (*write_blk)(io_channel channel, unsigned long block,
int count, const void *data);
errcode_t (*flush)(io_channel channel);
errcode_t (*write_byte)(io_channel channel, unsigned long offset,
int count, const void *data);
errcode_t (*set_option)(io_channel channel, const char *option,
const char *arg);
errcode_t (*get_stats)(io_channel channel, io_stats *io_stats);
errcode_t (*read_blk64)(io_channel channel, unsigned long long block,
int count, void *data);
errcode_t (*write_blk64)(io_channel channel, unsigned long long block,
int count, const void *data);
errcode_t (*discard)(io_channel channel, unsigned long long block,
unsigned long long count);
long reserved[16];
};
#define IO_FLAG_RW 0x0001
#define IO_FLAG_EXCLUSIVE 0x0002
#define IO_FLAG_DIRECT_IO 0x0004
/*
* Convenience functions....
*/
#define io_channel_close(c) ((c)->manager->close((c)))
#define io_channel_set_blksize(c,s) ((c)->manager->set_blksize((c),s))
#define io_channel_read_blk(c,b,n,d) ((c)->manager->read_blk((c),b,n,d))
#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d))
#define io_channel_flush(c) ((c)->manager->flush((c)))
#define io_channel_bumpcount(c) ((c)->refcount++)
/* io_manager.c */
extern errcode_t io_channel_set_options(io_channel channel,
const char *options);
extern errcode_t io_channel_write_byte(io_channel channel,
unsigned long offset,
int count, const void *data);
extern errcode_t io_channel_read_blk64(io_channel channel,
unsigned long long block,
int count, void *data);
extern errcode_t io_channel_write_blk64(io_channel channel,
unsigned long long block,
int count, const void *data);
extern errcode_t io_channel_discard(io_channel channel,
unsigned long long block,
unsigned long long count);
/* unix_io.c */
extern io_manager unix_io_manager;
/* undo_io.c */
extern io_manager undo_io_manager;
extern errcode_t set_undo_io_backing_manager(io_manager manager);
extern errcode_t set_undo_io_backup_file(char *file_name);
/* test_io.c */
extern io_manager test_io_manager, test_io_backing_manager;
extern void (*test_io_cb_read_blk)
(unsigned long block, int count, errcode_t err);
extern void (*test_io_cb_write_blk)
(unsigned long block, int count, errcode_t err);
extern void (*test_io_cb_read_blk64)
(unsigned long long block, int count, errcode_t err);
extern void (*test_io_cb_write_blk64)
(unsigned long long block, int count, errcode_t err);
extern void (*test_io_cb_set_blksize)
(int blksize, errcode_t err);
#endif /* _EXT2FS_EXT2_IO_H */

Some files were not shown because too many files have changed in this diff Show More