Compare commits
17 commits
Author | SHA1 | Date | |
---|---|---|---|
|
910f6f5f22 | ||
|
1fed6e83f2 | ||
|
0cd2573062 | ||
|
da71bf99dc | ||
|
f145fb1e91 | ||
|
d90a6f0429 | ||
|
afb3b68349 | ||
|
3994181361 | ||
|
f6c9003574 | ||
|
d657e03e5f | ||
|
718245adcd | ||
|
9d46977121 | ||
|
85eb0a7ed2 | ||
|
9bcb476262 | ||
|
89fc757642 | ||
|
93ac37f27c | ||
|
0f17471b27 |
813 changed files with 99535 additions and 97228 deletions
44
HBC/META.XML
44
HBC/META.XML
|
@ -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>
|
BIN
HBC/icon.png
BIN
HBC/icon.png
Binary file not shown.
Before Width: | Height: | Size: 7.8 KiB |
1078
HBC/readMii.txt
1078
HBC/readMii.txt
File diff suppressed because it is too large
Load diff
1483
Languages/czech.lang
1483
Languages/czech.lang
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
1540
Languages/dutch.lang
1540
Languages/dutch.lang
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
1498
Languages/thai.lang
1498
Languages/thai.lang
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -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
279
Makefile
|
@ -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
|
||||
#---------------------------------------------------------------------------------
|
|
@ -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 ""
|
14
buildtype.sh
14
buildtype.sh
|
@ -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 |
BIN
data/certs.dat
BIN
data/certs.dat
Binary file not shown.
BIN
data/haxx.certs
BIN
data/haxx.certs
Binary file not shown.
Binary file not shown.
BIN
data/stub.bin
BIN
data/stub.bin
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
1
gui.pnps
1
gui.pnps
|
@ -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
11
libcustomext2fs/AUTHORS
Normal 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
10
libcustomext2fs/CREDITS
Normal 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
340
libcustomext2fs/LICENSE
Normal 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
27
libcustomext2fs/Makefile
Normal 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
|
||||
|
106
libcustomext2fs/include/ext2.h
Normal file
106
libcustomext2fs/include/ext2.h
Normal 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
|
130
libcustomext2fs/source/Makefile
Normal file
130
libcustomext2fs/source/Makefile
Normal 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
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
320
libcustomext2fs/source/alloc.c
Normal file
320
libcustomext2fs/source/alloc.c
Normal 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;
|
||||
}
|
82
libcustomext2fs/source/alloc_sb.c
Normal file
82
libcustomext2fs/source/alloc_sb.c
Normal 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 ;
|
||||
}
|
108
libcustomext2fs/source/alloc_stats.c
Normal file
108
libcustomext2fs/source/alloc_stats.c
Normal 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;
|
||||
}
|
245
libcustomext2fs/source/alloc_tables.c
Normal file
245
libcustomext2fs/source/alloc_tables.c
Normal 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;
|
||||
}
|
||||
|
328
libcustomext2fs/source/badblocks.c
Normal file
328
libcustomext2fs/source/badblocks.c
Normal 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;
|
||||
}
|
64
libcustomext2fs/source/bb_compat.c
Normal file
64
libcustomext2fs/source/bb_compat.c
Normal 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);
|
||||
}
|
267
libcustomext2fs/source/bb_inode.c
Normal file
267
libcustomext2fs/source/bb_inode.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
57
libcustomext2fs/source/bit_ops.h
Normal file
57
libcustomext2fs/source/bit_ops.h
Normal 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
|
308
libcustomext2fs/source/bitmaps.c
Normal file
308
libcustomext2fs/source/bitmaps.c
Normal 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));
|
||||
}
|
118
libcustomext2fs/source/bitops.c
Normal file
118
libcustomext2fs/source/bitops.c
Normal 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);
|
||||
}
|
||||
|
643
libcustomext2fs/source/bitops.h
Normal file
643
libcustomext2fs/source/bitops.h
Normal 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
|
328
libcustomext2fs/source/blkmap64_ba.c
Normal file
328
libcustomext2fs/source/blkmap64_ba.c
Normal 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,
|
||||
};
|
498
libcustomext2fs/source/blknum.c
Normal file
498
libcustomext2fs/source/blknum.c
Normal 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;
|
||||
}
|
||||
|
635
libcustomext2fs/source/block.c
Normal file
635
libcustomext2fs/source/block.c
Normal 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);
|
||||
}
|
||||
|
398
libcustomext2fs/source/bmap.c
Normal file
398
libcustomext2fs/source/bmap.c
Normal 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;
|
||||
}
|
62
libcustomext2fs/source/bmap64.h
Normal file
62
libcustomext2fs/source/bmap64.h
Normal 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;
|
167
libcustomext2fs/source/bmove.c
Normal file
167
libcustomext2fs/source/bmove.c
Normal 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;
|
||||
}
|
||||
|
86
libcustomext2fs/source/brel.h
Normal file
86
libcustomext2fs/source/brel.h
Normal 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)))
|
||||
|
199
libcustomext2fs/source/brel_ma.c
Normal file
199
libcustomext2fs/source/brel_ma.c
Normal 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;
|
||||
}
|
102
libcustomext2fs/source/check_desc.c
Normal file
102
libcustomext2fs/source/check_desc.c
Normal 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;
|
||||
}
|
474
libcustomext2fs/source/closefs.c
Normal file
474
libcustomext2fs/source/closefs.c
Normal 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;
|
||||
}
|
||||
|
35
libcustomext2fs/source/com_err.c
Normal file
35
libcustomext2fs/source/com_err.c
Normal 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");
|
||||
}
|
70
libcustomext2fs/source/com_err.h
Normal file
70
libcustomext2fs/source/com_err.h
Normal 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__)*/
|
603
libcustomext2fs/source/config.h
Normal file
603
libcustomext2fs/source/config.h
Normal 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
|
74
libcustomext2fs/source/crc16.c
Normal file
74
libcustomext2fs/source/crc16.c
Normal 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;
|
||||
}
|
26
libcustomext2fs/source/crc16.h
Normal file
26
libcustomext2fs/source/crc16.h
Normal 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 */
|
1144
libcustomext2fs/source/crc32c.c
Normal file
1144
libcustomext2fs/source/crc32c.c
Normal file
File diff suppressed because it is too large
Load diff
51
libcustomext2fs/source/crc32c_defs.h
Normal file
51
libcustomext2fs/source/crc32c_defs.h
Normal 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
|
1065
libcustomext2fs/source/crc32c_table.h
Normal file
1065
libcustomext2fs/source/crc32c_table.h
Normal file
File diff suppressed because it is too large
Load diff
289
libcustomext2fs/source/csum.c
Normal file
289
libcustomext2fs/source/csum.c
Normal 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(¶m, 0, sizeof(param));
|
||||
ext2fs_blocks_count_set(¶m, 32768);
|
||||
|
||||
retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m,
|
||||
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
|
415
libcustomext2fs/source/dblist.c
Normal file
415
libcustomext2fs/source/dblist.c
Normal 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;
|
||||
}
|
||||
|
80
libcustomext2fs/source/dblist_dir.c
Normal file
80
libcustomext2fs/source/dblist_dir.c
Normal 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;
|
||||
}
|
271
libcustomext2fs/source/dir_iterate.c
Normal file
271
libcustomext2fs/source/dir_iterate.c
Normal 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;
|
||||
}
|
||||
|
127
libcustomext2fs/source/dirblock.c
Normal file
127
libcustomext2fs/source/dirblock.c
Normal 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);
|
||||
}
|
||||
|
261
libcustomext2fs/source/dirhash.c
Normal file
261
libcustomext2fs/source/dirhash.c
Normal 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;
|
||||
}
|
374
libcustomext2fs/source/disc_cache.c
Normal file
374
libcustomext2fs/source/disc_cache.c
Normal 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;
|
||||
}
|
||||
}
|
118
libcustomext2fs/source/disc_cache.h
Normal file
118
libcustomext2fs/source/disc_cache.h
Normal 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
|
||||
|
97
libcustomext2fs/source/dupfs.c
Normal file
97
libcustomext2fs/source/dupfs.c
Normal 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;
|
||||
|
||||
}
|
||||
|
46
libcustomext2fs/source/e2image.h
Normal file
46
libcustomext2fs/source/e2image.h
Normal 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];
|
||||
};
|
137
libcustomext2fs/source/expanddir.c
Normal file
137
libcustomext2fs/source/expanddir.c
Normal 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;
|
||||
}
|
423
libcustomext2fs/source/ext2.c
Normal file
423
libcustomext2fs/source/ext2.c
Normal 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, §or.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, §or, 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, §or))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
199
libcustomext2fs/source/ext2_err.c
Normal file
199
libcustomext2fs/source/ext2_err.c
Normal 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;
|
||||
}
|
169
libcustomext2fs/source/ext2_err.h
Normal file
169
libcustomext2fs/source/ext2_err.h
Normal 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
|
||||
|
71
libcustomext2fs/source/ext2_ext_attr.h
Normal file
71
libcustomext2fs/source/ext2_ext_attr.h
Normal 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 */
|
60
libcustomext2fs/source/ext2_frag.c
Normal file
60
libcustomext2fs/source/ext2_frag.c
Normal 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;
|
||||
}
|
854
libcustomext2fs/source/ext2_fs.h
Normal file
854
libcustomext2fs/source/ext2_fs.h
Normal 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 */
|
1076
libcustomext2fs/source/ext2_internal.c
Normal file
1076
libcustomext2fs/source/ext2_internal.c
Normal file
File diff suppressed because it is too large
Load diff
102
libcustomext2fs/source/ext2_internal.h
Normal file
102
libcustomext2fs/source/ext2_internal.h
Normal 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
|
145
libcustomext2fs/source/ext2_io.h
Normal file
145
libcustomext2fs/source/ext2_io.h
Normal 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
Loading…
Reference in a new issue